0

So, I've got an interesting design problem and I honestly don't know how to tackle this. I have an application that will be ran on a dozen of workstations. Of those workstations, it is impossible to know at any given time how many of them will be on or using my application. Every 4 hours of local time if any of the applications are on, they would check database and perform some changes. The problem is that if more than one tries to do that, there will be some major complications. So I need a way for only one application to perform the updates if more than one are running.

I was thinking of creating a file that would reside on the network drive where applications would append their workstation addresses as they're turned on and remove as they're turned off. Every 4 hours of local time, applications would check the file and whoever is at the top would be the one to run the update. The problem with that is that if an application is shut down in the way that it can't remove itself from the top of the list, no updates will appear from there on.

I don't have an option to put any applications to run on the server itself, besides storing files there, so that's out of question. Does anyone know of a solution to this problem? I can't seem to wrap my brain around it.

Edit: What I have implemented right now is this:

        int updateTimerOffset = (Convert.ToInt32(DateTime.Now.ToString("mm")) * 60000) - 120000;

        updateTimer = new System.Timers.Timer(3600000 - updateTimerOffset);
        updateTimer.AutoReset = true;
        updateTimer.Enabled = true;

        updateTimer.Elapsed += new System.Timers.ElapsedEventHandler(PerformUpdates);

and then down in my PerformUpdates I have some code that looks like this:

        int currentHr = Convert.ToInt32(DateTime.Now.ToString("HH"));

        if (currentHr % 4 >= 0 && currentHr >= fileNum)
        {
            // change fileNum in the file to currentHr + 4 if currentHr is not 24,
            // if it is, then make the value equal to 4
            // Update database stuff
        }

fileNum is a number that is stored in a file on the server.

This is done on every application's start up. So, every application, unless started absolutely at the exact same second will have a difference of 2 minutes (120,000 milliseconds) plus some seconds that I didn't account for between their start ups.

What I can do is have a simple file holding a number for the target hour (fileNum). So that when the application checks it, it looks at the number to do comparison.

So let's say that it's 16:00, in which case 16 % 4 gives us 0 and it's time for an update. That application checks the file and sees that the value is 12. 16 is equal to or greater than 12. So it changes the value to current hour (16) + 4, which is 20.

The next application's timer elapses a minute or so later, and it has 0 for its hour mod value. So, it looks at the file and sees that value is 20, which is greater than 16, so it doesn't do anything.

What do you guys think of this solution? It wouldn't work if there were hundreds of workstations, since chances of having both applications trying to do this at the same time are higher, but with a dozen or so workstations I can pull this off? Unless someone has a better solution?

  • What is the nature of these updates? Are you talking about changes to the data, or changes to the database schema? – Robert Harvey Oct 12 '13 at 5:35
  • @RobertHarvey changes to data and some ftp actions. It will look at one database and check to see if there are any matches for what it's looking for. If there are, it'll quickly update a second database and send an ftp file with a summary of certain fields. – B.K. Oct 12 '13 at 5:50
  • What is it looking for? – Robert Harvey Oct 12 '13 at 5:51
  • @RobertHarvey I can't release details. But it's looking for specific match of fields in the database entries for that day. – B.K. Oct 12 '13 at 5:55
1

Put an agent program on the server, and allow your client programs to initiate an update through the agent, rather than updating the database directly. This will give you the ability to manage the clients in a way that they don't clash with each other.

For example, if one client requests an update cycle, you can set a flag on the agent program to accept update requests from other clients, but simply ignore them. You can even send status back to the second client, saying "Thanks, but this update is already in progress."

You can use a Windows Service and WCF to build the agent, and talk to it as a WCF service from the clients.

| improve this answer | |
  • 1
    I mentioned in my post that I can't put any programs on the server. Otherwise this would not be an issue. – B.K. Oct 12 '13 at 5:55
  • 3
    Well, that sucks. Guess you're going to have to update a field in some table in the database as your flag, and then have all of the clients check that flag before they start their update cycle (so only the first one wins). When the update is done, you can clear the flag. If you need versioning, devote a table specifically to that purpose. You'll have to be careful about race conditions. – Robert Harvey Oct 12 '13 at 5:56
  • Yeah, that's my biggest concern is the race condition... I need to find a class that would allow me to open a file exclusively. Or figure out how to lock down a table in SQLite database for 1 read at a time. That way, in either case, by the time next one reads, it's already changed. – B.K. Oct 12 '13 at 6:06
  • I know it costs money but VistaDB has multi user access support in this way. – Rig Oct 12 '13 at 14:40
  • 1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.