1 21 package com.db4o.tools; 22 23 import java.io.*; 24 import java.lang.reflect.*; 25 26 import com.db4o.*; 27 import com.db4o.ext.*; 28 import com.db4o.foundation.*; 29 import com.db4o.types.*; 30 31 60 public class Defragment { 61 62 63 private static Hashtable4 _secondClassNames; 64 65 66 69 public Defragment() { 70 } 71 72 77 public static void main(String [] args) { 78 Db4o.configure().messageLevel(-1); 79 if (args != null && args.length > 0) { 80 81 boolean forceBackupDelete = (args.length > 1 && "!".equals(args[1])); 84 85 new Defragment().run(args[0], forceBackupDelete); 86 87 } else { 88 System.out.println("Usage: java com.db4o.tools.Defragment <database filename>"); 89 } 90 } 91 92 101 public static void setSecondClass(String className){ 102 if(_secondClassNames == null){ 103 _secondClassNames = new Hashtable4(); 104 } 105 _secondClassNames.put(className, className); 106 } 107 108 116 public void run(String filename, boolean forceBackupDelete) { 117 File file = new File(filename); 118 if (file.exists()) { 119 boolean canRun = true; 120 ExtFile backupTest = new ExtFile(file.getAbsolutePath() + ".bak"); 121 if (backupTest.exists()) { 122 if (forceBackupDelete) { 123 backupTest.delete(); 124 } else { 125 canRun = false; 126 System.out.println("A backup file with the name "); 127 System.out.println("'" + backupTest.getAbsolutePath() + "'"); 128 System.out.println("already exists."); 129 System.out.println("Remove this file before calling 'Defragment'."); 130 } 131 } 132 if (canRun) { 133 file.renameTo(backupTest); 134 try { 135 configureDb4o(); 136 ObjectContainer readFrom = Db4o.openFile(backupTest.getAbsolutePath()); 137 ObjectContainer writeTo = Db4o.openFile(file.getAbsolutePath()); 138 writeTo.ext().migrateFrom(readFrom); 139 migrate(readFrom, writeTo); 140 readFrom.close(); 141 writeTo.close(); 142 System.out.println("Defragment operation completed successfully."); 143 } catch (Exception e) { 144 System.out.println("Defragment operation failed."); 145 e.printStackTrace(); 146 try { 147 new File(filename).delete(); 148 backupTest.copy(filename); 149 } catch (Exception ex) { 150 System.out.println("Restore failed."); 151 System.out.println("Please use the backup file:"); 152 System.out.println("'" + backupTest.getAbsolutePath() + "'"); 153 return; 154 } 155 System.out.println("The original file was restored."); 156 try { 157 new File(backupTest.getAbsolutePath()).delete(); 158 } catch (Exception ex) { 159 } 160 } finally{ 161 restoreConfiguration(); 162 } 163 } 164 } else { 165 System.out.println("File '" + file.getAbsolutePath() + "' does not exist."); 166 } 167 } 168 169 private void configureDb4o() { 170 Db4o.configure().activationDepth(0); 171 Db4o.configure().callbacks(false); 172 Db4o.configure().classActivationDepthConfigurable(false); 173 Db4o.configure().weakReferences(false); 174 } 175 176 private void restoreConfiguration(){ 177 Db4o.configure().activationDepth(5); 178 Db4o.configure().callbacks(true); 179 Db4o.configure().classActivationDepthConfigurable(true); 180 Db4o.configure().weakReferences(true); 181 } 182 183 private void migrate(ObjectContainer origin, ObjectContainer destination) 184 throws ClassNotFoundException { 185 186 StoredClass[] classes = origin.ext().storedClasses(); 188 removeUnavailableSecondAndAbstractClasses(classes); 189 removeSubclasses(classes); 190 migrateClasses(origin, destination, classes); 191 } 192 193 private void migrateClasses(ObjectContainer origin, ObjectContainer destination, StoredClass[] classes) { 194 195 for (int i = 0; i < classes.length; i++) { 196 if(migrateClass(origin, destination, classes[i], true)){ 197 classes[i] = null; 198 } 199 } 200 if(_secondClassNames != null){ 201 for (int i = 0; i < classes.length; i++) { 202 migrateClass(origin, destination, classes[i], false); 203 } 204 } 205 206 } 207 208 private boolean migrateClass(ObjectContainer origin, ObjectContainer destination, StoredClass clazz, boolean firstClassPass){ 209 if(clazz == null){ 210 return false; 211 } 212 if(firstClassPass){ 213 if(_secondClassNames != null){ 214 if(_secondClassNames.get(clazz.getName()) != null){ 215 return false; 216 } 217 } 218 } 219 220 long[] ids = clazz.getIDs(); 221 origin.ext().purge(); 222 destination.commit(); 223 destination.ext().purge(); 224 for (int j = 0; j < ids.length; j++) { 225 Object obj = origin.ext().getByID(ids[j]); 226 227 if(firstClassPass || destination.ext().isStored(obj)){ 228 229 origin.activate(obj, 1); 231 origin.deactivate(obj, 2); 232 233 origin.activate(obj, 3); 234 destination.set(obj); 235 236 origin.deactivate(obj, 1); 239 destination.deactivate(obj, 1); 240 } 241 } 242 return true; 243 } 244 245 private void removeSubclasses(StoredClass[] classes) throws ClassNotFoundException { 246 for (int i = 0; i < classes.length; i++) { 248 if (classes[i] != null) { 249 Class javaClass = Class.forName(classes[i].getName()); 250 for (int j = 0; j < classes.length; j++) { 251 if (classes[j] != null && classes[i] != classes[j]) { 252 Class superClass = Class.forName(classes[j].getName()); 253 if (superClass.isAssignableFrom(javaClass)) { 254 classes[i] = null; 255 break; 256 } 257 } 258 } 259 } 260 } 261 } 262 263 private void removeUnavailableSecondAndAbstractClasses(StoredClass[] classes) { 264 for (int i = 0; i < classes.length; i++) { 267 try { 268 Class javaClass = Class.forName(classes[i].getName()); 269 if (javaClass == null 270 || SecondClass.class.isAssignableFrom(javaClass) 271 || Modifier.isAbstract(javaClass.getModifiers())) { 272 classes[i] = null; 273 } 274 } catch (Throwable t) { 275 classes[i] = null; 276 } 277 } 278 } 279 280 private class ExtFile extends File { 281 282 public ExtFile(String path) { 283 super(path); 284 } 285 286 public ExtFile copy(String toPath) throws Exception { 287 try { 288 new ExtFile(toPath).mkdirs(); 289 new ExtFile(toPath).delete(); 290 final int bufferSize = 64000; 291 292 RandomAccessFile rafIn = new RandomAccessFile(getAbsolutePath(), "r"); 293 RandomAccessFile rafOut = new RandomAccessFile(toPath, "rw"); 294 long len = rafIn.length(); 295 byte[] bytes = new byte[bufferSize]; 296 297 while (len > 0) { 298 len -= bufferSize; 299 if (len < 0) { 300 bytes = new byte[(int) (len + bufferSize)]; 301 } 302 rafIn.read(bytes); 303 rafOut.write(bytes); 304 } 305 rafIn.close(); 306 rafOut.close(); 307 return new ExtFile(toPath); 308 } catch (Exception e) { 309 e.printStackTrace(); 310 throw e; 311 } 312 } 313 } 314 315 } 316 | Popular Tags |