| 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
|
|---|