Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

idiomatic file locking in clojure?

Tags:

clojure

I have a group of futures processing jobs from a queue that involve writing to files. What's the idiomatic way to make sure only one future accesses a particular file at a time?

like image 435
jhickner Avatar asked Jun 19 '11 19:06

jhickner


People also ask

What do you mean by file locking?

File locking is a mechanism that restricts access to a computer file, or to a region of a file, by allowing only one user or process to modify or delete it at a specific time and to prevent reading of the file while it's being modified or deleted.

Why is file locking necessary?

File locking is a mechanism to restrict access to a file among multiple processes. It allows only one process to access the file in a specific time, thus avoiding the interceding update problem.

What is file locking in Java?

A token representing a lock on a region of a file. A file-lock object is created each time a lock is acquired on a file via one of the lock or tryLock methods of the FileChannel class, or the lock or tryLock methods of the AsynchronousFileChannel class. A file-lock object is initially valid.

What is lock in Unix?

The lock command requests a password from the user, reads it, and requests the password a second time to verify it. In the interim, the command locks the terminal and does not relinquish it until the password is received the second time or one of the following occurs: The timeout interval is exceeded.


1 Answers

How about using agents instead of locks to ensure this?

I think using agents to safe guard shared mutable state, regardless if it's in memory or on disk is more idiomatic in clojure than using locks.

If you create one agent at a time and send the access tries to the agents, you can ensure that only on thread at time accesses a given file.

For example like this:

(use 'clojure.contrib.duck-streams)

(defn file-agent [file-name]
  (add-watch (agent nil) :file-writer 
    (fn [key agent old new] 
      (append-spit file-name new))))

(defn async-append [file-agent content]
  (send file-agent (constantly content)))

then append your file through the agent:

(async-append "content written to file" (file-agent "temp-file-name"))

If you need synchronous usage of the file it could be achieved with await. Like this:

(defn sync-append [file-agent content]
  (await (send file-agent (constantly content))))
like image 143
Verneri Åberg Avatar answered Oct 06 '22 03:10

Verneri Åberg