views:

199

answers:

1

Hello,

I have following problem. I want to create a file system based session storage where each session data is stored in simple file named with session ids.

I want following API: write(sid,data,timeout), read(sid,data,timeout), remove(sid) where sid==file name, Also I want to have some kind of GC that may remove all timed-out sessions.

Quite simple task if you work with single process but absolutly not trivial when working with multiple processes or even over NFS.

The simplest solution I thought about was:

write/read:
   fd=open(file_name,O_CREAT | O_RDWR); // create a new file or use exsting
   fcntl_lock_file(fd)
   save data to fd/read data from fd
   fcntl_unlock_file(fd)
   close(fd)

GC:
   fd=open(file_name,O_RDWR);
   fcntl_lock_file(fd)
   if(timed_out)
      unlink(file_name)
   fcntl_unlock_file(fd)
   close(fd)

The biggest issue that file unlinking works on file names and file locks work on file descriptors. So the above would not work in following scenario:

GC - open,
write - open
GC lock, unlink, unlock, close // file still exists because held by write
wrute lock, write, unlock, close // file removed

Does anybody have an idea how such issue may be solved? Are there any tricks that allow combine file locking and file removal or make operation on file atomic?

Notes:

  • I don't want to use Database,
  • I look for a solution for Unix
  • Solution should work with standard POSIX calls like fcnl, open, close, unlink

Thanks.

Clearification the major issue is that operation on files (names -- unlink) should be done atomically with operation of file descriptors -- locking:

  • open, unlink -- work on files
  • fnctl -- work on descriptors
+1  A: 

Wouldn't this work?

write/read:
   fd=open(file_name,O_CREAT | O_RDWR); // create a new file or use exsting
   fcntl_lock_file(fd)
   if stat(file_name).{st_dev, st_ino} != fstat(fd).{st_dev, st_ino}
       unlock, close, retry
   save data to fd/read data from fd
   fcntl_unlock_file(fd)
   close(fd)

If stat fails with EEXIST (file name does not exist) or shows that the current file is not the same as the one you opened, bail.

ephemient
I think this should work! Thanks a lot, this defenatly would connect the path and fd.
Artyom