001: /**
002: * Copyright (C) 2001-2005 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: *
018: *
019: *
020: * Authors: S.Chassande-Barrioz.
021: * Created on 17 fevr. 2005
022: *
023: */package org.objectweb.speedo.runtime.collection;
024:
025: import java.util.ArrayList;
026: import java.util.Arrays;
027: import java.util.Collection;
028: import java.util.Collections;
029: import java.util.List;
030: import java.util.Properties;
031:
032: import javax.jdo.PersistenceManager;
033: import javax.jdo.PersistenceManagerFactory;
034:
035: import org.objectweb.speedo.SpeedoTestHelper;
036: import org.objectweb.speedo.api.SpeedoProperties;
037: import org.objectweb.speedo.pobjects.collection.Group;
038: import org.objectweb.speedo.pobjects.collection.User;
039: import org.objectweb.util.monolog.api.BasicLevel;
040:
041: /**
042: * It tests the thin locking on a collection.
043: *
044: * @author S.Chassande-Barrioz
045: */
046: public class TestThinLock extends SpeedoTestHelper {
047:
048: /**
049: * @param s
050: */
051: public TestThinLock(String s) {
052: super (s);
053: }
054:
055: /**
056: * @see org.objectweb.speedo.SpeedoTestHelper#getLoggerName()
057: */
058: protected String getLoggerName() {
059: return LOG_NAME + ".rt.collection.TestThinLock";
060: }
061:
062: /**
063: * Specify the properties activating the thin lock for the Group.users
064: * collection field.
065: * @see org.objectweb.speedo.SpeedoTestHelper#getPMFProperties()
066: */
067: public Properties getPMFProperties() {
068: Properties p = super .getPMFProperties();
069: p.put(SpeedoProperties.TRANSACTION_LOCKING_LEVEL_ENABLETHIN,
070: "true");
071: p.put(SpeedoProperties.TRANSACTION_LOCKING_LEVEL + "("
072: + Group.class.getName() + "#*)",
073: SpeedoProperties.TRANSACTION_LOCKING_LEVEL_FIELD);
074: return p;
075: }
076:
077: public void testGroupUser2WithBarrier() {
078: testGroupUser(2, true);
079: }
080:
081: public void testGroupUser20WithBarrier() {
082: testGroupUser(20, true);
083: }
084:
085: public void testGroupUser20() {
086: testGroupUser(20, false);
087: }
088:
089: public void testGroupUser50() {
090: testGroupUser(50, true);
091: }
092:
093: /**
094: * Create A group with several users
095: *
096: */
097: public void testGroupUser(final int NB, final boolean withBarrier) {
098: logger.log(BasicLevel.INFO, "testGroupUser" + NB
099: + (withBarrier ? "WithBarrier" : ""));
100: final Waiter waiter = new Waiter(0, withBarrier);
101: final Group group = new Group(
102: "TestThinLock.testGroupUser.group1");
103: final User[] users = new User[NB];
104: for (int i = 0; i < NB; i++) {
105: users[i] = new User("TestThinLock.testGroupUser.user" + i);
106: group.getUsers().add(users[i]);
107: }
108: PersistenceManager pm = pmf.getPersistenceManager();
109: pm.currentTransaction().begin();
110: pm.makePersistent(group);
111: pm.currentTransaction().commit();
112: pm.close();
113: Thread[] ths = new Thread[NB];
114: for (int i = 0; i < NB; i++) {
115: ths[i] = new Thread(new TestGroupUser(waiter, group,
116: users[i], new User(
117: "TestThinLock.testGroupUser.user"
118: + (NB + i)), pmf));
119: }
120: for (int i = 0; i < NB; i++) {
121: ths[i].start();
122: }
123: Collection threads = Arrays.asList(ths);
124: List res = waiter.nextAction(threads, 1000);
125: assertTrue("Thread blocked on first point: " + res, res
126: .isEmpty());
127: res = waiter.nextAction(threads, 1000);
128: if (!res.isEmpty()) {
129: for (int i = 0; i < ths.length; i++) {
130: if (ths[i].isAlive()) {
131: ths[i].interrupt();
132: }
133: }
134: }
135: assertTrue("Thread blocked on second point: " + res, res
136: .isEmpty());
137: res = waiter.nextAction(threads, 1000);
138: for (int i = 0; i < ths.length; i++) {
139: if (ths[i].isAlive()) {
140: try {
141: ths[i].join(1000);
142: } catch (InterruptedException e) {
143: e.printStackTrace();
144: }
145: }
146: }
147: pm = pmf.getPersistenceManager();
148: int size = group.getUsers().size();
149: pm.currentTransaction().begin();
150: pm.deletePersistentAll(group.getUsers());
151: pm.deletePersistent(group);
152: pm.currentTransaction().commit();
153: pm.close();
154: assertEquals("Bad number of users", NB, size);
155: }
156:
157: public static class Waiter {
158: int actionId;
159: ArrayList waiters = new ArrayList();
160: boolean withBarrier;
161:
162: public Waiter(int actionId, boolean withBarrier) {
163: this .actionId = actionId;
164: this .withBarrier = withBarrier;
165: }
166:
167: public synchronized void waitAction(int aid) {
168: if (!withBarrier) {
169: return;
170: }
171: waiters.add(Thread.currentThread());
172: notifyAll();
173: while (actionId < aid) {
174: try {
175: wait();
176: } catch (InterruptedException e) {
177: e.printStackTrace();
178: }
179: }
180: }
181:
182: public synchronized List nextAction(Collection threads,
183: long time) {
184: if (!withBarrier) {
185: return Collections.EMPTY_LIST;
186: }
187: while (!waiters.containsAll(threads)) {
188: try {
189: wait(time);
190: } catch (InterruptedException e) {
191: e.printStackTrace();
192: break;
193: }
194: }
195: if (waiters.containsAll(threads)) {
196: actionId++;
197: waiters.clear();
198: notifyAll();
199: return Collections.EMPTY_LIST;
200: } else {
201: return Collections.unmodifiableList(new ArrayList(
202: waiters));
203: }
204: }
205: }
206:
207: public static class TestGroupUser implements Runnable {
208: public Waiter waiter;
209: public Group group;
210: public User userToRemove;
211: public User userToAdd;
212: public PersistenceManagerFactory pmf;
213:
214: public TestGroupUser(Waiter waiter, Group group,
215: User userToRemove, User userToAdd,
216: PersistenceManagerFactory pmf) {
217: super ();
218: this .waiter = waiter;
219: this .group = group;
220: this .userToRemove = userToRemove;
221: this .userToAdd = userToAdd;
222: this .pmf = pmf;
223: }
224:
225: public void run() {
226: PersistenceManager pm = pmf.getPersistenceManager();
227: pm.currentTransaction().begin();
228: Collection users = group.getUsers();
229: waiter.waitAction(1);
230:
231: users.add(userToAdd);
232: users.remove(userToRemove);
233: pm.deletePersistent(userToRemove);
234:
235: waiter.waitAction(2);
236: pm.currentTransaction().commit();
237: pm.close();
238:
239: waiter.waitAction(3);
240: }
241: }
242: }
|