1 |
|
---|
2 | import threading
|
---|
3 | import xapian
|
---|
4 | import time
|
---|
5 |
|
---|
6 | class context(object):
|
---|
7 | def __init__(self):
|
---|
8 | self.mutex = threading.Lock()
|
---|
9 | self.opencount = 0
|
---|
10 | self.threadcount = 0
|
---|
11 | self.logitems = []
|
---|
12 | self.failed = False
|
---|
13 |
|
---|
14 | def get_threadnum(self):
|
---|
15 | self.threadcount += 1
|
---|
16 | return self.threadcount
|
---|
17 |
|
---|
18 | def inccount(self):
|
---|
19 | self.mutex.acquire()
|
---|
20 | try:
|
---|
21 | self.opencount += 1
|
---|
22 | result = self.opencount
|
---|
23 | finally:
|
---|
24 | self.mutex.release()
|
---|
25 | return result
|
---|
26 |
|
---|
27 | def deccount(self):
|
---|
28 | self.mutex.acquire()
|
---|
29 | try:
|
---|
30 | self.opencount -= 1
|
---|
31 | result = self.opencount
|
---|
32 | finally:
|
---|
33 | self.mutex.release()
|
---|
34 | return result
|
---|
35 |
|
---|
36 | def log(self, msg):
|
---|
37 | self.logitems.append(msg)
|
---|
38 |
|
---|
39 | def fail(self):
|
---|
40 | self.failed = True
|
---|
41 |
|
---|
42 | class test(threading.Thread):
|
---|
43 | def __init__(self, context, **kwargs):
|
---|
44 | threading.Thread.__init__(self, **kwargs)
|
---|
45 | self.context = context
|
---|
46 | self.threadnum = context.get_threadnum()
|
---|
47 |
|
---|
48 | def run(self):
|
---|
49 | time.sleep(0.01)
|
---|
50 | self.context.log("opening %d" % self.threadnum)
|
---|
51 | try:
|
---|
52 | db = xapian.WritableDatabase('testdb', xapian.DB_CREATE_OR_OPEN)
|
---|
53 | except:
|
---|
54 | self.context.log("already open %d" % self.threadnum)
|
---|
55 | return
|
---|
56 |
|
---|
57 | self.context.log("opened %d" % self.threadnum)
|
---|
58 | open = self.context.inccount()
|
---|
59 | if open != 1:
|
---|
60 | self.context.log("FAIL: simultanous open from thread %d" % self.threadnum)
|
---|
61 | self.context.fail()
|
---|
62 | raise RuntimeError("Opened %d databases simultaneously" % open)
|
---|
63 | time.sleep(0.01)
|
---|
64 | self.context.deccount() # Might be too soon, but we'll never overcount
|
---|
65 | self.context.log("closing %d" % self.threadnum)
|
---|
66 | del db
|
---|
67 | self.context.log("closed %d" % self.threadnum)
|
---|
68 |
|
---|
69 | def runtest():
|
---|
70 | c=context()
|
---|
71 | threads=[]
|
---|
72 | for num in xrange(10):
|
---|
73 | threads.append(test(c))
|
---|
74 |
|
---|
75 | for thread in threads:
|
---|
76 | thread.start()
|
---|
77 |
|
---|
78 | for thread in threads:
|
---|
79 | thread.join()
|
---|
80 |
|
---|
81 | if c.failed:
|
---|
82 | print '\n'.join(c.logitems)
|
---|
83 | else:
|
---|
84 | print "passed"
|
---|
85 | return c.failed
|
---|
86 |
|
---|
87 | for i in xrange(100):
|
---|
88 | f = runtest()
|
---|
89 | if f:
|
---|
90 | break
|
---|