import repository from arizona
[raven.git] / 2.0 / python / logging / uniqify.py
1 import os
2 import time
3 import sys
4
5 def sort(fn_in, fn_out):
6     result = os.system("sort -n < " + fn_in + " > " + fn_out)
7     if result != 0:
8         raise IOError
9
10 def uniq(fn_in, fn_out):
11     result = os.system("uniq < " + fn_in + " > " + fn_out)
12     if result != 0:
13         raise IOError
14
15 def mergelist(fnlist_in, fn_out):
16     args = " ".join(fnlist_in)
17     result = os.system("cat " + args + " > " + fn_out)
18     if result != 0:
19         raise IOError
20
21 def uniqify(fn_list, dest_fn):
22
23     # if we only have one filename, then it is already unique, so ignore it
24     if len(fn_list) <= 1:
25         return
26
27     print "uniqify: " + str(len(fn_list)) + " files --> " + dest_fn
28
29     temp_fn = "/data/tmp/uniqify.tmp"
30     backup_fn = None
31
32     # remove temp_fn if it already exists
33     if os.path.exists(temp_fn):
34         os.remove(temp_fn)
35
36     # merge the files into a single big file
37     mergelist(fn_list, temp_fn)
38
39     # sort it, and remove duplicate entries
40     sort(temp_fn, temp_fn + ".sorted")
41     uniq(temp_fn + ".sorted", temp_fn + ".uniq")
42
43     # backup dest_fn if it exists
44     if os.path.exists(dest_fn):
45         backup_fn = dest_fn + ".old"
46         # remove the old backup if it exists
47         try:
48             os.remove(backup_fn)
49         except:
50             pass
51         os.rename(dest_fn, backup_fn)
52
53     try:
54         os.rename(temp_fn + ".uniq", dest_fn)
55     except:
56         print "failed to rename " + temp_fn + " to " + dest_fn
57         # if we failed, restore the backup back to the original filename
58         if backup_fn:          
59            os.rename(backup_fn, dest_fn)
60         return
61
62     # invariants:
63     #   all data from the original files is present in dest_fn
64     #   original filenames can be safely deleted
65
66     # remove the original filenames
67     for fn in fn_list:
68         if fn != dest_fn:
69             os.remove(fn)
70
71 def isnumber(x):
72     try:
73        int(x)
74        return True
75     except:
76        return False
77
78 def get_file_size(fn):
79     try:
80        return os.stat(fn)[6]
81     except:
82        return 0
83
84 def uniqify_dir(dir):
85     print "getting filename list from " + dir
86
87     # get a sorted list of filenames
88
89     # ls doesn't work because it's very slow on nr05 (is this because new files
90     # being written to the directory cause it to re-read?)
91 #    tmp_out = os.popen("ls " + dir + " 2>&1")
92
93     # use our own directory reader -- would python's directory read & sort work?
94     tmp_out = os.popen("./dumpdir " + dir + " 100000 | sort")
95
96     filenames = tmp_out.readlines()
97     filenames = [fn.strip() for fn in filenames]
98
99     print "sleeping 60 seconds to wait for any pending transfers to complete"
100 #    time.sleep(60)
101
102     work_list = []
103     work_prefix = None
104     work_bytes = 0
105     work_count = 0
106
107     for fn in filenames:
108         # make sure the filename ends in either .uniq or .<number>
109         suffixPos = fn.rfind(".")
110         if suffixPos == -1:
111             continue
112         prefix = fn[:suffixPos]
113         suffix = fn[suffixPos+1:]
114         if not suffix:
115             continue
116         if not (suffix == "uniq") and not (isnumber(suffix)):
117             continue
118
119         if (work_prefix != prefix) or ((work_count>1) and (work_bytes>5000000)):
120             if work_list:
121                 work_list = [os.path.join(dir, tmpfn) for tmpfn in work_list]
122                 print "bytes = " + str(work_bytes)
123                 uniqify(work_list, os.path.join(dir, work_prefix + ".uniq"))
124
125             work_list = []
126             work_prefix = prefix
127             work_bytes = 0
128             work_count = 0
129
130         work_list.append(fn)
131         work_bytes = work_bytes + get_file_size(os.path.join(dir, fn))
132         work_count = work_count + 1
133
134 def main():
135     args = sys.argv[:]
136
137     # get rid of the program name
138     args = args[1:]
139
140     if len(args)<1 or args[0]=='help':
141        print "syntax: uniqify <dir>"
142        print "example: uniqify /home/logging/logs/strace"
143        sys.exit(1)
144
145     uniqify_dir(args[0])
146
147 if __name__ == "__main__":
148     main()
149