001: /**
002: * Copyright (C) 2006 NetMind Consulting Bt.
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 3 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 hu.netmind.persistence;
018:
019: import java.util.*;
020: import org.apache.log4j.Logger;
021: import java.sql.Connection;
022: import java.sql.PreparedStatement;
023: import hu.netmind.persistence.node.*;
024:
025: /**
026: * Node tests.
027: * @author Brautigam Robert
028: * @version Revision: $Revision$
029: */
030: public class NodeTests extends AbstractPersistenceTest {
031: private static Logger logger = Logger.getLogger(NodeTests.class);
032:
033: public NodeTests(String name) throws Exception {
034: super (name);
035: }
036:
037: private void addNode(int index, String ips, int port)
038: throws Exception {
039: PreparedStatement pstmt = getConnection().prepareStatement(
040: "insert into nodes (heartbeat,nodeindex,ips,command_port) values (1,"
041: + index + ",'" + ips + "'," + port + ")");
042: int rows = pstmt.executeUpdate();
043: pstmt.close();
044: getConnection().commit();
045: assertEquals(1, rows);
046: }
047:
048: public void testNodesConcept() throws Exception {
049: // Drop
050: dropTables("book");
051: Store store2 = getStore();
052: try {
053: // Create
054: Book book = new Book("The Concept of Nodes", "1-2");
055: logger.debug("saving book...");
056: store.save(book);
057: logger.debug("book saved.");
058: // Create in the other node too (or else the class will not
059: // be known)
060: store2.save(new Book("The Class", "1"));
061: // Get back from the other node
062: logger.debug("executing query...");
063: List books = store2.find("find book");
064: logger.debug("query returned.");
065: // Check stuff
066: assertEquals(2, books.size());
067: } finally {
068: store2.close();
069: }
070: }
071:
072: public void testMultipleNodesConcept() throws Exception {
073: // Drop
074: dropTables("book");
075: Store stores[] = new Store[10];
076: for (int i = 0; i < stores.length; i++)
077: stores[i] = getStore();
078: try {
079: // Create
080: for (int i = 0; i < stores.length; i++) {
081: Book book = new Book("The Concept of Nodes", "1-2");
082: logger.debug("saving book #" + i + "...");
083: stores[i].save(book);
084: logger.debug("book saved.");
085: }
086: // Get back from the other node
087: logger.debug("executing query...");
088: List books = store.find("find book");
089: logger.debug("query returned.");
090: // Check stuff
091: assertEquals(stores.length, books.size());
092: } finally {
093: for (int i = 0; i < stores.length; i++)
094: stores[i].close();
095: }
096: }
097:
098: public void testNodeCleanup() throws Exception {
099: int oldCount = getCount("nodes");
100: // Allocate new store, and close it
101: Store store2 = getStore();
102: assertEquals(oldCount + 1, getCount("nodes"));
103: store2.close();
104: assertEquals(oldCount, getCount("nodes"));
105: }
106:
107: public void testCacheUpdateEvents() throws Exception {
108: // Drop books
109: dropTables("book");
110: // Allocate second store
111: Store store2 = getStore();
112: try {
113: // Get second store to cache the result on books
114: Transaction tx = store2.getTransactionTracker()
115: .getTransaction(TransactionTracker.TX_REQUIRED);
116: tx.begin();
117: List result = store2.find("find book");
118: result.size(); // Force load
119: tx.commit();
120: assertEquals(1, tx.getStats().getSelectCount());
121: // Second query should not make any phisical statements
122: tx = store2.getTransactionTracker().getTransaction(
123: TransactionTracker.TX_REQUIRED);
124: tx.begin();
125: result = store2.find("find book");
126: result.size(); // Force load
127: tx.commit();
128: assertEquals(0, tx.getStats().getSelectCount());
129: // Now the first store will update the books
130: store
131: .save(new Book("Learn Cache Update In Seven Days",
132: "1"));
133: // A query after this update should again yield a physical query
134: tx = store2.getTransactionTracker().getTransaction(
135: TransactionTracker.TX_REQUIRED);
136: tx.begin();
137: result = store2.find("find book");
138: result.size(); // Force load
139: tx.commit();
140: assertEquals(1, tx.getStats().getSelectCount());
141: } finally {
142: store2.close();
143: }
144: }
145:
146: public void testCacheWhenReconnect() throws Exception {
147: // Drop books
148: dropTables("book");
149: // Allocate second store
150: Store store2 = getStore();
151: try {
152: // Get second store to cache the result on books
153: Transaction tx = store2.getTransactionTracker()
154: .getTransaction(TransactionTracker.TX_REQUIRED);
155: tx.begin();
156: List result = store2.find("find book");
157: result.size(); // Force load
158: tx.commit();
159: assertEquals(1, tx.getStats().getSelectCount());
160: // Second query should not make any phisical statements
161: tx = store2.getTransactionTracker().getTransaction(
162: TransactionTracker.TX_REQUIRED);
163: tx.begin();
164: result = store2.find("find book");
165: result.size(); // Force load
166: tx.commit();
167: assertEquals(0, tx.getStats().getSelectCount());
168: // Now the first store (which is the server) will be shut down,
169: // and re-inited. This means, this client should empty the cache
170: store.close();
171: store = getStore();
172: // A query after this update should again yield a physical query
173: tx = store2.getTransactionTracker().getTransaction(
174: TransactionTracker.TX_REQUIRED);
175: tx.begin();
176: result = store2.find("find book");
177: result.size(); // Force load
178: tx.commit();
179: assertEquals(1, tx.getStats().getSelectCount());
180: } finally {
181: store2.close();
182: }
183: }
184:
185: public void testLockFromClientNode() throws Exception {
186: // Drop books
187: dropTables("book");
188: // Allocate second store
189: Store store2 = getStore();
190: try {
191: // Insert a book
192: Book originalBook = new Book("Necronomicon", "999");
193: store.save(originalBook);
194: // Start a transaction to that book in the first store
195: Transaction tx = store.getTransactionTracker()
196: .getTransaction(TransactionTracker.TX_REQUIRED);
197: tx.begin();
198: Book bookInstance1 = (Book) store.findSingle("find book");
199: bookInstance1.setTitle("Store 1's Book");
200: store.save(bookInstance1);
201: // Try to modify in the second transaction
202: Transaction tx2 = store2.getTransactionTracker()
203: .getTransaction(TransactionTracker.TX_REQUIRED);
204: tx2.begin();
205: Book bookInstance2 = (Book) store2.findSingle("find book");
206: bookInstance2.setTitle("Store 2's Book");
207: try {
208: store2.save(bookInstance2);
209: fail("I could modify the same object in another store.");
210: } catch (ConcurrentModificationException e) {
211: // Ok, this should be
212: }
213: // Close all
214: tx2.commit();
215: tx.commit();
216: } finally {
217: store2.close();
218: }
219: }
220:
221: public void testLockFromServerNode() throws Exception {
222: // Drop books
223: dropTables("book");
224: // Allocate second store
225: Store store2 = getStore();
226: try {
227: // Insert a book
228: Book originalBook = new Book("Necronomicon", "999");
229: store.save(originalBook);
230: // Start a transaction to that book in the first store
231: Transaction tx2 = store2.getTransactionTracker()
232: .getTransaction(TransactionTracker.TX_REQUIRED);
233: tx2.begin();
234: Book bookInstance2 = (Book) store2.findSingle("find book");
235: bookInstance2.setTitle("Store 2's Book");
236: store2.save(bookInstance2);
237: // Try to modify in the second transaction
238: Transaction tx = store.getTransactionTracker()
239: .getTransaction(TransactionTracker.TX_REQUIRED);
240: tx.begin();
241: Book bookInstance = (Book) store.findSingle("find book");
242: bookInstance.setTitle("Store 1's Book");
243: try {
244: store.save(bookInstance);
245: fail("I could modify the same object in another store.");
246: } catch (ConcurrentModificationException e) {
247: // Ok, this should be
248: }
249: // Close all
250: tx2.commit();
251: tx.commit();
252: } finally {
253: store2.close();
254: }
255: }
256:
257: public void testLockFromSameRemoteNode() throws Exception {
258: // Drop books
259: dropTables("book");
260: // Allocate second store
261: Store store2 = getStore();
262: try {
263: // Insert a book
264: Book originalBook = new Book("Necronomicon", "999");
265: store.save(originalBook);
266: // Start a transaction to that book in the first store
267: Transaction tx = store2.getTransactionTracker()
268: .getTransaction(TransactionTracker.TX_REQUIRED);
269: tx.begin();
270: Book bookInstance = (Book) store2.findSingle("find book");
271: bookInstance.setTitle("Store 2's Book");
272: store2.save(bookInstance); // First save
273: // Do a second save on the same object
274: bookInstance.setTitle("Store 2's Book for Sure");
275: store2.save(bookInstance);
276: // Close all
277: tx.commit();
278: } finally {
279: store2.close();
280: }
281: }
282:
283: public void testModifyObjectFromAnotherNode() throws Exception {
284: // Test object tracker attribute cache. This cache stores
285: // object attributes, so the second time it is saved, not
286: // all attributes need to be saved.
287: dropTables("book");
288: // Allocate second store
289: Store store2 = getStore();
290: try {
291: // Insert a book in the first store
292: Book originalBook = new Book("Original Title", "999");
293: store.save(originalBook);
294: // Select the book in the second store, and re-save
295: Book copyBook = (Book) store2.findSingle("find book");
296: assertEquals(originalBook, copyBook);
297: copyBook.setTitle("Modified Title");
298: store2.save(copyBook);
299: assertEquals(1, store.find("find book").size());
300: // Now save in the first store. The book should be
301: // totally overridden.
302: originalBook.setIsbn("1000");
303: store.save(originalBook);
304: // Select the book
305: Book dbBook = (Book) store.findSingle("find book");
306: assertEquals(originalBook, dbBook);
307: } finally {
308: store2.close();
309: }
310: }
311:
312: public void testModifyMemberListFromAnotherNode() throws Exception {
313: // Test object tracker attribute cache. This cache stores
314: // object attributes, so the second time it is saved, not
315: // all attributes need to be saved.
316: dropTables("book");
317: // Allocate second store
318: Store store2 = getStore();
319: try {
320: // Insert a book in the first store
321: Book originalBook = new Book("Original Title", "999");
322: Vector authors = new Vector();
323: authors.add(new Author("Mr", "Original"));
324: originalBook.setAuthors(authors);
325: store.save(originalBook);
326: // Select the book in the second store, and re-save
327: Book copyBook = (Book) store2.findSingle("find book");
328: assertEquals(originalBook, copyBook);
329: copyBook.setAuthors(new Vector());
330: store2.save(copyBook);
331: // Now select
332: Book dbBook = (Book) store2.findSingle("find book");
333: assertEquals(0, dbBook.getAuthors().size());
334: } finally {
335: store2.close();
336: }
337: }
338:
339: public void testAlreadyLockedTransactionInfo() throws Exception {
340: // Drop books
341: dropTables("book");
342: // Allocate second store
343: Store store2 = getStore();
344: try {
345: // Insert a book
346: Book originalBook = new Book("Necronomicon", "999");
347: store.save(originalBook);
348: // Start a transaction to that book in the first store
349: Transaction tx = store.getTransactionTracker()
350: .getTransaction(TransactionTracker.TX_REQUIRED);
351: tx.put("user", "joe");
352: tx.put("userid", "1");
353: tx.begin();
354: Book bookInstance1 = (Book) store.findSingle("find book");
355: bookInstance1.setTitle("Store 1's Book");
356: store.save(bookInstance1);
357: // Try to modify in the second transaction
358: Transaction tx2 = store2.getTransactionTracker()
359: .getTransaction(TransactionTracker.TX_REQUIRED);
360: tx2.begin();
361: Book bookInstance2 = (Book) store2.findSingle("find book");
362: bookInstance2.setTitle("Store 2's Book");
363: try {
364: store2.save(bookInstance2);
365: fail("I could modify the same object in another store.");
366: } catch (ConcurrentModificationException e) {
367: // Ok, this should be the session info with the data
368: SessionInfo locker = e.getSessionInfo();
369: assertEquals("joe", locker.get("user"));
370: assertEquals("1", locker.get("userid"));
371: }
372: // Close all
373: tx2.commit();
374: tx.commit();
375: } finally {
376: store2.close();
377: }
378: }
379:
380: public void testNormalInitialization() throws Exception {
381: // Tests initialization when no dead nodes are in the nodes table
382: Store stores[] = new Store[10];
383: for (int i = 0; i < stores.length; i++)
384: stores[i] = getStore();
385: for (int i = 0; i < stores.length; i++)
386: stores[i].close();
387: }
388:
389: public void testDeadNodeInitialization() throws Exception {
390: // First insert dummy node info
391: dropTables("book");
392: addNode(2, "1.2.3.4", 99);
393: store.close();
394: // Try to initialize
395: store = getStore();
396: // Save
397: store.save(new Book("The Insert to Success", "1-1-1-1"));
398: }
399:
400: public void testMultipleDeadNodeInitialization() throws Exception {
401: // First insert dummy node info
402: dropTables("book");
403: for (int i = 2; i < 20; i++)
404: addNode(i, "1.2.3.4", 99 + i);
405: store.close();
406: // Try to initialize
407: store = getStore();
408: // Try to insert a book
409: store.save(new Book("The Insert to Success", "1-1-1-1"));
410: }
411:
412: public void testMultipleCloses() throws Exception {
413: store.close();
414: store.close();
415: }
416:
417: public void testDiedOnlyServerReconnect() throws Exception {
418: // Allocate second store
419: Store store2 = getStore();
420: try {
421: // Make some operation
422: store2.save(new Book("Dune", "1-2-3-4"));
423: // Disconnect server
424: store.close();
425: // Next operation should successfully complete,
426: // using store2 as server
427: store2.save(new Book("Dune II", "1-2-3-4-II"));
428: } finally {
429: // Close
430: store2.close();
431: }
432: }
433:
434: public void testDiedSomeServerReconnect() throws Exception {
435: // Allocate second store
436: Store store2 = getStore();
437: // Allocate third store
438: Store store3 = getStore();
439: try {
440: // Make some operation
441: store3.save(new Book("Dune", "1-2-3-4"));
442: // Disconnect first server
443: store.close();
444: // Make again some operation. It should succseed, because
445: // store2 should become the server
446: store3.save(new Book("Dune II", "1-2-3-4-II"));
447: } finally {
448: store2.close();
449: store3.close();
450: }
451: }
452:
453: public void testDeadNodeCleanup() throws Exception {
454: // First insert dummy node info
455: dropTables("book");
456: for (int i = 2; i < 20; i++)
457: addNode(i, "1.2.3.4", 99 + i);
458: store.close();
459: // Try to initialize
460: setUp(); // Allocate new store
461: // Determine settings
462: store.save(new Book("The Insert to Success", "1-1-1-1"));
463: // Check whether dummy nodes were deleted
464: assertEquals(1, getCount("nodes"));
465: }
466:
467: public void testClientNodeReconnectTransactions() throws Exception {
468: // Allocate second store
469: Store store2 = getStore();
470: // Allocate third store
471: Store store3 = getStore();
472: try {
473: // Make some operation
474: Transaction tx = store3.getTransactionTracker()
475: .getTransaction(TransactionTracker.TX_REQUIRED);
476: tx.begin();
477: store3.save(new Book("Dune", "1-2-3-4"));
478: // Disconnect first server
479: store.close();
480: // Try to finish
481: try {
482: tx.commit();
483: fail("commit was successful, but reconnect should have killed it");
484: } catch (Exception e) {
485: logger.debug("received rollback exception", e);
486: }
487: } finally {
488: store2.close();
489: store3.close();
490: }
491: }
492:
493: public void testClientNodeReconnectSelfTransactions()
494: throws Exception {
495: // Allocate second store
496: Store store2 = getStore();
497: try {
498: // Make some operation
499: Transaction tx = store2.getTransactionTracker()
500: .getTransaction(TransactionTracker.TX_REQUIRED);
501: tx.begin();
502: store2.save(new Book("Dune", "1-2-3-4"));
503: // Disconnect server
504: store.close();
505: // Try to finish
506: try {
507: tx.commit();
508: fail("commit was successful, but reconnect should have killed it");
509: } catch (Exception e) {
510: logger.debug("received rollback exception", e);
511: }
512: } finally {
513: // Close
514: store2.close();
515: }
516: }
517:
518: public void testClientReconnectWithUnknownNodes() throws Exception {
519: // Insert dummy nodes additionally
520: for (int i = 2; i < 20; i++)
521: addNode(i, "1.2.3.4", 99 + i);
522: // Try to initialize
523: Store store2 = getStore();
524: Store store3 = getStore();
525: try {
526: // Make a successful operation (server is store1)
527: store3.save(new Book("Success", "1"));
528: // Kill store
529: store.close();
530: // Try to insert a book (store3 should reconnect to store2)
531: store3.save(new Book("The Insert to Success", "1-1-1-1"));
532: // Two nodes should stay in the nodes table, plus one with setup
533: setUp();
534: assertEquals(3, getCount("nodes"));
535: } finally {
536: // Close all
537: store2.close();
538: store3.close();
539: }
540: }
541:
542: public void testListTwiceAdd() throws Exception {
543: dropTables("book");
544: // Allocate second store
545: Store store2 = getStore();
546: try {
547: // Insert author
548: Author author = new Author("First", "Name");
549: store.save(author);
550: // Insert original book
551: Book originalBook = new Book("Original", "1");
552: store.save(originalBook);
553: // Insert an item as list
554: Book copyBook = (Book) store.findSingle("find book");
555: Author copyAuthor = (Author) store
556: .findSingle("find author");
557: Vector authors2 = new Vector();
558: authors2.add(copyAuthor);
559: copyBook.setAuthors(authors2);
560: store2.save(copyBook);
561: // Insert into second also
562: Vector authors = new Vector();
563: authors.add(author);
564: originalBook.setAuthors(authors);
565: store.save(originalBook);
566: // Check
567: assertEquals(1, ((Book) store.findSingle("find book"))
568: .getAuthors().size());
569: assertEquals(1, ((Book) store2.findSingle("find book"))
570: .getAuthors().size());
571: } finally {
572: // Close
573: store2.close();
574: }
575: }
576:
577: public void testListTwiceRemove() throws Exception {
578: dropTables("book");
579: // Allocate second store
580: Store store2 = getStore();
581: try {
582: // Insert author
583: Author author = new Author("First", "Name");
584: store.save(author);
585: // Insert original book
586: Book originalBook = new Book("Original", "1");
587: Vector authors = new Vector();
588: authors.add(author);
589: originalBook.setAuthors(authors);
590: store.save(originalBook);
591: // Insert an item as list
592: Book copyBook = (Book) store.findSingle("find book");
593: copyBook.getAuthors().clear();
594: store2.save(copyBook);
595: // Insert into second also
596: originalBook.getAuthors().clear();
597: store.save(originalBook);
598: // Check
599: assertEquals(0, ((Book) store.findSingle("find book"))
600: .getAuthors().size());
601: assertEquals(0, ((Book) store2.findSingle("find book"))
602: .getAuthors().size());
603: } finally {
604: // Close
605: store2.close();
606: }
607: }
608:
609: public void testMapTwiceAdd() throws Exception {
610: dropTables("mapholder");
611: // Allocate second store
612: Store store2 = getStore();
613: try {
614: // Insert author
615: Author author = new Author("First", "Name");
616: store.save(author);
617: // Insert original book
618: MapHolder originalHolder = new MapHolder();
619: originalHolder.setMeta(new HashMap());
620: store.save(originalHolder);
621: // Insert an item as list
622: MapHolder copyHolder = (MapHolder) store
623: .findSingle("find mapholder");
624: Author copyAuthor = (Author) store
625: .findSingle("find author");
626: copyHolder.getMeta().put("test", author);
627: store2.save(copyHolder);
628: // Insert into second also
629: originalHolder.getMeta().put("test", author);
630: store.save(originalHolder);
631: // Check
632: assertEquals(1, ((MapHolder) store
633: .findSingle("find mapholder")).getMeta().size());
634: assertEquals(1, ((MapHolder) store2
635: .findSingle("find mapholder")).getMeta().size());
636: } finally {
637: // Close
638: store2.close();
639: }
640: }
641:
642: public void testMapTwiceRemove() throws Exception {
643: dropTables("mapholder");
644: // Allocate second store
645: Store store2 = getStore();
646: try {
647: // Insert author
648: Author author = new Author("First", "Name");
649: store.save(author);
650: // Insert original book
651: MapHolder originalHolder = new MapHolder();
652: originalHolder.setMeta(new HashMap());
653: originalHolder.getMeta().put("test", author);
654: store.save(originalHolder);
655: // Insert an item as list
656: MapHolder copyHolder = (MapHolder) store
657: .findSingle("find mapholder");
658: copyHolder.getMeta().clear();
659: store2.save(copyHolder);
660: // Insert into second also
661: originalHolder.getMeta().clear();
662: store.save(originalHolder);
663: // Check
664: assertEquals(0, ((MapHolder) store
665: .findSingle("find mapholder")).getMeta().size());
666: assertEquals(0, ((MapHolder) store2
667: .findSingle("find mapholder")).getMeta().size());
668: } finally {
669: // Close
670: store2.close();
671: }
672: }
673:
674: public void testLocalDeadNode() throws Exception {
675: // First insert dummy node info
676: dropTables("book");
677: addNode(2, NodeServer.getHostAddresses(), 99);
678: store.close();
679: // Try to initialize
680: store = getStore();
681: // Try to insert a book. If this fails, the local
682: // dead node was not recognized.
683: store.save(new Book("The Insert to Success", "1-1-1-1"));
684: }
685:
686: public void testLockModifyFromOtherNodeUnlock() throws Exception {
687: // Get the lockmanager
688: LockTracker lockTracker = store.getLockTracker();
689: // Lock and object
690: dropTables("book");
691: Book book = new Book("Locks", "1");
692: store.save(book);
693: lockTracker.lock(book);
694: // Do some modification from another node
695: // Test if we can modify it
696: Store store2 = getStore();
697: try {
698: Book dbBook = (Book) store2.findSingle("find book");
699: dbBook.setTitle("Return of the Locks");
700: store2.save(dbBook);
701: fail("book was modifiable, but it should have been locked.");
702: } catch (Exception e) {
703: // Nothing to do
704: } finally {
705: store2.close();
706: }
707: // Unlock
708: lockTracker.unlock(book);
709: }
710:
711: public void testLockModifyFromOtherNodeWait() throws Exception {
712: // Get the lockmanager
713: LockTracker lockTracker = store.getLockTracker();
714: // Lock and object
715: dropTables("book");
716: Book book = new Book("Locks", "1");
717: store.save(book);
718: lockTracker.lock(book);
719: // Do some modification from another node
720: // Test if we can modify it
721: Store store2 = getStore();
722: LockTracker lockTracker2 = store2.getLockTracker();
723: try {
724: Book dbBook = (Book) store2.findSingle("find book");
725: lockTracker2.lock(dbBook, 100);
726: fail("book was modifiable, but it should have been locked.");
727: } catch (Exception e) {
728: // Nothing to do
729: } finally {
730: store2.close();
731: }
732: // Unlock
733: lockTracker.unlock(book);
734: }
735:
736: public void testLockModifyFromOtherNodeWaitForUnlock()
737: throws Exception {
738: // Get the lockmanager
739: final LockTracker lockTracker = store.getLockTracker();
740: // Lock object
741: dropTables("book");
742: final Book book = new Book("Locks", "1");
743: store.save(book);
744: lockTracker.lock(book);
745: // Start thread
746: final Vector exceptions = new Vector();
747: Thread lockThread = new Thread(new Runnable() {
748: public void run() {
749: Store store2 = null;
750: try {
751: store2 = getStore();
752: LockTracker lockTracker2 = store2.getLockTracker();
753: Book dbBook = (Book) store2.findSingle("find book");
754: lockTracker2.lock(dbBook, 1000);
755: } catch (Exception e) {
756: exceptions.add(e);
757: } finally {
758: if (store2 != null)
759: store2.close();
760: }
761: }
762: });
763: lockThread.start();
764: // Wait and unlock
765: try {
766: Thread.sleep(500);
767: } catch (Exception e) {
768: }
769: lockTracker.unlock(book);
770: // Check whether lock thread was successful
771: lockThread.join();
772: assertEquals(0, exceptions.size());
773: }
774:
775: public void testLockEnsureModifyOtherNode() throws Exception {
776: // Get the lockmanager
777: LockTracker lockTracker = store.getLockTracker();
778: // Lock and object
779: dropTables("book");
780: Book book = new Book("Locks", "1");
781: store.save(book);
782: // Do some modification in another node
783: Store store2 = getStore();
784: Book dbBook = (Book) store2.findSingle("find book");
785: dbBook.setTitle("Return of the Locks");
786: store2.save(dbBook);
787: // Try to lock original version
788: try {
789: lockTracker.lockEnsureCurrent(book);
790: fail("book was modified, original instance should not be current");
791: } catch (Exception e) {
792: // Nothing to do
793: } finally {
794: // Close other instance
795: store2.close();
796: }
797: }
798:
799: }
|