Re: using cdb for 'update' without race condition?
ari edelkind <[email protected]> Thu, 10 Apr 2008 16:43:22 -0400
| Newsgroups | gmane.comp.djb.cdb |
|---|---|
| Message-ID | <[email protected]> |
[email protected] wrote: > I'm interested in checking out cdb for a database that will be updated > programmatically. Since the database is 'constant', 'update' is a bit > of a contradiction in terms, but I believe the effect of an atomic > update for a cdb database works like this: > > 1. My app reads a database and extracts all the key-value pairs. > > 2. My app produces a new set of key-value pairs. You ought to have the source file around already, which would obviate these two steps. You can have your program edit the source file, which is easily machine-parseable, and regenerate it as desired. > 3. I atomically make a new database. I cannot do this through a C > API but only via the cdbmake program. Atomicity is guaranteed by > the way cdbmake uses the filesystem. The way cdbmake "uses the filesystem" is, it generates a temporary file and renames it into place using the rename(2) call, just as mv(1) does if the target is on the same filesystem. The operation isn't _exactly_ atomic, but the kernel guarantees that the target filename will always resolve to either the old file's inode or the new file's inode, which is the only part anyone generally cares about. > It appears to me that if I want to avoid losing an update via race > conditions that my cdb file needs to be protected by some kind of > lock, and it's up to my app to use liblockfile or something similar. You should never need to lock the database file. That's the whole point. You might want to lock your source file while editing it. Or lock your output file if you must dump the database every time -- in which case, you'd lock the output file before opening the database, and unlock it after completing the update. And frankly, for locking in this case, you may as well simply use open(...,O_CREAT|O_EXCL) for the output file, coupled with rename(2) or unlink(2)... so long as the file doesn't reside on an nfs-mounted filesystem, in which case symlink(2) is a little better than the aforementioned open(2) call (not to mention most file locking alternatives). If you'd rather use shell scripts for any of this, you can use the 'noclobber' option, `mv` or `rm`, and `ln -s`, respectively. Or you can still use liblockfile if you feel like it. ari