KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > tools > Defragment


1 /* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com
2
3 This file is part of the db4o open source object database.
4
5 db4o is free software; you can redistribute it and/or modify it under
6 the terms of version 2 of the GNU General Public License as published
7 by the Free Software Foundation and as clarified by db4objects' GPL
8 interpretation policy, available at
9 http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
10 Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
11 Suite 350, San Mateo, CA 94403, USA.
12
13 db4o is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */

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 /**
32  * old Deframent source code, now replaced by the built-in functionality in com.db4o.defragment.Defragment.
33  * <br><br><b>This class is deprecated. Please use {@link com.db4o.defragment.Defragment}.</b><br>
34  * This class is delivered as sourcecode in the
35  * path ../com/db4o/tools/<br><br> <b>Prerequites:</b><br> - The database file may not be
36  * in use.<br> - All stored classes need to be available.<br> - If you use yor own special
37  * Db4o translators, they need to be installed before starting Defragment.<br><br>
38  * <b>Performed tasks:</b><br> - Free filespace is removed.<br> - Deleted IDs are
39  * removed.<br> - Unavailable classes are removed.<br> - Unavailable class members are
40  * removed.<br> - Class indices are restored.<br> - Previous rename tasks are removed.<br>
41  * <br>
42  * <b>Backup:</b><br>
43  * Defragment creates a backup file with the name [filename].bak. If
44  * a file with this name is already present, Defragment will not run
45  * for safety reasons.<br><br>
46  * <b>Recommendations:</b><br>
47  * - Keep the backup copy of your database file.<br>
48  * - <b>Always</b> back up your class files with your database files also.<br>
49  * You will need them to restore the full data of all objects from old database file versions.<br>
50  * - Scan the output log for "Class not available" messages.<br><br>
51  * You may also run this task programmatically on a scheduled basis.
52  * In this case note that <code>Defragment</code> modifies db4o
53  * configuration parameters. You may have to restore them for your
54  * application. See the private methods Defragment#configureDb4o() and
55  * Db4o#restoreConfiguration() in the sourcecode of
56  * com.db4o.tools.Defragment.java for the exact changed parameters that
57  * may need to be restored.
58  * @deprecated Please use com.db4o.defragment.Defragment
59  */

60 public class Defragment {
61     
62     
63     private static Hashtable4 _secondClassNames;
64     
65     
66     /**
67      * the main method is the only entry point
68      */

69     public Defragment() {
70     }
71
72     /**
73      * the main method that runs Defragment.
74      * @param args a String array of length 1, with the name of the database
75      * file as element 0.
76      */

77     public static void main(String JavaDoc[] args) {
78         Db4o.configure().messageLevel(-1);
79         if (args != null && args.length > 0) {
80
81             // This is a hidden feature: For fast debugging reasons, delete
82
// can be forced by supplying an additional "!" parameter.
83
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     /**
93      * allows to specify a class to be treated as "second class".
94      * Second class objects are not migrated to the new database on their own. A second
95      * class objects is only migrated, if it is referenced by another object.
96      * @param className the fully qualified classname, including the package name for Java,
97      * including the namespaces and assembly name for .NET. Format examples:<br>
98      * Java: 'com.db4o.f1.Pilot'<br>
99      * .NET: 'com.db4o.f1.Pilot, MyAssembly'
100      */

101     public static void setSecondClass(String JavaDoc className){
102         if(_secondClassNames == null){
103             _secondClassNames = new Hashtable4();
104         }
105         _secondClassNames.put(className, className);
106     }
107     
108     /**
109      * programmatic interface to run Defragment with a forced delete of a possible
110      * old Defragment backup.
111      * <br>This method is supplied for regression tests only. It is not recommended
112      * to be used by application programmers.
113      * @param filename the database file.
114      * @param forceBackupDelete forces deleting an old backup. <b>Not recommended.</b>
115      */

116     public void run(String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc {
185
186         // get all stored classes
187
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 JavaDoc obj = origin.ext().getByID(ids[j]);
226             
227             if(firstClassPass || destination.ext().isStored(obj)){
228
229                 // prevent possible constructor side effects
230
origin.activate(obj, 1);
231                 origin.deactivate(obj, 2);
232     
233                 origin.activate(obj, 3);
234                 destination.set(obj);
235     
236                 // Both Containers keep track of state individually,
237
// so we need to make sure, both know, the object is deactivated
238
origin.deactivate(obj, 1);
239                 destination.deactivate(obj, 1);
240             }
241         }
242         return true;
243     }
244
245     private void removeSubclasses(StoredClass[] classes) throws ClassNotFoundException JavaDoc {
246         // rule out inheritance dependancies
247
for (int i = 0; i < classes.length; i++) {
248             if (classes[i] != null) {
249                 Class JavaDoc 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 JavaDoc 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         // remove classes that are currently not available,
265
// abstract classes and all second class objects
266
for (int i = 0; i < classes.length; i++) {
267             try {
268                 Class JavaDoc 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 JavaDoc t) {
275                 classes[i] = null;
276             }
277         }
278     }
279
280     private class ExtFile extends File {
281
282         public ExtFile(String JavaDoc path) {
283             super(path);
284         }
285
286         public ExtFile copy(String JavaDoc toPath) throws Exception JavaDoc {
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 JavaDoc e) {
309                 e.printStackTrace();
310                 throw e;
311             }
312         }
313     }
314
315 }
316
Popular Tags