summaryrefslogtreecommitdiff
path: root/java/src/IceUtilInternal/FileLock.java
blob: 869057b877a58f52f6a3b5a0378fdb1164e3e777 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// **********************************************************************
//
// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************

package IceUtilInternal;

import java.io.File;
import java.io.RandomAccessFile;
import java.io.FileWriter;
import java.nio.channels.FileChannel;
import java.nio.channels.OverlappingFileLockException;
import java.lang.management.ManagementFactory;

public final class FileLock
{
    //
    // The constructor opens the given file (eventually creating it)
    // and acquires a lock on the file or throws FileLockException if
    // the file couldn't be locked.
    //
    // If the lock can be acquired, the Java VM name is written to the
    // file.
    //
    public FileLock(String path)
    {
        _file = new File(path);

        FileChannel channel;
        try
        {
            _randFile = new RandomAccessFile(_file, "rw");
            channel = _randFile.getChannel();
        }
        catch(java.io.FileNotFoundException e)
        {
            throw new IceUtil.FileLockException(path);
        }
        
        java.nio.channels.FileLock lock;
        try
        {
            lock = channel.tryLock();
        }
        catch(Exception ex)
        {
            throw new IceUtil.FileLockException(path, ex);
        }
        
        if(lock == null)
        {
            throw new IceUtil.FileLockException(path);
        }

        //
        // In Windows we don't write the process pid to the file, as is  not posible
        // to read the file from other process while it is locked here.
        //
        if(!System.getProperty("os.name").startsWith("Windows"))
        {
            try
            {
                //
                // Java doesn't provide get pid operation. This code
                // writes the Java VM name instead of the pid.
                //
                // The output is JVM dependent. With the Sun
                // implementation it's `pid@hostname'
                //
                _randFile.writeUTF(ManagementFactory.getRuntimeMXBean().getName());

                //
                // Don't close _randFile here or the lock will be released. It is called
                // during release see comments there.
                //
            }
            catch(java.io.IOException ex)
            {
                release();
                throw new IceUtil.FileLockException(path);
            }
        }
    }

    //
    // Remove the lock if it is owned by the class instance.
    //
    public void release()
    {
        if(System.getProperty("os.name").startsWith("Windows"))
        {
            if(_randFile != null)
            {
                //
                // In Windows we need to close the file handler before
                // we try to delete the file. Note that the call to close
                // also release the file lock.
                //
                try
                {
                    _randFile.close();
                }
                catch(java.io.IOException ex)
                {
                }
                _randFile = null;
            }
        }
        //
        // on UNIX the call to delete remove the file and that
        // release the lock.
        //
        // In Windows the call to delete will success if at that point
        // the file has not been opened by any process.
        //
        if(_file != null)
        {
            _file.delete();
            _file = null;
        }
    }

    //
    // We need to keep these refrences to delete the lock file during release
    //
    private File _file;
    private RandomAccessFile _randFile;

}