Moe Sisko
Moe Sisko

Reputation: 12015

Locking issues with replacing files on a website

I want to replace existing files on an IIS website with updated versions. Say these files are large pdf documents, which can be accessed via hyperlinks. The site is up 24x7, so I'm concerned about locking issues when a file is being updated at exactly the same time that someone is trying to read the file.

The files are updated using C# code run on the server. I can think of two options for opening the file for writing.

Option 1) Open the file for writing, using FileShare.Read :

using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))

While this file is open, and a user requests the same file for reading in a web browser via a hyperlink, the document opens up as a blank page.

Option 2) Open the file for writing using FileShare.None :

using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) 

While this file is open, and a user requests the same file for reading in a web browser via a hyperlink, the browser shows an error. In IE 8, you get HTTP 500, "The website cannot display the page", and in Firefox 3.5, you get : "The process cannot access the file because it is being used by another process."

The browser behaviour kind of makes sense, and seem reasonable. I guess its highly unlikely that a user will attempt to read a file at exactly the same time you are updating it. It would be nice if somehow, the file update was atomic, like updating a database with SQL wrapped around a transaction.

I'm wondering if you guys worry about this sort of thing, and prefer either of the above options, or even have other options of your own for updating files.

Upvotes: 1

Views: 262

Answers (5)

Uwe Keim
Uwe Keim

Reputation: 40736

Having a similar issue, I developed my own solution (basically having multiple versions of a file, serving them through an ASHX handler).

Please see my CodeProject article discussing the solution (and possible caveats)

Upvotes: 0

G-Wiz
G-Wiz

Reputation: 7426

This is a threading issue at heart, and those can be tricky to solve in a clean way. Conceptually, you want to synchronize read and write access to the file from multiple threads.

To achieve this, I would store the file outside of IIS' website root so that IIS does not serve it directly. I would create a separate HttpHandler to serve it instead. The HttpHandler would lock on an object that the write code would also lock on. You should use a ReaderWriterLockSlim so that you can have multiple concurrent reads (EnterReadLock) while also ensuring only a single write thread can execute (EnterWriteLock) and that reads are blocked while writing.

Upvotes: 1

jvilalta
jvilalta

Reputation: 6789

One option is to build an extra layer between the hyperlink and the file. Instead of linking directly to the file have the hyperlink point to another page (or similar resource). This resource/page can then determine which is the latest file that needs to be sent to the browser and then send it down to the browser. This way the link will always be the same, but the file can change.

Upvotes: 1

Rubens Farias
Rubens Farias

Reputation: 57956

I usually don't worry about this kind of problem, but you could work it around this way:

  • Create a link to an ASPX page which downloads referenced file, like "Download.aspx?Name=Document1.pdf"
  • In that page, before download that file, look for a folder named "Updated"
  • If you find it, get your file from it
  • If not, go get it from "Current" folder

To update your files:

  • Create a folder name "Updating"
  • Copy your new files into it
  • Rename it to "Updated" (so new downloads use it as source)
  • Update your "Current" folder
  • Delete your "Updated" folder

Upvotes: 1

Gonzalo
Gonzalo

Reputation: 21175

How about copying the new version of the file with a different name and then do File.Move() setting the overwrite argument to true? While you're writing it you won't interfere with the web server and moving the file(s) will be quick.

Upvotes: 1

Related Questions