--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/releasing/blocks/framework/src/Blocks/filelock.py Thu Sep 02 15:02:14 2010 +0800
@@ -0,0 +1,136 @@
+#
+# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+# Implements file locking mechanism
+#
+
+# TODO: Prevent lock file deletion
+
+import os
+import time
+import errno
+import logging
+import platform
+import tempfile
+import atexit
+
+if platform.system() == "Windows":
+ import win32api
+ import win32process
+
+class AcquireError(Exception):
+ ''' Acquire Error '''
+
+class FileLock(object):
+ ''' File lock '''
+ POLL_INTERVAL = 0.1
+
+ def __init__(self, path):
+ logging.log(logging.DEBUG, "FileLock path: %s", path)
+ self.path = path
+ self.locked = False
+ self.creatorPid = os.getpid()
+
+ def acquire(self, timeout=0):
+ '''Acquires lock on file
+
+ Timeout in milliseconds, use None for no timeout
+ Returns True if succesful otherwise False
+ '''
+
+ if self.locked:
+ return True
+
+ sleepcount = 0
+ tmpname = atomicCreateTempFile(str(os.getpid()))
+ logging.log(logging.DEBUG, "FileLock acquire temp file name: %s", tmpname)
+ try:
+ while not self.locked:
+ try:
+ # Create file with pid atomically
+ os.rename(tmpname, self.path)
+ except OSError, ex:
+ # Lock in use?
+ if ex.errno == errno.EEXIST:
+ with open(self.path) as lockfile:
+ pid = int(lockfile.read())
+ if processRunning(pid):
+ timeElapsed = sleepcount * (self.POLL_INTERVAL * 1000)
+ timeoutElapsed = timeout > 0 and timeElapsed >= timeout
+ if timeout == 0 or timeoutElapsed:
+ break
+ else:
+ time.sleep(self.POLL_INTERVAL)
+ sleepcount += 1
+ else:
+ logging.info("Stale lock file detected with pid %s. Removing...", pid)
+ os.remove(self.path)
+ continue
+ raise
+ self.locked = True
+ # Call release on exit
+ atexit.register(self.release)
+ return self.locked
+ finally:
+ if not self.locked:
+ os.remove(tmpname)
+ return False
+
+ def release(self):
+ if self.locked and os.getpid() == self.creatorPid:
+ if os.path.exists(self.path):
+ os.remove(self.path)
+ self.locked = False
+
+PROCESS_QUERY_INFORMATION = 0x0400
+STILL_ACTIVE = 259
+def processRunning(pid):
+ if platform.system() == "Windows":
+ running = False
+ try:
+ handle = win32api.OpenProcess(PROCESS_QUERY_INFORMATION, True, pid)
+ except win32api.error:
+ pass
+ else:
+ # code == 0 -> problem
+ code = win32process.GetExitCodeProcess(handle)
+ win32api.CloseHandle(handle)
+ running = code == STILL_ACTIVE
+ return running
+ else:
+ try:
+ os.kill(pid, 0)
+ except OSError:
+ return False
+ return True
+
+def atomicCreateTempFile(data):
+ tmpfile = tempfile.NamedTemporaryFile(bufsize=0, delete=False)
+ try:
+ tmpfile.write(data)
+ tmpfile.flush()
+ os.fsync(tmpfile.fileno())
+ tmpfile.close()
+ return tmpfile.name
+ except Exception: # cleanup
+ tmpfile.close()
+ os.remove(tmpfile.name)
+ raise
+
+if __name__ == "__main__":
+ fl = FileLock(r"c:\temp\test123")
+ print "Acquiring..."
+ print fl.acquire(5000)
+ raw_input("press enter")
+ fl.release()
\ No newline at end of file