# Function to lock a file using memcache, Version 1

I have a web application where I list files in the UI to many users at the same time. There are many people who monitor the files and process them. However, I don't want multiple users processing the same file.

I am using simple memcache dictionary as data structure to interpret if it is locked. If the key "filename" is present then it is considered as locked, otherwise the key "filename" is added (maybe with username as value) so that another user cant access it and access is granted for that user. The files "locked" by a user is processed at a later point by that user itself and no other. "Process" here means to move it to some another folder.

I was recommended to use Ghetto Central Locking by the development team but I still feel that it doesn't cover my scenario of locking and delayed action. The problem there is that the "locking" and "action" both are combined operation but in my case can be delayed. Also the user should have the ability to unlock and not specify a time-out value as mentioned there.

So I came up with an API that covers my scenarios:

def addToCart(filename):
fileExists = os.file.ispath(filename)
if ableToLock:
if fileExists:
else:
memcache.delete(filename)
return "Processed by another user."
else:
if fileExists:
return "Processed by another user."
else:
user = memcache.get(filename)
return "%s is Processing" % user

def process(source):
shutil.move(source, destination)


process happens any point of time later.

Does anyone see logical flaws or race-conditions if this code is run concurrently?

I consider it as flawed if a request comes from a user to process one of his locked file and one of the ever gets a file not found error. Scenarios like DOM manipulation etc are not considered valid because it interferes with the logic.

PS: Memcache has some drawbacks if we use as a locking mechanism like for example remote server disconnection and data eviction, but we don't consider that as an issue.

1. The code only acquires a lock for the source of the move, and not for the destination. This means that there's a race between two users trying to move two different files to the same destination.

2. There's a race between:

memcache.delete(filename)


and:

user = memcache.get(filename)

3. It's not clear how the lock is released. It doesn't happen in process.

4. The test else: if fileExists: seems backwards.