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.slots;
022:
023: import com.db4o.*;
024: import com.db4o.internal.*;
025:
026: /**
027: * @exclude
028: */
029: public class SlotChange extends TreeInt {
030:
031: private int _action;
032:
033: private Slot _newSlot;
034:
035: private ReferencedSlot _shared;
036:
037: private static final int FREE_ON_COMMIT_BIT = 1;
038:
039: private static final int FREE_ON_ROLLBACK_BIT = 2;
040:
041: private static final int SET_POINTER_BIT = 3;
042:
043: private static final int FREE_POINTER_ON_COMMIT_BIT = 4;
044:
045: private static final int FREE_POINTER_ON_ROLLBACK_BIT = 5;
046:
047: private static final int FREESPACE_BIT = 6;
048:
049: public SlotChange(int id) {
050: super (id);
051: }
052:
053: public Object shallowClone() {
054: SlotChange sc = new SlotChange(0);
055: sc._action = _action;
056: sc._newSlot = _newSlot;
057: sc._shared = _shared;
058: return super .shallowCloneInternal(sc);
059: }
060:
061: private final void doFreeOnCommit() {
062: setBit(FREE_ON_COMMIT_BIT);
063: }
064:
065: private final void doFreeOnRollback() {
066: setBit(FREE_ON_ROLLBACK_BIT);
067: }
068:
069: private final void doFreePointerOnCommit() {
070: setBit(FREE_POINTER_ON_COMMIT_BIT);
071: }
072:
073: private final void doFreePointerOnRollback() {
074: setBit(FREE_POINTER_ON_ROLLBACK_BIT);
075: }
076:
077: private final void doSetPointer() {
078: setBit(SET_POINTER_BIT);
079: }
080:
081: public void freeDuringCommit(LocalObjectContainer file,
082: boolean forFreespace) {
083: if (isFreeOnCommit() && (isForFreeSpace() == forFreespace)) {
084: file.freeDuringCommit(_shared, _newSlot);
085: }
086: }
087:
088: public final void freeOnCommit(LocalObjectContainer file, Slot slot) {
089:
090: if (_shared != null) {
091:
092: // second call or later.
093: // The object has already been rewritten once, so we can free
094: // directly
095:
096: file.free(slot);
097: return;
098: }
099:
100: doFreeOnCommit();
101:
102: ReferencedSlot refSlot = file.produceFreeOnCommitEntry(_key);
103:
104: if (refSlot.addReferenceIsFirst()) {
105: refSlot.pointTo(slot);
106: }
107:
108: _shared = refSlot;
109: }
110:
111: public void freeOnRollback(Slot slot) {
112: doFreeOnRollback();
113: _newSlot = slot;
114: }
115:
116: public void freeOnRollbackSetPointer(Slot slot) {
117: doSetPointer();
118: freeOnRollback(slot);
119: }
120:
121: public void freePointerOnCommit() {
122: doFreePointerOnCommit();
123: }
124:
125: public void freePointerOnRollback() {
126: doFreePointerOnRollback();
127: }
128:
129: private final boolean isBitSet(int bitPos) {
130: return (_action | (1 << bitPos)) == _action;
131: }
132:
133: public boolean isDeleted() {
134: return isSetPointer() && (_newSlot.address() == 0);
135: }
136:
137: public boolean isNew() {
138: return isFreePointerOnRollback();
139: }
140:
141: private final boolean isForFreeSpace() {
142: return isBitSet(FREESPACE_BIT);
143: }
144:
145: private final boolean isFreeOnCommit() {
146: return isBitSet(FREE_ON_COMMIT_BIT);
147: }
148:
149: private final boolean isFreeOnRollback() {
150: return isBitSet(FREE_ON_ROLLBACK_BIT);
151: }
152:
153: public final boolean isSetPointer() {
154: return isBitSet(SET_POINTER_BIT);
155: }
156:
157: /**
158: * FIXME: Check where pointers should be freed on commit.
159: * This should be triggered in this class.
160: */
161: // private final boolean isFreePointerOnCommit() {
162: // return isBitSet(FREE_POINTER_ON_COMMIT_BIT);
163: // }
164: public final boolean isFreePointerOnRollback() {
165: return isBitSet(FREE_POINTER_ON_ROLLBACK_BIT);
166: }
167:
168: public Slot newSlot() {
169: return _newSlot;
170: }
171:
172: public Slot oldSlot() {
173: if (_shared == null) {
174: return null;
175: }
176: return _shared.slot();
177: }
178:
179: public Object read(Buffer reader) {
180: SlotChange change = new SlotChange(reader.readInt());
181: change._newSlot = new Slot(reader.readInt(), reader.readInt());
182: change.doSetPointer();
183: return change;
184: }
185:
186: public void rollback(LocalObjectContainer yapFile) {
187: if (_shared != null) {
188: yapFile.reduceFreeOnCommitReferences(_shared);
189: }
190: if (isFreeOnRollback()) {
191: yapFile.free(_newSlot);
192: }
193: if (isFreePointerOnRollback()) {
194: if (DTrace.enabled) {
195: DTrace.FREE_POINTER_ON_ROLLBACK.logLength(_key,
196: Const4.POINTER_LENGTH);
197: }
198: yapFile.free(_key, Const4.POINTER_LENGTH);
199: }
200: }
201:
202: private final void setBit(int bitPos) {
203: _action |= (1 << bitPos);
204: }
205:
206: public void setPointer(Slot slot) {
207: doSetPointer();
208: _newSlot = slot;
209: }
210:
211: public void write(Buffer writer) {
212: if (isSetPointer()) {
213: writer.writeInt(_key);
214: writer.writeInt(_newSlot.address());
215: writer.writeInt(_newSlot.length());
216: }
217: }
218:
219: public final void writePointer(LocalTransaction trans) {
220: if (isSetPointer()) {
221: trans.writePointer(_key, _newSlot);
222: }
223: }
224:
225: public void forFreespace(boolean flag) {
226: if (flag) {
227: setBit(FREESPACE_BIT);
228: }
229: }
230: }
|