views:

53

answers:

2

What is the best way to share a file between two "writer" services in the same application?

Edit: Sorry I should have given more details I guess.

I have a Service that saves entries into a buffer. When the buffer gets full it writes all the entries to the file (and so on). Another Service running will come at some point and read the file (essentially copy/compress it) and then empty it.

+1  A: 

Here is a general idea of what you can do:

public class FileManager
{
    private final FileWriter writer = new FileWriter("SomeFile.txt");
    private final object sync = new object();

    public void writeBuffer(string buffer)
    {
        synchronized(sync)
        {
            writer.write(buffer.getBytes());
        }
    }        

    public void copyAndCompress()
    {
        synchronized(sync)
        {
            // copy and/or compress
        }
    }

}

You will have to do some extra work to get it all to work safe, but this is just a basic example to give you an idea of how it looks.

Lirik
Thanks but I don't think it's what I was looking for. I'll update the first post to give more details. Sorry :)
roul
@roul, ok I've updated the answer based on your clarification.
Lirik
I wanted to avoid something like that to be honest :) but I can't think of anything else right now. In my case, since I have android services, the object lock and the methods should probably be static and the services would make calls to the FileManager.
roul
roul, Is the goal to avoiding the `synchronized` keyword? If you want, you can go back to my Consumer/Producer example and instead of processing strings, you can be processing commands/operations. The commands are added to the blocking queue, and the consumer takes the commands and executes them on a file: there would be no locking with the `synchronized` keyword in that case.
Lirik
I guess I just wanted to avoid "centralizing" the locking somewhere - either be one of the two Services or a new FileManager class. But I guess that's the best way to do it. Thanks for the help!
roul
A: 

A common method for locking is to create a second file in the same location as the main file. The second file may contain locking data or be blank. The benefit to having locking data (such as a process ID) is that you can easily detect a stale lockfile, which is an inevitability you must plan for. Although PID might not be the best locking data in your case.

example: Service1:

  • creates myfile.lock
  • creates/opens myfile

Service2:

  • Notices that myfile.lock is present and pauses/blocks/waits
  • When myfile.lock goes away, it creates it and then opens myfile.

It would also be advantageous for you to double-check that the file contains your locking information (identification specific to your service) right after creating it - just in case two or more services are waiting and create a lock at the exact same time. The last one succeeds and so all other services should notice that their locking data is no longer in the file. Also - pause a few milliseconds before checking its contents.

Brad Hein
Interesting solution but I can't see how I could use it in my case. Thanks anyway.
roul
I see. My solution would be appropriate for multiple applications but I see you are synchronizing processes within your application. I was confused because you called them "services". I agree with the accepted answer - the `synchronized` keyword would be appropriate in your case.
Brad Hein