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.stress;
018:
019: import org.objectweb.speedo.pobjects.userid.LinkedIntUserId;
020: import org.objectweb.util.monolog.api.BasicLevel;
021:
022: import junit.framework.Assert;
023:
024: import javax.jdo.PersistenceManager;
025: import javax.jdo.JDOFatalException;
026:
027: /**
028: *
029: * @author S.Chassande-Barrioz
030: */
031: public abstract class LinkedIntUserIdHelper extends StressHelper {
032:
033: /**
034: * is the lists of object identifier prepared before the transaction
035: * execution.
036: * if (oids == null) {
037: * db is not initialised
038: * } else if (oids != null && oids.length==0) {
039: * db initialised and keepOid = false
040: * } else {
041: * db initialised and keepOid == true
042: * }
043: */
044: protected static Object[] oids = null;
045: protected String DBSIZE = getLoggerName() + ".dbsize";
046: protected String NO_DB_INIT = getLoggerName() + ".nodbinit";
047:
048: public LinkedIntUserIdHelper(String s) {
049: super (s);
050: }
051:
052: protected String[] getClassNamesToInit() {
053: return new String[] { LinkedIntUserId.class.getName() };
054: }
055:
056: protected boolean linkObject() {
057: return true;
058: }
059:
060: protected boolean keepOid() {
061: return true;
062: }
063:
064: /**
065: * IMPORTANT: dot not removed data on support in order to avoid next
066: * creations
067: */
068: public void setUp() throws Exception {
069: logger.log(BasicLevel.DEBUG, "LinkedIntUserIdHelper.setUp");
070: cleanup();
071: initDataStructure(false);
072: }
073:
074: /**
075: * Creates the persistent object if it is not already done.
076: * @param task the task to prepare
077: * @param _ctx the context of the test.
078: */
079: protected void prepareTask(Task task, Object _ctx) {
080: debug = logger.isLoggable(BasicLevel.DEBUG);
081: logger.log(BasicLevel.INFO, "LinkedIntUserIdHelper.debug="
082: + debug);
083: super .prepareTask(task, _ctx);
084: LIUICtx ctx = (LIUICtx) _ctx;
085: if (oids == null) {
086: synchronized (TestGetObject.class) {
087: if (oids == null && !Boolean.getBoolean(NO_DB_INIT)) {
088: //Initialisation the database
089: logger.log(BasicLevel.INFO, "\tPreparing test...");
090: new PrepareTestLinked(this ).prepare(ctx, keepOid(),
091: linkObject());
092: if (keepOid()) {
093: //keep oids in the static variable
094: oids = ctx.oids;
095: } else {
096: //db initialized without oids
097: oids = new Object[0];
098: }
099: logger.log(BasicLevel.INFO, "\tTest Prepared.");
100: }
101: }
102: }
103: ctx.oids = oids;
104:
105: }
106:
107: /**
108: * The context to use for the LinkedIntUserId object
109: */
110: public class LIUICtx {
111: /**
112: * The identifier of the created object (see keepOid method)
113: */
114: public Object oids[];
115: /**
116: * The number of persistent object
117: */
118: public int dbSize;
119: /**
120: * indicates if the oid must be kept during the preparation of the task
121: */
122: public boolean keepOidOnPrepare;
123: public boolean linkOnPrepare;
124: public boolean endPrepare;
125: public Object[] currentsOnPrepare;
126: public Object[] nextsOnPrepare;
127:
128: public LIUICtx(int dbSize) {
129: this .dbSize = dbSize;
130: oids = new Object[dbSize];
131: }
132:
133: public void initOnPrepare(int nbTx, boolean fetchOid,
134: boolean linkOnPrepare) {
135: this .keepOidOnPrepare = fetchOid;
136: this .linkOnPrepare = linkOnPrepare;
137: this .endPrepare = false;
138: nextsOnPrepare = new Object[nbTx];
139: currentsOnPrepare = new Object[nbTx];
140: }
141:
142: public void endOnPrepare(int nbTx, boolean fetchOid,
143: boolean linkOnPrepare) {
144: this .endPrepare = true;
145: }
146:
147: public String toString() {
148: return "dbSize = " + dbSize;
149: }
150: }
151: }
152:
153: class PrepareTestLinked extends StressHelper {
154:
155: private final static int NB_CREATION = 1000;
156: private final static int NB_THREAD = 4;
157:
158: public PrepareTestLinked(LinkedIntUserIdHelper helper) {
159: super (helper.getName());
160: }
161:
162: protected String[] getClassNamesToInit() {
163: return new String[] { LinkedIntUserId.class.getName() };
164: }
165:
166: protected String getLoggerName() {
167: return STRESS_LOG_NAME + ".LinkedIntUserIdHelper";
168: }
169:
170: protected String getLogPrefix() {
171: return super .getLogPrefix() + "\t";
172: }
173:
174: protected void perform(StressHelper.Task task, int threadId,
175: int txId, Object ctx, PerformResult res) {
176: LinkedIntUserIdHelper.LIUICtx pctx = (LinkedIntUserIdHelper.LIUICtx) ctx;
177: int plus = pctx.dbSize % NB_CREATION;
178: int nbTx = task.txToExecute.length;
179: PersistenceManager pm = getPM(task, threadId, txId);
180: try {
181: res.beginTest();
182: beginTx(pm, task, threadId, txId);
183: LinkedIntUserId current = null, next = null;
184:
185: if (!pctx.linkOnPrepare) {
186: if (plus > 0) {
187: //The first transaction creates the additional object
188: for (int oid = 0; txId == 0 && oid < plus; oid++) {
189: current = new LinkedIntUserId(oid, "Obj No "
190: + oid, null);
191: pm.makePersistent(current);
192: if (pctx.keepOidOnPrepare) {
193: pctx.oids[oid] = pm.getObjectId(current);
194: }
195: }
196: }
197: // The other transactions create 'nbCreation' objects
198: for (int no = 0; no < NB_CREATION; no++) {
199: int oid = (txId * NB_CREATION) + no + plus;
200: if (oid < pctx.dbSize) {
201: current = new LinkedIntUserId(oid, "Obj No "
202: + oid, null);
203: pm.makePersistent(current);
204: if (pctx.keepOidOnPrepare) {
205: pctx.oids[oid] = pm.getObjectId(current);
206: }
207: }
208: }
209: } else if (!pctx.endPrepare) {
210:
211: /*
212: * First : save the oid of objects to be linked between transactions
213: */
214:
215: int oid = 0;
216: if (plus > 0 && txId == 0) {
217: current = new LinkedIntUserId(oid, "Obj No " + oid,
218: null);
219: pm.makePersistent(current);
220: if (pctx.keepOidOnPrepare) {
221: pctx.oids[oid] = pm.getObjectId(current);
222: }
223:
224: oid++;
225: next = new LinkedIntUserId(oid, "Obj No " + oid,
226: null);
227: pm.makePersistent(next);
228: if (pctx.keepOidOnPrepare) {
229: pctx.oids[oid] = pm.getObjectId(next);
230: }
231:
232: current.setNext(next);
233: pctx.currentsOnPrepare[txId] = pm
234: .getObjectId(current);
235:
236: //The first transaction creates the additional object
237: for (oid = 2; oid < plus; oid++) {
238: current = new LinkedIntUserId(oid, "Obj No "
239: + oid, null);
240: pm.makePersistent(current);
241: if (pctx.keepOidOnPrepare) {
242: pctx.oids[oid] = pm.getObjectId(current);
243: }
244: next.setNext(current);
245: pm.makePersistent(next);
246: next = current;
247: }
248: }
249:
250: // The other transactions create 'nbCreation' objects
251: for (int no = 0; no < NB_CREATION; no++) {
252: oid = (txId * NB_CREATION) + no + plus;
253: if (oid < pctx.dbSize) {
254: current = new LinkedIntUserId(oid, "Obj No "
255: + oid, null);
256: pm.makePersistent(current);
257: if (no == 0
258: && pctx.currentsOnPrepare[txId] == null) {
259: pctx.currentsOnPrepare[txId] = pm
260: .getObjectId(current);
261:
262: }
263: if (pctx.keepOidOnPrepare) {
264: pctx.oids[oid] = pm.getObjectId(current);
265: }
266: if (next != null) {
267: next.setNext(current);
268: pm.makePersistent(next);
269: }
270: next = current;
271: }
272: }
273:
274: // save the oid of objects to be linked between transactions
275: pctx.nextsOnPrepare[txId] = pm.getObjectId(next);
276:
277: } else if (txId == nbTx - 1) { // do it once only
278:
279: /*
280: * Second : link the oid
281: */
282: if (debug) {
283: for (int i = 0; i < nbTx; i++) {
284: logger.log(BasicLevel.DEBUG,
285: "currentsOnPrepare[" + i + "]="
286: + pctx.currentsOnPrepare[i]);
287: logger.log(BasicLevel.DEBUG, "nextsOnPrepare["
288: + i + "]=" + pctx.nextsOnPrepare[i]);
289: }
290: }
291:
292: // make circular list
293: next = (LinkedIntUserId) pm.getObjectById(
294: pctx.currentsOnPrepare[0], false);
295: current = (LinkedIntUserId) pm.getObjectById(
296: pctx.nextsOnPrepare[txId], false);
297:
298: if (plus != 0) {
299: if (txId == 0) {
300: current = (LinkedIntUserId) pm.getObjectById(
301: pctx.nextsOnPrepare[txId], false);
302: } else {
303: current = (LinkedIntUserId) pm.getObjectById(
304: pctx.nextsOnPrepare[txId - 1], false);
305: }
306: }
307:
308: current.setNext(next);
309: pm.makePersistent(current);
310: if (pctx.keepOidOnPrepare) {
311: int indice = (nbTx * NB_CREATION) - 1;
312: if (plus != 0) {
313: indice = (txId * NB_CREATION) + plus - 1;
314: }
315: pctx.oids[indice] = pm.getObjectId(current);
316: }
317:
318: // link objects between transactions
319: for (int no = 0; no < nbTx - 1; no++) {
320: if (pctx.currentsOnPrepare[no + 1] != null) {
321: next = (LinkedIntUserId) pm.getObjectById(
322: pctx.currentsOnPrepare[no + 1], false);
323: current = (LinkedIntUserId) pm.getObjectById(
324: pctx.nextsOnPrepare[no], false);
325: current.setNext(next);
326: }
327: }
328:
329: // verify all
330: for (int i = 0; i < pctx.oids.length - 1; i++) {
331: Assert.assertNotNull("i=" + i, pctx.oids[i]);
332: Assert
333: .assertNotNull("i=" + i + 1,
334: pctx.oids[i + 1]);
335: current = (LinkedIntUserId) pm.getObjectById(
336: pctx.oids[i], false);
337: next = (LinkedIntUserId) pm.getObjectById(
338: pctx.oids[i + 1], false);
339: Assert
340: .assertEquals("name=" + current.getName(),
341: current.getNext().getName(), next
342: .getName());
343: }
344: next = (LinkedIntUserId) pm.getObjectById(pctx.oids[0],
345: false);
346: current = (LinkedIntUserId) pm.getObjectById(
347: pctx.oids[pctx.oids.length - 1], false);
348: Assert.assertEquals("name=" + current.getName(),
349: current.getNext().getName(), next.getName());
350:
351: }
352: commitTx(pm, task, threadId, txId);
353: res.endTest();
354: } catch (JDOFatalException e) {
355: rollbackOnException(pm, e, res, task, threadId, txId);
356: } catch (Throwable e) {
357: stopOnError(pm, e, res, task, threadId, txId);
358: } finally {
359: closePM(pm, threadId, txId, task, res);
360: }
361:
362: }
363:
364: public void prepare(LinkedIntUserIdHelper.LIUICtx ctx,
365: boolean fetchOid, boolean link) {
366: int plus = ctx.dbSize % NB_CREATION;
367: int nbTx = (ctx.dbSize / NB_CREATION) + (plus > 0 ? 1 : 0);
368: ctx.initOnPrepare(nbTx, fetchOid, link);
369: perform(NB_THREAD, nbTx, Integer.getInteger(TIMEOUT, 200000)
370: .intValue(), ctx);
371: ctx.endOnPrepare(nbTx, fetchOid, link);
372: perform(NB_THREAD, nbTx, Integer.getInteger(TIMEOUT, 200000)
373: .intValue(), ctx);
374:
375: }
376: }
|