1 11 package org.eclipse.core.internal.indexing; 12 13 import java.util.*; 14 15 public class ObjectStore implements Observer { 16 17 public static final int MAXIMUM_OBJECT_SIZE = ObjectPage.ObjectSpaceSize - ObjectHeader.SIZE; 18 protected static final int CurrentObjectStoreVersion = 1; 19 protected static final int ObjectStoreMetadataAreaID = 1; 20 21 protected PageStore pageStore; 22 protected String name; 23 protected Map acquiredObjects; protected Map modifiedObjects; protected LinkedList cachedObjects; protected Set phantoms; protected ReservationTable reservations; 28 29 protected ObjectStorePagePolicy pagePolicy; 30 protected AbstractObjectPolicy objectPolicy; 31 32 35 public static void create(String path) throws ObjectStoreException { 36 try { 37 PageStore.create(path); 38 } catch (PageStoreException e) { 39 throw new ObjectStoreException(ObjectStoreException.StoreCreateFailure, e); 40 } 41 } 42 43 46 public static void delete(String path) { 47 PageStore.delete(path); 48 } 49 50 53 public static boolean exists(String path) { 54 return PageStore.exists(path); 55 } 56 57 60 public ObjectStore(AbstractObjectPolicy objectPolicy) { 61 this.pagePolicy = new ObjectStorePagePolicy(); 62 this.objectPolicy = objectPolicy; 63 } 64 65 68 public void open(String name) throws ObjectStoreException { 69 try { 70 pageStore = new PageStore(pagePolicy); 71 pageStore.open(name); 72 } catch (PageStoreException e) { 73 throw new ObjectStoreException(ObjectStoreException.StoreOpenFailure, e); 74 } 75 checkMetadata(); 76 acquiredObjects = new HashMap(); 77 modifiedObjects = new HashMap(); 78 cachedObjects = new LinkedList(); 79 phantoms = new HashSet(); 80 reservations = new ReservationTable(); 81 } 82 83 86 public void close() throws ObjectStoreException { 87 try { 88 commit(); 89 } catch (ObjectStoreException e) { 90 pageStore.close(false); 92 throw e; 93 } 94 try { 95 pageStore.close(); 96 } catch (Exception e) { 97 } 99 acquiredObjects = null; 100 modifiedObjects = null; 101 cachedObjects = null; 102 phantoms = null; 103 reservations = null; 104 } 105 106 public Buffer getMetadataArea(int i) throws ObjectStoreException { 107 try { 108 return new Buffer(pageStore.readMetadataArea(i)); 109 } catch (PageStoreException e) { 110 throw new ObjectStoreException(ObjectStoreException.MetadataRequestFailure, e); 111 } 112 } 113 114 public void putMetadataArea(int i, Buffer buffer) throws ObjectStoreException { 115 try { 116 pageStore.writeMetadataArea(i, buffer.getByteArray()); 117 } catch (PageStoreException e) { 118 throw new ObjectStoreException(ObjectStoreException.MetadataRequestFailure, e); 119 } 120 } 121 122 126 protected void checkMetadata() throws ObjectStoreException { 127 Buffer metadata = getMetadataArea(ObjectStoreMetadataAreaID); 128 Field versionField = metadata.getField(0, 4); 129 int objectStoreVersion = versionField.getInt(); 130 if (objectStoreVersion == 0) { 131 versionField.put(CurrentObjectStoreVersion); 133 putMetadataArea(ObjectStoreMetadataAreaID, metadata); 134 return; 135 } 136 if (objectStoreVersion == CurrentObjectStoreVersion) 137 return; 138 convert(objectStoreVersion); 139 } 140 141 145 protected void convert(int fromVersion) throws ObjectStoreException { 146 throw new ObjectStoreException(ObjectStoreException.StoreConversionFailure); 147 } 148 149 152 public void commit() throws ObjectStoreException { 153 for (Iterator z = acquiredObjects.values().iterator(); z.hasNext();) { 154 StoredObject object = (StoredObject) z.next(); 155 object.notifyObservers(); 156 } 157 for (Iterator z = phantoms.iterator(); z.hasNext();) { 158 ObjectAddress address = (ObjectAddress) z.next(); 159 int pageNumber = address.getPageNumber(); 160 ObjectPage page = acquireObjectPage(pageNumber); 161 page.removeObject(address.getObjectNumber()); 162 updateSpaceMapPage(page.getPageNumber(), page.getFreeSpace()); 163 page.release(); 164 } 165 phantoms.clear(); 166 for (Iterator z = modifiedObjects.values().iterator(); z.hasNext();) { 167 StoredObject object = (StoredObject) z.next(); 168 z.remove(); 169 addToCache(object); 170 ObjectAddress address = object.getAddress(); 171 int pageNumber = address.getPageNumber(); 172 ObjectPage page = acquireObjectPage(pageNumber); 173 if (reservations.contains(address)) { 174 page.insertObject(object); 175 updateSpaceMapPage(pageNumber, page.getFreeSpace()); 176 } else { 177 page.updateObject(object); 178 } 179 page.release(); 180 } 181 reservations.clear(); 182 try { 183 pageStore.commit(); 184 } catch (PageStoreException e) { 185 throw new ObjectStoreException(ObjectStoreException.PageWriteFailure, e); 186 } 187 } 188 189 193 public StoredObject acquireObject(ObjectAddress address) throws ObjectStoreException { 194 if (phantoms.contains(address)) { 195 throw new ObjectStoreException(ObjectStoreException.ObjectExistenceFailure); 196 } 197 StoredObject object = (StoredObject) acquiredObjects.get(address); 198 if (object == null) { 199 object = (StoredObject) modifiedObjects.get(address); 200 if (object == null) { 201 object = removeFromCache(address); 202 if (object == null) { 203 int pageNumber = address.getPageNumber(); 204 ObjectPage page = acquireObjectPage(pageNumber); 205 try { 206 Field f = page.getObjectField(address.getObjectNumber()); 207 if (f == null) 208 throw new ObjectStoreException(ObjectStoreException.ObjectExistenceFailure); 209 object = objectPolicy.createObject(f, this, address); 210 } catch (ObjectStoreException e) { 211 page.release(); 212 throw e; 213 } 214 page.release(); 215 } 216 } 217 acquiredObjects.put(address, object); 218 object.addObserver(this); 219 } 220 object.addReference(); 221 return object; 222 } 223 224 230 public void releaseObject(StoredObject object) throws ObjectStoreException { 231 object.removeReference(); 232 if (object.hasReferences()) 233 return; 234 object.notifyObservers(); object.deleteObserver(this); 236 acquiredObjects.remove(object.getAddress()); 237 addToCache(object); 238 } 239 240 246 public void update(Observable object, Object arg) { 247 StoredObject storedObject = (StoredObject) object; 248 modifiedObjects.put(storedObject.getAddress(), storedObject); 249 } 250 251 255 protected void addToCache(StoredObject object) { 256 synchronized (cachedObjects) { 257 if (acquiredObjects.containsKey(object.getAddress())) 258 return; 259 if (modifiedObjects.containsKey(object.getAddress())) 260 return; 261 cachedObjects.addFirst(object); 262 if (cachedObjects.size() <= 50) 263 return; 264 cachedObjects.removeLast(); 265 } 266 } 267 268 271 protected StoredObject removeFromCache(ObjectAddress address) { 272 synchronized (cachedObjects) { 273 StoredObject object = null; 274 for (Iterator z = cachedObjects.iterator(); z.hasNext();) { 275 StoredObject o = (StoredObject) z.next(); 276 if (o.getAddress().equals(address)) { 277 z.remove(); 278 object = o; 279 break; 280 } 281 } 282 return object; 283 } 284 } 285 286 290 308 public ObjectAddress insertObject(StoredObject object) throws ObjectStoreException { 309 int bytesNeeded = object.length() + ObjectHeader.SIZE; 310 ObjectPage page = acquireObjectPageForSize(bytesNeeded); 311 int pageNumber = page.getPageNumber(); 312 int objectNumber = page.reserveObject(object, reservations); 313 page.release(); 314 ObjectAddress address = new ObjectAddress(pageNumber, objectNumber); 315 object.setAddress(address); 316 object.setStore(this); 317 modifiedObjects.put(address, object); 318 return address; 319 } 320 321 324 public void removeObject(ObjectAddress address) throws ObjectStoreException { 325 if (phantoms.contains(address)) { 326 throw new ObjectStoreException(ObjectStoreException.ObjectExistenceFailure); 327 } 328 if (acquiredObjects.containsKey(address)) { 329 throw new ObjectStoreException(ObjectStoreException.ObjectIsLocked); 330 } 331 StoredObject object = (StoredObject) modifiedObjects.get(address); 332 boolean inStore = !reservations.contains(address); 333 if (object != null) { 334 reservations.remove(address); 335 modifiedObjects.remove(address); 336 } 337 removeFromCache(address); 338 if (inStore) 339 phantoms.add(address); 340 } 341 342 347 358 protected void updateSpaceMapPage(int objectPageNumber, int freeSpace) throws ObjectStoreException { 359 SpaceMapPage p = acquireSpaceMapPage(objectPageNumber); 360 p.setFreeSpace(objectPageNumber, freeSpace); 361 p.release(); 362 } 363 364 367 protected ObjectPage acquireObjectPage(int pageNumber) throws ObjectStoreException { 368 ObjectPage page; 369 try { 370 page = (ObjectPage) pageStore.acquire(pageNumber); 371 } catch (PageStoreException e) { 372 throw new ObjectStoreException(ObjectStoreException.PageReadFailure, e); 373 } 374 return page; 375 } 376 377 387 protected ObjectPage acquireObjectPageForSize(int bytesNeeded) throws ObjectStoreException { 388 int oPageNumber = 0; 389 int numberOfSpans = ((pageStore.numberOfPages() - 1) / ObjectStorePage.SIZE) + 1; 390 for (int i = 0; i <= numberOfSpans; i++) { 391 try { 392 int sPageNumber = i * ObjectStorePage.SIZE; 393 SpaceMapPage sPage = (SpaceMapPage) pageStore.acquire(sPageNumber); 394 for (int j = 1; j < ObjectStorePage.SIZE; j++) { 395 int n = sPageNumber + j; 396 Reservation r = reservations.get(n); 397 int bytesAvailable = (r == null) ? sPage.getFreeSpace(n) : r.getFreeSpace(); 398 if (bytesNeeded <= bytesAvailable) { 399 oPageNumber = n; 400 break; 401 } 402 } 403 sPage.release(); 404 } catch (PageStoreException e) { 405 throw new ObjectStoreException(ObjectStoreException.PageReadFailure, e); 406 } 407 if (oPageNumber != 0) 408 break; 409 } 410 if (oPageNumber == 0) { 411 throw new ObjectStoreException(ObjectStoreException.PageReadFailure); 412 } 413 try { 414 ObjectPage oPage = (ObjectPage) pageStore.acquire(oPageNumber); 415 return oPage; 416 } catch (PageStoreException e) { 417 throw new ObjectStoreException(ObjectStoreException.PageReadFailure, e); 418 } 419 } 420 421 424 protected SpaceMapPage acquireSpaceMapPage(int objectPageNumber) throws ObjectStoreException { 425 int pageNumber = objectPageNumber & 0xFFFFE000; 426 SpaceMapPage p = null; 427 try { 428 p = (SpaceMapPage) pageStore.acquire(pageNumber); 429 } catch (PageStoreException e) { 430 throw new ObjectStoreException(ObjectStoreException.PageReadFailure, e); 431 } 432 return p; 433 } 434 435 } 436 | Popular Tags |