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.relations.C;
020: import org.objectweb.speedo.pobjects.relations.D;
021: import org.objectweb.util.monolog.api.BasicLevel;
022: import org.objectweb.speedo.Alea;
023:
024: import javax.jdo.PersistenceManager;
025: import javax.jdo.JDOFatalException;
026:
027: /**
028: *
029: * @author M. Guillemin
030: */
031: public abstract class CDRelationHelper 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:
045: protected static Object[] oidsC = null;
046: protected static Object[] oidsD = null;
047: protected String DBSIZE = getLoggerName() + ".dbsize";
048: protected String NO_DB_INIT = getLoggerName() + ".nodbinit";
049:
050: public CDRelationHelper(String s) {
051: super (s);
052: }
053:
054: protected String[] getClassNamesToInit() {
055: return new String[] {
056: org.objectweb.speedo.pobjects.relations.C.class
057: .getName(),
058: org.objectweb.speedo.pobjects.relations.D.class
059: .getName() };
060: }
061:
062: protected boolean keepOid() {
063: return true;
064: }
065:
066: protected abstract int getNbSucc();
067:
068: /**
069: * IMPORTANT: dot not removed data on support in order to avoid next
070: * creations
071: */
072: public void setUp() throws Exception {
073: logger.log(BasicLevel.DEBUG, "setUp.");
074: cleanup();
075: initDataStructure(false);
076: debug = logger.isLoggable(BasicLevel.DEBUG);
077: }
078:
079: protected void prepareTest(TaskManager tm, Object ctx) {
080: super .prepareTest(tm, ctx);
081: Task task = tm.tasks[0];
082: CDCtx cdctx = (CDCtx) ctx;
083:
084: if (task.txToExecute.length * getNbSucc() > cdctx.dbSize) {
085: fail("Adjust parameter: tx <= " + cdctx.dbSize
086: / getNbSucc() + " OR dbSize >= "
087: + task.txToExecute.length * getNbSucc());
088: }
089: }
090:
091: /**
092: * Creates the persistent object if it is not already done.
093: * @param task the task to prepare
094: * @param _ctx the context of the test.
095: */
096: protected void prepareTask(Task task, Object _ctx) {
097: super .prepareTask(task, _ctx);
098: CDCtx ctx = (CDCtx) _ctx;
099: if (oidsC == null) {
100: synchronized (getClass()) {
101: if (oidsC == null && !Boolean.getBoolean(NO_DB_INIT)) {
102: //Initialisation the database
103: logger.log(BasicLevel.INFO, "\tPreparing test...");
104: new PrepareTestCDRelation(this ).prepare(ctx,
105: keepOid());
106: if (keepOid()) {
107: //keep oids in the static variable
108: oidsC = ctx.oidsC;
109: oidsD = ctx.oidsD;
110: } else {
111: //db initialized without oids
112: oidsC = new Object[0];
113: oidsD = new Object[0];
114: }
115: logger.log(BasicLevel.INFO, "\tTest Prepared.");
116: }
117: }
118: }
119: ctx.oidsC = oidsC;
120: ctx.oidsD = oidsD;
121: }
122:
123: protected int getOid(CDCtx cdctx, boolean useTwiceTheSameOid,
124: int nbSucc) {
125: int oid = Alea.rand(0, cdctx.dbSize - nbSucc);
126: if (!useTwiceTheSameOid) {
127: synchronized (cdctx.usedOids) {
128: while (oid % nbSucc != 0) {
129: oid++;
130: }
131: while (cdctx.usedOids[oid]) {
132: oid = Alea.rand(0, cdctx.dbSize - nbSucc);
133: while (oid % nbSucc != 0) {
134: oid++;
135: }
136: }
137: for (int i = 0; i < nbSucc; i++) {
138: cdctx.usedOids[oid + i] = true;
139: }
140: }
141: }
142: return oid;
143: }
144:
145: /**
146: * The context to use for the CDRelation object
147: */
148: public class CDCtx {
149: /**
150: * The identifier of the created object (see keepOid method)
151: */
152: public Object oidsC[];
153: public Object oidsD[];
154: public boolean usedOids[];
155: /**
156: * The number of persistent object
157: */
158: public int dbSize;
159: /**
160: * indicates if the oid must be kept during the preparation of the task
161: */
162: public boolean keepOid;
163:
164: public CDCtx(int dbSize) {
165: this .dbSize = dbSize;
166: oidsC = new Object[dbSize];
167: oidsD = new Object[dbSize];
168: usedOids = new boolean[dbSize];
169: }
170:
171: public void initOnPrepare(int nbTx, boolean fetchOid) {
172: this .keepOid = fetchOid;
173: for (int i = 0; i < dbSize; i++)
174: usedOids[i] = false;
175: }
176:
177: public String toString() {
178: return "dbSize = " + dbSize;
179: }
180: }
181: }
182:
183: class PrepareTestCDRelation extends StressHelper {
184:
185: private final static int NB_CREATION = 100;
186: private final static int NB_THREAD = 4;
187:
188: public PrepareTestCDRelation(CDRelationHelper helper) {
189: super (helper.getName());
190: }
191:
192: protected String[] getClassNamesToInit() {
193: return new String[] {
194: org.objectweb.speedo.pobjects.relations.C.class
195: .getName(),
196: org.objectweb.speedo.pobjects.relations.D.class
197: .getName() };
198: }
199:
200: protected String getLoggerName() {
201: return STRESS_LOG_NAME + ".CDRelationHelper";
202: }
203:
204: protected String getLogPrefix() {
205: return super .getLogPrefix() + "\t";
206: }
207:
208: protected void perform(StressHelper.Task task, int threadId,
209: int txId, Object ctx, PerformResult res) {
210: CDRelationHelper.CDCtx pctx = (CDRelationHelper.CDCtx) ctx;
211: int plus = pctx.dbSize % NB_CREATION;
212: int nbTx = task.txToExecute.length;
213: PersistenceManager pm = getPM(task, threadId, txId);
214: try {
215: res.beginTest();
216: beginTx(pm, task, threadId, txId);
217: if (plus > 0) {
218: //The first transaction creates the additional object
219: for (int oid = 0; txId == 0 && oid < plus; oid++) {
220: C c = new C("c" + oid);
221: D d = new D("d" + oid);
222: pm.makePersistent(c);
223: pm.makePersistent(d);
224: if (pctx.keepOid) {
225: pctx.oidsC[oid] = pm.getObjectId(c);
226: pctx.oidsD[oid] = pm.getObjectId(d);
227: }
228: }
229: }
230: // The other transactions create 'nbCreation' objects
231: for (int no = 0; no < NB_CREATION; no++) {
232: int oid = (txId * NB_CREATION) + no + plus;
233: if (oid < pctx.dbSize) {
234: C c = new C("c" + oid);
235: D d = new D("d" + oid);
236: pm.makePersistent(c);
237: pm.makePersistent(d);
238: if (pctx.keepOid) {
239: pctx.oidsC[oid] = pm.getObjectId(c);
240: pctx.oidsD[oid] = pm.getObjectId(d);
241: }
242: }
243: }
244:
245: commitTx(pm, task, threadId, txId);
246: res.endTest();
247: } catch (JDOFatalException e) {
248: rollbackOnException(pm, e, res, task, threadId, txId);
249: } catch (Throwable e) {
250: stopOnError(pm, e, res, task, threadId, txId);
251: } finally {
252: closePM(pm, threadId, txId, task, res);
253: }
254:
255: }
256:
257: public void prepare(CDRelationHelper.CDCtx ctx, boolean fetchOid) {
258: int plus = ctx.dbSize % NB_CREATION;
259: int nbTx = (ctx.dbSize / NB_CREATION) + (plus > 0 ? 1 : 0);
260: ctx.initOnPrepare(nbTx, fetchOid);
261: perform(NB_THREAD, nbTx, Integer.getInteger(TIMEOUT, 200000)
262: .intValue(), ctx);
263: }
264: }
|