1 11 package org.eclipse.core.internal.indexing; 12 13 24 25 class ObjectPage extends ObjectStorePage { 26 27 protected static final int MaxEntries = 256; 28 protected static final int ObjectDirectoryOffset = 64; 29 protected static final int ObjectSpaceOffset = ObjectDirectoryOffset + 512; 30 protected static final int FlagOffset = 0; 31 protected static final int UsedSpaceOffset = 2; 32 protected static final int UsedEntriesOffset = 4; 33 protected static final int InitialEntryOffset = 6; 34 protected static final int FreeSpaceOffset = 8; 35 36 public static final int ObjectSpaceSize = SIZE - ObjectSpaceOffset; 37 38 protected int usedSpace; 39 protected int usedEntries; 40 protected int freeSpaceOffset; 41 protected int initialEntry; 42 43 46 public ObjectPage(int pageNumber, byte[] buffer, PageStore pageStore) { 47 super(pageNumber, buffer, pageStore); 48 } 49 50 53 public void toBuffer(byte[] buffer) { 54 dematerialize(); 55 pageBuffer.copyTo(buffer); 56 } 57 58 62 63 protected void materialize() { 64 int initialized = pageBuffer.getUInt(FlagOffset, 2); 65 if (initialized == 0xEEEE) { 66 usedSpace = pageBuffer.getUInt(UsedSpaceOffset, 2); 67 usedEntries = pageBuffer.getUInt(UsedEntriesOffset, 2); 68 initialEntry = pageBuffer.getUInt(InitialEntryOffset, 2); 69 freeSpaceOffset = pageBuffer.getUInt(FreeSpaceOffset, 2); 70 } else { 71 usedSpace = 0; 72 usedEntries = 0; 73 initialEntry = 0; 74 freeSpaceOffset = ObjectSpaceOffset; 75 } 76 } 77 78 82 protected void dematerialize() { 83 pageBuffer.put(FlagOffset, 2, 0xEEEE); 84 pageBuffer.put(UsedSpaceOffset, 2, usedSpace); 85 pageBuffer.put(UsedEntriesOffset, 2, usedEntries); 86 pageBuffer.put(InitialEntryOffset, 2, initialEntry); 87 pageBuffer.put(FreeSpaceOffset, 2, freeSpaceOffset); 88 } 89 90 93 public Field getObjectField(int objectNumber) throws ObjectStoreException { 94 int entryOffset = ObjectDirectoryOffset + 2 * objectNumber; 95 int blockOffset = pageBuffer.getUInt(entryOffset, 2); 96 if (blockOffset == 0) 97 return null; 98 ObjectHeader header = new ObjectHeader(pageBuffer.get(blockOffset, ObjectHeader.SIZE)); 99 Field f = pageBuffer.getField(blockOffset + ObjectHeader.SIZE, header.getObjectLength()); 100 return f; 101 } 102 103 106 public void insertObject(StoredObject object) throws ObjectStoreException { 107 108 int blockLength = object.length() + ObjectHeader.SIZE; 110 if (getFreeSpace() < blockLength) { 111 throw new ObjectStoreException(ObjectStoreException.ObjectSizeFailure); 112 } 113 114 int objectNumber = object.getAddress().getObjectNumber(); 116 int entryOffset = ObjectDirectoryOffset + (objectNumber * 2); 117 int blockOffset = pageBuffer.getUInt(entryOffset, 2); 118 if (blockOffset != 0) { 119 throw new ObjectStoreException(ObjectStoreException.PageVacancyFailure); 120 } 121 122 if (blockLength > (SIZE - freeSpaceOffset)) 124 compress(); blockOffset = freeSpaceOffset; ObjectHeader header = new ObjectHeader(object.length()); 127 pageBuffer.put(blockOffset, header); 128 pageBuffer.put(blockOffset + ObjectHeader.SIZE, object.toByteArray()); 129 pageBuffer.put(entryOffset, 2, blockOffset); 130 freeSpaceOffset += blockLength; usedSpace += blockLength; usedEntries++; initialEntry = (objectNumber + 1) % MaxEntries; setChanged(); 135 notifyObservers(); 136 } 137 138 142 public int reserveObject(StoredObject object, ReservationTable reservations) throws ObjectStoreException { 143 144 int blockLength = object.length() + ObjectHeader.SIZE; 146 if (getFreeSpace() < blockLength) { 147 throw new ObjectStoreException(ObjectStoreException.ObjectSizeFailure); 148 } 149 150 Reservation r = reservations.get(pageNumber); 152 if (r == null) { 153 r = new Reservation(getFreeSpace(), MaxEntries - usedEntries, initialEntry); 154 reservations.put(pageNumber, r); 155 } 156 157 int objectNumber = r.getInitialEntry(); 159 int blockOffset = 0; 160 int entryOffset = 0; 161 for (int i = 0; i < MaxEntries; i++) { 162 if (!r.contains(objectNumber)) { 163 entryOffset = ObjectDirectoryOffset + (objectNumber * 2); 164 blockOffset = pageBuffer.getUInt(entryOffset, 2); 165 if (blockOffset == 0) 166 break; 167 } 168 objectNumber = (objectNumber + 1) % MaxEntries; 169 } 170 if (blockOffset != 0) { 171 throw new ObjectStoreException(ObjectStoreException.PageVacancyFailure); 172 } 173 174 r.setInitialEntry((objectNumber + 1) % MaxEntries); 176 177 r.add(objectNumber, blockLength); 179 return objectNumber; 180 } 181 182 public void removeObject(int objectNumber) throws ObjectStoreException { 183 184 185 int entryOffset = ObjectDirectoryOffset + 2 * objectNumber; 186 int blockOffset = pageBuffer.getUInt(entryOffset, 2); 187 if (blockOffset == 0) 188 throw new ObjectStoreException(ObjectStoreException.ObjectExistenceFailure); 189 190 191 pageBuffer.put(entryOffset, 2, 0); ObjectHeader h = new ObjectHeader(pageBuffer.get(blockOffset, ObjectHeader.SIZE)); 193 int objectLength = h.getObjectLength(); 194 int blockLength = objectLength + ObjectHeader.SIZE; pageBuffer.clear(blockOffset, blockLength); usedSpace -= blockLength; usedEntries--; setChanged(); 199 notifyObservers(); 200 } 201 202 205 public void updateObject(StoredObject object) throws ObjectStoreException { 206 207 int objectNumber = object.getAddress().getObjectNumber(); 208 209 210 int entryOffset = ObjectDirectoryOffset + 2 * objectNumber; 211 int blockOffset = pageBuffer.getUInt(entryOffset, 2); 212 if (blockOffset == 0) { 213 throw new ObjectStoreException(ObjectStoreException.ObjectExistenceFailure); 214 } 215 216 217 ObjectHeader header = new ObjectHeader(pageBuffer.get(blockOffset, ObjectHeader.SIZE)); 218 if (header.getObjectLength() != object.length()) { 219 throw new ObjectStoreException(ObjectStoreException.ObjectSizeFailure); 220 } 221 222 223 int objectOffset = blockOffset + ObjectHeader.SIZE; 224 pageBuffer.put(objectOffset, object.toByteArray()); 225 setChanged(); 226 notifyObservers(); 227 } 228 229 235 private void compress() throws ObjectStoreException { 236 Buffer temp = new Buffer(SIZE); 237 int newBlockOffset = ObjectSpaceOffset; 238 int entryOffset = ObjectDirectoryOffset; 239 usedEntries = 0; 240 for (int i = 0; i < MaxEntries; i++) { 241 int oldBlockOffset = pageBuffer.getUInt(entryOffset, 2); 242 if (oldBlockOffset > 0) { 243 ObjectHeader h = new ObjectHeader(pageBuffer.get(oldBlockOffset, ObjectHeader.SIZE)); 244 int blockLength = h.getObjectLength() + ObjectHeader.SIZE; 245 temp.put(newBlockOffset, pageBuffer.get(oldBlockOffset, blockLength)); 246 pageBuffer.put(entryOffset, 2, newBlockOffset); 247 newBlockOffset += blockLength; 248 usedEntries++; 249 } 250 entryOffset += 2; 251 } 252 pageBuffer.put(ObjectSpaceOffset, temp.get(ObjectSpaceOffset, SIZE - ObjectSpaceOffset)); 253 freeSpaceOffset = newBlockOffset; 254 } 255 256 259 public int getFreeSpace() { 260 if (usedEntries >= MaxEntries) 261 return 0; 262 return SIZE - (ObjectSpaceOffset + usedSpace); 263 } 264 } 265 | Popular Tags |