Merge branch 'master' of git://git.assembla.com/fpdb-eric
Conflicts: pyfpdb/HandHistoryConverter.py
This commit is contained in:
commit
116141b833
5554
pyfpdb/SQL.py
5554
pyfpdb/SQL.py
File diff suppressed because it is too large
Load Diff
|
@ -1,271 +1,271 @@
|
||||||
|
|
||||||
# Code from http://ender.snowburst.org:4747/~jjohns/interlocks.py
|
# Code from http://ender.snowburst.org:4747/~jjohns/interlocks.py
|
||||||
# Thanks JJ!
|
# Thanks JJ!
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os, os.path
|
import os, os.path
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
import signal
|
import signal
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
InterProcessLock = None
|
InterProcessLock = None
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Just use me like a thread lock. acquire() / release() / locked()
|
Just use me like a thread lock. acquire() / release() / locked()
|
||||||
|
|
||||||
Differences compared to thread locks:
|
Differences compared to thread locks:
|
||||||
1. By default, acquire()'s wait parameter is false.
|
1. By default, acquire()'s wait parameter is false.
|
||||||
2. When acquire fails, SingleInstanceError is thrown instead of simply returning false.
|
2. When acquire fails, SingleInstanceError is thrown instead of simply returning false.
|
||||||
3. acquire() can take a 3rd parameter retry_time, which, if wait is True, tells the locking
|
3. acquire() can take a 3rd parameter retry_time, which, if wait is True, tells the locking
|
||||||
mechanism how long to sleep between retrying the lock. Has no effect for unix/InterProcessLockFcntl.
|
mechanism how long to sleep between retrying the lock. Has no effect for unix/InterProcessLockFcntl.
|
||||||
|
|
||||||
Differences in fpdb version to JJ's original:
|
Differences in fpdb version to JJ's original:
|
||||||
1. Changed acquire() to return false like other locks
|
1. Changed acquire() to return false like other locks
|
||||||
2. Made acquire fail if same process already has the lock
|
2. Made acquire fail if same process already has the lock
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class SingleInstanceError(RuntimeError):
|
class SingleInstanceError(RuntimeError):
|
||||||
"Thrown when you try to acquire an InterProcessLock and another version of the process is already running."
|
"Thrown when you try to acquire an InterProcessLock and another version of the process is already running."
|
||||||
|
|
||||||
class InterProcessLockBase:
|
class InterProcessLockBase:
|
||||||
def __init__(self, name=None ):
|
def __init__(self, name=None ):
|
||||||
self._has_lock = False
|
self._has_lock = False
|
||||||
if not name:
|
if not name:
|
||||||
name = sys.argv[0]
|
name = sys.argv[0]
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def getHashedName(self):
|
def getHashedName(self):
|
||||||
return base64.b64encode(self.name).replace('=','')
|
return base64.b64encode(self.name).replace('=','')
|
||||||
|
|
||||||
def acquire_impl(self, wait): abstract
|
def acquire_impl(self, wait): abstract
|
||||||
|
|
||||||
def acquire(self, wait=False, retry_time=1):
|
def acquire(self, wait=False, retry_time=1):
|
||||||
if self._has_lock: # make sure 2nd acquire in same process fails
|
if self._has_lock: # make sure 2nd acquire in same process fails
|
||||||
return False
|
return False
|
||||||
while not self._has_lock:
|
while not self._has_lock:
|
||||||
try:
|
try:
|
||||||
self.acquire_impl(wait)
|
self.acquire_impl(wait)
|
||||||
self._has_lock = True
|
self._has_lock = True
|
||||||
#print 'i have the lock'
|
#print 'i have the lock'
|
||||||
except SingleInstanceError:
|
except SingleInstanceError:
|
||||||
if not wait:
|
if not wait:
|
||||||
# raise # change back to normal acquire functionality, sorry JJ!
|
# raise # change back to normal acquire functionality, sorry JJ!
|
||||||
return False
|
return False
|
||||||
time.sleep(retry_time)
|
time.sleep(retry_time)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def release(self):
|
def release(self):
|
||||||
self.release_impl()
|
self.release_impl()
|
||||||
self._has_lock = False
|
self._has_lock = False
|
||||||
|
|
||||||
def locked(self):
|
def locked(self):
|
||||||
if self._has_lock:
|
if self._has_lock:
|
||||||
return True
|
return True
|
||||||
try:
|
try:
|
||||||
self.acquire()
|
self.acquire()
|
||||||
self.release()
|
self.release()
|
||||||
return False
|
return False
|
||||||
except SingleInstanceError:
|
except SingleInstanceError:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
LOCK_FILE_DIRECTORY = '/tmp'
|
LOCK_FILE_DIRECTORY = '/tmp'
|
||||||
|
|
||||||
class InterProcessLockFcntl(InterProcessLockBase):
|
class InterProcessLockFcntl(InterProcessLockBase):
|
||||||
def __init__(self, name=None):
|
def __init__(self, name=None):
|
||||||
InterProcessLockBase.__init__(self, name)
|
InterProcessLockBase.__init__(self, name)
|
||||||
self.lockfd = 0
|
self.lockfd = 0
|
||||||
self.lock_file_name = os.path.join(LOCK_FILE_DIRECTORY, self.getHashedName() + '.lck')
|
self.lock_file_name = os.path.join(LOCK_FILE_DIRECTORY, self.getHashedName() + '.lck')
|
||||||
assert(os.path.isdir(LOCK_FILE_DIRECTORY))
|
assert(os.path.isdir(LOCK_FILE_DIRECTORY))
|
||||||
|
|
||||||
# This is the suggested way to get a safe file name, but I like having a descriptively named lock file.
|
# This is the suggested way to get a safe file name, but I like having a descriptively named lock file.
|
||||||
def getHashedName(self):
|
def getHashedName(self):
|
||||||
import re
|
import re
|
||||||
bad_filename_character_re = re.compile(r'/\?<>\\\:;\*\|\'\"\^=\.\[\]')
|
bad_filename_character_re = re.compile(r'/\?<>\\\:;\*\|\'\"\^=\.\[\]')
|
||||||
return bad_filename_character_re.sub('_',self.name)
|
return bad_filename_character_re.sub('_',self.name)
|
||||||
|
|
||||||
def acquire_impl(self, wait):
|
def acquire_impl(self, wait):
|
||||||
self.lockfd = open(self.lock_file_name, 'w')
|
self.lockfd = open(self.lock_file_name, 'w')
|
||||||
fcntrl_options = fcntl.LOCK_EX
|
fcntrl_options = fcntl.LOCK_EX
|
||||||
if not wait:
|
if not wait:
|
||||||
fcntrl_options |= fcntl.LOCK_NB
|
fcntrl_options |= fcntl.LOCK_NB
|
||||||
try:
|
try:
|
||||||
fcntl.flock(self.lockfd, fcntrl_options)
|
fcntl.flock(self.lockfd, fcntrl_options)
|
||||||
except IOError:
|
except IOError:
|
||||||
self.lockfd.close()
|
self.lockfd.close()
|
||||||
self.lockfd = 0
|
self.lockfd = 0
|
||||||
raise SingleInstanceError('Could not acquire exclusive lock on '+self.lock_file_name)
|
raise SingleInstanceError('Could not acquire exclusive lock on '+self.lock_file_name)
|
||||||
|
|
||||||
def release_impl(self):
|
def release_impl(self):
|
||||||
fcntl.lockf(self.lockfd, fcntl.LOCK_UN)
|
fcntl.lockf(self.lockfd, fcntl.LOCK_UN)
|
||||||
self.lockfd.close()
|
self.lockfd.close()
|
||||||
self.lockfd = 0
|
self.lockfd = 0
|
||||||
try:
|
try:
|
||||||
os.unlink(self.lock_file_name)
|
os.unlink(self.lock_file_name)
|
||||||
except IOError:
|
except IOError:
|
||||||
# We don't care about the existence of the file too much here. It's the flock() we care about,
|
# We don't care about the existence of the file too much here. It's the flock() we care about,
|
||||||
# And that should just go away magically.
|
# And that should just go away magically.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class InterProcessLockWin32(InterProcessLockBase):
|
class InterProcessLockWin32(InterProcessLockBase):
|
||||||
def __init__(self, name=None):
|
def __init__(self, name=None):
|
||||||
InterProcessLockBase.__init__(self, name)
|
InterProcessLockBase.__init__(self, name)
|
||||||
self.mutex = None
|
self.mutex = None
|
||||||
|
|
||||||
def acquire_impl(self,wait):
|
def acquire_impl(self,wait):
|
||||||
self.mutex = win32event.CreateMutex(None, 0, self.getHashedName())
|
self.mutex = win32event.CreateMutex(None, 0, self.getHashedName())
|
||||||
if win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS:
|
if win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS:
|
||||||
self.mutex.Close()
|
self.mutex.Close()
|
||||||
self.mutex = None
|
self.mutex = None
|
||||||
raise SingleInstanceError('Could not acquire exclusive lock on ' + self.name)
|
raise SingleInstanceError('Could not acquire exclusive lock on ' + self.name)
|
||||||
|
|
||||||
def release_impl(self):
|
def release_impl(self):
|
||||||
self.mutex.Close()
|
self.mutex.Close()
|
||||||
|
|
||||||
class InterProcessLockSocket(InterProcessLockBase):
|
class InterProcessLockSocket(InterProcessLockBase):
|
||||||
def __init__(self, name=None):
|
def __init__(self, name=None):
|
||||||
InterProcessLockBase.__init__(self, name)
|
InterProcessLockBase.__init__(self, name)
|
||||||
self.socket = None
|
self.socket = None
|
||||||
self.portno = 65530 - abs(self.getHashedName().__hash__()) % 32749
|
self.portno = 65530 - abs(self.getHashedName().__hash__()) % 32749
|
||||||
|
|
||||||
def acquire_impl(self, wait):
|
def acquire_impl(self, wait):
|
||||||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
try:
|
try:
|
||||||
self.socket.bind(('127.0.0.1', self.portno))
|
self.socket.bind(('127.0.0.1', self.portno))
|
||||||
except socket.error:
|
except socket.error:
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
self.socket = None
|
self.socket = None
|
||||||
raise SingleInstanceError('Could not acquire exclusive lock on ' + self.name)
|
raise SingleInstanceError('Could not acquire exclusive lock on ' + self.name)
|
||||||
|
|
||||||
def release_impl(self):
|
def release_impl(self):
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
self.socket = None
|
self.socket = None
|
||||||
|
|
||||||
# Set InterProcessLock to the correct type given the sysem parameters available
|
# Set InterProcessLock to the correct type given the sysem parameters available
|
||||||
try:
|
try:
|
||||||
import fcntl
|
import fcntl
|
||||||
InterProcessLock = InterProcessLockFcntl
|
InterProcessLock = InterProcessLockFcntl
|
||||||
except ImportError:
|
except ImportError:
|
||||||
try:
|
try:
|
||||||
import win32event
|
import win32event
|
||||||
import win32api
|
import win32api
|
||||||
import winerror
|
import winerror
|
||||||
InterProcessLock = InterProcessLockWin32
|
InterProcessLock = InterProcessLockWin32
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import socket
|
import socket
|
||||||
InterProcessLock = InterProcessLockSocket
|
InterProcessLock = InterProcessLockSocket
|
||||||
|
|
||||||
def test_construct():
|
def test_construct():
|
||||||
"""
|
"""
|
||||||
# Making the name of the test unique so it can be executed my multiple users on the same machine.
|
# Making the name of the test unique so it can be executed my multiple users on the same machine.
|
||||||
>>> test_name = 'InterProcessLockTest' +str(os.getpid()) + str(time.time())
|
>>> test_name = 'InterProcessLockTest' +str(os.getpid()) + str(time.time())
|
||||||
|
|
||||||
>>> lock1 = InterProcessLock(name=test_name)
|
>>> lock1 = InterProcessLock(name=test_name)
|
||||||
>>> lock1.acquire()
|
>>> lock1.acquire()
|
||||||
|
|
||||||
>>> lock2 = InterProcessLock(name=test_name)
|
>>> lock2 = InterProcessLock(name=test_name)
|
||||||
>>> lock3 = InterProcessLock(name=test_name)
|
>>> lock3 = InterProcessLock(name=test_name)
|
||||||
|
|
||||||
# Since lock1 is locked, other attempts to acquire it fail.
|
# Since lock1 is locked, other attempts to acquire it fail.
|
||||||
>>> lock2.acquire()
|
>>> lock2.acquire()
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
||||||
|
|
||||||
>>> lock3.acquire()
|
>>> lock3.acquire()
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
||||||
|
|
||||||
# Release the lock and let lock2 have it.
|
# Release the lock and let lock2 have it.
|
||||||
>>> lock1.release()
|
>>> lock1.release()
|
||||||
>>> lock2.acquire()
|
>>> lock2.acquire()
|
||||||
|
|
||||||
>>> lock3.acquire()
|
>>> lock3.acquire()
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
||||||
|
|
||||||
# Release it and give it back to lock1
|
# Release it and give it back to lock1
|
||||||
>>> lock2.release()
|
>>> lock2.release()
|
||||||
>>> lock1.acquire()
|
>>> lock1.acquire()
|
||||||
|
|
||||||
>>> lock2.acquire()
|
>>> lock2.acquire()
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
||||||
|
|
||||||
# Test lock status
|
# Test lock status
|
||||||
>>> lock2.locked()
|
>>> lock2.locked()
|
||||||
True
|
True
|
||||||
>>> lock3.locked()
|
>>> lock3.locked()
|
||||||
True
|
True
|
||||||
>>> lock1.locked()
|
>>> lock1.locked()
|
||||||
True
|
True
|
||||||
|
|
||||||
>>> lock1.release()
|
>>> lock1.release()
|
||||||
|
|
||||||
>>> lock2.locked()
|
>>> lock2.locked()
|
||||||
False
|
False
|
||||||
>>> lock3.locked()
|
>>> lock3.locked()
|
||||||
False
|
False
|
||||||
>>> lock1.locked()
|
>>> lock1.locked()
|
||||||
False
|
False
|
||||||
|
|
||||||
>>> if os.name == 'posix':
|
>>> if os.name == 'posix':
|
||||||
... def os_independent_kill(pid):
|
... def os_independent_kill(pid):
|
||||||
... import signal
|
... import signal
|
||||||
... os.kill(pid, signal.SIGKILL)
|
... os.kill(pid, signal.SIGKILL)
|
||||||
... else:
|
... else:
|
||||||
... assert(os.name == 'nt')
|
... assert(os.name == 'nt')
|
||||||
... def os_independent_kill(pid):
|
... def os_independent_kill(pid):
|
||||||
... ''' http://www.python.org/doc/faq/windows/#how-do-i-emulate-os-kill-in-windows '''
|
... ''' http://www.python.org/doc/faq/windows/#how-do-i-emulate-os-kill-in-windows '''
|
||||||
... import win32api
|
... import win32api
|
||||||
... import win32con
|
... import win32con
|
||||||
... import pywintypes
|
... import pywintypes
|
||||||
... handle = win32api.OpenProcess(win32con.PROCESS_TERMINATE , pywintypes.FALSE, pid)
|
... handle = win32api.OpenProcess(win32con.PROCESS_TERMINATE , pywintypes.FALSE, pid)
|
||||||
... return (0 != win32api.TerminateProcess(handle, 0))
|
... return (0 != win32api.TerminateProcess(handle, 0))
|
||||||
|
|
||||||
# Test to acquire the lock in another process.
|
# Test to acquire the lock in another process.
|
||||||
>>> def execute(cmd):
|
>>> def execute(cmd):
|
||||||
... cmd = 'import time;' + cmd + 'time.sleep(10);'
|
... cmd = 'import time;' + cmd + 'time.sleep(10);'
|
||||||
... process = subprocess.Popen([sys.executable, '-c', cmd])
|
... process = subprocess.Popen([sys.executable, '-c', cmd])
|
||||||
... pid = process.pid
|
... pid = process.pid
|
||||||
... time.sleep(2) # quick hack, but we test synchronization in the end
|
... time.sleep(2) # quick hack, but we test synchronization in the end
|
||||||
... return pid
|
... return pid
|
||||||
|
|
||||||
>>> pid = execute('import interlocks;a=interlocks.InterProcessLock(name=\\''+test_name+ '\\');a.acquire();')
|
>>> pid = execute('import interlocks;a=interlocks.InterProcessLock(name=\\''+test_name+ '\\');a.acquire();')
|
||||||
|
|
||||||
>>> lock1.acquire()
|
>>> lock1.acquire()
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
||||||
|
|
||||||
>>> os_independent_kill(pid)
|
>>> os_independent_kill(pid)
|
||||||
|
|
||||||
>>> time.sleep(1)
|
>>> time.sleep(1)
|
||||||
|
|
||||||
>>> lock1.acquire()
|
>>> lock1.acquire()
|
||||||
>>> lock1.release()
|
>>> lock1.release()
|
||||||
|
|
||||||
# Testing wait
|
# Testing wait
|
||||||
|
|
||||||
>>> pid = execute('import interlocks;a=interlocks.InterProcessLock(name=\\''+test_name+ '\\');a.acquire();')
|
>>> pid = execute('import interlocks;a=interlocks.InterProcessLock(name=\\''+test_name+ '\\');a.acquire();')
|
||||||
|
|
||||||
>>> lock1.acquire()
|
>>> lock1.acquire()
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
SingleInstanceError: Could not acquire exclusive lock on /tmp/test.lck
|
||||||
|
|
||||||
>>> os_independent_kill(pid)
|
>>> os_independent_kill(pid)
|
||||||
|
|
||||||
>>> lock1.acquire(True)
|
>>> lock1.acquire(True)
|
||||||
>>> lock1.release()
|
>>> lock1.release()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
import doctest
|
import doctest
|
||||||
doctest.testmod(optionflags=doctest.IGNORE_EXCEPTION_DETAIL)
|
doctest.testmod(optionflags=doctest.IGNORE_EXCEPTION_DETAIL)
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
|
|
||||||
# script to update indexes on mysql (+other?) database
|
# script to update indexes on mysql (+other?) database
|
||||||
|
|
||||||
select '1. Dropping indexes' as ' ';
|
select '1. Dropping indexes' as ' ';
|
||||||
select 'Can''t drop messages indicate index already gone' as ' ';
|
select 'Can''t drop messages indicate index already gone' as ' ';
|
||||||
|
|
||||||
ALTER TABLE `fpdb`.`Settings` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`Settings` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`Sites` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`Sites` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`Gametypes` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`Gametypes` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`Players` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`Players` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`Autorates` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`Autorates` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`Hands` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`Hands` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`BoardCards` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`BoardCards` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`TourneyTypes` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`TourneyTypes` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`Tourneys` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`Tourneys` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`TourneysPlayers` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`TourneysPlayers` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`HandsPlayers` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`HandsPlayers` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`HandsActions` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`HandsActions` DROP INDEX `id`;
|
||||||
ALTER TABLE `fpdb`.`HudCache` DROP INDEX `id`;
|
ALTER TABLE `fpdb`.`HudCache` DROP INDEX `id`;
|
||||||
|
|
||||||
select '2. Adding extra indexes on useful fields' as ' ';
|
select '2. Adding extra indexes on useful fields' as ' ';
|
||||||
select 'Duplicate key name messages indicate new indexes already there' as ' ';
|
select 'Duplicate key name messages indicate new indexes already there' as ' ';
|
||||||
|
|
||||||
ALTER TABLE `fpdb`.`tourneys` ADD INDEX `siteTourneyNo`(`siteTourneyNo`);
|
ALTER TABLE `fpdb`.`tourneys` ADD INDEX `siteTourneyNo`(`siteTourneyNo`);
|
||||||
ALTER TABLE `fpdb`.`hands` ADD INDEX `siteHandNo`(`siteHandNo`);
|
ALTER TABLE `fpdb`.`hands` ADD INDEX `siteHandNo`(`siteHandNo`);
|
||||||
ALTER TABLE `fpdb`.`players` ADD INDEX `name`(`name`);
|
ALTER TABLE `fpdb`.`players` ADD INDEX `name`(`name`);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user