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.defragment;
022:
023: import com.db4o.foundation.*;
024: import com.db4o.internal.*;
025: import com.db4o.internal.btree.*;
026: import com.db4o.internal.mapping.*;
027:
028: /**
029: * BTree mapping for IDs during a defragmentation run.
030: *
031: * @see Defragment
032: */
033: public class BTreeIDMapping extends AbstractContextIDMapping {
034:
035: private String _fileName;
036:
037: private LocalObjectContainer _mappingDb;
038:
039: private BTree _idTree;
040:
041: private MappedIDPair _cache = new MappedIDPair(0, 0);
042:
043: private BTreeSpec _treeSpec = null;
044:
045: private int _commitFrequency = 0; // <=0 : never commit
046: private int _insertCount = 0;
047:
048: /**
049: * Will maintain the ID mapping as a BTree in the file with the given path.
050: * If a file exists in this location, it will be DELETED.
051: *
052: * Node size and cache height of the tree will be the default values used by
053: * the BTree implementation. The tree will never commit.
054: *
055: * @param fileName The location where the BTree file should be created.
056: */
057: public BTreeIDMapping(String fileName) {
058: this (fileName, null, 0);
059: }
060:
061: /**
062: * Will maintain the ID mapping as a BTree in the file with the given path.
063: * If a file exists in this location, it will be DELETED.
064: *
065: * @param fileName The location where the BTree file should be created.
066: * @param nodeSize The size of a BTree node
067: * @param cacheHeight The height of the BTree node cache
068: * @param commitFrequency The number of inserts after which a commit should be issued (<=0: never commit)
069: */
070: public BTreeIDMapping(String fileName, int nodeSize,
071: int cacheHeight, int commitFrequency) {
072: this (fileName, new BTreeSpec(nodeSize, cacheHeight),
073: commitFrequency);
074: }
075:
076: private BTreeIDMapping(String fileName, BTreeSpec treeSpec,
077: int commitFrequency) {
078: _fileName = fileName;
079: _treeSpec = treeSpec;
080: _commitFrequency = commitFrequency;
081: }
082:
083: public int mappedID(int oldID, boolean lenient) {
084: if (_cache.orig() == oldID) {
085: return _cache.mapped();
086: }
087: int classID = mappedClassID(oldID);
088: if (classID != 0) {
089: return classID;
090: }
091: BTreeRange range = _idTree.search(trans(), new MappedIDPair(
092: oldID, 0));
093: Iterator4 pointers = range.pointers();
094: if (pointers.moveNext()) {
095: BTreePointer pointer = (BTreePointer) pointers.current();
096: _cache = (MappedIDPair) pointer.key();
097: return _cache.mapped();
098: }
099: if (lenient) {
100: return mapLenient(oldID, range);
101: }
102: return 0;
103: }
104:
105: private int mapLenient(int oldID, BTreeRange range) {
106: range = range.smaller();
107: BTreePointer pointer = range.lastPointer();
108: if (pointer == null) {
109: return 0;
110: }
111: MappedIDPair mappedIDs = (MappedIDPair) pointer.key();
112: return mappedIDs.mapped() + (oldID - mappedIDs.orig());
113: }
114:
115: protected void mapNonClassIDs(int origID, int mappedID) {
116: _cache = new MappedIDPair(origID, mappedID);
117: _idTree.add(trans(), _cache);
118: if (_commitFrequency > 0) {
119: _insertCount++;
120: if (_commitFrequency == _insertCount) {
121: _idTree.commit(trans());
122: _insertCount = 0;
123: }
124: }
125: }
126:
127: public void open() {
128: _mappingDb = DefragContextImpl.freshYapFile(_fileName, 1);
129: Indexable4 handler = new MappedIDPairHandler(_mappingDb);
130: _idTree = (_treeSpec == null ? new BTree(trans(), 0, handler)
131: : new BTree(trans(), 0, handler, _treeSpec.nodeSize(),
132: _treeSpec.cacheHeight()));
133: }
134:
135: public void close() {
136: _mappingDb.close();
137: }
138:
139: private Transaction trans() {
140: return _mappingDb.systemTransaction();
141: }
142:
143: private static class BTreeSpec {
144: private int _nodeSize;
145: private int _cacheHeight;
146:
147: public BTreeSpec(int nodeSize, int cacheHeight) {
148: _nodeSize = nodeSize;
149: _cacheHeight = cacheHeight;
150: }
151:
152: public int nodeSize() {
153: return _nodeSize;
154: }
155:
156: public int cacheHeight() {
157: return _cacheHeight;
158: }
159: }
160: }
|