001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.internal.btree;
022:
023: /**
024: * @exclude
025: */
026: import com.db4o.foundation.No4;
027: import com.db4o.internal.*;
028:
029: public abstract class BTreeUpdate extends BTreePatch {
030:
031: protected BTreeUpdate _next;
032:
033: public BTreeUpdate(Transaction transaction, Object obj) {
034: super (transaction, obj);
035: }
036:
037: protected boolean hasNext() {
038: return _next != null;
039: }
040:
041: public BTreePatch forTransaction(Transaction trans) {
042: if (_transaction == trans) {
043: return this ;
044: }
045: if (_next == null) {
046: return null;
047: }
048: return _next.forTransaction(trans);
049: }
050:
051: public BTreeUpdate removeFor(Transaction trans) {
052: if (_transaction == trans) {
053: return _next;
054: }
055: if (_next == null) {
056: return this ;
057: }
058: return _next.removeFor(trans);
059: }
060:
061: public void append(BTreeUpdate patch) {
062: if (_transaction == patch._transaction) {
063: // don't allow two patches for the same transaction
064: throw new IllegalArgumentException();
065: }
066: if (!hasNext()) {
067: _next = patch;
068: } else {
069: _next.append(patch);
070: }
071: }
072:
073: protected void applyKeyChange(Object obj) {
074: _object = obj;
075: if (hasNext()) {
076: _next.applyKeyChange(obj);
077: }
078: }
079:
080: protected abstract void committed(BTree btree);
081:
082: public Object commit(Transaction trans, BTree btree) {
083: final BTreeUpdate patch = (BTreeUpdate) forTransaction(trans);
084: if (patch instanceof BTreeCancelledRemoval) {
085: Object obj = patch.getCommittedObject();
086: applyKeyChange(obj);
087: } else if (patch instanceof BTreeRemove) {
088: removedBy(trans, btree);
089: patch.committed(btree);
090: return No4.INSTANCE;
091: }
092: return internalCommit(trans, btree);
093: }
094:
095: protected final Object internalCommit(Transaction trans, BTree btree) {
096: if (_transaction == trans) {
097: committed(btree);
098: if (hasNext()) {
099: return _next;
100: }
101: return getCommittedObject();
102: }
103: if (hasNext()) {
104: setNextIfPatch(_next.internalCommit(trans, btree));
105: }
106: return this ;
107: }
108:
109: private void setNextIfPatch(Object newNext) {
110: if (newNext instanceof BTreeUpdate) {
111: _next = (BTreeUpdate) newNext;
112: } else {
113: _next = null;
114: }
115: }
116:
117: protected abstract Object getCommittedObject();
118:
119: public Object rollback(Transaction trans, BTree btree) {
120: if (_transaction == trans) {
121: if (hasNext()) {
122: return _next;
123: }
124: return getObject();
125: }
126: if (hasNext()) {
127: setNextIfPatch(_next.rollback(trans, btree));
128: }
129: return this ;
130: }
131:
132: public Object key(Transaction trans) {
133: BTreePatch patch = forTransaction(trans);
134: if (patch == null) {
135: return getObject();
136: }
137: if (patch.isRemove()) {
138: return No4.INSTANCE;
139: }
140: return patch.getObject();
141: }
142:
143: public BTreeUpdate replacePatch(BTreePatch patch, BTreeUpdate update) {
144: if (patch == this ) {
145: update._next = _next;
146: return update;
147: }
148: if (_next == null) {
149: throw new IllegalStateException();
150: }
151: _next = _next.replacePatch(patch, update);
152: return this ;
153: }
154:
155: public void removedBy(Transaction trans, BTree btree) {
156: if (trans != _transaction) {
157: adjustSizeOnRemovalByOtherTransaction(btree);
158: }
159: if (hasNext()) {
160: _next.removedBy(trans, btree);
161: }
162: }
163:
164: protected abstract void adjustSizeOnRemovalByOtherTransaction(
165: BTree btree);
166:
167: }
|