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;
022:
023: import com.db4o.*;
024: import com.db4o.foundation.*;
025: import com.db4o.internal.slots.*;
026:
027: /**
028: * @exclude
029: *
030: */
031: public abstract class PersistentBase implements Persistent {
032:
033: protected int _id; // UID and address of pointer to the object in our file
034:
035: protected int _state = 2; // DIRTY and ACTIVE
036:
037: public final boolean beginProcessing() {
038: if (bitIsTrue(Const4.PROCESSING)) {
039: return false;
040: }
041: bitTrue(Const4.PROCESSING);
042: return true;
043: }
044:
045: final void bitFalse(int bitPos) {
046: _state &= ~(1 << bitPos);
047: }
048:
049: final boolean bitIsFalse(int bitPos) {
050: return (_state | (1 << bitPos)) != _state;
051: }
052:
053: final boolean bitIsTrue(int bitPos) {
054: return (_state | (1 << bitPos)) == _state;
055: }
056:
057: final void bitTrue(int bitPos) {
058: _state |= (1 << bitPos);
059: }
060:
061: void cacheDirty(Collection4 col) {
062: if (!bitIsTrue(Const4.CACHED_DIRTY)) {
063: bitTrue(Const4.CACHED_DIRTY);
064: col.add(this );
065: }
066: }
067:
068: public void endProcessing() {
069: bitFalse(Const4.PROCESSING);
070: }
071:
072: public void free(Transaction trans) {
073: trans.systemTransaction().slotFreePointerOnCommit(getID());
074: }
075:
076: public int getID() {
077: return _id;
078: }
079:
080: public final boolean isActive() {
081: return bitIsTrue(Const4.ACTIVE);
082: }
083:
084: public boolean isDirty() {
085: return bitIsTrue(Const4.ACTIVE) && (!bitIsTrue(Const4.CLEAN));
086: }
087:
088: public final boolean isNew() {
089: return getID() == 0;
090: }
091:
092: public int linkLength() {
093: return Const4.ID_LENGTH;
094: }
095:
096: final void notCachedDirty() {
097: bitFalse(Const4.CACHED_DIRTY);
098: }
099:
100: public void read(Transaction trans) {
101: if (!beginProcessing()) {
102: return;
103: }
104: try {
105: Buffer reader = trans.container().readReaderByID(trans,
106: getID());
107: if (Deploy.debug) {
108: reader.readBegin(getIdentifier());
109: }
110: readThis(trans, reader);
111: setStateOnRead(reader);
112: } finally {
113: endProcessing();
114: }
115: }
116:
117: public void setID(int a_id) {
118: if (DTrace.enabled) {
119: DTrace.YAPMETA_SET_ID.log(a_id);
120: }
121: _id = a_id;
122: }
123:
124: public final void setStateClean() {
125: bitTrue(Const4.ACTIVE);
126: bitTrue(Const4.CLEAN);
127: }
128:
129: public final void setStateDeactivated() {
130: bitFalse(Const4.ACTIVE);
131: }
132:
133: public void setStateDirty() {
134: bitTrue(Const4.ACTIVE);
135: bitFalse(Const4.CLEAN);
136: }
137:
138: void setStateOnRead(Buffer reader) {
139: if (Deploy.debug) {
140: reader.readEnd();
141: }
142: if (bitIsTrue(Const4.CACHED_DIRTY)) {
143: setStateDirty();
144: } else {
145: setStateClean();
146: }
147: }
148:
149: public final void write(Transaction trans) {
150:
151: if (!writeObjectBegin()) {
152: return;
153: }
154: try {
155:
156: LocalObjectContainer stream = (LocalObjectContainer) trans
157: .container();
158:
159: int length = ownLength();
160: length = stream.blockAlignedBytes(length);
161:
162: Buffer writer = new Buffer(length);
163:
164: Slot slot;
165:
166: if (isNew()) {
167: Pointer4 pointer = stream.newSlot(length);
168: setID(pointer._id);
169: slot = pointer._slot;
170:
171: trans.setPointer(pointer);
172: // FIXME: Free everything on rollback here too?
173:
174: } else {
175: slot = stream.getSlot(length);
176: trans.slotFreeOnRollbackCommitSetPointer(_id, slot,
177: isFreespaceComponent());
178: }
179:
180: writeToFile(trans, writer, slot);
181: } finally {
182: endProcessing();
183: }
184:
185: }
186:
187: public boolean isFreespaceComponent() {
188: return false;
189: }
190:
191: private final void writeToFile(Transaction trans, Buffer writer,
192: Slot slot) {
193:
194: if (DTrace.enabled) {
195: DTrace.YAPMETA_WRITE.log(getID());
196: }
197:
198: LocalObjectContainer container = (LocalObjectContainer) trans
199: .container();
200:
201: if (Deploy.debug) {
202: writer.writeBegin(getIdentifier());
203: }
204:
205: writeThis(trans, writer);
206:
207: if (Deploy.debug) {
208: writer.writeEnd();
209: }
210:
211: container.writeEncrypt(writer, slot.address(), 0);
212:
213: if (isActive()) {
214: setStateClean();
215: }
216: }
217:
218: public boolean writeObjectBegin() {
219: if (isDirty()) {
220: return beginProcessing();
221: }
222: return false;
223: }
224:
225: public void writeOwnID(Transaction trans, Buffer writer) {
226: write(trans);
227: writer.writeInt(getID());
228: }
229:
230: public int hashCode() {
231: if (isNew()) {
232: throw new IllegalStateException();
233: }
234: return getID();
235: }
236:
237: }
|