001: /**
002: * Copyright (C) 2001-2004 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.speedo.runtime.tck;
018:
019: import org.objectweb.speedo.SpeedoTestHelper;
020: import org.objectweb.speedo.pobjects.basic.BasicA;
021: import org.objectweb.util.monolog.api.BasicLevel;
022: import org.objectweb.util.monolog.api.Logger;
023:
024: import java.io.FileInputStream;
025: import java.io.InputStream;
026: import java.util.Collection;
027: import java.util.Iterator;
028: import java.util.Properties;
029:
030: import javax.jdo.JDOHelper;
031: import javax.jdo.JDOUserException;
032: import javax.jdo.PersistenceManager;
033: import javax.jdo.PersistenceManagerFactory;
034: import javax.jdo.Query;
035: import javax.jdo.Transaction;
036:
037: import junit.framework.Assert;
038:
039: public class PersistenceManagerTck extends SpeedoTestHelper {
040:
041: public static final int TRANSIENT = 0;
042: public static final int PERSISTENT_NEW = 1;
043: public static final int PERSISTENT_CLEAN = 2;
044: public static final int PERSISTENT_DIRTY = 3;
045: public static final int HOLLOW = 4;
046: public static final int TRANSIENT_CLEAN = 5;
047: public static final int TRANSIENT_DIRTY = 6;
048: public static final int PERSISTENT_NEW_DELETED = 7;
049: public static final int PERSISTENT_DELETED = 8;
050: public static final int PERSISTENT_NONTRANSACTIONAL = 9;
051: public static final int NUM_STATES = 10;
052: public static final int ILLEGAL_STATE = 10;
053:
054: public static final String[] states = { "transient",
055: "persistent-new", "persistent-clean", "persistent-dirty",
056: "hollow", "transient-clean", "transient-dirty",
057: "persistent-new-deleted", "persistent-deleted",
058: "persistent-nontransactional", "illegal" };
059:
060: private static final int IS_PERSISTENT = 0;
061: private static final int IS_TRANSACTIONAL = 1;
062: private static final int IS_DIRTY = 2;
063: private static final int IS_NEW = 3;
064: private static final int IS_DELETED = 4;
065: private static final int NUM_STATUSES = 5;
066:
067: private static final boolean state_statuses[][] = {
068: // IS_PERSISTENT IS_TRANSACTIONAL IS_DIRTY IS_NEW IS_DELETED
069: // transient
070: { false, false, false, false, false },
071:
072: // persistent-new
073: { true, true, true, true, false },
074:
075: // persistent-clean
076: { true, true, false, false, false },
077:
078: // persistent-dirty
079: { true, true, true, false, false },
080:
081: // hollow
082: { true, false, false, false, false },
083:
084: // transient-clean
085: { false, true, false, false, false },
086:
087: // transient-dirty
088: { false, true, true, false, false },
089:
090: // persistent-new-deleted
091: { true, true, true, true, true },
092:
093: // persistent-deleted
094: { true, true, true, false, true },
095:
096: // persistent-nontransactional
097: { true, false, false, false, false } };
098:
099: /**
100: *This utility method returns a <code>String</code> that indicates the current state of an instance.
101: *@param o The object.
102: *@return The current state of the instance, by using the <code>JDOHelper</code> state
103: *interrogation methods.
104: */
105: public static String getStateOfInstance(Object o) {
106: boolean existingEntries = false;
107: StringBuffer buff = new StringBuffer("{");
108: if (JDOHelper.isPersistent(o)) {
109: buff.append("persistent");
110: existingEntries = true;
111: }
112: if (JDOHelper.isTransactional(o)) {
113: if (existingEntries)
114: buff.append(", ");
115: buff.append("transactional");
116: existingEntries = true;
117: }
118: if (JDOHelper.isDirty(o)) {
119: if (existingEntries)
120: buff.append(", ");
121: buff.append("dirty");
122: existingEntries = true;
123: }
124: if (JDOHelper.isNew(o)) {
125: if (existingEntries)
126: buff.append(", ");
127: buff.append("new");
128: existingEntries = true;
129: }
130: if (JDOHelper.isDeleted(o)) {
131: if (existingEntries)
132: buff.append(", ");
133: buff.append("deleted");
134: }
135: buff.append("}");
136: return buff.toString();
137: }
138:
139: public static int currentState(Object o) {
140: boolean[] status = new boolean[5];
141: status[IS_PERSISTENT] = JDOHelper.isPersistent(o);
142: status[IS_TRANSACTIONAL] = JDOHelper.isTransactional(o);
143: status[IS_DIRTY] = JDOHelper.isDirty(o);
144: status[IS_NEW] = JDOHelper.isNew(o);
145: status[IS_DELETED] = JDOHelper.isDeleted(o);
146: int i, j;
147: outerloop: for (i = 0; i < NUM_STATES; ++i) {
148: for (j = 0; j < NUM_STATUSES; ++j) {
149: if (status[j] != state_statuses[i][j])
150: continue outerloop;
151: }
152: return i;
153: }
154: return NUM_STATES;
155: }
156:
157: // These values MUST correspond to index in sorted array below.
158: private static final int OPTION_APPLICATIONIDENTITY = 0;
159: private static final int OPTION_ARRAY = 1;
160: private static final int OPTION_ARRAYLIST = 2;
161: private static final int OPTION_CHANGEAPPLICATIONIDENTITY = 3;
162: private static final int OPTION_DATASTOREIDENTITY = 4;
163: private static final int OPTION_HASHMAP = 5;
164: private static final int OPTION_HASHTABLE = 6;
165: private static final int OPTION_LINKEDLIST = 7;
166: private static final int OPTION_LIST = 8;
167: private static final int OPTION_MAP = 9;
168: private static final int OPTION_NONDURABLEIDENTITY = 10;
169: private static final int OPTION_NONTRANSACTIONALREAD = 11;
170: private static final int OPTION_NONTRANSACTIONALWRITE = 12;
171: private static final int OPTION_NULLCOLLECTION = 13;
172: private static final int OPTION_OPTIMISTIC = 14;
173: private static final int OPTION_RETAINVALUES = 15;
174: private static final int OPTION_TRANSIENTTRANSACTIONAL = 16;
175: private static final int OPTION_TREEMAP = 17;
176: private static final int OPTION_TREESET = 18;
177: private static final int OPTION_VECTOR = 19;
178:
179: private static boolean[] options = new boolean[OPTION_VECTOR + 1];
180:
181: static {
182: for (int i = 0; i < OPTION_VECTOR + 1; i++)
183: options[i] = true;
184:
185: options[OPTION_CHANGEAPPLICATIONIDENTITY] = false;
186: options[OPTION_NONDURABLEIDENTITY] = false;
187: }
188:
189: /**
190: * Reports whether Optimistic is supported.
191: */
192: public static boolean isOptimisticSupported() {
193: return options[OPTION_OPTIMISTIC];
194: }
195:
196: static PersistenceManager pm10 = null;
197: static PersistenceManager pm20 = null;
198:
199: BasicA ba1 = null;
200: BasicA ba2 = null;
201: BasicA ba3 = null;
202: BasicA ba4 = null;
203: BasicA ba5 = null;
204: private PersistenceManager pm;
205: private Transaction tx;
206:
207: BasicA b1 = null;
208: private int totalThreadCount = 10;
209: private int completedThreadCount = 0;
210: private int succeeds = 0;
211: private int catchNumber = 0;
212:
213: public PersistenceManagerTck(String s) {
214: super (s);
215: }
216:
217: protected String getLoggerName() {
218: return LOG_NAME + ".rt.tck.PersistenceManagerTck";
219: }
220:
221: protected PersistenceManager getPM() {
222: if (pm == null) {
223: pm = getPMF().getPersistenceManager();
224: }
225: return pm;
226: }
227:
228: protected void closePM() {
229: if (pm != null) {
230: pm.close();
231: pm = null;
232: }
233: }
234:
235: /*
236: private void createObjects() {
237: try {
238:
239: getPM().currentTransaction().begin();
240: ba1 = new BasicA();
241: ba2 = new BasicA();
242: ba3 = new BasicA();
243: ba4 = new BasicA();
244: ba5 = new BasicA();
245:
246: getPM().makePersistent(ba1);
247: getPM().makePersistent(ba2);
248: getPM().makePersistent(ba3);
249: getPM().makePersistent(ba4);
250: getPM().makePersistent(ba5);
251:
252: getPM().currentTransaction().commit();
253:
254: } catch (Exception ex) {
255: logger.log(BasicLevel.ERROR, "Unexception caught in createObjects", ex);
256: closePM();
257: fail(ex.getMessage());
258: }
259: }
260: */
261:
262: public void testConcurrentPersistenceManagersSameClasses() {
263:
264: logger.log(BasicLevel.INFO,
265: "testConcurrentPersistenceManagersSameClasses");
266: Properties pmfProperties = loadPMF2Properties();
267: PersistenceManagerFactory pmf2 = JDOHelper
268: .getPersistenceManagerFactory(pmfProperties);
269: PersistenceManager pm2 = pmf2.getPersistenceManager();
270: logger.log(BasicLevel.DEBUG, "begin getTransactions");
271: Transaction tx2 = pm2.currentTransaction();
272: tx = getPM().currentTransaction();
273: logger.log(BasicLevel.DEBUG, "begin initData");
274: tx.begin();
275: tx2.begin();
276:
277: BasicA ba11 = new BasicA();
278: ba11.writeF1("ba11");
279: BasicA ba12 = new BasicA();
280: ba11.writeF1("ba12");
281:
282: getPM().makePersistent(ba11);
283: getPM().makePersistent(ba12);
284:
285: BasicA ba21 = new BasicA();
286: ba11.writeF1("ba21");
287: BasicA ba22 = new BasicA();
288: ba11.writeF1("ba22");
289:
290: pm2.makePersistent(ba21);
291: pm2.makePersistent(ba22);
292:
293: tx.commit();
294: tx2.commit();
295:
296: logger.log(BasicLevel.DEBUG, "begin test");
297: tx.begin();
298: tx2.begin();
299:
300: BasicA ba11a = findBasicA(pm, "ba11");
301: Assert.assertEquals(ba11a, ba11);
302:
303: BasicA ba21a = findBasicA(pm2, "ba21");
304: Assert.assertEquals(ba21a, ba21);
305:
306: tx.commit();
307: tx2.commit();
308:
309: closePM();
310: pm2.close();
311:
312: logger
313: .log(BasicLevel.DEBUG,
314: "passed in testConcurrentPersistenceManagersSameClasses");
315:
316: }
317:
318: Properties loadPMF2Properties() {
319: /*
320: String PMF2 = System.getProperty("PMF2Properties", "c:\\jdotck\\jdori2.properties");
321: logger.log(BasicLevel.DEBUG, "Got PMF2Properties file name:" + PMF2);
322: Properties ret = loadProperties(PMF2);
323: logger.log(BasicLevel.DEBUG, "Got PMF2Properties: " + ret);
324: */
325: return getPMFPropertiesFromFile();
326: }
327:
328: BasicA findBasicA(PersistenceManager pm, String param) {
329: Query q = pm.newQuery(BasicA.class);
330: q.declareParameters("String param");
331: q.setFilter("(param == f1)");
332: Collection results = (Collection) q.execute(param);
333: Iterator it = results.iterator();
334: BasicA ret = (BasicA) it.next();
335: return ret;
336: }
337:
338: /**
339: * This method load Properties from a given file.
340: */
341: protected Properties loadProperties(String fileName) {
342: if (fileName == null) {
343: fileName = System.getProperty("user.dir")
344: + "/jdori2.properties";
345: }
346: Properties props = new Properties();
347: InputStream propStream = null;
348: try {
349: propStream = new FileInputStream(fileName);
350: } catch (java.io.IOException ex) {
351: logger.log(BasicLevel.ERROR,
352: "Could not open properties file \"" + fileName
353: + "\"");
354: logger
355: .log(
356: BasicLevel.ERROR,
357: "Please specify PMF properties file name"
358: + " -PMFProperties argument (defaults to {user.dir}/jdori2.properties)");
359: System.exit(1);
360: }
361: try {
362: props.load(propStream);
363: } catch (java.io.IOException ex) {
364: logger.log(BasicLevel.ERROR,
365: "Error loading properties file \"" + fileName
366: + "\"", ex);
367: System.exit(1);
368: }
369: return props;
370: }
371:
372: public void testDeletePersistentFailsIfInstanceManagedByAnotherPersistenceManager() {
373: logger
374: .log(BasicLevel.INFO,
375: "testDeletePersistentFailsIfInstanceManagedByAnotherPersistenceManager");
376: pmf = getPMF();
377: PersistenceManager pm1 = pmf.getPersistenceManager();
378: PersistenceManager pm2 = pmf.getPersistenceManager();
379:
380: Assert.assertTrue("same persistence manager", !pm1.equals(pm2));
381:
382: try {
383:
384: pm1.currentTransaction().begin();
385: ba1 = new BasicA();
386: ba2 = new BasicA();
387: ba3 = new BasicA();
388: ba4 = new BasicA();
389: ba5 = new BasicA();
390:
391: pm1.makePersistent(ba1);
392: pm1.makePersistent(ba2);
393: pm1.makePersistent(ba3);
394: pm1.makePersistent(ba4);
395: pm1.makePersistent(ba5);
396: pm = JDOHelper.getPersistenceManager(ba1);
397: logger.log(BasicLevel.DEBUG, "before commit pm=" + pm);
398: pm1.currentTransaction().commit();
399: pm = JDOHelper.getPersistenceManager(ba1);
400: logger.log(BasicLevel.DEBUG, "after commit pm=" + pm);
401:
402: } catch (Exception ex) {
403: logger
404: .log(
405: BasicLevel.ERROR,
406: "Unexception caught in testDeletePersistentFailsIfInstanceManagedByAnotherPersistenceManager",
407: ex);
408: pm1.close();
409: pm2.close();
410: fail(ex.getMessage());
411: }
412:
413: /* test deletePersistent (Object pc) */
414: try {
415:
416: pm2.currentTransaction().begin();
417: pm = JDOHelper.getPersistenceManager(ba1);
418: logger.log(BasicLevel.DEBUG, "pm1=" + pm1 + " pm=" + pm);
419: Assert.assertTrue("not same persistence manager 1", pm1
420: .equals(pm));
421: pm2.deletePersistent(ba1);
422: logger.log(BasicLevel.DEBUG, "pm2=" + pm2 + " pm=" + pm);
423:
424: throw new Exception(
425: "FAILED in deletePersistentPM2() - should not go that further");
426: } catch (Exception ex) {
427: if (ex instanceof JDOUserException) {
428: ; // expected result
429: } else {
430: logger
431: .log(
432: BasicLevel.ERROR,
433: "Unexception caught in deletePersistentPM2",
434: ex);
435:
436: }
437: pm2.currentTransaction().rollback();
438: }
439:
440: /* test deletePersistentAll (Collection pcs) */
441: try {
442: pm2.currentTransaction().begin();
443:
444: Collection col1 = new java.util.HashSet();
445: col1.add(ba2);
446: col1.add(ba3);
447:
448: pm2.deletePersistentAll(col1);
449:
450: throw new Exception(
451: "FAILED in deletePersistentAll1() - should not go that further");
452: } catch (Exception ex) {
453: if (ex instanceof JDOUserException) {
454: ; // expected result
455: } else {
456: logger.log(BasicLevel.ERROR,
457: "Unexception caught in deletePersistentAll1",
458: ex);
459: }
460: pm2.currentTransaction().rollback();
461: }
462:
463: /* test deletePersistentAll (Object[] o) */
464: try {
465:
466: pm2.currentTransaction().begin();
467:
468: Collection col1 = new java.util.HashSet();
469: col1.add(ba4);
470: col1.add(ba5);
471:
472: Object[] obj1 = col1.toArray();
473:
474: pm2.deletePersistentAll(obj1);
475:
476: throw new Exception(
477: "FAILED in deletePersistentAll2() - should not go that further");
478: } catch (Exception ex) {
479: if (ex instanceof JDOUserException) {
480: ; // expected result
481: } else {
482: logger.log(BasicLevel.ERROR,
483: "Unexception caught in deletePersistentAll2",
484: ex);
485: }
486: pm2.currentTransaction().rollback();
487: }
488:
489: logger
490: .log(
491: BasicLevel.DEBUG,
492: "passed in testDeletePersistentFailsIfInstanceManagedByAnotherPersistenceManager");
493:
494: pm1.close();
495: pm2.close();
496:
497: }
498:
499: public void testOneInstanceOfObjectPerPersistenceManager() {
500: logger.log(BasicLevel.INFO,
501: "testOneInstanceOfObjectPerPersistenceManager");
502: tx = getPM().currentTransaction();
503: //tx.setRetainValues(false);
504: tx.setRestoreValues(false);
505:
506: tx.begin();
507: BasicA ba11 = new BasicA();
508: ba11.writeF1("ba11");
509: getPM().makePersistent(ba11);
510: tx.commit();
511:
512: tx.begin();
513: Object p1Id = getPM().getObjectId(ba11);
514: BasicA ba11a = (BasicA) getPM().getObjectById(p1Id, true);
515: BasicA ba11c = findBasicA(getPM(), "ba11");
516: tx.commit();
517: closePM();
518:
519: Assert
520: .assertEquals(
521: "Assertion A5.4-2 failed; getObjectById results differ",
522: ba11a, ba11);
523: Assert.assertEquals(
524: "Assertion A5.4-2 failed; query results differ", ba11c,
525: ba11);
526: tx = getPM().currentTransaction();
527: tx.begin();
528: getPM().deletePersistent(ba11);
529: tx.commit();
530: closePM();
531:
532: logger
533: .log(BasicLevel.DEBUG,
534: "passed in testOneInstanceOfObjectPerPersistenceManager");
535: }
536:
537: public void testRefreshAllWithNoParameters() {
538: logger.log(BasicLevel.INFO, "testRefreshAllWithNoParameters");
539: tx = getPM().currentTransaction();
540: tx.begin();
541: BasicA ba11 = new BasicA();
542: ba11.writeF1("ba11");
543: ba11.writeF2(200);
544: getPM().makePersistent(ba11);
545: tx.commit();
546:
547: tx.begin();
548: ba11.writeF1("xx");
549: //ba11.writeF2(800);
550:
551: /*
552: * Collection col1 = new java.util.HashSet(); col1.add(ba11); try { getPM().refresh(ba11); } catch (Exception
553: * ex) { logger.log(BasicLevel.DEBUG, "passed in refresh(ba11)" + ex.getMessage()); }
554: *
555: * try { getPM().refresh(col1); } catch (Exception ex) { logger.log(BasicLevel.DEBUG, "passed in refresh(col1)" +
556: * ex.getMessage()); }
557: */
558: getPM().refreshAll();
559:
560: Assert.assertEquals(
561: "Assertion A12.5.1-6 failed; values not refreshed",
562: ba11.readF1(), "ba11");
563: Assert.assertEquals(
564: "Assertion A12.5.1-6 failed; values not refreshed",
565: ba11.readF2(), 200);
566: tx.commit();
567: closePM();
568: logger.log(BasicLevel.DEBUG,
569: "passed in testRefreshAllWithNoParameters");
570: }
571:
572: public void testThreadSafe() {
573: logger.log(BasicLevel.INFO, "testThreadSafe");
574: try {
575:
576: /**
577: * The implementation must synchronize instances of PersistenceCapable during state transitions that
578: * replace the StateManager. This is to avoid race conditions where the application attempts to make the
579: * same instance persistent in multiple PersistenceManagers.
580: */
581:
582: b1 = new BasicA();
583: for (int i = 0; i < totalThreadCount; i++) {
584: Thread t = new Thread(new PMThread(pmf, b1, this ));
585: t.setName("ThreadSafeID-" + i);
586: t.start();
587: }
588:
589: while (totalThreadCount != completedThreadCount) {
590: try {
591: Thread.sleep(100);
592: } catch (InterruptedException ex) {
593: logger.log(BasicLevel.INFO, "interrupted");
594: }
595: }
596:
597: //logger.log(BasicLevel.DEBUG, "succeeds=" + succeeds + " catchNumber=" + catchNumber);
598:
599: /**
600: * Only the first thread may
601: */
602: Assert
603: .assertTrue(
604: "Failed: succeeds = " + succeeds
605: + " catchNumber = " + catchNumber,
606: ((succeeds == 1) && (catchNumber == totalThreadCount - 1)));
607:
608: } catch (Exception ex) {
609: logger.log(BasicLevel.ERROR,
610: "Unexception caught in testThreadSafe", ex);
611: fail(ex.getMessage());
612: }
613:
614: }
615:
616: protected synchronized void complete() {
617: completedThreadCount++;
618: }
619:
620: protected synchronized void winning(BasicA pc) {
621: logger.log(BasicLevel.DEBUG, "*** ThreadID : "
622: + Thread.currentThread().getName() + " succeeds");
623: succeeds++;
624: }
625:
626: class PMThread implements Runnable {
627: private final PersistenceManager pm;
628: private final Object pc;
629: private final PersistenceManagerTck owner;
630:
631: PMThread(PersistenceManagerFactory pmf, BasicA pc,
632: PersistenceManagerTck owner) {
633:
634: this .pm = pmf.getPersistenceManager(); // should return different pm
635: this .pc = pc;
636: this .owner = owner;
637: }
638:
639: public void run() {
640: Transaction tx = null;
641: try {
642: logger.log(BasicLevel.DEBUG, " Running thread: "
643: + Thread.currentThread().getName());
644: // the application attempts to make the same instance persistent in multiple PersistenceManagers.
645: tx = pm.currentTransaction();
646: tx.begin();
647: logger.log(BasicLevel.DEBUG,
648: "before makePersistent pm=" + pm);
649: pm.makePersistent(pc);
650: logger.log(BasicLevel.DEBUG, "after makePersistent pm="
651: + JDOHelper.getPersistenceManager(pc));
652: tx.commit();
653: winning((BasicA) pc);
654: complete();
655:
656: while (totalThreadCount != completedThreadCount) {
657: try {
658: Thread.sleep(100);
659: } catch (InterruptedException ex) {
660: logger.log(BasicLevel.INFO, "interrupted");
661: }
662: }
663: } catch (Exception ex) {
664: catchNumber++;
665: if (ex instanceof JDOUserException) {
666: logger.log(BasicLevel.DEBUG,
667: "JDOUserException caught in PMThread.run()"
668: + Thread.currentThread().getName(),
669: ex);
670: ; // expected result
671: } else {
672: logger.log(BasicLevel.ERROR,
673: "Unexception caught in PMThread.run()"
674: + Thread.currentThread().getName(),
675: ex);
676: }
677: complete();
678: } finally {
679: try {
680: if (tx.isActive()) {
681: tx.rollback();
682: }
683: pm.close();
684: } catch (Exception fex) {
685: logger.log(BasicLevel.ERROR,
686: "Unexception caught in PMThread()", fex);
687: }
688: }
689: } // run
690:
691: } // class PMThread
692:
693: public Object createBasicAInstance() {
694: try {
695: BasicA p1 = new BasicA();
696: pm = getPM();
697:
698: tx = pm.currentTransaction();
699: tx.begin();
700: pm.makePersistent(p1);
701: Object oid = pm.getObjectId(p1);
702: tx.commit();
703: return oid;
704: } catch (Exception ex) {
705: logger.log(BasicLevel.ERROR,
706: "Unexception caught in createPCPointInstance", ex);
707: return null;
708: }
709: }
710:
711: public void testGetObjectById() {
712: logger.log(BasicLevel.INFO, "testGetObjectById");
713: try {
714:
715: Object oid = createBasicAInstance();
716:
717: // nontransactional access
718: logger.log(BasicLevel.DEBUG, "nontransactional");
719: pm = null; // make sure to get a different pm so obj is not in cache
720: tx = getPM().currentTransaction();
721: tx.setNontransactionalRead(true);
722: Object obj = pm.getObjectById(oid, true);
723: int state = currentState(obj);
724: if (state != PERSISTENT_NONTRANSACTIONAL & state != HOLLOW) {
725: //incrementErrorCount();
726: logger.log(BasicLevel.ERROR,
727: "Expected persistent-nontransactional or hollow; got "
728: + getStateOfInstance(obj));
729: }
730:
731: // pessimistic transactional access
732: logger.log(BasicLevel.DEBUG, "pessimistic");
733: pm = null; // make sure to get a different pm so obj is not in cache
734: tx = getPM().currentTransaction();
735: tx.setOptimistic(false);
736: tx.begin();
737: obj = pm.getObjectById(oid, true);
738: state = currentState(obj);
739: tx.commit();
740: if (state != PERSISTENT_CLEAN) {
741: //incrementErrorCount();
742: logger.log(BasicLevel.ERROR,
743: "Expected persistent-clean; got "
744: + getStateOfInstance(obj));
745: }
746:
747: // optimistic transactional access
748: if (isOptimisticSupported()) {
749: logger.log(BasicLevel.DEBUG, "optimistic");
750: pm = null; // make sure to get a different pm so obj is not in cache
751: tx = getPM().currentTransaction();
752: tx.setOptimistic(true);
753: tx.begin();
754: obj = pm.getObjectById(oid, true);
755: state = currentState(obj);
756: tx.commit();
757: if (state != PERSISTENT_NONTRANSACTIONAL
758: & state != HOLLOW) {
759: //incrementErrorCount();
760: logger.log(BasicLevel.ERROR,
761: "Expected persistent-nontransactional; got "
762: + state + getStateOfInstance(obj));
763: }
764: } else {
765: logger.log(BasicLevel.INFO, "optimistic test skipped");
766: }
767: } catch (Exception ex) {
768: logger.log(BasicLevel.ERROR,
769: "Unexception caught in testGetObjectById", ex);
770: fail(ex.getMessage());
771: }
772: }
773:
774: public void testRefreshSideEffects() {
775: logger.log(BasicLevel.INFO, "testRefreshSideEffects");
776:
777: pm10 = getPMF().getPersistenceManager();
778: pm20 = getPMF().getPersistenceManager();
779:
780: try {
781:
782: RefreshThreadT1 thread1 = new RefreshThreadT1(logger);
783: Thread T1 = new Thread(thread1);
784: RefreshThreadT2 thread2 = new RefreshThreadT2(logger);
785: Thread T2 = new Thread(thread2);
786:
787: T1.start();
788: T2.start();
789:
790: T1.join();
791: T2.join();
792:
793: logger.log(BasicLevel.DEBUG, "thread1.state="
794: + thread1.state);
795: logger.log(BasicLevel.DEBUG, "thread2.state="
796: + thread2.state);
797: if (thread1.state != 1 || thread2.state != 1)
798: logger.log(BasicLevel.ERROR,
799: "RefreshSideEffects: thread1.state="
800: + thread1.state + " thread2.state="
801: + thread2.state);
802: //incrementErrorCount();
803:
804: } catch (Exception ex) {
805: logger.log(BasicLevel.ERROR,
806: "Unexception caught in testRefreshSideEffects", ex);
807: fail(ex.getMessage());
808: }
809:
810: }
811:
812: }
813:
814: class RefreshThreadT1 implements Runnable {
815:
816: volatile int state = 0;
817: static final int DELAY = 100;
818: static boolean commitDone = false;
819: static boolean doneFlag = false;
820: Transaction tx1 = null;
821: Logger logger = null;
822: static BasicA n1 = new BasicA();
823:
824: RefreshThreadT1(Logger logger) {
825: tx1 = PersistenceManagerTck.pm10.currentTransaction();
826: tx1.setOptimistic(true);
827: this .logger = logger;
828:
829: }
830:
831: public static void initVariables() {
832: commitDone = false;
833: doneFlag = false;
834: }
835:
836: synchronized public void run() {
837: try {
838: state = 1;
839: tx1.begin();
840: n1.writeF2(500);
841: PersistenceManagerTck.pm10.makePersistent(n1);
842: PersistenceManagerTck.pm10.refresh(n1);
843:
844: while (!RefreshThreadT2.doneFlag) {
845: Thread.sleep(DELAY);
846: }
847:
848: tx1.commit();
849: commitDone = true;
850:
851: } catch (Exception ex) {
852: //out.println (" Exception in T1 run ");
853: //ex.printStackTrace(out);
854: state = 13;
855: logger.log(BasicLevel.ERROR,
856: "Unexception caught in RefreshThreadT1", ex);
857: }
858: }
859:
860: }
861:
862: class RefreshThreadT2 implements Runnable {
863:
864: volatile int state = 0;
865: static final int DELAY = 100;
866: static boolean commitDone = false;
867: static boolean doneFlag = false;
868: Transaction tx2 = null;
869: Logger logger = null;
870: static BasicA p1 = new BasicA();
871:
872: RefreshThreadT2(Logger logger) {
873: tx2 = PersistenceManagerTck.pm20.currentTransaction();
874: tx2.setOptimistic(true);
875: this .logger = logger;
876: }
877:
878: public static void initVariables() {
879: commitDone = false;
880: doneFlag = false;
881: }
882:
883: /* test refresh() */
884: synchronized public void run() {
885: try {
886: state = 1;
887: tx2.begin();
888: p1.writeF2(201);
889: PersistenceManagerTck.pm20.makePersistent(p1);
890: PersistenceManagerTck.pm20.refresh(p1);
891: doneFlag = true;
892:
893: while (!RefreshThreadT1.commitDone) {
894: Thread.sleep(DELAY);
895:
896: }
897: tx2.commit();
898: commitDone = true;
899:
900: } catch (Exception ex) {
901: state = 10;
902: logger.log(BasicLevel.ERROR,
903: "Unexception caught in RefreshThreadT2", ex);
904: }
905: }
906:
907: }
|