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.classindex;
022:
023: import com.db4o.foundation.*;
024: import com.db4o.internal.*;
025:
026: /**
027: * @exclude
028: */
029: public class OldClassIndexStrategy extends AbstractClassIndexStrategy
030: implements TransactionParticipant {
031:
032: private ClassIndex _index;
033:
034: private final Hashtable4 _perTransaction = new Hashtable4();
035:
036: public OldClassIndexStrategy(ClassMetadata yapClass) {
037: super (yapClass);
038: }
039:
040: public void read(ObjectContainerBase stream, int indexID) {
041: _index = createClassIndex(stream);
042: if (indexID > 0) {
043: _index.setID(indexID);
044: }
045: _index.setStateDeactivated();
046: }
047:
048: private ClassIndex getActiveIndex(Transaction transaction) {
049: if (null != _index) {
050: _index.ensureActive(transaction);
051: }
052: return _index;
053: }
054:
055: public int entryCount(Transaction transaction) {
056: if (_index != null) {
057: return _index.entryCount(transaction);
058: }
059: return 0;
060: }
061:
062: public void initialize(ObjectContainerBase stream) {
063: _index = createClassIndex(stream);
064: }
065:
066: public void purge() {
067: if (_index != null) {
068: if (!_index.isDirty()) {
069: _index.clear();
070: _index.setStateDeactivated();
071: }
072: }
073: }
074:
075: public int write(Transaction transaction) {
076: if (_index == null) {
077: return 0;
078: }
079: _index.write(transaction);
080: return _index.getID();
081: }
082:
083: private void flushContext(final Transaction transaction) {
084: TransactionState context = getState(transaction);
085:
086: final ClassIndex index = getActiveIndex(transaction);
087: context.traverseAdded(new Visitor4() {
088: public void visit(Object a_object) {
089: index.add(idFromValue(a_object));
090: }
091: });
092:
093: context.traverseRemoved(new Visitor4() {
094: public void visit(Object a_object) {
095: int id = idFromValue(a_object);
096: ObjectReference yo = transaction.referenceForId(id);
097: if (yo != null) {
098: transaction.removeReference(yo);
099: }
100: index.remove(id);
101: }
102: });
103: }
104:
105: private void writeIndex(Transaction transaction) {
106: _index.setStateDirty();
107: _index.write(transaction);
108: }
109:
110: final static class TransactionState {
111:
112: private Tree i_addToClassIndex;
113:
114: private Tree i_removeFromClassIndex;
115:
116: public void add(int id) {
117: i_removeFromClassIndex = Tree.removeLike(
118: i_removeFromClassIndex, new TreeInt(id));
119: i_addToClassIndex = Tree.add(i_addToClassIndex,
120: new TreeInt(id));
121: }
122:
123: public void remove(int id) {
124: i_addToClassIndex = Tree.removeLike(i_addToClassIndex,
125: new TreeInt(id));
126: i_removeFromClassIndex = Tree.add(i_removeFromClassIndex,
127: new TreeInt(id));
128: }
129:
130: public void dontDelete(int id) {
131: i_removeFromClassIndex = Tree.removeLike(
132: i_removeFromClassIndex, new TreeInt(id));
133: }
134:
135: void traverse(Tree node, Visitor4 visitor) {
136: if (node != null) {
137: node.traverse(visitor);
138: }
139: }
140:
141: public void traverseAdded(Visitor4 visitor4) {
142: traverse(i_addToClassIndex, visitor4);
143: }
144:
145: public void traverseRemoved(Visitor4 visitor4) {
146: traverse(i_removeFromClassIndex, visitor4);
147: }
148: }
149:
150: protected void internalAdd(Transaction transaction, int id) {
151: getState(transaction).add(id);
152: }
153:
154: private TransactionState getState(Transaction transaction) {
155: synchronized (_perTransaction) {
156: TransactionState context = (TransactionState) _perTransaction
157: .get(transaction);
158: if (null == context) {
159: context = new TransactionState();
160: _perTransaction.put(transaction, context);
161: ((LocalTransaction) transaction).enlist(this );
162: }
163: return context;
164: }
165: }
166:
167: private Tree getAll(Transaction transaction) {
168: ClassIndex ci = getActiveIndex(transaction);
169: if (ci == null) {
170: return null;
171: }
172:
173: final Tree.ByRef tree = new Tree.ByRef(Tree.deepClone(ci
174: .getRoot(), null));
175: TransactionState context = getState(transaction);
176: context.traverseAdded(new Visitor4() {
177: public void visit(Object obj) {
178: tree.value = Tree.add(tree.value, new TreeInt(
179: idFromValue(obj)));
180: }
181: });
182: context.traverseRemoved(new Visitor4() {
183: public void visit(Object obj) {
184: tree.value = Tree.removeLike(tree.value, (TreeInt) obj);
185: }
186: });
187: return tree.value;
188: }
189:
190: protected void internalRemove(Transaction transaction, int id) {
191: getState(transaction).remove(id);
192: }
193:
194: public void traverseAll(Transaction transaction,
195: final Visitor4 command) {
196: Tree tree = getAll(transaction);
197: if (tree != null) {
198: tree.traverse(new Visitor4() {
199: public void visit(Object obj) {
200: command.visit(new Integer(idFromValue(obj)));
201: }
202: });
203: }
204: }
205:
206: public int idFromValue(Object value) {
207: return ((TreeInt) value)._key;
208: }
209:
210: private ClassIndex createClassIndex(ObjectContainerBase stream) {
211: if (stream.isClient()) {
212: return new ClassIndexClient(_yapClass);
213: }
214: return new ClassIndex(_yapClass);
215: }
216:
217: public void dontDelete(Transaction transaction, int id) {
218: getState(transaction).dontDelete(id);
219: }
220:
221: public void commit(Transaction trans) {
222: if (null != _index) {
223: flushContext(trans);
224: writeIndex(trans);
225: }
226: }
227:
228: public void dispose(Transaction transaction) {
229: synchronized (_perTransaction) {
230: _perTransaction.remove(transaction);
231: }
232: }
233:
234: public void rollback(Transaction transaction) {
235: // nothing to do
236: }
237:
238: public void defragReference(ClassMetadata yapClass,
239: BufferPair readers, int classIndexID) {
240: }
241:
242: public int id() {
243: return _index.getID();
244: }
245:
246: public Iterator4 allSlotIDs(Transaction trans) {
247: throw new NotImplementedException();
248: }
249:
250: public void defragIndex(BufferPair readers) {
251: }
252: }
|