1 # A parallelized "find(1)" using the thread module (SGI only for now).
3 # This demonstrates the use of a work queue and worker threads.
4 # It really does do more stats/sec when using multiple threads,
5 # although the improvement is only about 20-30 percent.
7 # I'm too lazy to write a command line parser for the full find(1)
8 # command line syntax, so the predicate it searches for is wired-in,
9 # see function selector() below. (It currently searches for files with
10 # group or world write permission.)
12 # Usage: parfind.py [-w nworkers] [directory] ...
13 # Default nworkers is 4, maximum appears to be 8 (on Irix 4.0.2)
25 # Work queue class. Usage:
27 # wq.addwork(func, (arg1, arg2, ...)) # one or more calls
29 # The work is done when wq.run() completes.
30 # The function calls executed by the workers may add more work.
31 # Don't use keyboard interrupts!
37 # - busy and work are only modified when mutex is locked
38 # - len(work) is the number of jobs ready to be taken
39 # - busy is the number of jobs being done
40 # - todo is locked iff there is no work and somebody is busy
43 self
.mutex
= thread
.allocate()
44 self
.todo
= thread
.allocate()
49 def addwork(self
, func
, args
):
54 if len(self
.work
) == 1:
60 if self
.busy
== 0 and len(self
.work
) == 0:
66 self
.busy
= self
.busy
+ 1
68 if len(self
.work
) > 0:
74 self
.busy
= self
.busy
- 1
75 if self
.busy
== 0 and len(self
.work
) == 0:
88 def run(self
, nworkers
):
90 return # Nothing to do
91 for i
in range(nworkers
-1):
92 thread
.start_new(self
._worker
, ())
101 opts
, args
= getopt
.getopt(sys
.argv
[1:], '-w:')
102 for opt
, arg
in opts
:
104 nworkers
= string
.atoi(arg
)
110 wq
.addwork(find
, (dir, selector
, wq
))
116 sys
.stderr
.write('Total time ' + `t2
-t1`
+ ' sec.\n')
119 # The predicate -- defines what files we look for.
120 # Feel free to change this to suit your purpose
122 def selector(dir, name
, fullname
, stat
):
123 # Look for group or world writable files
124 return (stat
[ST_MODE
] & 0022) != 0
127 # The find procedure -- calls wq.addwork() for subdirectories
129 def find(dir, pred
, wq
):
131 names
= os
.listdir(dir)
132 except os
.error
, msg
:
133 print `
dir`
, ':', msg
136 if name
not in (os
.curdir
, os
.pardir
):
137 fullname
= os
.path
.join(dir, name
)
139 stat
= os
.lstat(fullname
)
140 except os
.error
, msg
:
141 print `fullname`
, ':', msg
143 if pred(dir, name
, fullname
, stat
):
145 if S_ISDIR(stat
[ST_MODE
]):
146 if not os
.path
.ismount(fullname
):
147 wq
.addwork(find
, (fullname
, pred
, wq
))
150 # Call the main program