001: ///////////////////////////////////////////////////////////////////////////////
002: //
003: // Copyright (C) 2003-@year@ by Thomas M. Hazel, MyOODB (www.myoodb.org)
004: //
005: // All Rights Reserved
006: //
007: // This program is free software; you can redistribute it and/or modify
008: // it under the terms of the GNU General Public License and GNU Library
009: // General Public License as published by the Free Software Foundation;
010: // either version 2, or (at your option) any later version.
011: //
012: // This program is distributed in the hope that it will be useful,
013: // but WITHOUT ANY WARRANTY; without even the implied warranty of
014: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: // GNU General Public License and GNU Library General Public License
016: // for more details.
017: //
018: // You should have received a copy of the GNU General Public License
019: // and GNU Library General Public License along with this program; if
020: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
021: // MA 02139, USA.
022: //
023: ///////////////////////////////////////////////////////////////////////////////
024: package org.myoodb.collectable;
025:
026: public abstract class StoreCollectionDbImpl extends CollectableDbImpl
027: implements StoreCollection {
028: protected TreeMap m_ContainerOfContainers;
029:
030: public StoreCollectionDbImpl() {
031: m_ContainerOfContainers = (TreeMap) getDatabase().createObject(
032: TreeMapDbImpl.class.getName());
033: }
034:
035: private void balanceContainerOfContainersRight(TreeMap cTree) {
036: TreeMap nTree = (TreeMap) getDatabase().createObject(
037: TreeMapDbImpl.class.getName());
038:
039: java.util.ArrayList keys = new java.util.ArrayList(cTree
040: .keySet());
041: for (int i = cTree.size() - 1; i >= (Container.SIZE.intValue() / 2); i--) {
042: Object key = keys.get(i);
043: Object value = cTree.remove(key);
044: nTree.put(key, value);
045: }
046:
047: m_ContainerOfContainers.put(nTree.firstKey(), nTree);
048: }
049:
050: protected java.util.ArrayList getContainerOfContainersKeys() {
051: java.util.ArrayList retval = null;
052:
053: synchronized (this ) {
054: TreeMap rawTree = (TreeMap) getDatabase().getObject(
055: m_ContainerOfContainers);
056: retval = new java.util.ArrayList(rawTree.keySet());
057: }
058:
059: return retval;
060: }
061:
062: protected java.util.ArrayList getContainerOfContainersValues() {
063: java.util.ArrayList retval = null;
064:
065: synchronized (this ) {
066: TreeMap rawTree = (TreeMap) getDatabase().getObject(
067: m_ContainerOfContainers);
068: retval = new java.util.ArrayList(rawTree.values());
069: }
070:
071: return retval;
072: }
073:
074: protected Object getContainerIndex(Object start) {
075: Object retval = null;
076:
077: java.util.Iterator iter = getContainerOfContainersKeys()
078: .iterator();
079: while (iter.hasNext()) {
080: Comparable key = (Comparable) iter.next();
081: if (key.compareTo(start) > 0) {
082: break;
083: }
084:
085: retval = key;
086: }
087:
088: return retval;
089: }
090:
091: protected java.util.ArrayList getContainerIndexes(Object start,
092: Object end) {
093: Object prev = null;
094: boolean setPrev = true;
095: java.util.ArrayList indexes = new java.util.ArrayList();
096:
097: java.util.Iterator iter = getContainerOfContainersKeys()
098: .iterator();
099: while (iter.hasNext()) {
100: Comparable key = (Comparable) iter.next();
101: if (key.compareTo(start) > 0) {
102: setPrev = false;
103:
104: indexes.add(key);
105:
106: if (key.compareTo(end) > 0) {
107: break;
108: }
109: }
110:
111: if (setPrev == true) {
112: prev = key;
113: }
114: }
115:
116: if (prev != null) {
117: indexes.add(0, prev);
118: }
119:
120: return indexes;
121:
122: }
123:
124: protected StoreObject getStoreObject(Object index, Object key) {
125: StoreObject retval = null;
126:
127: synchronized (this ) {
128: TreeMap tree = (TreeMap) m_ContainerOfContainers.get(index);
129: if (tree != null) {
130: retval = (StoreObject) tree.get(key);
131: }
132: }
133:
134: return retval;
135: }
136:
137: protected java.util.ArrayList getStoreObjectKeys(Object index) {
138: java.util.ArrayList retval = new java.util.ArrayList(
139: Container.SIZE.intValue());
140:
141: synchronized (this ) {
142: TreeMap tree = (TreeMap) m_ContainerOfContainers.get(index);
143: if (tree != null) {
144: TreeMap rawTree = (TreeMap) getDatabase().getObject(
145: tree);
146: if (rawTree != null) {
147: retval.addAll(rawTree.keySet());
148: }
149: }
150: }
151:
152: return retval;
153: }
154:
155: protected java.util.ArrayList getStoreObjectKeys(
156: java.util.Collection indexList) {
157: java.util.ArrayList retval = new java.util.ArrayList(indexList
158: .size()
159: * Container.SIZE.intValue());
160:
161: java.util.Iterator iter = indexList.iterator();
162: while (iter.hasNext()) {
163: synchronized (this ) {
164: TreeMap tree = (TreeMap) m_ContainerOfContainers
165: .get(iter.next());
166: if (tree != null) {
167: TreeMap rawTree = (TreeMap) getDatabase()
168: .getObject(tree);
169: if (rawTree != null) {
170: retval.addAll(rawTree.keySet());
171: }
172: }
173: }
174: }
175:
176: return retval;
177: }
178:
179: protected java.util.ArrayList getStoreObjectValues(Object index) {
180: java.util.ArrayList retval = new java.util.ArrayList(
181: Container.SIZE.intValue());
182:
183: synchronized (this ) {
184: TreeMap tree = (TreeMap) m_ContainerOfContainers.get(index);
185: if (tree != null) {
186: TreeMap rawTree = (TreeMap) getDatabase().getObject(
187: tree);
188: retval.addAll(rawTree.values());
189: }
190: }
191:
192: return retval;
193: }
194:
195: protected java.util.ArrayList getStoreObjectValues(
196: java.util.Collection indexList) {
197: java.util.ArrayList retval = new java.util.ArrayList(indexList
198: .size()
199: * Container.SIZE.intValue());
200:
201: java.util.Iterator iter = indexList.iterator();
202: while (iter.hasNext()) {
203: synchronized (this ) {
204: TreeMap tree = (TreeMap) m_ContainerOfContainers
205: .get(iter.next());
206: if (tree != null) {
207: TreeMap rawTree = (TreeMap) getDatabase()
208: .getObject(tree);
209: retval.addAll(rawTree.values());
210: }
211: }
212: }
213:
214: return retval;
215: }
216:
217: public void fixUpReference(long fixUpTime) {
218: if (referenceHasBeenFixedUp(fixUpTime) == true) {
219: return;
220: }
221:
222: super .fixUpReference(fixUpTime);
223:
224: try {
225: m_ContainerOfContainers.fixUpReference(fixUpTime);
226: } catch (org.myoodb.exception.ObjectNotFoundException e) {
227: m_ContainerOfContainers = (TreeMap) getDatabase()
228: .createObject(TreeMapDbImpl.class.getName());
229: }
230: }
231:
232: public void cleanUpReference() {
233: java.util.Iterator iter = getStoreObjects().iterator();
234: while (iter.hasNext()) {
235: StoreObject storeObject = (StoreObject) iter.next();
236:
237: getDatabase().deleteObject(removeStoreObject(storeObject));
238: }
239:
240: getDatabase().deleteObject(m_ContainerOfContainers);
241: }
242:
243: protected StoreObject addStoreObject(StoreObject storeObject) {
244: ///* XXX: debug
245: if (isExplicitLock() == true) {
246: throw new org.myoodb.exception.PermissionException(
247: "Invocation cannot be part of a transaction");
248: }
249: //*/
250:
251: synchronized (this ) {
252: TreeMap tree = null;
253: Object key = storeObject.getKey();
254:
255: ///* XXX: debug
256: if (key == null) {
257: throw new org.myoodb.exception.PermissionException(
258: "StoreObject has no Key");
259: }
260: //*/
261:
262: while (tree == null) {
263: Object index = getContainerIndex(key);
264: tree = (TreeMap) m_ContainerOfContainers.get(index);
265: if (tree == null) {
266: tree = (TreeMap) getDatabase().createObject(
267: TreeMapDbImpl.class.getName());
268: m_ContainerOfContainers.put(key, tree);
269: } else if (tree.size() > Container.SIZE.intValue()) {
270: balanceContainerOfContainersRight(tree);
271: tree = null;
272: }
273: }
274:
275: /* XXX: debug
276: if (tree.get(key) != null)
277: {
278: throw new org.myoodb.exception.PermissionException("StoreObject already exists");
279: }
280: */
281:
282: tree.put(key, storeObject);
283: }
284:
285: return storeObject;
286: }
287:
288: protected StoreObject removeStoreObject(StoreObject storeObject) {
289: return removeStoreObject(storeObject.getKey());
290: }
291:
292: protected StoreObject removeStoreObject(Object key) {
293: ///* XXX: debug
294: if (isExplicitLock() == true) {
295: throw new org.myoodb.exception.PermissionException(
296: "Invocation cannot be part of a transaction");
297: }
298: //*/
299:
300: // TODO: add balancing (i.e. a balance tree) to this method
301:
302: StoreObject retval = null;
303:
304: synchronized (this ) {
305: Object index = getContainerIndex(key);
306: TreeMap tree = (TreeMap) m_ContainerOfContainers.get(index);
307: if (tree != null) {
308: retval = (StoreObject) tree.remove(key);
309: if (tree.size() == 0) {
310: tree = (TreeMap) m_ContainerOfContainers
311: .remove(index);
312: getDatabase().deleteObject(tree);
313: }
314: }
315: }
316:
317: return retval;
318: }
319:
320: protected StoreObject getFirstStoreObject() {
321: StoreObject retval = null;
322:
323: synchronized (this ) {
324: if (m_ContainerOfContainers.size() != 0) {
325: Object index = m_ContainerOfContainers.firstKey();
326: TreeMap tree = (TreeMap) m_ContainerOfContainers
327: .get(index);
328:
329: Object key = tree.firstKey();
330: retval = (StoreObject) tree.get(key);
331: }
332: }
333:
334: return retval;
335: }
336:
337: protected StoreObject getLastStoreObject() {
338: StoreObject retval = null;
339:
340: synchronized (this ) {
341: if (m_ContainerOfContainers.size() != 0) {
342: Object index = m_ContainerOfContainers.lastKey();
343: TreeMap tree = (TreeMap) m_ContainerOfContainers
344: .get(index);
345:
346: Object key = tree.lastKey();
347: retval = (StoreObject) tree.get(key);
348: }
349: }
350:
351: return retval;
352: }
353:
354: protected StoreObject getStoreObject(Object key) {
355: return getStoreObject(getContainerIndex(key), key);
356: }
357:
358: protected java.util.ArrayList getStoreObjectKeys() {
359: return getStoreObjectKeys(getContainerOfContainersKeys());
360: }
361:
362: protected java.util.ArrayList getStoreObjectKeys(Object start,
363: Object end) {
364: return getStoreObjectKeys(getContainerIndexes(start, end));
365: }
366:
367: protected java.util.ArrayList getStoreObjects() {
368: return getStoreObjectValues(getContainerOfContainersKeys());
369: }
370:
371: protected java.util.ArrayList getStoreObjects(Object start,
372: Object end) {
373: return getStoreObjects(start, end, StoreObject.class);
374: }
375:
376: protected java.util.ArrayList getStoreObjects(Object start,
377: Object end, Class type) {
378: java.util.ArrayList retval = new java.util.ArrayList();
379: java.util.ArrayList storeObjects = getStoreObjectValues(getContainerIndexes(
380: start, end));
381:
382: for (int i = 0; i < storeObjects.size(); i++) {
383: StoreObject storeObject = (StoreObject) storeObjects.get(i);
384:
385: if (type.isAssignableFrom(storeObject.getClass()) == false) {
386: continue;
387: }
388:
389: Comparable value = storeObject.getKey();
390:
391: if ((value.compareTo(start) >= 0)
392: && (value.compareTo(end) <= 0)) {
393: retval.add(storeObject);
394: }
395: }
396:
397: return retval;
398: }
399:
400: protected java.util.ArrayList getStoreObjects(Object start,
401: int number, Direction direction) {
402: return getStoreObjects(start, number, direction,
403: StoreObject.class);
404: }
405:
406: protected java.util.ArrayList getStoreObjects(Object start,
407: int number, Direction direction, Class type) {
408: boolean done = false;
409: java.util.ArrayList retval = new java.util.ArrayList();
410: java.util.LinkedList indexes = new java.util.LinkedList(
411: getContainerOfContainersKeys());
412:
413: // TODO: auto-add all objects in middle indexes if type is StoreObject ( performance enhancement )
414:
415: // walk forward
416: if (direction == StoreCollection.Direction.FORWARDS) {
417: java.util.ListIterator iter = indexes.listIterator();
418: while ((done == false) && iter.hasNext()) {
419: java.util.ArrayList storeObjects = getStoreObjectValues(iter
420: .next());
421:
422: for (int i = 0; (done == false)
423: && (i < storeObjects.size()); i++) {
424: StoreObject storeObject = (StoreObject) storeObjects
425: .get(i);
426:
427: if (type.isAssignableFrom(storeObject.getClass()) == false) {
428: continue;
429: }
430:
431: Comparable value = storeObject.getKey();
432:
433: if (value.compareTo(start) >= 0) {
434: retval.add(storeObject);
435: }
436:
437: if (retval.size() >= number) {
438: done = true;
439: break;
440: }
441: }
442: }
443: }
444: // walk backwards
445: else {
446: java.util.ListIterator iter = indexes.listIterator(indexes
447: .size());
448: while ((done == false) && iter.hasPrevious()) {
449: java.util.ArrayList storeObjects = getStoreObjectValues(iter
450: .previous());
451:
452: for (int i = (storeObjects.size() - 1); (done == false)
453: && (i >= 0); i--) {
454: StoreObject storeObject = (StoreObject) storeObjects
455: .get(i);
456:
457: if (type.isAssignableFrom(storeObject.getClass()) == false) {
458: continue;
459: }
460:
461: Comparable value = storeObject.getKey();
462:
463: if (value.compareTo(start) <= 0) {
464: retval.add(storeObject);
465: }
466:
467: if (retval.size() >= number) {
468: done = true;
469: break;
470: }
471: }
472: }
473: }
474:
475: return retval;
476: }
477:
478: public long getStoreSize() {
479: int size = 0;
480:
481: java.util.Iterator iter = getContainerOfContainersValues()
482: .iterator();
483: while (iter.hasNext()) {
484: TreeMap tree = (TreeMap) iter.next();
485:
486: try {
487: size += tree.size();
488: } catch (org.myoodb.exception.ObjectNotFoundException e) {
489: // nothing to do
490: }
491: }
492:
493: return size;
494: }
495: }
|