001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.tools;
022:
023: import com.db4o.Db4o;
024: import com.db4o.ObjectContainer;
025: import com.db4o.ext.StoredClass;
026: import com.db4o.foundation.Tree;
027: import com.db4o.foundation.Visitor4;
028: import com.db4o.internal.ReflectPlatform;
029: import com.db4o.internal.TreeInt;
030: import com.db4o.internal.TreeString;
031: import com.db4o.internal.TreeStringObject;
032:
033: /**
034: * prints statistics about a database file to System.out.
035: * <br><br>Pass the database file path as an argument.
036: * <br><br><b>This class is not part of db4o.jar!</b><br>
037: * It is delivered as sourcecode in the
038: * path ../com/db4o/tools/<br><br>
039: */
040: public class Statistics {
041:
042: /**
043: * the main method that runs the statistics.
044: * @param args a String array of length 1, with the name of the database
045: * file as element 0.
046: */
047: public static void main(String[] args) {
048: Db4o.configure().messageLevel(-1);
049: if (args == null || args.length != 1) {
050: System.out
051: .println("Usage: java com.db4o.tools.Statistics <database filename>");
052: } else {
053: new Statistics().run(args[0]);
054: }
055: }
056:
057: public void run(String filename) {
058: if (new java.io.File(filename).exists()) {
059: ObjectContainer con = null;
060: try {
061: con = Db4o.openFile(filename);
062: printHeader("STATISTICS");
063: System.out.println("File: " + filename);
064: printStats(con, filename);
065: con.close();
066: } catch (Exception e) {
067: System.out.println("Statistics failed for file: '"
068: + filename + "'");
069: System.out.println(e.getMessage());
070: e.printStackTrace();
071: }
072: } else {
073: System.out.println("File not found: '" + filename + "'");
074: }
075: }
076:
077: private static boolean canCallConstructor(String className) {
078: return ReflectPlatform.createInstance(className) != null;
079: }
080:
081: private void printStats(ObjectContainer con, String filename) {
082:
083: Tree unavailable = new TreeString(REMOVE);
084: Tree noConstructor = new TreeString(REMOVE);
085:
086: // one element too many, substract one in the end
087: StoredClass[] internalClasses = con.ext().storedClasses();
088: for (int i = 0; i < internalClasses.length; i++) {
089: String internalClassName = internalClasses[i].getName();
090: Class clazz = ReflectPlatform.forName(internalClassName);
091: if (clazz == null) {
092: unavailable = unavailable.add(new TreeString(
093: internalClassName));
094: } else {
095: if (!canCallConstructor(internalClassName)) {
096: noConstructor = noConstructor.add(new TreeString(
097: internalClassName));
098: }
099: }
100: }
101: unavailable = unavailable.removeLike(new TreeString(REMOVE));
102: noConstructor = noConstructor
103: .removeLike(new TreeString(REMOVE));
104: if (unavailable != null) {
105: printHeader("UNAVAILABLE");
106: unavailable.traverse(new Visitor4() {
107: public void visit(Object obj) {
108: System.out.println(((TreeString) obj)._key);
109: }
110: });
111: }
112: if (noConstructor != null) {
113: printHeader("NO PUBLIC CONSTRUCTOR");
114: noConstructor.traverse(new Visitor4() {
115: public void visit(Object obj) {
116: System.out.println(((TreeString) obj)._key);
117: }
118: });
119: }
120:
121: printHeader("CLASSES");
122: System.out.println("Number of objects per class:");
123:
124: final Tree.ByRef ids = new Tree.ByRef(new TreeInt(0));
125:
126: if (internalClasses.length > 0) {
127: Tree all = new TreeStringObject(internalClasses[0]
128: .getName(), internalClasses[0]);
129: for (int i = 1; i < internalClasses.length; i++) {
130: all = all.add(new TreeStringObject(internalClasses[i]
131: .getName(), internalClasses[i]));
132: }
133: all.traverse(new Visitor4() {
134: public void visit(Object obj) {
135: TreeStringObject node = (TreeStringObject) obj;
136: long[] newIDs = ((StoredClass) node._object)
137: .getIDs();
138: for (int j = 0; j < newIDs.length; j++) {
139: if (ids.value
140: .find(new TreeInt((int) newIDs[j])) == null) {
141: ids.value = ids.value.add(new TreeInt(
142: (int) newIDs[j]));
143: }
144: }
145: System.out
146: .println(node._key + ": " + newIDs.length);
147: }
148: });
149:
150: }
151:
152: printHeader("SUMMARY");
153: System.out.println("File: " + filename);
154: System.out.println("Stored classes: " + internalClasses.length);
155: if (unavailable != null) {
156: System.out.println("Unavailable classes: "
157: + unavailable.size());
158: }
159: if (noConstructor != null) {
160: System.out.println("Classes without public constructors: "
161: + noConstructor.size());
162: }
163: System.out.println("Total number of objects: "
164: + (ids.value.size() - 1));
165: }
166:
167: private void printHeader(String str) {
168: int stars = (39 - str.length()) / 2;
169: System.out.println("\n");
170: for (int i = 0; i < stars; i++) {
171: System.out.print("*");
172: }
173: System.out.print(" " + str + " ");
174: for (int i = 0; i < stars; i++) {
175: System.out.print("*");
176: }
177: System.out.println();
178: }
179:
180: private static final String REMOVE = "XXxxREMOVExxXX";
181:
182: }
|