1 # ====================================================================
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13 # ====================================================================
15 import os, sys, unittest, shutil
16 from threading import RLock
20 PythonLock, PythonLockFactory, \
21 PythonIndexInput, PythonIndexOutput, PythonDirectory, \
22 JavaError, IOException, JArray, String
25 The Directory Implementation here is for testing purposes only, not meant
26 as an example of writing one, the implementation here suffers from a lack
27 of safety when dealing with concurrent modifications as it does away with
28 the file locking in the default lucene fsdirectory implementation.
33 class DebugWrapper(object):
35 def __init__(self, obj):
38 def __getattr__(self, name):
39 print self.obj.__class__.__name__, self.obj.name, name
41 return getattr(self.obj, name)
43 class DebugFactory(object):
45 def __init__(self, klass):
48 def __call__(self, *args, **kw):
49 instance = self.klass(*args, **kw)
50 return DebugWrapper(instance)
53 class PythonDirLock(PythonLock):
54 # only safe for a single process
56 def __init__(self, name, path, lock):
57 super(PythonDirLock, self).__init__()
64 return self.lock.locked()
67 return self.lock.acquire()
70 return self.lock.release()
73 class PythonDirLockFactory(PythonLockFactory):
75 def __init__(self, path):
76 super(PythonDirLockFactory, self).__init__()
81 def makeLock(self, name):
83 lock = self._locks.get(name)
85 lock = PythonDirLock(name, os.path.join(self.path, name), RLock())
86 self._locks[name] = lock
90 def clearLock(self, name):
92 lock = self._locks.pop(name, None)
97 class PythonFileStreamInput(PythonIndexInput):
99 def __init__(self, name, fh, size, clone=False):
101 super(PythonFileStreamInput, self).__init__()
109 return long(self._length)
112 clone = PythonFileStreamInput(self.name, self.fh, self._length, True)
113 return super(PythonFileStreamInput, self).clone(clone)
121 def readInternal(self, length, pos):
123 return JArray('byte')(self.fh.read(length))
125 def seekInternal(self, pos):
129 class PythonFileStreamOutput(PythonIndexOutput):
131 def __init__(self, name, fh):
132 super(PythonFileStreamOutput, self).__init__()
140 super(PythonFileStreamOutput, self).close()
145 return long(self._length)
147 def seekInternal(self, pos):
150 def flushBuffer(self, bytes):
152 self.fh.write(bytes.string_)
154 self._length += len(bytes)
157 class PythonFileDirectory(PythonDirectory):
159 def __init__(self, path):
160 super(PythonFileDirectory, self).__init__(PythonDirLockFactory(path))
163 assert os.path.isdir(path)
168 for stream in self._streams:
172 def createOutput(self, name):
173 file_path = os.path.join(self.path, name)
174 fh = open(file_path, "wb")
175 stream = PythonFileStreamOutput(name, fh)
176 self._streams.append(stream)
179 def deleteFile(self, name):
180 if self.fileExists(name):
181 os.unlink(os.path.join(self.path, name))
183 def fileExists(self, name):
184 return os.path.exists(os.path.join(self.path, name))
186 def fileLength(self, name):
187 file_path = os.path.join(self.path, name)
188 return long(os.path.getsize(file_path))
190 def fileModified(self, name):
191 file_path = os.path.join(self.path, name)
192 return os.path.getmtime(file_path)
195 return os.listdir(self.path)
197 def sync(self, name):
200 def openInput(self, name, bufferSize=0):
201 file_path = os.path.join(self.path, name)
203 fh = open(file_path, "rb")
205 raise JavaError, IOException(name)
206 stream = PythonFileStreamInput(name, fh, os.path.getsize(file_path))
207 self._streams.append(stream)
210 def touchFile(self, name):
211 file_path = os.path.join(self.path, name)
212 os.utime(file_path, None)
217 _globals['PythonFileDirectory'] = DebugFactory(PythonFileDirectory)
218 _globals['PythonFileStreamInput'] = DebugFactory(PythonFileStreamInput)
219 _globals['PythonFileStreamOutput'] = DebugFactory(PythonFileStreamOutput)
220 _globals['PythonDirLock'] = DebugFactory(PythonDirLock)
223 class PythonDirectoryTests(unittest.TestCase, test_PyLucene.Test_PyLuceneBase):
225 STORE_DIR = "testpyrepo"
228 if not os.path.exists(self.STORE_DIR):
229 os.mkdir(self.STORE_DIR)
232 if os.path.exists(self.STORE_DIR):
233 shutil.rmtree(self.STORE_DIR)
236 return PythonFileDirectory(self.STORE_DIR)
238 def closeStore(self, store, *args):
244 def test_IncrementalLoop(self):
245 print "Testing Indexing Incremental Looping"
249 self.test_indexDocument()
252 if __name__ == "__main__":
254 env = lucene.initVM()
255 if '-loop' in sys.argv:
256 sys.argv.remove('-loop')
262 print 'inputs', env._dumpRefs(True).get('class org.osafoundation.lucene.store.PythonIndexOutput', 0)
263 print 'outputs', env._dumpRefs(True).get('class org.osafoundation.lucene.store.PythonIndexInput', 0)
264 print 'locks', env._dumpRefs(True).get('class org.osafoundation.lucene.store.PythonLock', 0)
265 print 'dirs', env._dumpRefs(True).get('class org.osafoundation.lucene.store.PythonLock', 0)