001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.common;
012:
013: import com.versant.core.metadata.ModelMetaData;
014: import com.versant.core.metadata.ClassMetaData;
015: import com.versant.core.util.OIDObjectOutput;
016: import com.versant.core.util.OIDObjectInput;
017: import com.versant.core.util.FastExternalizable;
018:
019: import java.io.*;
020: import java.util.Iterator;
021:
022: /**
023: * Collection of OIDs and States to be persisted.
024: */
025: public final class StatesToStore implements FastExternalizable {
026:
027: private static final int breakPoint = 100;
028: private static final int initialSize = 50;
029:
030: private ModelMetaData jmd;
031:
032: private static final int INITIAL_CAPACITY = 20;
033: private static final int GROW_SIZE = 2;
034:
035: public OID[] oids = new OID[INITIAL_CAPACITY];
036: public State[] states = new State[INITIAL_CAPACITY];
037: public State[] origStates = new State[INITIAL_CAPACITY];
038:
039: private int size; // the number of entries
040: private boolean fullSort;
041:
042: // These fields keep track of OIDs/instances of objectid-class'es and
043: // classes to evict from l2 cache if the transaction commits (epc = Evict
044: // Post Commit).
045: public boolean epcAll; // evict everything from l2 cache on commit
046: public OID[] epcOids; // may be null
047: public int[] epcClasses; // of class index, may be null
048: public int epcClassCount;
049:
050: public StatesToStore() {
051: }
052:
053: public StatesToStore(ModelMetaData jmd) {
054: this .jmd = jmd;
055: }
056:
057: /**
058: * Is a full topological sort required to persist the states in this
059: * graph? This will be true if any of the states are for new objects
060: * and are using a post-insert key generator.
061: *
062: * @see com.versant.core.server.PersistGraph
063: * @see com.versant.core.server.PersistGraphFullSort
064: */
065: public boolean isFullSortRequired() {
066: return fullSort;
067: }
068:
069: /**
070: * Add a state to the container to be persisted.
071: * @param state The state containing the changed fields
072: * @param origState The state containing original field values
073: * @param fullSort If true then the fullSort flag is set on the container
074: */
075: public void add(OID oid, State state, State origState,
076: boolean fullSort) {
077: resize();
078: oids[size] = oid;
079: states[size] = state;
080: origStates[size++] = origState;
081: if (fullSort)
082: this .fullSort = true;
083: }
084:
085: /**
086: * The number of entries in the container.
087: */
088: public int size() {
089: return size;
090: }
091:
092: /**
093: * Is the container empty?
094: */
095: public boolean isEmpty() {
096: return size == 0;
097: }
098:
099: /**
100: * Check if the arrays needs to grow some more.
101: */
102: private void resize() {
103: final int length = oids.length;
104: if (length == size) {
105: final int growTo = (length + 1) * GROW_SIZE;
106: final OID[] tmpOIDs = new OID[growTo];
107: final State[] tmpStates = new State[growTo];
108: final State[] tmpOStates = new State[growTo];
109:
110: for (int i = 0; i < length; i++) {
111: tmpOIDs[i] = oids[i];
112: tmpStates[i] = states[i];
113: tmpOStates[i] = origStates[i];
114: }
115:
116: oids = tmpOIDs;
117: states = tmpStates;
118: origStates = tmpOStates;
119: }
120: }
121:
122: /**
123: * Clear the container for reuse.
124: */
125: public void clear() {
126: if (size > breakPoint) {
127: oids = new OID[initialSize];
128: states = new State[initialSize];
129: origStates = new State[initialSize];
130: } else {
131: final int n = size;
132: for (int i = 0; i < n; i++) {
133: oids[i] = null;
134: states[i] = null;
135: origStates[i] = null;
136: }
137: }
138: size = 0;
139: fullSort = false;
140: epcAll = false;
141: epcClassCount = 0;
142: epcClasses = null;
143: epcOids = null;
144: }
145:
146: public void dump() {
147: StringBuffer sb = new StringBuffer("StoreOIDStateContainer: ");
148: for (int i = 0; i < oids.length; i++) {
149: OID oid = oids[i];
150: if (oid == null)
151: break;
152: sb.append("\nOID = " + oid.toSString());
153: sb.append("\nState = " + states[i]);
154: sb.append("\nOrigState = " + origStates[i]);
155: sb.append("\nNext");
156: }
157: System.out.println(sb.toString());
158: }
159:
160: public void dumpEPC() {
161: System.out.println("StatesToStore.dumpEPC");
162: System.out.println("epcAll = " + epcAll);
163: System.out.println("epcOids = " + epcOids);
164: if (epcOids != null) {
165: System.out.println("epcOids.length = " + epcOids.length);
166: }
167: System.out.println("epcClasses = " + epcClasses);
168: if (epcClasses != null) {
169: System.out.println("epcClasses.length = "
170: + epcClasses.length);
171: }
172: System.out.println("epcClassCount = " + epcClassCount);
173:
174: }
175:
176: public void writeExternal(OIDObjectOutput out) throws IOException {
177: out.writeBoolean(fullSort);
178: out.writeInt(size);
179: for (int i = 0; i < size; i++) {
180: State state = states[i];
181: OID oid = oids[i];
182: oid.resolve(state);
183: out.writeShort(state.getClassIndex());
184: out.writeWithoutCMD(oid);
185: state.writeExternal(out);
186: if (origStates[i] == null) {
187: out.writeBoolean(false);
188: } else {
189: out.writeBoolean(true);
190: origStates[i].writeExternal(out);
191: }
192: }
193: writeExternalEpc(out);
194: }
195:
196: public void readExternal(OIDObjectInput in) throws IOException,
197: ClassNotFoundException {
198: jmd = in.getModelMetaData();
199: fullSort = in.readBoolean();
200: size = in.readInt();
201: oids = new OID[size];
202: states = new State[size];
203: origStates = new State[size];
204: for (int i = 0; i < size; i++) {
205: ClassMetaData cmd = jmd.classes[in.readShort()];
206: oids[i] = in.readOID(cmd);
207: states[i] = cmd.createState();
208: states[i].readExternal(in);
209: if (in.readBoolean()) {
210: origStates[i] = cmd.createState();
211: origStates[i].readExternal(in);
212: }
213: }
214: readExternalEpc(in);
215: }
216:
217: private void writeExternalEpc(OIDObjectOutput out)
218: throws IOException {
219: out.writeBoolean(epcAll);
220: if (epcOids == null) {
221: out.writeByte(0);
222: } else {
223: out.writeByte(1);
224: int n = 0;
225: for (; n < epcOids.length;) {
226: if (epcOids[n] == null)
227: break;
228: n++;
229: }
230: out.writeInt(n);
231: for (int i = 0; i < n; i++) {
232: OID oid = epcOids[i];
233: if (oid.isNew()) {
234: throw BindingSupportImpl
235: .getInstance()
236: .internal(
237: "New oids should not be included for eviction");
238: }
239: out.write(oid);
240: }
241: }
242: if (epcClasses == null) {
243: out.writeByte(0);
244: } else {
245: out.writeByte(1);
246: out.writeByte(epcClasses.length);
247: for (int i = 0; i < epcClasses.length; i++) {
248: out.writeInt(epcClasses[i]);
249: }
250: }
251: out.writeInt(epcClassCount);
252: }
253:
254: private void readExternalEpc(OIDObjectInput in) throws IOException,
255: ClassNotFoundException {
256: epcAll = in.readBoolean();
257: if (in.readByte() != 0) {
258: int n = in.readInt();
259: OID[] oids = epcOids = new OID[n];
260: for (int i = 0; i < n; i++) {
261: oids[i] = in.readOID();
262: }
263: }
264: if (in.readByte() != 0) {
265: int n = in.readInt();
266: int[] ia = epcClasses = new int[n];
267: for (int i = 0; i < n; i++) {
268: ia[i] = in.readInt();
269: }
270: }
271: epcClassCount = in.readInt();
272: }
273:
274: /**
275: * Iterate over the OIDs.
276: */
277: public Iterator iteratorForOIDs() {
278: return new Iter();
279: }
280:
281: public class Iter implements Iterator {
282:
283: private int pos;
284:
285: public boolean hasNext() {
286: return pos < size - 1;
287: }
288:
289: public Object next() {
290: return oids[pos++];
291: }
292:
293: public void remove() {
294: throw new UnsupportedOperationException();
295: }
296:
297: }
298:
299: }
|