add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / src / java / org / apache / lucene / store / VerifyingLockFactory.java
1 package org.apache.lucene.store;
2
3 /**
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.
7  * The ASF licenses this file to You under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with
9  * the License.  You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 import java.net.Socket;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24
25 /**
26  * A {@link LockFactory} that wraps another {@link
27  * LockFactory} and verifies that each lock obtain/release
28  * is "correct" (never results in two processes holding the
29  * lock at the same time).  It does this by contacting an
30  * external server ({@link LockVerifyServer}) to assert that
31  * at most one process holds the lock at a time.  To use
32  * this, you should also run {@link LockVerifyServer} on the
33  * host & port matching what you pass to the constructor.
34  *
35  * @see LockVerifyServer
36  * @see LockStressTest
37  */
38
39 public class VerifyingLockFactory extends LockFactory {
40
41   LockFactory lf;
42   byte id;
43   String host;
44   int port;
45
46   private class CheckedLock extends Lock {
47     private Lock lock;
48
49     public CheckedLock(Lock lock) {
50       this.lock = lock;
51     }
52
53     private void verify(byte message) {
54       try {
55         Socket s = new Socket(host, port);
56         OutputStream out = s.getOutputStream();
57         out.write(id);
58         out.write(message);
59         InputStream in = s.getInputStream();
60         int result = in.read();
61         in.close();
62         out.close();
63         s.close();
64         if (result != 0)
65           throw new RuntimeException("lock was double acquired");
66       } catch (Exception e) {
67         throw new RuntimeException(e);
68       }
69     }
70
71     @Override
72     public synchronized boolean obtain(long lockWaitTimeout)
73       throws LockObtainFailedException, IOException {
74       boolean obtained = lock.obtain(lockWaitTimeout);
75       if (obtained)
76         verify((byte) 1);
77       return obtained;
78     }
79
80     @Override
81     public synchronized boolean obtain()
82       throws LockObtainFailedException, IOException {
83       return lock.obtain();
84     }
85
86     @Override
87     public synchronized boolean isLocked() throws IOException {
88       return lock.isLocked();
89     }
90
91     @Override
92     public synchronized void release() throws IOException {
93       if (isLocked()) {
94         verify((byte) 0);
95         lock.release();
96       }
97     }
98   }
99
100   /**
101    * @param id should be a unique id across all clients
102    * @param lf the LockFactory that we are testing
103    * @param host host or IP where {@link LockVerifyServer}
104             is running
105    * @param port the port {@link LockVerifyServer} is
106             listening on
107   */
108   public VerifyingLockFactory(byte id, LockFactory lf, String host, int port) throws IOException {
109     this.id = id;
110     this.lf = lf;
111     this.host = host;
112     this.port = port;
113   }
114
115   @Override
116   public synchronized Lock makeLock(String lockName) {
117     return new CheckedLock(lf.makeLock(lockName));
118   }
119
120   @Override
121   public synchronized void clearLock(String lockName)
122     throws IOException {
123     lf.clearLock(lockName);
124   }
125 }