0001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
0002:
0003: This file is part of the db4o open source object database.
0004:
0005: db4o is free software; you can redistribute it and/or modify it under
0006: the terms of version 2 of the GNU General Public License as published
0007: by the Free Software Foundation and as clarified by db4objects' GPL
0008: interpretation policy, available at
0009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
0010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
0011: Suite 350, San Mateo, CA 94403, USA.
0012:
0013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
0014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0016: for more details.
0017:
0018: You should have received a copy of the GNU General Public License along
0019: with this program; if not, write to the Free Software Foundation, Inc.,
0020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
0021: package com.db4o.internal;
0022:
0023: import com.db4o.*;
0024: import com.db4o.config.*;
0025: import com.db4o.ext.*;
0026: import com.db4o.foundation.*;
0027: import com.db4o.internal.callbacks.*;
0028: import com.db4o.internal.cs.*;
0029: import com.db4o.internal.handlers.*;
0030: import com.db4o.internal.marshall.*;
0031: import com.db4o.internal.query.*;
0032: import com.db4o.internal.query.processor.*;
0033: import com.db4o.internal.query.result.*;
0034: import com.db4o.internal.replication.*;
0035: import com.db4o.internal.slots.*;
0036: import com.db4o.query.*;
0037: import com.db4o.reflect.*;
0038: import com.db4o.reflect.generic.*;
0039: import com.db4o.replication.*;
0040: import com.db4o.types.*;
0041:
0042: /**
0043: * NOTE: This is just a 'partial' base class to allow for variant implementations
0044: * in db4oj and db4ojdk1.2. It assumes that itself is an instance of YapStream
0045: * and should never be used explicitly.
0046: *
0047: * @exclude
0048: * @sharpen.partial
0049: */
0050: public abstract class PartialObjectContainer implements TransientClass,
0051: Internal4, ObjectContainerSpec {
0052:
0053: // Collection of all classes
0054: // if (i_classCollection == null) the engine is down.
0055: protected ClassMetadataRepository _classCollection;
0056:
0057: protected ClassInfoHelper _classMetaHelper = new ClassInfoHelper();
0058:
0059: // the Configuration context for this ObjectContainer
0060: protected Config4Impl _config;
0061:
0062: // Counts the number of toplevel calls into YapStream
0063: private int _stackDepth;
0064:
0065: private final ReferenceSystemRegistry _referenceSystemRegistry = new ReferenceSystemRegistry();
0066:
0067: private Tree _justPeeked;
0068:
0069: public final Object _lock;
0070:
0071: // currently used to resolve self-linking concurrency problems
0072: // in cylic links, stores only YapClass objects
0073: private List4 _pendingClassUpdates;
0074:
0075: // the parent ObjectContainer for TransportObjectContainer or this for all
0076: // others. Allows identifying the responsible Objectcontainer for IDs
0077: final ObjectContainerBase _parent;
0078:
0079: // allowed adding refresh with little code changes.
0080: boolean _refreshInsteadOfActivate;
0081:
0082: // a value greater than 0 indicates class implementing the
0083: // "Internal" interface are visible in queries and can
0084: // be used.
0085: int _showInternalClasses = 0;
0086:
0087: private List4 _stillToActivate;
0088: private List4 _stillToDeactivate;
0089: private List4 _stillToSet;
0090:
0091: // used for ClassMetadata and ClassMetadataRepository
0092: // may be parent or equal to i_trans
0093: private Transaction _systemTransaction;
0094:
0095: // used for Objects
0096: protected Transaction _transaction;
0097:
0098: private boolean _instantiating;
0099:
0100: // all the per-YapStream references that we don't
0101: // want created in YapobjectCarrier
0102: public HandlerRegistry _handlers;
0103:
0104: // One of three constants in ReplicationHandler: NONE, OLD, NEW
0105: // Detailed replication variables are stored in i_handlers.
0106: // Call state has to be maintained here, so YapObjectCarrier (who shares i_handlers) does
0107: // not accidentally think it operates in a replication call.
0108: int _replicationCallState;
0109:
0110: // weak reference management
0111: WeakReferenceCollector _references;
0112:
0113: private NativeQueryHandler _nativeQueryHandler;
0114:
0115: private final ObjectContainerBase _this ;
0116:
0117: private Callbacks _callbacks = new com.db4o.internal.callbacks.NullCallbacks();
0118:
0119: protected final PersistentTimeStampIdGenerator _timeStampIdGenerator = new PersistentTimeStampIdGenerator();
0120:
0121: private int _topLevelCallId = 1;
0122:
0123: private IntIdGenerator _topLevelCallIdGenerator = new IntIdGenerator();
0124:
0125: private boolean _topLevelCallCompleted;
0126:
0127: protected PartialObjectContainer(Configuration config,
0128: ObjectContainerBase parent) {
0129: _this = cast(this );
0130: _parent = parent == null ? _this : parent;
0131: _lock = parent == null ? new Object() : parent._lock;
0132: _config = (Config4Impl) config;
0133: }
0134:
0135: public final void open() throws OldFormatException {
0136: boolean ok = false;
0137: synchronized (_lock) {
0138: try {
0139: initializeTransactions();
0140: initialize1(_config);
0141: openImpl();
0142: initializePostOpen();
0143: Platform4.postOpen(cast(_this ));
0144: ok = true;
0145: } finally {
0146: if (!ok) {
0147: shutdownObjectContainer();
0148: }
0149: }
0150: }
0151: }
0152:
0153: protected abstract void openImpl() throws Db4oIOException;
0154:
0155: public final void activateDefaultDepth(Transaction trans, Object obj) {
0156: activate(trans, obj, configImpl().activationDepth());
0157: }
0158:
0159: public final void activate(Transaction trans, Object obj, int depth) {
0160: synchronized (_lock) {
0161: trans = checkTransaction(trans);
0162: beginTopLevelCall();
0163: try {
0164: stillToActivate(trans, obj, depth);
0165: activatePending(trans);
0166: completeTopLevelCall();
0167: } catch (Db4oException e) {
0168: completeTopLevelCall(e);
0169: } finally {
0170: endTopLevelCall();
0171: }
0172: }
0173: }
0174:
0175: static final class PendingActivation {
0176: public final ObjectReference ref;
0177: public final int depth;
0178:
0179: public PendingActivation(ObjectReference ref, int depth) {
0180: this .ref = ref;
0181: this .depth = depth;
0182: }
0183: }
0184:
0185: final void activatePending(Transaction ta) {
0186: while (_stillToActivate != null) {
0187:
0188: // TODO: Optimize! A lightweight int array would be faster.
0189:
0190: final Iterator4 i = new Iterator4Impl(_stillToActivate);
0191: _stillToActivate = null;
0192:
0193: while (i.moveNext()) {
0194: final PendingActivation item = (PendingActivation) i
0195: .current();
0196: final ObjectReference ref = item.ref;
0197: final Object obj = ref.getObject();
0198: if (obj == null) {
0199: ta.removeReference(ref);
0200: } else {
0201: ref.activate1(ta, obj, item.depth,
0202: _refreshInsteadOfActivate);
0203: }
0204: }
0205: }
0206: }
0207:
0208: public final void bind(Transaction trans, Object obj, long id)
0209: throws ArgumentNullException, IllegalArgumentException {
0210: synchronized (_lock) {
0211: if (obj == null) {
0212: throw new ArgumentNullException();
0213: }
0214: if (DTrace.enabled) {
0215: DTrace.BIND.log(id, " ihc "
0216: + System.identityHashCode(obj));
0217: }
0218: trans = checkTransaction(trans);
0219: int intID = (int) id;
0220: Object oldObject = getByID(trans, id);
0221: if (oldObject == null) {
0222: throw new IllegalArgumentException("id");
0223: }
0224: ObjectReference yo = trans.referenceForId(intID);
0225: if (yo == null) {
0226: throw new IllegalArgumentException("obj");
0227: }
0228: if (trans.reflector().forObject(obj) == yo.classMetadata()
0229: .classReflector()) {
0230: ObjectReference newRef = bind2(trans, yo, obj);
0231: newRef.virtualAttributes(trans);
0232: } else {
0233: throw new RuntimeException(Messages.get(57));
0234: }
0235: }
0236: }
0237:
0238: public final ObjectReference bind2(Transaction trans,
0239: ObjectReference oldRef, Object obj) {
0240: int id = oldRef.getID();
0241: trans.removeReference(oldRef);
0242: ObjectReference newRef = new ObjectReference(
0243: classMetadataForObject(obj), id);
0244: newRef.setObjectWeak(_this , obj);
0245: newRef.setStateDirty();
0246: trans.referenceSystem().addExistingReference(newRef);
0247: return newRef;
0248: }
0249:
0250: private ClassMetadata classMetadataForObject(Object obj) {
0251: return classMetadataForReflectClass(reflector().forObject(obj));
0252: }
0253:
0254: public abstract byte blockSize();
0255:
0256: public final int bytesToBlocks(long bytes) {
0257: int blockLen = blockSize();
0258: return (int) ((bytes + blockLen - 1) / blockLen);
0259: }
0260:
0261: public final int blockAlignedBytes(int bytes) {
0262: return bytesToBlocks(bytes) * blockSize();
0263: }
0264:
0265: public final int blocksToBytes(int blocks) {
0266: return blocks * blockSize();
0267: }
0268:
0269: private final boolean breakDeleteForEnum(ObjectReference reference,
0270: boolean userCall) {
0271: if (Deploy.csharp) {
0272: return false;
0273: }
0274: if (userCall) {
0275: return false;
0276: }
0277: if (reference == null) {
0278: return false;
0279: }
0280: return Platform4.jdk().isEnum(reflector(),
0281: reference.classMetadata().classReflector());
0282: }
0283:
0284: boolean canUpdate() {
0285: return true;
0286: }
0287:
0288: public final void checkClosed() throws DatabaseClosedException {
0289: if (_classCollection == null) {
0290: throw new DatabaseClosedException();
0291: }
0292: }
0293:
0294: protected final void checkReadOnly()
0295: throws DatabaseReadOnlyException {
0296: if (_config.isReadOnly()) {
0297: throw new DatabaseReadOnlyException();
0298: }
0299: }
0300:
0301: final void processPendingClassUpdates() {
0302: if (_pendingClassUpdates == null) {
0303: return;
0304: }
0305: Iterator4 i = new Iterator4Impl(_pendingClassUpdates);
0306: while (i.moveNext()) {
0307: ClassMetadata yapClass = (ClassMetadata) i.current();
0308: yapClass.setStateDirty();
0309: yapClass.write(_systemTransaction);
0310: }
0311: _pendingClassUpdates = null;
0312: }
0313:
0314: public final Transaction checkTransaction() {
0315: return checkTransaction(null);
0316: }
0317:
0318: public final Transaction checkTransaction(Transaction ta) {
0319: checkClosed();
0320: if (ta != null) {
0321: return ta;
0322: }
0323: return transaction();
0324: }
0325:
0326: final public boolean close() {
0327: synchronized (_lock) {
0328: close1();
0329: return true;
0330: }
0331: }
0332:
0333: protected void handleExceptionOnClose(Exception exc) {
0334: fatalException(exc);
0335: }
0336:
0337: private void close1() {
0338: // this is set to null in close2 and is therefore our check for down.
0339: if (_classCollection == null) {
0340: return;
0341: }
0342: Platform4.preClose(cast(_this ));
0343: processPendingClassUpdates();
0344: if (stateMessages()) {
0345: logMsg(2, toString());
0346: }
0347: close2();
0348: }
0349:
0350: protected abstract void close2();
0351:
0352: public final void shutdownObjectContainer() {
0353: if (DTrace.enabled) {
0354: DTrace.CLOSE.log();
0355: }
0356: logMsg(3, toString());
0357: synchronized (_lock) {
0358: stopSession();
0359: shutdownDataStorage();
0360: }
0361: }
0362:
0363: protected abstract void shutdownDataStorage();
0364:
0365: public Db4oCollections collections(Transaction trans) {
0366: synchronized (_lock) {
0367: return Platform4.collections(checkTransaction(trans));
0368: }
0369: }
0370:
0371: public final void commit(Transaction trans)
0372: throws DatabaseReadOnlyException, DatabaseClosedException {
0373: synchronized (_lock) {
0374: if (DTrace.enabled) {
0375: DTrace.COMMIT.log();
0376: }
0377: trans = checkTransaction(trans);
0378: checkReadOnly();
0379: beginTopLevelCall();
0380: try {
0381: commit1(trans);
0382: trans.commitReferenceSystem();
0383: completeTopLevelCall();
0384: } catch (Db4oException e) {
0385: completeTopLevelCall(e);
0386: } finally {
0387: endTopLevelCall();
0388: }
0389: }
0390: }
0391:
0392: public abstract void commit1(Transaction trans);
0393:
0394: public Configuration configure() {
0395: return configImpl();
0396: }
0397:
0398: public Config4Impl config() {
0399: return configImpl();
0400: }
0401:
0402: public abstract int converterVersion();
0403:
0404: public abstract AbstractQueryResult newQueryResult(
0405: Transaction trans, QueryEvaluationMode mode);
0406:
0407: protected void createStringIO(byte encoding) {
0408: stringIO(LatinStringIO.forEncoding(encoding));
0409: }
0410:
0411: final protected void initializeTransactions() {
0412: _systemTransaction = newTransaction(null,
0413: createReferenceSystem());
0414: _transaction = newUserTransaction();
0415: }
0416:
0417: public abstract Transaction newTransaction(
0418: Transaction parentTransaction,
0419: TransactionalReferenceSystem referenceSystem);
0420:
0421: public Transaction newUserTransaction() {
0422: return newTransaction(systemTransaction(), null);
0423: }
0424:
0425: public abstract long currentVersion();
0426:
0427: public boolean createClassMetadata(ClassMetadata classMeta,
0428: ReflectClass clazz, ClassMetadata super ClassMeta) {
0429: return classMeta.init(_this , super ClassMeta, clazz);
0430: }
0431:
0432: /**
0433: * allows special handling for all Db4oType objects.
0434: * Redirected here from #set() so only instanceof check is necessary
0435: * in the #set() method.
0436: * @return object if handled here and #set() should not continue processing
0437: */
0438: public Db4oType db4oTypeStored(Transaction trans, Object obj) {
0439: if (!(obj instanceof Db4oDatabase)) {
0440: return null;
0441: }
0442: Db4oDatabase database = (Db4oDatabase) obj;
0443: if (trans.referenceForObject(obj) != null) {
0444: return database;
0445: }
0446: showInternalClasses(true);
0447: try {
0448: return database.query(trans);
0449: } finally {
0450: showInternalClasses(false);
0451: }
0452: }
0453:
0454: public final void deactivate(Transaction trans, Object obj,
0455: int depth) throws DatabaseClosedException {
0456: synchronized (_lock) {
0457: trans = checkTransaction(trans);
0458: beginTopLevelCall();
0459: try {
0460: deactivateInternal(trans, obj, depth);
0461: completeTopLevelCall();
0462: } catch (Db4oException e) {
0463: completeTopLevelCall(e);
0464: } finally {
0465: endTopLevelCall();
0466: }
0467: }
0468: }
0469:
0470: private final void deactivateInternal(Transaction trans,
0471: Object obj, int depth) {
0472: stillToDeactivate(trans, obj, depth, true);
0473: while (_stillToDeactivate != null) {
0474: Iterator4 i = new Iterator4Impl(_stillToDeactivate);
0475: _stillToDeactivate = null;
0476: while (i.moveNext()) {
0477: PendingActivation item = (PendingActivation) i
0478: .current();
0479: item.ref.deactivate(trans, item.depth);
0480: }
0481: }
0482: }
0483:
0484: public final void delete(Transaction trans, Object obj)
0485: throws DatabaseReadOnlyException, DatabaseClosedException {
0486: synchronized (_lock) {
0487: trans = checkTransaction(trans);
0488: checkReadOnly();
0489: delete1(trans, obj, true);
0490: trans.processDeletes();
0491: }
0492: }
0493:
0494: public final void delete1(Transaction trans, Object obj,
0495: boolean userCall) {
0496: if (obj == null) {
0497: return;
0498: }
0499: ObjectReference ref = trans.referenceForObject(obj);
0500: if (ref == null) {
0501: return;
0502: }
0503: if (userCall) {
0504: generateCallIDOnTopLevel();
0505: }
0506: try {
0507: beginTopLevelCall();
0508: delete2(trans, ref, obj, 0, userCall);
0509: completeTopLevelCall();
0510: } catch (Db4oException e) {
0511: completeTopLevelCall(e);
0512: } finally {
0513: endTopLevelCall();
0514: }
0515: }
0516:
0517: public final void delete2(Transaction trans, ObjectReference ref,
0518: Object obj, int cascade, boolean userCall) {
0519:
0520: // This check is performed twice, here and in delete3, intentionally.
0521: if (breakDeleteForEnum(ref, userCall)) {
0522: return;
0523: }
0524:
0525: if (obj instanceof SecondClass) {
0526: if (!flagForDelete(ref)) {
0527: return;
0528: }
0529: delete3(trans, ref, cascade, userCall);
0530: return;
0531: }
0532:
0533: trans.delete(ref, ref.getID(), cascade);
0534: }
0535:
0536: final void delete3(Transaction trans, ObjectReference ref,
0537: int cascade, boolean userCall) {
0538:
0539: // The passed reference can be null, when calling from Transaction.
0540: if (ref == null || !ref.beginProcessing()) {
0541: return;
0542: }
0543:
0544: // This check is performed twice, here and in delete2, intentionally.
0545: if (breakDeleteForEnum(ref, userCall)) {
0546: ref.endProcessing();
0547: return;
0548: }
0549:
0550: if (!ref.isFlaggedForDelete()) {
0551: ref.endProcessing();
0552: return;
0553: }
0554:
0555: ClassMetadata yc = ref.classMetadata();
0556: Object obj = ref.getObject();
0557:
0558: // We have to end processing temporarily here, otherwise the can delete callback
0559: // can't do anything at all with this object.
0560:
0561: ref.endProcessing();
0562:
0563: activateForDeletionCallback(trans, yc, obj);
0564:
0565: if (!objectCanDelete(trans, yc, obj)) {
0566: return;
0567: }
0568:
0569: ref.beginProcessing();
0570:
0571: if (DTrace.enabled) {
0572: DTrace.DELETE.log(ref.getID());
0573: }
0574:
0575: if (delete4(trans, ref, cascade, userCall)) {
0576: objectOnDelete(trans, yc, obj);
0577: if (configImpl().messageLevel() > Const4.STATE) {
0578: message("" + ref.getID() + " delete "
0579: + ref.classMetadata().getName());
0580: }
0581: }
0582:
0583: ref.endProcessing();
0584: }
0585:
0586: private void activateForDeletionCallback(Transaction trans,
0587: ClassMetadata yc, Object obj) {
0588: if (!isActive(trans, obj)
0589: && (caresAboutDeleting(yc) || caresAboutDeleted(yc))) {
0590: // Activate Objects for Callbacks, because in C/S mode Objects are not activated on the Server
0591: activate(trans, obj, 1);
0592: }
0593: }
0594:
0595: private boolean caresAboutDeleting(ClassMetadata yc) {
0596: return this ._callbacks.caresAboutDeleting()
0597: || yc.hasEventRegistered(_this ,
0598: EventDispatcher.CAN_DELETE);
0599: }
0600:
0601: private boolean caresAboutDeleted(ClassMetadata yc) {
0602: return this ._callbacks.caresAboutDeleted()
0603: || yc.hasEventRegistered(_this , EventDispatcher.DELETE);
0604: }
0605:
0606: private boolean objectCanDelete(Transaction transaction,
0607: ClassMetadata yc, Object obj) {
0608: return _this .callbacks().objectCanDelete(transaction, obj)
0609: && yc.dispatchEvent(_this , obj,
0610: EventDispatcher.CAN_DELETE);
0611: }
0612:
0613: private void objectOnDelete(Transaction transaction,
0614: ClassMetadata yc, Object obj) {
0615: _this .callbacks().objectOnDelete(transaction, obj);
0616: yc.dispatchEvent(_this , obj, EventDispatcher.DELETE);
0617: }
0618:
0619: public abstract boolean delete4(Transaction ta,
0620: ObjectReference yapObject, int a_cascade, boolean userCall);
0621:
0622: Object descend(Transaction trans, Object obj, String[] path) {
0623: synchronized (_lock) {
0624: trans = checkTransaction(trans);
0625: ObjectReference ref = trans.referenceForObject(obj);
0626: if (ref == null) {
0627: return null;
0628: }
0629:
0630: final String fieldName = path[0];
0631: if (fieldName == null) {
0632: return null;
0633: }
0634: ClassMetadata classMetadata = ref.classMetadata();
0635: final FieldMetadata[] field = new FieldMetadata[] { null };
0636: classMetadata.forEachFieldMetadata(new Visitor4() {
0637: public void visit(Object yf) {
0638: FieldMetadata yapField = (FieldMetadata) yf;
0639: if (yapField.canAddToQuery(fieldName)) {
0640: field[0] = yapField;
0641: }
0642: }
0643: });
0644: if (field[0] == null) {
0645: return null;
0646: }
0647:
0648: Object child = ref.isActive() ? field[0].get(trans, obj)
0649: : new UnmarshallingContext(trans, ref,
0650: Const4.ADD_TO_ID_TREE, false)
0651: .readFieldValue(field[0]);
0652:
0653: if (path.length == 1) {
0654: return child;
0655: }
0656: if (child == null) {
0657: return null;
0658: }
0659: String[] subPath = new String[path.length - 1];
0660: System.arraycopy(path, 1, subPath, 0, path.length - 1);
0661: return descend(trans, child, subPath);
0662: }
0663: }
0664:
0665: public boolean detectSchemaChanges() {
0666: // overriden in YapClient
0667: return configImpl().detectSchemaChanges();
0668: }
0669:
0670: public boolean dispatchsEvents() {
0671: return true;
0672: }
0673:
0674: protected boolean doFinalize() {
0675: return true;
0676: }
0677:
0678: /*
0679: * This method will be exuected on finalization, and vm exit if it's enabled
0680: * by configuration.
0681: */
0682: final void shutdownHook() {
0683: if (isClosed()) {
0684: return;
0685: }
0686: if (allOperationsCompleted()) {
0687: Messages.logErr(configImpl(), 50, toString(), null);
0688: close();
0689: } else {
0690: shutdownObjectContainer();
0691: if (operationIsProcessing()) {
0692: Messages.logErr(configImpl(), 24, null, null);
0693: }
0694: }
0695: }
0696:
0697: private boolean operationIsProcessing() {
0698: return _stackDepth > 0;
0699: }
0700:
0701: private boolean allOperationsCompleted() {
0702: return _stackDepth == 0;
0703: }
0704:
0705: void fatalException(int msgID) {
0706: fatalException(null, msgID);
0707: }
0708:
0709: final void fatalException(Throwable t) {
0710: fatalException(t, Messages.FATAL_MSG_ID);
0711: }
0712:
0713: final void fatalException(Throwable t, int msgID) {
0714: Messages.logErr(configImpl(),
0715: (msgID == Messages.FATAL_MSG_ID ? 18 : msgID), null, t);
0716: if (!isClosed()) {
0717: shutdownObjectContainer();
0718: }
0719: throw new RuntimeException(Messages.get(msgID));
0720: }
0721:
0722: /**
0723: * @sharpen.ignore
0724: */
0725: protected void finalize() {
0726: if (doFinalize() && configuredForAutomaticShutDown()) {
0727: shutdownHook();
0728: }
0729: }
0730:
0731: private boolean configuredForAutomaticShutDown() {
0732: return (configImpl() == null || configImpl()
0733: .automaticShutDown());
0734: }
0735:
0736: void gc() {
0737: _references.pollReferenceQueue();
0738: }
0739:
0740: public final ObjectSet get(Transaction trans, Object template) {
0741: synchronized (_lock) {
0742: trans = checkTransaction(trans);
0743: QueryResult res = null;
0744: try {
0745: beginTopLevelCall();
0746: res = getInternal(trans, template);
0747: completeTopLevelCall();
0748: } catch (Db4oException e) {
0749: completeTopLevelCall(e);
0750: } finally {
0751: endTopLevelCall();
0752: }
0753: return new ObjectSetFacade(res);
0754: }
0755: }
0756:
0757: private final QueryResult getInternal(Transaction trans,
0758: Object template) {
0759: if (template == null
0760: || template.getClass() == Const4.CLASS_OBJECT) {
0761: return getAll(trans);
0762: }
0763: Query q = query(trans);
0764: q.constrain(template);
0765: return executeQuery((QQuery) q);
0766: }
0767:
0768: public abstract AbstractQueryResult getAll(Transaction ta);
0769:
0770: public final Object getByID(Transaction ta, long id)
0771: throws DatabaseClosedException, InvalidIDException {
0772: synchronized (_lock) {
0773: if (id <= 0) {
0774: throw new IllegalArgumentException();
0775: }
0776: checkClosed();
0777: ta = checkTransaction(ta);
0778: beginTopLevelCall();
0779: try {
0780: Object obj = getByID2(ta, (int) id);
0781: completeTopLevelCall();
0782: return obj;
0783: } catch (Db4oException e) {
0784: completeTopLevelCall(new InvalidIDException(e));
0785: } finally {
0786: endTopLevelCall();
0787: }
0788: // only to make the compiler happy
0789: return null;
0790: }
0791: }
0792:
0793: public final Object getByID2(Transaction ta, int id) {
0794: Object obj = ta.objectForIdFromCache(id);
0795: if (obj != null) {
0796: // Take care about handling the returned candidate reference.
0797: // If you loose the reference, weak reference management might
0798: // also.
0799: return obj;
0800:
0801: }
0802: return new ObjectReference(id).read(ta, 0,
0803: Const4.ADD_TO_ID_TREE, true);
0804: }
0805:
0806: public final Object getActivatedObjectFromCache(Transaction ta,
0807: int id) {
0808: Object obj = ta.objectForIdFromCache(id);
0809: if (obj == null) {
0810: return null;
0811: }
0812: activate(ta, obj, configImpl().activationDepth());
0813: return obj;
0814: }
0815:
0816: public final Object readActivatedObjectNotInCache(Transaction ta,
0817: int id) {
0818: Object obj = null;
0819: beginTopLevelCall();
0820: try {
0821: obj = new ObjectReference(id).read(ta, configImpl()
0822: .activationDepth(), Const4.ADD_TO_ID_TREE, true);
0823: completeTopLevelCall();
0824: } catch (Db4oException e) {
0825: completeTopLevelCall(e);
0826: } finally {
0827: endTopLevelCall();
0828: }
0829: activatePending(ta);
0830: return obj;
0831: }
0832:
0833: public final Object getByUUID(Transaction trans, Db4oUUID uuid) {
0834: synchronized (_lock) {
0835: if (uuid == null) {
0836: return null;
0837: }
0838: trans = checkTransaction(trans);
0839: HardObjectReference hardRef = trans
0840: .getHardReferenceBySignature(uuid.getLongPart(),
0841: uuid.getSignaturePart());
0842: return hardRef._object;
0843: }
0844: }
0845:
0846: public final int getID(Transaction trans, Object obj) {
0847: synchronized (_lock) {
0848: trans = checkTransaction(trans);
0849: checkClosed();
0850:
0851: if (obj == null) {
0852: return 0;
0853: }
0854:
0855: ObjectReference yo = trans.referenceForObject(obj);
0856: if (yo != null) {
0857: return yo.getID();
0858: }
0859: return 0;
0860: }
0861: }
0862:
0863: public final ObjectInfo getObjectInfo(Transaction trans, Object obj) {
0864: synchronized (_lock) {
0865: trans = checkTransaction(trans);
0866: return trans.referenceForObject(obj);
0867: }
0868: }
0869:
0870: public final HardObjectReference getHardObjectReferenceById(
0871: Transaction trans, int id) {
0872: if (id <= 0) {
0873: return HardObjectReference.INVALID;
0874: }
0875:
0876: ObjectReference ref = trans.referenceForId(id);
0877: if (ref != null) {
0878:
0879: // Take care about handling the returned candidate reference.
0880: // If you loose the reference, weak reference management might also.
0881:
0882: Object candidate = ref.getObject();
0883: if (candidate != null) {
0884: return new HardObjectReference(ref, candidate);
0885: }
0886: trans.removeReference(ref);
0887: }
0888: ref = new ObjectReference(id);
0889: Object readObject = ref.read(trans, 0, Const4.ADD_TO_ID_TREE,
0890: true);
0891:
0892: if (readObject == null) {
0893: return HardObjectReference.INVALID;
0894: }
0895:
0896: // check class creation side effect and simply retry recursively
0897: // if it hits:
0898: if (readObject != ref.getObject()) {
0899: return getHardObjectReferenceById(trans, id);
0900: }
0901:
0902: return new HardObjectReference(ref, readObject);
0903: }
0904:
0905: public final StatefulBuffer getWriter(Transaction a_trans,
0906: int a_address, int a_length) {
0907: if (Debug.exceedsMaximumBlockSize(a_length)) {
0908: return null;
0909: }
0910: return new StatefulBuffer(a_trans, a_address, a_length);
0911: }
0912:
0913: public final Transaction systemTransaction() {
0914: return _systemTransaction;
0915: }
0916:
0917: public final Transaction transaction() {
0918: return _transaction;
0919: }
0920:
0921: public final ClassMetadata classMetadataForReflectClass(
0922: ReflectClass claxx) {
0923: if (cantGetClassMetadata(claxx)) {
0924: return null;
0925: }
0926: ClassMetadata yc = _handlers.classMetadataForClass(claxx);
0927: if (yc != null) {
0928: return yc;
0929: }
0930: return _classCollection.classMetadataForReflectClass(claxx);
0931: }
0932:
0933: // TODO: Some ReflectClass implementations could hold a
0934: // reference to ClassMetadata to improve lookup performance here.
0935: public ClassMetadata produceClassMetadata(ReflectClass claxx) {
0936: if (cantGetClassMetadata(claxx)) {
0937: return null;
0938: }
0939: ClassMetadata classMetadata = _handlers
0940: .classMetadataForClass(claxx);
0941: if (classMetadata != null) {
0942: return classMetadata;
0943: }
0944: return _classCollection.produceClassMetadata(claxx);
0945: }
0946:
0947: /**
0948: * Differentiating getActiveYapClass from getYapClass is a tuning
0949: * optimization: If we initialize a YapClass, #set3() has to check for
0950: * the possibility that class initialization associates the currently
0951: * stored object with a previously stored static object, causing the
0952: * object to be known afterwards.
0953: *
0954: * In this call we only return active YapClasses, initialization
0955: * is not done on purpose
0956: */
0957: final ClassMetadata getActiveClassMetadata(ReflectClass claxx) {
0958: if (cantGetClassMetadata(claxx)) {
0959: return null;
0960: }
0961: ClassMetadata yc = _handlers.classMetadataForClass(claxx);
0962: if (yc != null) {
0963: return yc;
0964: }
0965: return _classCollection.getActiveYapClass(claxx);
0966: }
0967:
0968: private final boolean cantGetClassMetadata(ReflectClass claxx) {
0969: if (claxx == null) {
0970: return true;
0971: }
0972: if ((!showInternalClasses())
0973: && _handlers.ICLASS_INTERNAL.isAssignableFrom(claxx)) {
0974: return true;
0975: }
0976: return false;
0977: }
0978:
0979: public int classMetadataIdForName(String name) {
0980: return _classCollection.classMetadataIdForName(name);
0981: }
0982:
0983: public ClassMetadata classMetadataForName(String name) {
0984: return classMetadataForId(classMetadataIdForName(name));
0985: }
0986:
0987: public ClassMetadata classMetadataForId(int id) {
0988: if (DTrace.enabled) {
0989: DTrace.YAPCLASS_BY_ID.log(id);
0990: }
0991: if (id == 0) {
0992: return null;
0993: }
0994: ClassMetadata yc = _handlers.classMetadataForId(id);
0995: if (yc != null) {
0996: return yc;
0997: }
0998: return _classCollection.getYapClass(id);
0999: }
1000:
1001: public HandlerRegistry handlers() {
1002: return _handlers;
1003: }
1004:
1005: public boolean needsLockFileThread() {
1006: if (!Debug.lockFile) {
1007: return false;
1008: }
1009: if (!Platform4.hasLockFileThread()) {
1010: return false;
1011: }
1012: if (Platform4.hasNio()) {
1013: return false;
1014: }
1015: if (configImpl().isReadOnly()) {
1016: return false;
1017: }
1018: return configImpl().lockFile();
1019: }
1020:
1021: protected boolean hasShutDownHook() {
1022: return configImpl().automaticShutDown();
1023: }
1024:
1025: protected void initialize1(Configuration config) {
1026: _config = initializeConfig(config);
1027: _handlers = new HandlerRegistry(_this , configImpl().encoding(),
1028: configImpl().reflector());
1029:
1030: if (_references != null) {
1031: gc();
1032: _references.stopTimer();
1033: }
1034:
1035: _references = new WeakReferenceCollector(_this );
1036:
1037: if (hasShutDownHook()) {
1038: Platform4.addShutDownHook(this );
1039: }
1040: _handlers.initEncryption(configImpl());
1041: initialize2();
1042: _stillToSet = null;
1043: }
1044:
1045: private Config4Impl initializeConfig(Configuration config) {
1046: Config4Impl impl = ((Config4Impl) config);
1047: impl.stream(_this );
1048: impl.reflector().setTransaction(systemTransaction());
1049: return impl;
1050: }
1051:
1052: /**
1053: * before file is open
1054: */
1055: void initialize2() {
1056: initialize2NObjectCarrier();
1057: }
1058:
1059: public final TransactionalReferenceSystem createReferenceSystem() {
1060: TransactionalReferenceSystem referenceSystem = new TransactionalReferenceSystem();
1061: _referenceSystemRegistry.addReferenceSystem(referenceSystem);
1062: return referenceSystem;
1063: }
1064:
1065: /**
1066: * overridden in YapObjectCarrier
1067: */
1068: void initialize2NObjectCarrier() {
1069: _classCollection = new ClassMetadataRepository(
1070: _systemTransaction);
1071: _references.startTimer();
1072: }
1073:
1074: private void initializePostOpen() {
1075: _showInternalClasses = 100000;
1076: initializePostOpenExcludingTransportObjectContainer();
1077: _showInternalClasses = 0;
1078: }
1079:
1080: protected void initializePostOpenExcludingTransportObjectContainer() {
1081: initializeEssentialClasses();
1082: rename(configImpl());
1083: _classCollection.initOnUp(_systemTransaction);
1084: if (configImpl().detectSchemaChanges()) {
1085: _systemTransaction.commit();
1086: }
1087: configImpl().applyConfigurationItems(cast(_this ));
1088: }
1089:
1090: void initializeEssentialClasses() {
1091: for (int i = 0; i < Const4.ESSENTIAL_CLASSES.length; i++) {
1092: produceClassMetadata(reflector().forClass(
1093: Const4.ESSENTIAL_CLASSES[i]));
1094: }
1095: }
1096:
1097: final void instantiating(boolean flag) {
1098: _instantiating = flag;
1099: }
1100:
1101: final boolean isActive(Transaction trans, Object obj) {
1102: synchronized (_lock) {
1103: trans = checkTransaction(trans);
1104: if (obj != null) {
1105: ObjectReference ref = trans.referenceForObject(obj);
1106: if (ref != null) {
1107: return ref.isActive();
1108: }
1109: }
1110: return false;
1111: }
1112: }
1113:
1114: public boolean isCached(Transaction trans, long id) {
1115: synchronized (_lock) {
1116: trans = checkTransaction(trans);
1117: return trans.objectForIdFromCache((int) id) != null;
1118: }
1119: }
1120:
1121: /**
1122: * overridden in YapClient
1123: * This method will make it easier to refactor than
1124: * an "instanceof YapClient" check.
1125: */
1126: public boolean isClient() {
1127: return false;
1128: }
1129:
1130: public final boolean isClosed() {
1131: synchronized (_lock) {
1132: return _classCollection == null;
1133: }
1134: }
1135:
1136: final boolean isInstantiating() {
1137: return _instantiating;
1138: }
1139:
1140: boolean isServer() {
1141: return false;
1142: }
1143:
1144: public final boolean isStored(Transaction trans, Object obj) {
1145: synchronized (_lock) {
1146: trans = checkTransaction(trans);
1147: if (obj == null) {
1148: return false;
1149: }
1150: ObjectReference ref = trans.referenceForObject(obj);
1151: if (ref == null) {
1152: return false;
1153: }
1154: return !trans.isDeleted(ref.getID());
1155: }
1156: }
1157:
1158: public ReflectClass[] knownClasses() {
1159: synchronized (_lock) {
1160: checkClosed();
1161: return reflector().knownClasses();
1162: }
1163: }
1164:
1165: public TypeHandler4 handlerByID(int id) {
1166: if (id < 1) {
1167: return null;
1168: }
1169: if (_handlers.isSystemHandler(id)) {
1170: return _handlers.handlerForID(id);
1171: }
1172: return classMetadataForId(id);
1173: }
1174:
1175: public Object lock() {
1176: return _lock;
1177: }
1178:
1179: public final void logMsg(int code, String msg) {
1180: Messages.logMsg(configImpl(), code, msg);
1181: }
1182:
1183: public boolean maintainsIndices() {
1184: return true;
1185: }
1186:
1187: void message(String msg) {
1188: new Message(_this , msg);
1189: }
1190:
1191: public void migrateFrom(ObjectContainer objectContainer) {
1192: if (objectContainer == null) {
1193: if (_replicationCallState == Const4.NONE) {
1194: return;
1195: }
1196: _replicationCallState = Const4.NONE;
1197: if (_handlers.i_migration != null) {
1198: _handlers.i_migration.terminate();
1199: }
1200: _handlers.i_migration = null;
1201: } else {
1202: ObjectContainerBase peer = (ObjectContainerBase) objectContainer;
1203: _replicationCallState = Const4.OLD;
1204: peer._replicationCallState = Const4.OLD;
1205: _handlers.i_migration = new MigrationConnection(_this ,
1206: (ObjectContainerBase) objectContainer);
1207: peer._handlers.i_migration = _handlers.i_migration;
1208: }
1209: }
1210:
1211: public final void needsUpdate(ClassMetadata a_yapClass) {
1212: _pendingClassUpdates = new List4(_pendingClassUpdates,
1213: a_yapClass);
1214: }
1215:
1216: public long generateTimeStampId() {
1217: return _timeStampIdGenerator.next();
1218: }
1219:
1220: public abstract int newUserObject();
1221:
1222: public final Object peekPersisted(Transaction trans, Object obj,
1223: int depth, boolean committed)
1224: throws DatabaseClosedException {
1225:
1226: // TODO: peekPersisted is not stack overflow safe, if depth is too high.
1227:
1228: synchronized (_lock) {
1229: checkClosed();
1230: beginTopLevelCall();
1231: try {
1232: trans = checkTransaction(trans);
1233: ObjectReference ref = trans.referenceForObject(obj);
1234: trans = committed ? _systemTransaction : trans;
1235: Object cloned = null;
1236: if (ref != null) {
1237: cloned = peekPersisted(trans, ref.getID(), depth,
1238: true);
1239: }
1240: completeTopLevelCall();
1241: return cloned;
1242: } catch (Db4oException e) {
1243: completeTopLevelCall(e);
1244: return null;
1245: } finally {
1246: endTopLevelCall();
1247: }
1248: }
1249: }
1250:
1251: public final Object peekPersisted(Transaction trans, int id,
1252: int depth, boolean resetJustPeeked) {
1253: if (depth < 0) {
1254: return null;
1255: }
1256: if (resetJustPeeked) {
1257: _justPeeked = null;
1258: } else {
1259: TreeInt ti = new TreeInt(id);
1260: TreeIntObject tio = (TreeIntObject) Tree.find(_justPeeked,
1261: ti);
1262: if (tio != null) {
1263: return tio._object;
1264: }
1265: }
1266: Object res = new ObjectReference(id)
1267: .peekPersisted(trans, depth);
1268: if (resetJustPeeked) {
1269: _justPeeked = null;
1270: }
1271: return res;
1272: }
1273:
1274: void peeked(int id, Object obj) {
1275: _justPeeked = Tree.add(_justPeeked, new TreeIntObject(id, obj));
1276: }
1277:
1278: public void purge() {
1279: synchronized (_lock) {
1280: checkClosed();
1281: System.gc();
1282: System.runFinalization();
1283: System.gc();
1284: gc();
1285: _classCollection.purge();
1286: }
1287: }
1288:
1289: public final void purge(Transaction trans, Object obj) {
1290: synchronized (_lock) {
1291: trans = checkTransaction(trans);
1292: trans.removeObjectFromReferenceSystem(obj);
1293: }
1294: }
1295:
1296: final void removeFromAllReferenceSystems(Object obj) {
1297: if (obj == null) {
1298: return;
1299: }
1300: if (obj instanceof ObjectReference) {
1301: _referenceSystemRegistry
1302: .removeReference((ObjectReference) obj);
1303: return;
1304: }
1305: _referenceSystemRegistry.removeObject(obj);
1306: }
1307:
1308: public final NativeQueryHandler getNativeQueryHandler() {
1309: synchronized (_lock) {
1310: if (null == _nativeQueryHandler) {
1311: _nativeQueryHandler = new NativeQueryHandler(
1312: cast(_this ));
1313: }
1314: return _nativeQueryHandler;
1315: }
1316: }
1317:
1318: public final ObjectSet query(Transaction trans, Predicate predicate) {
1319: return query(trans, predicate, (QueryComparator) null);
1320: }
1321:
1322: public final ObjectSet query(Transaction trans,
1323: Predicate predicate, QueryComparator comparator) {
1324: synchronized (_lock) {
1325: trans = checkTransaction(trans);
1326: return getNativeQueryHandler().execute(query(trans),
1327: predicate, comparator);
1328: }
1329: }
1330:
1331: public final ObjectSet query(Transaction trans, Class clazz) {
1332: return get(trans, clazz);
1333: }
1334:
1335: public final Query query(Transaction ta) {
1336: return new QQuery(checkTransaction(ta), null, null);
1337: }
1338:
1339: public abstract void raiseVersion(long a_minimumVersion);
1340:
1341: public abstract void readBytes(byte[] a_bytes, int a_address,
1342: int a_length) throws Db4oIOException;
1343:
1344: public abstract void readBytes(byte[] bytes, int address,
1345: int addressOffset, int length) throws Db4oIOException;
1346:
1347: public final Buffer bufferByAddress(int address, int length)
1348: throws Db4oIOException {
1349: checkAddress(address);
1350:
1351: Buffer reader = new Buffer(length);
1352: readBytes(reader._buffer, address, length);
1353: _handlers.decrypt(reader);
1354: return reader;
1355: }
1356:
1357: private void checkAddress(int address)
1358: throws IllegalArgumentException {
1359: if (address <= 0) {
1360: throw new IllegalArgumentException(
1361: "Invalid address offset: " + address);
1362: }
1363: }
1364:
1365: public final StatefulBuffer readWriterByAddress(
1366: Transaction a_trans, int address, int length)
1367: throws Db4oIOException {
1368: checkAddress(address);
1369: StatefulBuffer reader = getWriter(a_trans, address, length);
1370: reader.readEncrypt(_this , address);
1371: return reader;
1372: }
1373:
1374: public abstract StatefulBuffer readWriterByID(Transaction a_ta,
1375: int a_id);
1376:
1377: public abstract Buffer readReaderByID(Transaction a_ta, int a_id);
1378:
1379: public abstract StatefulBuffer[] readWritersByIDs(Transaction a_ta,
1380: int[] ids);
1381:
1382: private void reboot() {
1383: commit(null);
1384: close();
1385: open();
1386: }
1387:
1388: public GenericReflector reflector() {
1389: return _handlers._reflector;
1390: }
1391:
1392: public final void refresh(Transaction trans, Object obj, int depth) {
1393: synchronized (_lock) {
1394: _refreshInsteadOfActivate = true;
1395: try {
1396: activate(trans, obj, depth);
1397: } finally {
1398: _refreshInsteadOfActivate = false;
1399: }
1400: }
1401: }
1402:
1403: final void refreshClasses() {
1404: synchronized (_lock) {
1405: _classCollection.refreshClasses();
1406: }
1407: }
1408:
1409: public abstract void releaseSemaphore(String name);
1410:
1411: public void flagAsHandled(ObjectReference ref) {
1412: ref.flagAsHandled(_topLevelCallId);
1413: }
1414:
1415: boolean flagForDelete(ObjectReference ref) {
1416: if (ref == null) {
1417: return false;
1418: }
1419: if (handledInCurrentTopLevelCall(ref)) {
1420: return false;
1421: }
1422: ref.flagForDelete(_topLevelCallId);
1423: return true;
1424: }
1425:
1426: public abstract void releaseSemaphores(Transaction ta);
1427:
1428: void rename(Config4Impl config) {
1429: boolean renamedOne = false;
1430: if (config.rename() != null) {
1431: renamedOne = rename1(config);
1432: }
1433: _classCollection.checkChanges();
1434: if (renamedOne) {
1435: reboot();
1436: }
1437: }
1438:
1439: protected boolean rename1(Config4Impl config) {
1440: boolean renamedOne = false;
1441: Iterator4 i = config.rename().iterator();
1442: while (i.moveNext()) {
1443: Rename ren = (Rename) i.current();
1444: if (get(systemTransaction(), ren).size() == 0) {
1445: boolean renamed = false;
1446: boolean isField = ren.rClass.length() > 0;
1447: ClassMetadata yapClass = _classCollection
1448: .getYapClass(isField ? ren.rClass : ren.rFrom);
1449: if (yapClass != null) {
1450: if (isField) {
1451: renamed = yapClass.renameField(ren.rFrom,
1452: ren.rTo);
1453: } else {
1454: ClassMetadata existing = _classCollection
1455: .getYapClass(ren.rTo);
1456: if (existing == null) {
1457: yapClass.setName(ren.rTo);
1458: renamed = true;
1459: } else {
1460: logMsg(9, "class " + ren.rTo);
1461: }
1462: }
1463: }
1464: if (renamed) {
1465: renamedOne = true;
1466: setDirtyInSystemTransaction(yapClass);
1467:
1468: logMsg(8, ren.rFrom + " to " + ren.rTo);
1469:
1470: // delete all that rename from the new name
1471: // to allow future backswitching
1472: ObjectSet backren = get(systemTransaction(),
1473: new Rename(ren.rClass, null, ren.rFrom));
1474: while (backren.hasNext()) {
1475: delete(systemTransaction(), backren.next());
1476: }
1477:
1478: // store the rename, so we only do it once
1479: set(systemTransaction(), ren);
1480: }
1481: }
1482: }
1483:
1484: return renamedOne;
1485: }
1486:
1487: /**
1488: * @deprecated see {@link ReplicationProcess}
1489: */
1490: public ReplicationProcess replicationBegin(ObjectContainer peerB,
1491: ReplicationConflictHandler conflictHandler) {
1492: return new ReplicationImpl(_this , (ObjectContainerBase) peerB,
1493: conflictHandler);
1494: }
1495:
1496: /**
1497: * @deprecated
1498: */
1499: public final int oldReplicationHandles(Transaction trans, Object obj) {
1500:
1501: // The double check on i_migrateFrom is necessary:
1502: // i_handlers.i_replicateFrom may be set in YapObjectCarrier for parent
1503: // YapStream
1504: if (_replicationCallState != Const4.OLD) {
1505: return 0;
1506: }
1507:
1508: if (_handlers.i_replication == null) {
1509: return 0;
1510: }
1511:
1512: if (obj instanceof Internal4) {
1513: return 0;
1514: }
1515:
1516: ObjectReference reference = trans.referenceForObject(obj);
1517: if (reference != null
1518: && handledInCurrentTopLevelCall(reference)) {
1519: return reference.getID();
1520: }
1521:
1522: return _handlers.i_replication.tryToHandle(_this , obj);
1523: }
1524:
1525: public final boolean handledInCurrentTopLevelCall(
1526: ObjectReference ref) {
1527: return ref.isFlaggedAsHandled(_topLevelCallId);
1528: }
1529:
1530: public abstract void reserve(int byteCount);
1531:
1532: public final void rollback(Transaction trans) {
1533: synchronized (_lock) {
1534: trans = checkTransaction(trans);
1535: checkReadOnly();
1536: rollback1(trans);
1537: trans.rollbackReferenceSystem();
1538: }
1539: }
1540:
1541: public abstract void rollback1(Transaction trans);
1542:
1543: /** @param obj */
1544: public void send(Object obj) {
1545: // TODO: implement
1546: throw new NotSupportedException();
1547: }
1548:
1549: public final void set(Transaction trans, Object obj)
1550: throws DatabaseClosedException, DatabaseReadOnlyException {
1551: set(trans, obj, Const4.UNSPECIFIED);
1552: }
1553:
1554: public final void set(Transaction trans, Object obj, int depth)
1555: throws DatabaseClosedException, DatabaseReadOnlyException {
1556: synchronized (_lock) {
1557: setInternal(trans, obj, depth, true);
1558: }
1559: }
1560:
1561: public final int setInternal(Transaction trans, Object obj,
1562: boolean checkJustSet) throws DatabaseClosedException,
1563: DatabaseReadOnlyException {
1564: return setInternal(trans, obj, Const4.UNSPECIFIED, checkJustSet);
1565: }
1566:
1567: public final int setInternal(Transaction trans, Object obj,
1568: int depth, boolean checkJustSet)
1569: throws DatabaseClosedException, DatabaseReadOnlyException {
1570: trans = checkTransaction(trans);
1571: checkReadOnly();
1572: beginTopLevelSet();
1573: try {
1574: int id = oldReplicationHandles(trans, obj);
1575: if (id != 0) {
1576: completeTopLevelSet();
1577: if (id < 0) {
1578: return 0;
1579: }
1580: return id;
1581: }
1582: id = setAfterReplication(trans, obj, depth, checkJustSet);
1583: completeTopLevelSet();
1584: return id;
1585: } catch (Db4oException e) {
1586: completeTopLevelSet(e);
1587: return 0;
1588: } finally {
1589: endTopLevelSet(trans);
1590: }
1591: }
1592:
1593: public final int setAfterReplication(Transaction trans, Object obj,
1594: int depth, boolean checkJust) {
1595:
1596: if (obj instanceof Db4oType) {
1597: Db4oType db4oType = db4oTypeStored(trans, obj);
1598: if (db4oType != null) {
1599: return getID(trans, db4oType);
1600: }
1601: }
1602:
1603: if (Deploy.debug) {
1604: return set2(trans, obj, depth, checkJust);
1605: }
1606:
1607: try {
1608: return set2(trans, obj, depth, checkJust);
1609: } catch (ObjectNotStorableException e) {
1610: throw e;
1611: } catch (Db4oException exc) {
1612: throw exc;
1613: }
1614: }
1615:
1616: public final void setByNewReplication(
1617: Db4oReplicationReferenceProvider referenceProvider,
1618: Object obj) {
1619: synchronized (_lock) {
1620: _replicationCallState = Const4.NEW;
1621: _handlers._replicationReferenceProvider = referenceProvider;
1622:
1623: set2(checkTransaction(), obj, 1, false);
1624:
1625: _replicationCallState = Const4.NONE;
1626: _handlers._replicationReferenceProvider = null;
1627: }
1628: }
1629:
1630: private final int set2(Transaction trans, Object obj, int depth,
1631: boolean checkJust) {
1632: int id = set3(trans, obj, depth, checkJust);
1633: if (stackIsSmall()) {
1634: checkStillToSet();
1635: }
1636: return id;
1637: }
1638:
1639: public void checkStillToSet() {
1640: List4 postponedStillToSet = null;
1641: while (_stillToSet != null) {
1642: Iterator4 i = new Iterator4Impl(_stillToSet);
1643: _stillToSet = null;
1644: while (i.moveNext()) {
1645: PendingSet item = (PendingSet) i.current();
1646:
1647: ObjectReference ref = item.ref;
1648: Transaction trans = item.transaction;
1649:
1650: if (!ref.continueSet(trans, item.depth)) {
1651: postponedStillToSet = new List4(
1652: postponedStillToSet, item);
1653: }
1654: }
1655: }
1656: _stillToSet = postponedStillToSet;
1657: }
1658:
1659: void notStorable(ReflectClass claxx, Object obj) {
1660: if (!configImpl().exceptionsOnNotStorable()) {
1661: return;
1662: }
1663:
1664: // FIXME: Exceptions configuration setting cant be modified
1665: // from running ObjectContainer.
1666: // Right now all tests fail, if we don't jump out here.
1667:
1668: // The StorePrimitiveDirectly test case documents the err.
1669:
1670: if (true) {
1671: return;
1672: }
1673:
1674: if (claxx != null) {
1675: throw new ObjectNotStorableException(claxx);
1676: }
1677:
1678: throw new ObjectNotStorableException(obj.toString());
1679: }
1680:
1681: public final int set3(Transaction trans, Object obj,
1682: int updateDepth, boolean checkJustSet) {
1683: if (obj == null || (obj instanceof TransientClass)) {
1684: return 0;
1685: }
1686:
1687: if (obj instanceof Db4oTypeImpl) {
1688: ((Db4oTypeImpl) obj).storedTo(trans);
1689: }
1690:
1691: ObjectAnalyzer analyzer = new ObjectAnalyzer(this , obj);
1692: analyzer.analyze(trans);
1693: if (analyzer.notStorable()) {
1694: return 0;
1695: }
1696:
1697: ObjectReference ref = analyzer.objectReference();
1698:
1699: if (ref == null) {
1700: ClassMetadata classMetadata = analyzer.classMetadata();
1701: if (!objectCanNew(trans, classMetadata, obj)) {
1702: return 0;
1703: }
1704: ref = new ObjectReference();
1705: ref.store(trans, classMetadata, obj);
1706: trans.addNewReference(ref);
1707: if (obj instanceof Db4oTypeImpl) {
1708: ((Db4oTypeImpl) obj).setTrans(trans);
1709: }
1710: if (configImpl().messageLevel() > Const4.STATE) {
1711: message("" + ref.getID() + " new "
1712: + ref.classMetadata().getName());
1713: }
1714:
1715: flagAsHandled(ref);
1716: stillToSet(trans, ref, updateDepth);
1717:
1718: } else {
1719: if (canUpdate()) {
1720: if (checkJustSet) {
1721: if ((!ref.isNew())
1722: && handledInCurrentTopLevelCall(ref)) {
1723: return ref.getID();
1724: }
1725: }
1726: if (updateDepthSufficient(updateDepth)) {
1727: flagAsHandled(ref);
1728: ref.writeUpdate(trans, updateDepth);
1729: }
1730: }
1731: }
1732: processPendingClassUpdates();
1733: return ref.getID();
1734: }
1735:
1736: private final boolean updateDepthSufficient(int updateDepth) {
1737: return (updateDepth == Const4.UNSPECIFIED) || (updateDepth > 0);
1738: }
1739:
1740: private boolean objectCanNew(Transaction transaction,
1741: ClassMetadata yc, Object obj) {
1742: return callbacks().objectCanNew(transaction, obj)
1743: && yc
1744: .dispatchEvent(_this , obj,
1745: EventDispatcher.CAN_NEW);
1746: }
1747:
1748: public abstract void setDirtyInSystemTransaction(
1749: PersistentBase a_object);
1750:
1751: public abstract boolean setSemaphore(String name, int timeout);
1752:
1753: void stringIO(LatinStringIO io) {
1754: _handlers.stringIO(io);
1755: }
1756:
1757: final boolean showInternalClasses() {
1758: return isServer() || _showInternalClasses > 0;
1759: }
1760:
1761: /**
1762: * Objects implementing the "Internal4" marker interface are
1763: * not visible to queries, unless this flag is set to true.
1764: * The caller should reset the flag after the call.
1765: */
1766: public synchronized void showInternalClasses(boolean show) {
1767: if (show) {
1768: _showInternalClasses++;
1769: } else {
1770: _showInternalClasses--;
1771: }
1772: if (_showInternalClasses < 0) {
1773: _showInternalClasses = 0;
1774: }
1775: }
1776:
1777: private final boolean stackIsSmall() {
1778: return _stackDepth < Const4.MAX_STACK_DEPTH;
1779: }
1780:
1781: boolean stateMessages() {
1782: return true; // overridden to do nothing in YapObjectCarrier
1783: }
1784:
1785: /**
1786: * returns true in case an unknown single object is passed
1787: * This allows deactivating objects before queries are called.
1788: */
1789: final List4 stillTo1(Transaction trans, List4 still, Object obj,
1790: int depth, boolean forceUnknownDeactivate) {
1791:
1792: if (obj == null || depth <= 0) {
1793: return still;
1794: }
1795:
1796: ObjectReference ref = trans.referenceForObject(obj);
1797: if (ref != null) {
1798: if (handledInCurrentTopLevelCall(ref)) {
1799: return still;
1800: }
1801: flagAsHandled(ref);
1802: return new List4(still, new PendingActivation(ref, depth));
1803: }
1804: final ReflectClass clazz = reflector().forObject(obj);
1805: if (clazz.isArray()) {
1806: if (!clazz.getComponentType().isPrimitive()) {
1807: Object[] arr = ArrayHandler.toArray(_this , obj);
1808: for (int i = 0; i < arr.length; i++) {
1809: still = stillTo1(trans, still, arr[i], depth,
1810: forceUnknownDeactivate);
1811: }
1812: }
1813: } else {
1814: if (obj instanceof Entry) {
1815: still = stillTo1(trans, still, ((Entry) obj).key,
1816: depth, false);
1817: still = stillTo1(trans, still, ((Entry) obj).value,
1818: depth, false);
1819: } else {
1820: if (forceUnknownDeactivate) {
1821: // Special handling to deactivate Top-Level unknown objects only.
1822: ClassMetadata yc = classMetadataForObject(obj);
1823: if (yc != null) {
1824: yc.deactivate(trans, obj, depth);
1825: }
1826: }
1827: }
1828: }
1829: return still;
1830: }
1831:
1832: public final void stillToActivate(Transaction trans,
1833: Object a_object, int a_depth) {
1834:
1835: // TODO: We don't want the simple classes to search the hc_tree
1836: // Kick them out here.
1837:
1838: // if (a_object != null) {
1839: // Class clazz = a_object.getClass();
1840: // if(! clazz.isPrimitive()){
1841:
1842: _stillToActivate = stillTo1(trans, _stillToActivate, a_object,
1843: a_depth, false);
1844:
1845: // }
1846: // }
1847: }
1848:
1849: public final void stillToDeactivate(Transaction trans,
1850: Object a_object, int a_depth,
1851: boolean a_forceUnknownDeactivate) {
1852: _stillToDeactivate = stillTo1(trans, _stillToDeactivate,
1853: a_object, a_depth, a_forceUnknownDeactivate);
1854: }
1855:
1856: static class PendingSet {
1857: public final Transaction transaction;
1858: public final ObjectReference ref;
1859: public final int depth;
1860:
1861: public PendingSet(Transaction transaction, ObjectReference ref,
1862: int depth) {
1863: this .transaction = transaction;
1864: this .ref = ref;
1865: this .depth = depth;
1866: }
1867: }
1868:
1869: void stillToSet(Transaction transaction, ObjectReference ref,
1870: int updateDepth) {
1871: if (stackIsSmall()) {
1872: if (ref.continueSet(transaction, updateDepth)) {
1873: return;
1874: }
1875: }
1876: _stillToSet = new List4(_stillToSet, new PendingSet(
1877: transaction, ref, updateDepth));
1878: }
1879:
1880: protected final void stopSession() {
1881: if (hasShutDownHook()) {
1882: Platform4.removeShutDownHook(this );
1883: }
1884: _classCollection = null;
1885: if (_references != null) {
1886: _references.stopTimer();
1887: }
1888: _systemTransaction = null;
1889: _transaction = null;
1890: }
1891:
1892: public final StoredClass storedClass(Transaction trans, Object clazz) {
1893: synchronized (_lock) {
1894: trans = checkTransaction(trans);
1895: ReflectClass claxx = ReflectorUtils.reflectClassFor(
1896: reflector(), clazz);
1897: if (claxx == null) {
1898: return null;
1899: }
1900: ClassMetadata classMetadata = classMetadataForReflectClass(claxx);
1901: if (classMetadata == null) {
1902: return null;
1903: }
1904: return new StoredClassImpl(trans, classMetadata);
1905: }
1906: }
1907:
1908: public StoredClass[] storedClasses(Transaction trans) {
1909: synchronized (_lock) {
1910: trans = checkTransaction(trans);
1911: StoredClass[] classMetadata = _classCollection
1912: .storedClasses();
1913: StoredClass[] storedClasses = new StoredClass[classMetadata.length];
1914: for (int i = 0; i < classMetadata.length; i++) {
1915: storedClasses[i] = new StoredClassImpl(trans,
1916: (ClassMetadata) classMetadata[i]);
1917: }
1918: return storedClasses;
1919: }
1920: }
1921:
1922: public LatinStringIO stringIO() {
1923: return _handlers.stringIO();
1924: }
1925:
1926: public abstract SystemInfo systemInfo();
1927:
1928: private final void beginTopLevelCall() {
1929: if (DTrace.enabled) {
1930: DTrace.BEGIN_TOP_LEVEL_CALL.log();
1931: }
1932: generateCallIDOnTopLevel();
1933: if (_stackDepth == 0) {
1934: _topLevelCallCompleted = false;
1935: }
1936: _stackDepth++;
1937: }
1938:
1939: public final void beginTopLevelSet() {
1940: beginTopLevelCall();
1941: }
1942:
1943: /*
1944: * This method has to be invoked in the end of top level call to indicate
1945: * it's ended as expected
1946: */
1947: private final void completeTopLevelCall() {
1948: if (_stackDepth == 1) {
1949: _topLevelCallCompleted = true;
1950: }
1951: }
1952:
1953: private void completeTopLevelCall(Db4oException e)
1954: throws Db4oException {
1955: completeTopLevelCall();
1956: throw e;
1957: }
1958:
1959: /*
1960: * This method has to be invoked in the end of top level of set call to
1961: * indicate it's ended as expected
1962: */
1963: public final void completeTopLevelSet() {
1964: completeTopLevelCall();
1965: }
1966:
1967: public final void completeTopLevelSet(Db4oException e) {
1968: completeTopLevelCall();
1969: throw e;
1970: }
1971:
1972: private final void endTopLevelCall() {
1973: if (DTrace.enabled) {
1974: DTrace.END_TOP_LEVEL_CALL.log();
1975: }
1976: _stackDepth--;
1977: generateCallIDOnTopLevel();
1978: if (_stackDepth == 0) {
1979: if (!_topLevelCallCompleted) {
1980: shutdownObjectContainer();
1981: }
1982: }
1983: }
1984:
1985: public final void endTopLevelSet(Transaction trans) {
1986: endTopLevelCall();
1987: if (_stackDepth == 0 && _topLevelCallCompleted) {
1988: trans.processDeletes();
1989: }
1990: }
1991:
1992: private final void generateCallIDOnTopLevel() {
1993: if (_stackDepth == 0) {
1994: _topLevelCallId = _topLevelCallIdGenerator.next();
1995: }
1996: }
1997:
1998: public int stackDepth() {
1999: return _stackDepth;
2000: }
2001:
2002: public void stackDepth(int depth) {
2003: _stackDepth = depth;
2004: }
2005:
2006: public int topLevelCallId() {
2007: return _topLevelCallId;
2008: }
2009:
2010: public void topLevelCallId(int id) {
2011: _topLevelCallId = id;
2012: }
2013:
2014: public long version() {
2015: synchronized (_lock) {
2016: return currentVersion();
2017: }
2018: }
2019:
2020: public abstract void shutdown();
2021:
2022: public abstract void writeDirty();
2023:
2024: public abstract void writeNew(Transaction trans, Pointer4 pointer,
2025: ClassMetadata classMetadata, Buffer buffer);
2026:
2027: public abstract void writeTransactionPointer(int address);
2028:
2029: public abstract void writeUpdate(Transaction trans,
2030: Pointer4 pointer, ClassMetadata classMetadata, Buffer buffer);
2031:
2032: // cheat emulating '(YapStream)this'
2033: private static ExternalObjectContainer cast(
2034: PartialObjectContainer obj) {
2035: return (ExternalObjectContainer) obj;
2036: }
2037:
2038: public Callbacks callbacks() {
2039: return _callbacks;
2040: }
2041:
2042: public void callbacks(Callbacks cb) {
2043: if (cb == null) {
2044: throw new IllegalArgumentException();
2045: }
2046: _callbacks = cb;
2047: }
2048:
2049: public Config4Impl configImpl() {
2050: return _config;
2051: }
2052:
2053: public UUIDFieldMetadata uUIDIndex() {
2054: return _handlers.indexes()._uUID;
2055: }
2056:
2057: public VersionFieldMetadata versionIndex() {
2058: return _handlers.indexes()._version;
2059: }
2060:
2061: public ClassMetadataRepository classCollection() {
2062: return _classCollection;
2063: }
2064:
2065: public ClassInfoHelper getClassMetaHelper() {
2066: return _classMetaHelper;
2067: }
2068:
2069: public abstract long[] getIDsForClass(Transaction trans,
2070: ClassMetadata clazz);
2071:
2072: public abstract QueryResult classOnlyQuery(Transaction trans,
2073: ClassMetadata clazz);
2074:
2075: public abstract QueryResult executeQuery(QQuery query);
2076:
2077: public void replicationCallState(int state) {
2078: _replicationCallState = state;
2079: }
2080:
2081: public abstract void onCommittedListener();
2082:
2083: public ReferenceSystemRegistry referenceSystemRegistry() {
2084: return _referenceSystemRegistry;
2085: }
2086:
2087: public ObjectContainerBase container() {
2088: return _this;
2089: }
2090: }
|