1 21 package com.db4o.defragment; 22 23 import java.io.*; 24 25 import com.db4o.*; 26 import com.db4o.ext.*; 27 import com.db4o.foundation.*; 28 import com.db4o.foundation.io.*; 29 import com.db4o.inside.btree.*; 30 import com.db4o.inside.classindex.*; 31 32 62 public class Defragment { 63 64 73 public static void defrag(String origPath) throws IOException { 74 defrag(new DefragmentConfig(origPath), new NullListener()); 75 } 76 77 88 public static void defrag(String origPath, String backupPath) 89 throws IOException { 90 defrag(new DefragmentConfig(origPath, backupPath), new NullListener()); 91 } 92 93 103 public static void defrag(DefragmentConfig config) throws IOException { 104 defrag(config, new NullListener()); 105 } 106 107 120 public static void defrag(DefragmentConfig config, DefragmentListener listener) throws IOException { 121 File backupFile = new File(config.backupPath()); 122 if (backupFile.exists()) { 123 if (!config.forceBackupDelete()) { 124 throw new IOException("Could not use '" + config.backupPath() 125 + "' as backup path - file exists."); 126 } 127 backupFile.delete(); 128 } 129 File4.rename(config.origPath(), config.backupPath()); 130 DefragContextImpl context = new DefragContextImpl(config, listener); 131 int newClassCollectionID = 0; 132 int targetIdentityID = 0; 133 int targetUuidIndexID = 0; 134 try { 135 firstPass(context, config); 136 secondPass(context, config); 137 defragUnindexed(context); 138 newClassCollectionID = context.mappedID(context 139 .sourceClassCollectionID()); 140 int sourceIdentityID = context 141 .databaseIdentityID(DefragContextImpl.SOURCEDB); 142 targetIdentityID = context.mappedID(sourceIdentityID); 143 context.targetClassCollectionID(newClassCollectionID); 144 targetUuidIndexID = context 145 .mappedID(context.sourceUuidIndexID(), 0); 146 } catch (CorruptionException exc) { 147 exc.printStackTrace(); 148 } finally { 149 context.close(); 150 } 151 setIdentity(config.origPath(), targetIdentityID, targetUuidIndexID); 152 } 153 154 private static void defragUnindexed(DefragContextImpl context) 155 throws CorruptionException { 156 Iterator4 unindexedIDs = context.unindexedIDs(); 157 while (unindexedIDs.moveNext()) { 158 final int origID = ((Integer ) unindexedIDs.current()).intValue(); 159 ReaderPair.processCopy(context, origID, new SlotCopyHandler() { 160 public void processCopy(ReaderPair readers) 161 throws CorruptionException { 162 YapClass.defragObject(readers); 163 } 164 165 }, true); 166 } 167 } 168 169 private static void setIdentity(String targetFile, int targetIdentityID, 170 int targetUuidIndexID) { 171 YapFile targetDB = (YapFile) Db4o.openFile(DefragmentConfig 172 .vanillaDb4oConfig(), targetFile); 173 try { 174 Db4oDatabase identity = (Db4oDatabase) targetDB 175 .getByID(targetIdentityID); 176 targetDB.setIdentity(identity); 177 targetDB.systemData().uuidIndexId(targetUuidIndexID); 178 } finally { 179 targetDB.close(); 180 } 181 } 182 183 private static void firstPass(DefragContextImpl context, 184 DefragmentConfig config) throws CorruptionException { 185 pass(context, config, new FirstPassCommand()); 187 } 188 189 private static void secondPass(final DefragContextImpl context, 190 DefragmentConfig config) throws CorruptionException { 191 pass(context, config, new SecondPassCommand()); 193 } 194 195 private static void pass(DefragContextImpl context, 196 DefragmentConfig config, PassCommand command) 197 throws CorruptionException { 198 command.processClassCollection(context); 199 StoredClass[] classes = context 200 .storedClasses(DefragContextImpl.SOURCEDB); 201 for (int classIdx = 0; classIdx < classes.length; classIdx++) { 202 YapClass yapClass = (YapClass) classes[classIdx]; 203 if (!config.storedClassFilter().accept(yapClass)) { 204 continue; 205 } 206 processYapClass(context, yapClass, command); 207 command.flush(context); 208 } 209 BTree uuidIndex = context.sourceUuidIndex(); 210 if (uuidIndex != null) { 211 command.processBTree(context, uuidIndex); 212 } 213 command.flush(context); 214 context.targetCommit(); 215 } 216 217 private static void processYapClass(final DefragContextImpl context, 225 final YapClass curClass, final PassCommand command) 226 throws CorruptionException { 227 processClassIndex(context, curClass, command); 228 if (!parentHasIndex(curClass)) { 229 processObjectsForYapClass(context, curClass, command); 230 } 231 processYapClassAndFieldIndices(context, curClass, command); 232 } 233 234 private static boolean parentHasIndex(YapClass curClass) { 235 YapClass parentClass = curClass.i_ancestor; 236 while (parentClass != null) { 237 if (parentClass.hasIndex()) { 238 return true; 239 } 240 parentClass = parentClass.i_ancestor; 241 } 242 return false; 243 } 244 245 private static void processObjectsForYapClass( 246 final DefragContextImpl context, final YapClass curClass, 247 final PassCommand command) { 248 final boolean withStringIndex = withFieldIndex(curClass); 249 context.traverseAll(curClass, new Visitor4() { 250 public void visit(Object obj) { 251 int id = ((Integer ) obj).intValue(); 252 try { 253 command.processObjectSlot(context, curClass, id, 254 withStringIndex); 255 } catch (CorruptionException e) { 256 e.printStackTrace(); 257 } 258 } 259 }); 260 } 261 262 private static boolean withFieldIndex(YapClass clazz) { 263 Iterator4 fieldIter = clazz.fields(); 264 while (fieldIter.moveNext()) { 265 YapField curField = (YapField) fieldIter.current(); 266 if (curField.hasIndex() 267 && (curField.getHandler() instanceof YapString)) { 268 return true; 269 } 270 } 271 return false; 272 } 273 274 private static void processYapClassAndFieldIndices( 275 final DefragContextImpl context, final YapClass curClass, 276 final PassCommand command) throws CorruptionException { 277 int sourceClassIndexID = 0; 278 int targetClassIndexID = 0; 279 if (curClass.hasIndex()) { 280 sourceClassIndexID = curClass.index().id(); 281 targetClassIndexID = context.mappedID(sourceClassIndexID, -1); 282 } 283 command.processClass(context, curClass, curClass.getID(), 284 targetClassIndexID); 285 } 286 287 private static void processClassIndex(final DefragContextImpl context, 288 final YapClass curClass, final PassCommand command) 289 throws CorruptionException { 290 if (curClass.hasIndex()) { 291 BTreeClassIndexStrategy indexStrategy = (BTreeClassIndexStrategy) curClass 292 .index(); 293 final BTree btree = indexStrategy.btree(); 294 command.processBTree(context, btree); 295 } 296 } 297 298 static class NullListener implements DefragmentListener { 299 public void notifyDefragmentInfo(DefragmentInfo info) { 300 } 301 } 302 } 303
| Popular Tags
|