001: /*
002: * Jalisto - JAva LIght STOrage
003: * Copyright (C) 2000-2005 Xcalia http://www.xcalia.com
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
018: *
019: * Xcalia
020: * 71, rue Desnouettes
021: * 75014 Paris - France
022: * http://www.xcalia.com
023: */
024: package org.objectweb.jalisto.se.impl.multi;
025:
026: import org.objectweb.jalisto.se.api.*;
027: import org.objectweb.jalisto.se.api.internal.multi.LockManager;
028: import org.objectweb.jalisto.se.api.internal.multi.LockTable;
029: import org.objectweb.jalisto.se.api.internal.multi.SessionMulti;
030: import org.objectweb.jalisto.se.api.internal.DataWrapper;
031: import org.objectweb.jalisto.se.api.internal.Constants;
032: import org.objectweb.jalisto.se.exception.JalistoException;
033: import org.objectweb.jalisto.se.exception.IdentityException;
034: import org.objectweb.jalisto.se.exception.TransactionException;
035: import org.objectweb.jalisto.se.impl.*;
036: import org.objectweb.jalisto.se.impl.server.PhysicalOid;
037: import org.objectweb.jalisto.se.impl.server.SessionImpl;
038: import org.objectweb.jalisto.se.impl.lock.*;
039: import org.objectweb.jalisto.se.impl.trace.Trace;
040: import org.objectweb.jalisto.se.JalistoFactory;
041:
042: public class SessionMultiImpl extends SessionImpl implements
043: SessionMulti {
044:
045: public SessionMultiImpl(JalistoProperties properties) {
046: super (properties);
047: trace.println(Trace.DEBUG, "CREATE A MULTI SESSION, id = {0}",
048: sessionId);
049: lockTable = JalistoFactory.getInternalFactory().getLockTable(
050: properties);
051: accessController = JalistoFactory.getInternalFactory()
052: .getAccessController(properties);
053: String txMode = properties
054: .getProperty(JalistoProperties.CONCURRENCY_MODE_KEY);
055: if (txMode.equalsIgnoreCase(Constants.OPTIMISTIC_MODE)) {
056: setOptimistic();
057: } else if (txMode.equalsIgnoreCase(Constants.PESSIMISTIC_MODE)) {
058: setPessimistic();
059: } else {
060: throw new JalistoException(
061: JalistoProperties.CONCURRENCY_MODE_KEY
062: + " not valide in database properties");
063: }
064: try {
065: timeOut = (new Integer(properties
066: .getProperty(JalistoProperties.TIME_OUT_KEY)))
067: .intValue();
068: } catch (Exception e) {
069: throw new JalistoException(JalistoProperties.TIME_OUT_KEY
070: + " not valide in database properties");
071: }
072: new DeadLockToken(sessionId);
073: }
074:
075: public Object makeNewFileOid(Class objectClass) {
076: return makeNewFileOid(objectClass.getName());
077: }
078:
079: public Object makeNewFileOid(String objectClassName) {
080: trace.println(Trace.SESSION, "{0} makeNewFileOid({1})",
081: sessionId, objectClassName);
082: checkValidity("makeNewFileOid", true);
083: try {
084: accessController.getAccessControl(AccessController.NEW_OID);
085: Object theClid = repository
086: .getClidFromClassName(objectClassName);
087: LogicalOid floid = oidTable
088: .allocateNewFloid(((Short) theClid).shortValue());
089: PhysicalOid fpoid = fileAccess.allocateNewFpoid(sessionId,
090: theClid);
091: oidTable.insertFpoid(sessionId, floid, fpoid);
092: lockManager.finishMakeNewFileOid(floid);
093: return floid.getClone();
094: } finally {
095: accessController
096: .releaseAccessControl(AccessController.NEW_OID);
097: }
098: }
099:
100: public Object makeNewFileOid(LogicalOid floid) {
101: trace.println(Trace.SESSION, "{0} makeNewFileOid({1})",
102: sessionId, floid);
103: checkValidity("makeNewFileOid", true);
104: try {
105: LogicalOid clone = floid.getClone();
106: accessController.getAccessControl(AccessController.NEW_OID);
107: Object theClid = new Short(clone.getClid());
108: PhysicalOid fpoid = fileAccess.allocateNewFpoid(sessionId,
109: theClid);
110: oidTable.insertFpoid(sessionId, clone, fpoid);
111: lockManager.finishMakeNewFileOid(clone);
112: return floid;
113: } finally {
114: accessController
115: .releaseAccessControl(AccessController.NEW_OID);
116: }
117: }
118:
119: public void makeNewFileOidCommit(LogicalOid floid) {
120: // nothing to do
121: }
122:
123: public void makeNewFileOidRollback(LogicalOid floid) {
124: PhysicalOid fpoid = oidTable.getFpoid(sessionId, floid);
125: oidTable.removeFloid(sessionId, floid);
126: if (fpoid != null) {
127: fileAccess.desallocateFpoid(sessionId, fpoid);
128: } else {
129: throw new IdentityException("the given oid " + floid
130: + " doesn't exist in this Jalisto datastore");
131: }
132: }
133:
134: public Object createObject(Object oid, Object[] objectToCreate) {
135: checkValidity("createObject", true);
136: DataWrapper datas = JalistoFactory.getInternalFactory()
137: .getNewDataWrapper(props, objectToCreate);
138: LogicalOid floid = getFloidFromOid(oid);
139: oidTable.markAsCreated(sessionId, floid);
140: lockManager.prepareCreateObject(floid, datas);
141: cache.put(floid, datas);
142: lockManager.finishCreateObject(floid, datas);
143: return floid;
144: }
145:
146: public void createObjectCommit(LogicalOid floid) {
147: trace.println(Trace.SESSION, "{0} createObjectCommit({1})",
148: sessionId, floid);
149: PhysicalOid fpoid = oidTable.getFpoid(sessionId, floid);
150: DataWrapper datas = (DataWrapper) cache.get(floid);
151: if (datas == null) {
152: datas = lockManager.getLockedValue(floid, sessionId);
153: }
154: fileAccess.insertDatas(sessionId, fpoid, datas);
155: }
156:
157: public void createObjectRollback(LogicalOid floid) {
158: trace.println(Trace.SESSION, "{0} createObjectRollback({1})",
159: sessionId, floid);
160: if (cache.containsKey(floid)) {
161: cache.remove(floid);
162: }
163: PhysicalOid fpoid = oidTable.getFpoid(sessionId, floid);
164: oidTable.removeFloid(sessionId, floid);
165: if (fpoid != null) {
166: fileAccess.desallocateFpoid(sessionId, fpoid);
167: } else {
168: throw new IdentityException("the given oid " + floid
169: + " doesn't exist in this Jalisto datastore");
170: }
171: }
172:
173: public Object[] readObjectByOid(Object oid, boolean withCache) {
174: return readObjectByOidInDataObject(oid, withCache).getDatas();
175: }
176:
177: public DataWrapper readObjectByOidInDataObject(Object oid,
178: boolean withCache) {
179: trace.println(Trace.SESSION,
180: "{0} readObjectByOidInDataObject({1})", sessionId, oid);
181: checkValidity("readObjectByOidInDataObject", true);
182: LogicalOid floid = getFloidFromOid(oid);
183:
184: // delete not commited for this session
185: if (lockManager.containsDeletedValue(floid, sessionId)) {
186: lockManager.finishReadObjectByOid(floid, null, (short) -1);
187: throw new IdentityException("the given oid " + oid
188: + " doesn't exist in this Jalisto datastore");
189: }
190:
191: lockManager.prepareReadObjectByOid(floid);
192:
193: DataWrapper result = null;
194: short update;
195: boolean readedFromCache = false;
196:
197: if (withCache && cache.containsKey(floid)) {
198: result = (DataWrapper) cache.get(floid);
199: if (result != null) {
200: readedFromCache = true;
201: }
202: }
203: // create or update not commited for this session
204: if (lockManager.containsLockedValue(floid, sessionId)) {
205: if (!readedFromCache) {
206: result = lockManager.getLockedValue(floid, sessionId);
207: }
208: update = lockManager.getUpdate(floid, sessionId);
209: // object not modified by current session, read it in base
210: } else {
211: try {
212: if (!readedFromCache) {
213: PhysicalOid fpoid = oidTable.getFpoid(sessionId,
214: floid);
215: if (fpoid != null) {
216: result = fileAccess.readDatas(sessionId, fpoid);
217: }
218: }
219: update = oidTable.getUpdate(sessionId, floid, true);
220: } catch (IdentityException jalistoIe) {
221: lockManager.finishReadObjectByOid(floid, null,
222: (short) -1);
223: throw new IdentityException("the given oid " + oid
224: + " doesn't exist in this Jalisto datastore",
225: jalistoIe);
226: }
227: }
228:
229: if (result == null) {
230: lockManager.finishReadObjectByOid(floid, null, (short) -1);
231: throw new IdentityException("the given oid " + oid
232: + " doesn't exist in this Jalisto datastore");
233: }
234:
235: if (withCache && readedFromCache) {
236: cache.put(floid, result);
237: }
238:
239: lockManager.finishReadObjectByOid(floid, result, update);
240: return result;
241: }
242:
243: public Object[] refreshObjectByOid(Object oid) {
244: trace.println(Trace.SESSION, "{0} refreshObjectByOid({1})",
245: sessionId, oid);
246: checkValidity("refreshObjectByOid", true);
247: LogicalOid floid = getFloidFromOid(oid);
248:
249: if (!lockManager.containsLockedValue(floid, sessionId)) {
250: return readObjectByOidInDataObject(oid, true).getDatas();
251: }
252:
253: // delete not commited for this session
254: if (lockManager.containsDeletedValue(floid, sessionId)) {
255: throw new IdentityException("the given oid " + oid
256: + " doesn't exist in this Jalisto datastore");
257: }
258:
259: DataWrapper result = null;
260: short update = lockManager.getUpdate(floid, sessionId);
261: try {
262: PhysicalOid fpoid = oidTable.getFpoid(sessionId, floid);
263: if (fpoid != null) {
264: result = fileAccess.readDatas(sessionId, fpoid);
265: update = oidTable.getUpdate(sessionId, floid, false);
266: oidTable.setUpdate(sessionId, floid, update);
267: }
268: } catch (IdentityException jalistoIe) {
269: throw new IdentityException("the given oid " + oid
270: + " doesn't exist in this Jalisto datastore",
271: jalistoIe);
272: }
273: if (result == null) {
274: throw new IdentityException("the given oid " + oid
275: + " doesn't exist in this Jalisto datastore");
276: }
277:
278: lockManager.setLockedValue(floid, sessionId, result, update);
279: cache.put(floid, result);
280:
281: return result.getDatas();
282: }
283:
284: public Object updateObjectByOid(Object oid, Object[] objectToUpdate) {
285: trace.println(Trace.SESSION, "{0} updateObjectByOid({1})",
286: sessionId, oid);
287: checkValidity("updateObjectByOid", true);
288: checkSerialisable(objectToUpdate);
289: LogicalOid floid = getFloidFromOid(oid);
290: short update;
291: DataWrapper datas;
292: if (lockManager.containsLockedValue(floid, sessionId)) {
293: datas = lockManager.getLockedValue(floid, sessionId);
294: update = lockManager.getUpdate(floid, sessionId);
295: } else {
296: datas = JalistoFactory.getInternalFactory()
297: .getNewDataWrapper(props, objectToUpdate);
298: update = oidTable.getUpdate(sessionId, floid, true);
299: }
300: datas.setDatas(objectToUpdate);
301: cache.put(floid, datas);
302: lockManager.finishUpdateObjectByOid(floid, datas, update);
303: return floid.getClone();
304: }
305:
306: public void updateObjectCommit(LogicalOid floid) {
307: trace.println(Trace.SESSION, "{0} updateObjectCommit({1})",
308: sessionId, floid);
309: boolean findInCache = true;
310: DataWrapper datas = (DataWrapper) cache.get(floid);
311: if (datas == null) {
312: findInCache = false;
313: datas = lockManager.getLockedValue(floid, sessionId);
314: }
315: PhysicalOid fpoid = oidTable.getFpoid(sessionId, floid);
316: if (fpoid != null) {
317: PhysicalOid updatedFpoid = fileAccess.updateDatas(
318: sessionId, fpoid, datas);
319: if (!updatedFpoid.equals(fpoid)) {
320: oidTable.updatePoid(sessionId, floid, updatedFpoid);
321: }
322: } else {
323: throw new IdentityException("the given oid " + floid
324: + " doesn't exist in this Jalisto datastore");
325: }
326: if (!findInCache) {
327: cache.put(floid, datas);
328: }
329: }
330:
331: public void updateObjectRollback(LogicalOid floid) {
332: trace.println(Trace.SESSION, "{0} updateObjectRollback({1})",
333: sessionId, floid);
334: if (cache.containsKey(floid)) {
335: cache.remove(floid);
336: }
337: }
338:
339: public void deleteObjectByOid(Object oid) {
340: trace.println(Trace.SESSION, "{0} deleteObjectByOid({1})",
341: sessionId, oid);
342: checkValidity("deleteObjectByOid", true);
343: LogicalOid floid = getFloidFromOid(oid);
344:
345: short update;
346: if (lockManager.containsLockedValue(floid, sessionId)) {
347: update = lockManager.getUpdate(floid, sessionId);
348: } else {
349: update = oidTable.getUpdate(sessionId, floid, true);
350: }
351: if (update == -1) {
352: throw new IdentityException("the given oid " + floid
353: + " doesn't exist in this Jalisto datastore");
354: }
355:
356: lockManager.prepareDeleteObjectByOid(floid, update);
357:
358: if (cache.containsKey(floid)) {
359: cache.remove(floid);
360: }
361: oidTable.removeFloid(sessionId, floid);
362: lockManager.finishDeleteObjectByOid(floid);
363: }
364:
365: public void deleteObjectCommit(LogicalOid floid) {
366: trace.println(Trace.SESSION, "{0} deleteObjectCommit({1})",
367: sessionId, floid);
368: PhysicalOid fpoid = oidTable.getDeletedFpoid(sessionId, floid);
369: if (fpoid != null) {
370: fileAccess.deleteDatas(sessionId, fpoid);
371: }
372: }
373:
374: public void deleteObjectRollback(LogicalOid floid) {
375: // nothing to do here
376: }
377:
378: public void begin() {
379: trace.println(Trace.SESSION, "{0} begin()", sessionId);
380: checkIsOpen("begin");
381: cache.clear();
382: lockManager.begin();
383: fileAccess.begin(sessionId);
384: }
385:
386: public void commit() {
387: trace.println(Trace.SESSION, "{0} commit()", sessionId);
388: checkIsOpen("commit");
389: lockManager.commit();
390: }
391:
392: public void rollback() {
393: trace.println(Trace.SESSION, "{0} rollback()", sessionId);
394: checkIsOpen("rollback");
395: lockManager.rollback();
396: }
397:
398: public LockManager getLockManager() {
399: return lockManager;
400: }
401:
402: public AccessController getAccessController() {
403: return accessController;
404: }
405:
406: public void setOptimistic() {
407: trace.println(Trace.SESSION, "{0} setOptimistic()", sessionId);
408: if (isOpen) {
409: throw new TransactionException(
410: "Session must not be open during setOptimistic");
411: }
412: if (transaction.isActive()) {
413: throw new TransactionException(
414: "Transaction must not be active during setOptimistic");
415: }
416: lockManager = new LockManagerOptimistic();
417: lockManager.setLockTable(lockTable);
418: lockManager.setSession(this );
419: }
420:
421: public void setPessimistic() {
422: trace.println(Trace.SESSION, "{0} setPessimistic()", sessionId);
423: if (isOpen) {
424: throw new TransactionException(
425: "Session must not be open during setPessimistic");
426: }
427: if (transaction.isActive()) {
428: throw new TransactionException(
429: "Transaction must not be active during setPessimistic");
430: }
431: lockManager = new LockManagerPessimistic();
432: lockManager.setLockTable(lockTable);
433: lockManager.setSession(this );
434: }
435:
436: public void goToBed() {
437: trace.println(Trace.SESSION, "{0} goToBed()", sessionId);
438: sessionIsSleeping = true;
439: }
440:
441: public void inspectLocks() {
442: lockTable.publishLocks();
443: }
444:
445: public void sleep(LogicalOid floid) {
446: sleep(floid, "");
447: }
448:
449: public void sleep(Object floid, String message) {
450: trace.println(Trace.SESSION, "{0} sleeps()", sessionId);
451: trace.println(Trace.DEBUG, "{0} sleeps()", sessionId);
452: if (sessionIsSleeping) {
453: int i = 0;
454: while (sessionIsSleeping && (i < timeOut)) {
455: Thread.yield();
456: i++;
457: }
458: if (i == timeOut) {
459: sessionIsSleeping = false;
460: lockTable.getLock(floid).resolveTimeOut(sessionId);
461: }
462: }
463: trace.println(Trace.DEBUG, "{0} awakes", sessionId);
464: }
465:
466: public void wakeUp() {
467: trace.println(Trace.SESSION, "{0} wakeUp()", sessionId);
468: sessionIsSleeping = false;
469: }
470:
471: private LockManager lockManager;
472: private LockTable lockTable;
473: private AccessController accessController;
474: private volatile boolean sessionIsSleeping = false;
475: private int timeOut;
476: }
|