KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > indexing > IndexedStore


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.internal.indexing;
12
13 import java.util.*;
14
15 public class IndexedStore {
16
17     private static final int CurrentVersion = 1;
18     private static final int MetadataID = 2;
19     /*
20      * Provides the storage for the registry of stores. Key is the name the store
21      * was opened under. The value is the store itself. This is used to facilitate
22      * recovery in the event of a thread being killed or dying.
23      */

24     private static final Map registry = Collections.synchronizedMap(new HashMap());
25
26     private static final ObjectAddress ContextAddress10 = new ObjectAddress(1, 0);
27     private static final ObjectAddress ContextAddress11 = new ObjectAddress(1, 1);
28
29     private ObjectAddress objectDirectoryAddress; /* initialized at open */
30     private Index objectDirectory; /* initialized at open */
31     private IndexCursor objectDirectoryCursor; /* initialized at open */
32
33     private ObjectAddress indexDirectoryAddress; /* initialized at open */
34     private Index indexDirectory; /* initialized at open */
35     private IndexCursor indexDirectoryCursor; /* initialized at open */
36     private ObjectAddress contextAddress;
37
38     private ObjectStore objectStore; /* initialized at open */
39     private String JavaDoc name; /* initialized at open */
40
41     /**
42      * Acquires an anchor.
43      */

44     IndexAnchor acquireAnchor(ObjectAddress address) throws IndexedStoreException {
45         return (IndexAnchor) acquireObject(address);
46     }
47
48     /**
49      * Acquires a context. Returns null if the context could not be acquired.
50      */

51     IndexedStoreContext acquireContext(ObjectAddress address) {
52         try {
53             return (IndexedStoreContext) acquireObject(address);
54         } catch (IndexedStoreException e) {
55             //context couldn't be acquired - return null
56
return null;
57         }
58     }
59
60     /**
61      * Acquire an index node.
62      */

63     IndexNode acquireNode(ObjectAddress address) throws IndexedStoreException {
64         return (IndexNode) acquireObject(address);
65     }
66
67     /**
68      * Acquires an object.
69      */

70     private StoredObject acquireObject(ObjectAddress address) throws IndexedStoreException {
71         StoredObject object;
72         try {
73             object = objectStore.acquireObject(address);
74         } catch (ObjectStoreException e) {
75             throw new IndexedStoreException(IndexedStoreException.ObjectNotAcquired, e);
76         }
77         return object;
78     }
79
80     /**
81      * Acquires a Binary Object.
82      */

83     BinarySmallObject acquireBinarySmallObject(ObjectAddress address) throws IndexedStoreException {
84         return (BinarySmallObject) acquireObject(address);
85     }
86
87     /**
88      * Checks to see if the metadata stored in the object store matches that expected by this
89      * code. If not, a conversion is necessary.
90      */

91     private void checkMetadata() throws IndexedStoreException {
92         Buffer metadata = getMetadataArea(MetadataID);
93         Field versionField = metadata.getField(0, 4);
94         int version = versionField.getInt();
95         if (version == 0) {
96             // 0 indicates that the store is new
97
versionField.put(CurrentVersion);
98             putMetadataArea(MetadataID, metadata);
99             return;
100         }
101         if (version == CurrentVersion)
102             return;
103         convert(version);
104     }
105
106     /**
107      * Closes the store. This is required to free the underlying file.
108      */

109     public synchronized void close() throws IndexedStoreException {
110         if (name == null)
111             return;//already closed
112
try {
113             commit();
114             if (objectDirectoryCursor != null)
115                 objectDirectoryCursor.close();
116             if (indexDirectoryCursor != null)
117                 indexDirectoryCursor.close();
118         } catch (IndexedStoreException e) {
119             //make sure the file gets closed no matter what
120
try {
121                 objectStore.close();
122             } catch (ObjectStoreException e2) {
123                 //ignore this and rethrow the underlying exception
124
}
125             throw e;
126         }
127         try {
128             objectStore.close();
129         } catch (ObjectStoreException e) {
130             throw new IndexedStoreException(IndexedStoreException.StoreNotClosed, e);
131         }
132         registry.remove(name);
133         name = null;
134         objectDirectory = null;
135         objectDirectoryAddress = null;
136         objectDirectoryCursor = null;
137         indexDirectory = null;
138         indexDirectoryAddress = null;
139         indexDirectoryCursor = null;
140     }
141
142     public synchronized void commit() throws IndexedStoreException {
143         try {
144             objectStore.commit();
145         } catch (Exception JavaDoc e) {
146             throw new IndexedStoreException(IndexedStoreException.StoreNotCommitted, e);
147         }
148     }
149
150     /**
151      * Converts the store from a previous to the current version.
152      * No conversions are yet defined.
153      */

154     private void convert(int fromVersion) throws IndexedStoreException {
155         throw new IndexedStoreException(IndexedStoreException.StoreNotConverted);
156     }
157
158     /**
159      * Creates and initializes an IndexedStore.
160      */

161     public static synchronized void create(String JavaDoc name) throws IndexedStoreException {
162         ObjectStore store = new ObjectStore(new IndexedStoreObjectPolicy());
163         try {
164             ObjectStore.create(name);
165             store.open(name);
166             ObjectAddress contextAddress = store.insertObject(new IndexedStoreContext());
167             IndexedStoreContext context = (IndexedStoreContext) store.acquireObject(contextAddress);
168             IndexAnchor anchor = new IndexAnchor();
169             ObjectAddress address = store.insertObject(anchor);
170             context.setIndexDirectoryAddress(address);
171             anchor = new IndexAnchor();
172             address = store.insertObject(anchor);
173             context.setObjectDirectoryAddress(address);
174             context.release();
175             store.commit();
176             store.close();
177         } catch (Exception JavaDoc e1) {
178             try {
179                 store.close();
180             } catch (ObjectStoreException e2) {
181                 //real exception thrown below
182
}
183             ObjectStore.delete(name);
184             throw new IndexedStoreException(IndexedStoreException.StoreNotCreated, e1);
185         }
186     }
187
188     /**
189      * Creates an Index with the given name.
190      */

191     public synchronized Index createIndex(String JavaDoc indexName) throws IndexedStoreException {
192         Index index = null;
193         indexDirectoryCursor.find(indexName);
194         if (indexDirectoryCursor.keyMatches(indexName)) {
195             throw new IndexedStoreException(IndexedStoreException.IndexExists);
196         }
197         ObjectAddress address = insertObject(new IndexAnchor());
198         indexDirectory.insert(indexName, address.toByteArray());
199         index = new Index(this, address);
200         return index;
201     }
202
203     /**
204      * Places a byte array into the store, return a new object identifier.
205      */

206     public synchronized ObjectID createObject(byte[] b) throws IndexedStoreException {
207         ObjectAddress address = insertObject(new BinarySmallObject(b));
208         ObjectID id = getNextObjectID();
209         objectDirectory.insert(id.toByteArray(), address.toByteArray());
210         return id;
211     }
212
213     /**
214      * Places a String into the store.
215      */

216     public synchronized ObjectID createObject(String JavaDoc s) throws IndexedStoreException {
217         return createObject(Convert.toUTF8(s));
218     }
219
220     /**
221      * Tests to see if the file acting as the store exists.
222      */

223     public static synchronized boolean exists(String JavaDoc filename) {
224         return ObjectStore.exists(filename);
225     }
226
227     /**
228      * If a store disappears unexpectedly, make sure it gets closed.
229      */

230     protected void finalize() {
231         try {
232             close();
233         } catch (Exception JavaDoc e) {
234             //unsafe to throw exceptions from a finalize
235
}
236     }
237
238     /**
239      * Finds the handle of an open store for a given its name. The store may continue with the current transaction,
240      * or may abort the current transaction. Used to initiate recovery if the reference to the store should be
241      * lost for some reason. Will return null if the store has not been opened. The name of the store to be found
242      * must compare equal to the name the store was opened under.
243      */

244     public synchronized static IndexedStore find(String JavaDoc name) {
245         return (IndexedStore) registry.get(name);
246     }
247
248     /**
249      * Returns an index given its name.
250      */

251     public synchronized Index getIndex(String JavaDoc indexName) throws IndexedStoreException {
252         Index index;
253         byte[] key = Convert.toUTF8(indexName);
254         indexDirectoryCursor.find(key);
255         if (!indexDirectoryCursor.keyMatches(key))
256             throw new IndexedStoreException(IndexedStoreException.IndexNotFound);
257         ObjectAddress address = indexDirectoryCursor.getValueAsObjectAddress();
258         index = new Index(this, address);
259         return index;
260     }
261
262     private Buffer getMetadataArea(int i) throws IndexedStoreException {
263         try {
264             return objectStore.getMetadataArea(i);
265         } catch (ObjectStoreException e) {
266             throw new IndexedStoreException(IndexedStoreException.MetadataRequestError, e);
267         }
268     }
269
270     /**
271      * Returns the next ObjectID
272      */

273     private ObjectID getNextObjectID() throws IndexedStoreException {
274         IndexedStoreContext context = acquireContext(contextAddress);
275         if (context == null)
276             throw new IndexedStoreException(IndexedStoreException.ContextNotAvailable);
277         long objectNumber = context.getNextObjectNumber();
278         context.release();
279         return new ObjectID(objectNumber);
280     }
281
282     /**
283      * Returns a byte array given its object identifier.
284      */

285     public synchronized byte[] getObject(ObjectID id) throws IndexedStoreException {
286         objectDirectoryCursor.find(id.toByteArray());
287         ObjectAddress address = objectDirectoryCursor.getValueAsObjectAddress();
288         BinarySmallObject object = acquireBinarySmallObject(address);
289         byte[] b = object.getValue();
290         object.release();
291         return b;
292     }
293
294     /**
295      * Returns an object as a string, truncated at the first null.
296      */

297     public synchronized String JavaDoc getObjectAsString(ObjectID id) throws IndexedStoreException {
298         String JavaDoc s;
299         s = Convert.fromUTF8(getObject(id));
300         int i = s.indexOf(0);
301         if (i == -1)
302             return s;
303         return s.substring(0, i);
304     }
305
306     /**
307      * Inserts a new object into my store.
308      */

309     ObjectAddress insertObject(StoredObject object) throws IndexedStoreException {
310         try {
311             ObjectAddress address = objectStore.insertObject(object);
312             return address;
313         } catch (ObjectStoreException e) {
314             throw new IndexedStoreException(IndexedStoreException.ObjectNotStored, e);
315         }
316     }
317
318     /**
319      * Opens the store.
320      */

321     public synchronized void open(String JavaDoc name) throws IndexedStoreException {
322         if (registry.get(name) != null) {
323             throw new IndexedStoreException(IndexedStoreException.StoreIsOpen);
324         }
325         if (!exists(name))
326             create(name);
327         try {
328             objectStore = new ObjectStore(new IndexedStoreObjectPolicy());
329             objectStore.open(name);
330             // setting the name signals the indexed store as open
331
this.name = name;
332             checkMetadata();
333             contextAddress = ContextAddress10;
334             IndexedStoreContext context = acquireContext(contextAddress);
335             if (context == null) {
336                 contextAddress = ContextAddress11;
337                 context = acquireContext(contextAddress);
338             }
339             if (context == null) {
340                 throw new IndexedStoreException(IndexedStoreException.StoreFormatError);
341             }
342             indexDirectoryAddress = context.getIndexDirectoryAddress();
343             objectDirectoryAddress = context.getObjectDirectoryAddress();
344             context.release();
345             indexDirectory = new Index(this, indexDirectoryAddress);
346             indexDirectoryCursor = indexDirectory.open();
347             objectDirectory = new Index(this, objectDirectoryAddress);
348             objectDirectoryCursor = objectDirectory.open();
349             registry.put(name, this);
350         } catch (IndexedStoreException e) {
351             throw e;
352         } catch (Exception JavaDoc e) {
353             throw new IndexedStoreException(IndexedStoreException.GenericError, e);
354         }
355     }
356
357     private void putMetadataArea(int i, Buffer b) throws IndexedStoreException {
358         try {
359             objectStore.putMetadataArea(i, b);
360         } catch (ObjectStoreException e) {
361             throw new IndexedStoreException(IndexedStoreException.MetadataRequestError, e);
362         }
363     }
364
365     /**
366      * Removes an object from my store.
367      */

368     void removeObject(ObjectAddress address) throws IndexedStoreException {
369         try {
370             objectStore.removeObject(address);
371         } catch (ObjectStoreException e) {
372             throw new IndexedStoreException(IndexedStoreException.ObjectNotRemoved, e);
373         }
374     }
375
376     /**
377      * Removes the object identified by id from the store.
378      */

379     public synchronized void removeObject(ObjectID id) throws IndexedStoreException {
380         byte[] key = id.toByteArray();
381         objectDirectoryCursor.find(key);
382         if (!objectDirectoryCursor.keyMatches(key)) {
383             throw new IndexedStoreException(IndexedStoreException.ObjectNotFound);
384         }
385         ObjectAddress address = objectDirectoryCursor.getValueAsObjectAddress();
386         objectDirectoryCursor.remove();
387         removeObject(address);
388     }
389 }
390
Popular Tags