001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.objectserver.persistence.sleepycat;
006:
007: import com.tc.io.serializer.api.StringIndex;
008: import com.tc.logging.TCLogger;
009: import com.tc.logging.TCLogging;
010: import com.tc.object.ObjectID;
011: import com.tc.object.SerializationUtil;
012: import com.tc.object.tx.TransactionID;
013: import com.tc.objectserver.api.ObjectInstanceMonitor;
014: import com.tc.objectserver.core.api.ManagedObject;
015: import com.tc.objectserver.core.api.ManagedObjectState;
016: import com.tc.objectserver.core.api.TestDNA;
017: import com.tc.objectserver.core.api.TestDNACursor;
018: import com.tc.objectserver.impl.ObjectInstanceMonitorImpl;
019: import com.tc.objectserver.managedobject.BackReferences;
020: import com.tc.objectserver.managedobject.ManagedObjectImpl;
021: import com.tc.objectserver.managedobject.ManagedObjectStateFactory;
022: import com.tc.objectserver.managedobject.NullManagedObjectChangeListenerProvider;
023: import com.tc.objectserver.persistence.api.ManagedObjectPersistor;
024: import com.tc.objectserver.persistence.api.PersistenceTransaction;
025: import com.tc.objectserver.persistence.api.PersistenceTransactionProvider;
026: import com.tc.test.TCTestCase;
027:
028: import java.io.File;
029: import java.io.IOException;
030: import java.util.ArrayList;
031: import java.util.Date;
032: import java.util.HashMap;
033: import java.util.HashSet;
034: import java.util.Iterator;
035: import java.util.LinkedHashMap;
036: import java.util.Random;
037: import java.util.Set;
038: import java.util.TreeMap;
039: import java.util.TreeSet;
040:
041: /**
042: * XXX: This test needs to test more of the persistor interface.
043: */
044: public class SleepycatSerializationTest extends TCTestCase {
045: private SleepycatPersistor persistor;
046: private PersistenceTransactionProvider ptp;
047: private DBEnvironment env;
048: private ManagedObjectPersistor mop;
049: private TCLogger logger;
050: private StringIndex stringIndex;
051: private int transactionSequence;
052: private int objectIDSequence;
053: private Set rootIDs;
054: private Set rootNames;
055: private Set mos;
056: private ObjectInstanceMonitor imo;
057: private int version = 0;
058: private static int dbHomeCounter = 0;
059: private static File tempDirectory;
060:
061: public void setUp() throws Exception {
062: // XXX: This static temp directory is here to solve file problems
063: // on Windows. Each test spawns a new instance of the test class
064: // which causes a cleaning of the old temp directory which fails
065: // because the je lock file can't be removed because it's still open
066: // by sleepycat (sleepycat has a static cache).
067: // The static temp directory is here to stop subsequent test instances
068: // from trying to clean the temp directory and failing.
069: if (tempDirectory == null)
070: tempDirectory = getTempDirectory();
071: logger = TCLogging.getLogger(getClass());
072: rootIDs = new HashSet();
073: rootNames = new HashSet();
074: mos = new HashSet();
075: imo = new ObjectInstanceMonitorImpl();
076:
077: }
078:
079: public void tearDown() throws Exception {
080: persistor = null;
081: ptp = null;
082: env = null;
083: mop = null;
084: logger = null;
085: stringIndex = null;
086: rootIDs = null;
087: rootNames = null;
088: mos = null;
089: }
090:
091: public void testSleepycatSerializer() throws Exception {
092: SerializationAdapterFactory saf = new SleepycatSerializationAdapterFactory();
093: doTest(saf);
094: }
095:
096: public void testCustomSerializer() throws Exception {
097: SerializationAdapterFactory saf = new CustomSerializationAdapterFactory();
098: doTest(saf);
099: }
100:
101: public void doTest(SerializationAdapterFactory saf)
102: throws Exception {
103: File dbHome = newDBHome();
104: initDB(dbHome, saf);
105:
106: PersistenceTransaction ptx = ptp.newTransaction();
107:
108: String rootOne = "rootName";
109: ObjectID rootID = newObjectID();
110:
111: // add some roots and objects
112: addRoot(ptx, rootOne, rootID);
113:
114: for (int i = 0; i < 100; i++) {
115: ObjectID oid = newObjectID();
116: addRoot(ptx, "foo" + i, oid);
117: ManagedObject mo = newManagedObject(oid, i);
118: assertTrue(mo.isDirty());
119: mos.add(mo);
120: }
121: mop.saveAllObjects(ptx, mos);
122:
123: ManagedObject mo = newPhysicalObject(newObjectID());
124: mop.saveObject(ptx, mo);
125: mos.add(mo);
126:
127: mo = newLogicalDateObject(newObjectID());
128: mop.saveObject(ptx, mo);
129: mos.add(mo);
130:
131: ptx.commit();
132:
133: System.err.println("String index before: " + stringIndex);
134: initDB(dbHome, saf);
135:
136: System.err.println("String index after: " + stringIndex);
137:
138: assertEquals(rootID, mop.loadRootID(rootOne));
139: assertNotSame(rootID, mop.loadRootID(rootOne));
140: assertEquals(rootIDs, mop.loadRoots());
141: assertEquals(rootNames, mop.loadRootNames());
142:
143: for (Iterator i = mos.iterator(); i.hasNext();) {
144: ManagedObjectImpl test = (ManagedObjectImpl) i.next();
145: ManagedObjectImpl loaded = (ManagedObjectImpl) mop
146: .loadObjectByID(test.getID());
147: assertFalse(test.isDirty());
148: assertFalse(loaded.isDirty());
149: assertFalse(test.isNew());
150: assertFalse(loaded.isNew());
151: assertTrue(test.isEqual(loaded));
152: assertNotSame(test, loaded);
153: assertNotSame(mop.loadObjectByID(test.getID()), mop
154: .loadObjectByID(test.getID()));
155:
156: byte type = loaded.getManagedObjectState().getType();
157: switch (type) {
158: case ManagedObjectState.PHYSICAL_TYPE:
159: loaded.apply(newPhysicalDNA(true), new TransactionID(
160: ++transactionSequence), new BackReferences(),
161: imo, false);
162: break;
163: case ManagedObjectState.MAP_TYPE:
164: case ManagedObjectState.PARTIAL_MAP_TYPE:
165: loaded.apply(newLogicalMapDNA(true), new TransactionID(
166: ++transactionSequence), new BackReferences(),
167: imo, false);
168: break;
169: case ManagedObjectState.LIST_TYPE:
170: loaded.apply(newLogicalListDNA(true),
171: new TransactionID(++transactionSequence),
172: new BackReferences(), imo, false);
173: break;
174: case ManagedObjectState.SET_TYPE:
175: loaded.apply(newLogicalSetDNA(true), new TransactionID(
176: ++transactionSequence), new BackReferences(),
177: imo, false);
178: break;
179: case ManagedObjectState.ARRAY_TYPE:
180: loaded.apply(newLogicalArrayDNA(true),
181: new TransactionID(++transactionSequence),
182: new BackReferences(), imo, false);
183: break;
184: case ManagedObjectState.LINKED_HASHMAP_TYPE:
185: loaded.apply(newLogicalLinkedHashMapDNA(true),
186: new TransactionID(++transactionSequence),
187: new BackReferences(), imo, false);
188: break;
189: case ManagedObjectState.DATE_TYPE:
190: loaded.apply(newLogicalDateDNA(true),
191: new TransactionID(++transactionSequence),
192: new BackReferences(), imo, false);
193: break;
194: case ManagedObjectState.LITERAL_TYPE:
195: loaded.apply(newLiteralDNA(true), new TransactionID(
196: ++transactionSequence), new BackReferences(),
197: imo, false);
198: break;
199: case ManagedObjectState.TREE_MAP_TYPE:
200: loaded.apply(newLogicalTreeMapDNA(true),
201: new TransactionID(++transactionSequence),
202: new BackReferences(), imo, false);
203: break;
204: case ManagedObjectState.TREE_SET_TYPE:
205: loaded.apply(newLogicalTreeSetDNA(true),
206: new TransactionID(++transactionSequence),
207: new BackReferences(), imo, false);
208: break;
209: }
210:
211: }
212: }
213:
214: private ManagedObject newManagedObject(ObjectID oid, int i) {
215: switch (i % 10) {
216: case 0:
217: return newPhysicalObject(oid);
218: case 1:
219: return newLogicalMapObject(oid);
220: case 2:
221: return newLogicalArrayObject(oid);
222: case 3:
223: return newLogicalLiteralObject(oid);
224: case 4:
225: return newLogicalLinkedHashMapObject(oid);
226: case 5:
227: return newLogicalListObject(oid);
228: case 6:
229: return newLogicalSetObject(oid);
230: case 7:
231: return newLogicalTreeSetObject(oid);
232: case 8:
233: return newLogicalTreeMapObject(oid);
234: default:
235: return newLogicalDateObject(oid);
236: }
237: }
238:
239: private ManagedObject newLogicalTreeMapObject(ObjectID oid) {
240: return newLogicalObject(oid, newLogicalTreeMapDNA(false));
241: }
242:
243: private TestDNA newLogicalTreeMapDNA(boolean delta) {
244: TestDNACursor cursor = new TestDNACursor();
245: cursor.addLogicalAction(SerializationUtil.PUT, new Object[] {
246: new Short((short) 10), "good bad and ugly" });
247: cursor.addLogicalAction(SerializationUtil.PUT, new Object[] {
248: new Boolean(true), "mapped" });
249: cursor.addLogicalAction(SerializationUtil.PUT, new Object[] {
250: new Boolean(true), "Remapped" });
251: TestDNA dna = new TestDNA(cursor, TreeMap.class.getName());
252: dna.version = version++;
253: dna.isDelta = delta;
254: return dna;
255: }
256:
257: private ManagedObject newLogicalTreeSetObject(ObjectID oid) {
258: return newLogicalObject(oid, newLogicalTreeSetDNA(false));
259: }
260:
261: private TestDNA newLogicalTreeSetDNA(boolean delta) {
262: TestDNACursor cursor = new TestDNACursor();
263: cursor.addLogicalAction(SerializationUtil.ADD,
264: new Object[] { new Integer(10343) });
265: cursor.addLogicalAction(SerializationUtil.ADD,
266: new Object[] { "Hello" });
267: cursor.addLogicalAction(SerializationUtil.ADD,
268: new Object[] { new ObjectID(25) });
269: cursor.addLogicalAction(SerializationUtil.ADD,
270: new Object[] { newLong() });
271: TestDNA dna = new TestDNA(cursor, TreeSet.class.getName());
272: dna.version = version++;
273: dna.isDelta = delta;
274: return dna;
275: }
276:
277: private ManagedObject newLogicalSetObject(ObjectID oid) {
278: return newLogicalObject(oid, newLogicalSetDNA(false));
279: }
280:
281: private TestDNA newLogicalSetDNA(boolean delta) {
282: TestDNACursor cursor = new TestDNACursor();
283: cursor.addLogicalAction(SerializationUtil.ADD,
284: new Object[] { new Integer(10343) });
285: cursor.addLogicalAction(SerializationUtil.ADD,
286: new Object[] { "Hello" });
287: cursor.addLogicalAction(SerializationUtil.ADD,
288: new Object[] { new ObjectID(25) });
289: cursor.addLogicalAction(SerializationUtil.ADD,
290: new Object[] { newLong() });
291: TestDNA dna = new TestDNA(cursor, HashSet.class.getName());
292: dna.version = version++;
293: dna.isDelta = delta;
294: return dna;
295: }
296:
297: private ManagedObject newLogicalListObject(ObjectID oid) {
298: return newLogicalObject(oid, newLogicalListDNA(false));
299: }
300:
301: private TestDNA newLogicalListDNA(boolean delta) {
302: TestDNACursor cursor = new TestDNACursor();
303: cursor.addLogicalAction(SerializationUtil.ADD,
304: new Object[] { new Integer(10343) });
305: cursor.addLogicalAction(SerializationUtil.ADD,
306: new Object[] { "Hello" });
307: cursor.addLogicalAction(SerializationUtil.ADD,
308: new Object[] { new ObjectID(25) });
309: cursor.addLogicalAction(SerializationUtil.ADD,
310: new Object[] { newLong() });
311: TestDNA dna = new TestDNA(cursor, ArrayList.class.getName());
312: dna.version = version++;
313: dna.isDelta = delta;
314: return dna;
315: }
316:
317: private ManagedObject newLogicalLinkedHashMapObject(ObjectID oid) {
318: return newLogicalObject(oid, newLogicalLinkedHashMapDNA(false));
319: }
320:
321: private TestDNA newLogicalLinkedHashMapDNA(boolean delta) {
322: TestDNACursor cursor = new TestDNACursor();
323: cursor.addPhysicalAction("java.util.LinkedHashMap.accessOrder",
324: Boolean.TRUE);
325: cursor.addLogicalAction(SerializationUtil.PUT, new Object[] {
326: new Integer(10), "King Kong" });
327: cursor.addLogicalAction(SerializationUtil.PUT, new Object[] {
328: new Integer(20), "Mad Max" });
329: cursor.addLogicalAction(SerializationUtil.PUT, new Object[] {
330: new Integer(25), "Mummy Returns" });
331: cursor.addLogicalAction(SerializationUtil.GET,
332: new Object[] { new Integer(20) });
333: TestDNA dna = new TestDNA(cursor, LinkedHashMap.class.getName());
334: dna.version = version++;
335: dna.isDelta = delta;
336: return dna;
337: }
338:
339: private ManagedObject newLogicalLiteralObject(ObjectID oid) {
340: return newLogicalObject(oid, newLiteralDNA(false));
341: }
342:
343: private TestDNA newLiteralDNA(boolean delta) {
344: TestDNACursor cursor = new TestDNACursor();
345: Short s = new Short((short) 0x0045);
346: cursor.addLiteralAction("literal", s);
347: TestDNA dna = new TestDNA(cursor, Short.class.getName());
348: dna.version = version++;
349: dna.isDelta = delta;
350: return dna;
351: }
352:
353: private ManagedObject newLogicalArrayObject(ObjectID oid) {
354: return newLogicalObject(oid, newLogicalArrayDNA(false));
355: }
356:
357: private TestDNA newLogicalArrayDNA(boolean delta) {
358: TestDNACursor cursor = new TestDNACursor();
359: Object[] array = new Object[] { newLong(), newLong(), newLong() };
360: cursor.addArrayAction(array);
361: TestDNA dna = new TestDNA(cursor, array.getClass().getName());
362: dna.version = version++;
363: dna.isDelta = delta;
364: return dna;
365: }
366:
367: Random r = new Random();
368:
369: private Long newLong() {
370: return new Long(r.nextLong());
371: }
372:
373: private ManagedObject newLogicalDateObject(ObjectID objectID) {
374: return newLogicalObject(objectID, newLogicalDateDNA(false));
375: }
376:
377: private ManagedObject newLogicalObject(ObjectID objectID,
378: TestDNA dna) {
379: ManagedObjectImpl rv = new ManagedObjectImpl(objectID);
380: assertTrue(rv.isNew());
381: rv.apply(dna, new TransactionID(++transactionSequence),
382: new BackReferences(), imo, false);
383: assertFalse(rv.isNew());
384: return rv;
385: }
386:
387: private ManagedObject newLogicalMapObject(ObjectID oid) {
388: return newLogicalObject(oid, newLogicalMapDNA(false));
389: }
390:
391: private void addRoot(PersistenceTransaction ptx, String rootName,
392: ObjectID objectID) {
393: mop.addRoot(ptx, rootName, objectID);
394: rootIDs.add(objectID);
395: rootNames.add(rootName);
396: }
397:
398: private ObjectID newObjectID() {
399: return new ObjectID(++objectIDSequence);
400: }
401:
402: private ManagedObject newPhysicalObject(ObjectID objectID) {
403: ManagedObjectImpl rv = new ManagedObjectImpl(objectID);
404: TestDNA dna = newPhysicalDNA(false);
405: assertTrue(rv.isNew());
406: rv.apply(dna, new TransactionID(++transactionSequence),
407: new BackReferences(), imo, false);
408: assertFalse(rv.isNew());
409: return rv;
410: }
411:
412: private TestDNA newPhysicalDNA(boolean delta) {
413: TestDNACursor cursor = new TestDNACursor();
414: cursor.addPhysicalAction("stringField", "Foo");
415: cursor.addPhysicalAction("referenceField", newObjectID());
416: TestDNA dna = new TestDNA(cursor);
417: dna.version = version++;
418: dna.isDelta = delta;
419: return dna;
420: }
421:
422: private TestDNA newLogicalMapDNA(boolean delta) {
423: TestDNACursor cursor = new TestDNACursor();
424: cursor.addLogicalAction(SerializationUtil.PUT, new Object[] {
425: new Integer(10), "King Kong" });
426: cursor.addLogicalAction(SerializationUtil.PUT, new Object[] {
427: new Integer(20), "Mad Max" });
428: cursor.addLogicalAction(SerializationUtil.PUT, new Object[] {
429: new Integer(25), "Mummy Returns" });
430: TestDNA dna = new TestDNA(cursor, HashMap.class.getName());
431: dna.version = version++;
432: dna.isDelta = delta;
433: return dna;
434: }
435:
436: private TestDNA newLogicalDateDNA(boolean delta) {
437: TestDNACursor cursor = new TestDNACursor();
438: cursor.addLogicalAction(SerializationUtil.SET_TIME,
439: new Object[] { new Long(100233434L) });
440: TestDNA dna = new TestDNA(cursor, Date.class.getName());
441: dna.version = version++;
442: dna.isDelta = delta;
443: return dna;
444: }
445:
446: private File newDBHome() {
447: File file;
448: // XXX: UGH... this extra increment is here because of a weird interaction with the static cache of the sleepycat
449: // database and JUnit's test running junk, and something else I don't quite understand about the File.exists(). I
450: // had to add this to ensure that the db counter was actually incremented and that a new directory was actually
451: // used.
452: ++dbHomeCounter;
453: for (file = new File(tempDirectory, "db" + dbHomeCounter); file
454: .exists(); ++dbHomeCounter) {
455: //
456: }
457: assertFalse(file.exists());
458: return file;
459: }
460:
461: private void initDB(File dbHome, SerializationAdapterFactory saf)
462: throws IOException, TCDatabaseException {
463: if (env != null)
464: env.close();
465: env = new DBEnvironment(true, dbHome);
466: persistor = new SleepycatPersistor(logger, env, saf);
467: ptp = persistor.getPersistenceTransactionProvider();
468: mop = persistor.getManagedObjectPersistor();
469: stringIndex = persistor.getStringIndex();
470:
471: ManagedObjectStateFactory.disableSingleton(true);
472: ManagedObjectStateFactory.createInstance(
473: new NullManagedObjectChangeListenerProvider(),
474: persistor);
475:
476: }
477: }
|