001: /*
002: * Created on 14-Mar-2006
003: *
004: * TODO To change the template for this generated file go to
005: * Window - Preferences - Java - Code Style - Code Templates
006: */
007: package com.jofti.store;
008:
009: import java.nio.ByteBuffer;
010: import java.util.Arrays;
011:
012: import org.apache.commons.logging.Log;
013: import org.apache.commons.logging.LogFactory;
014:
015: import com.jofti.btree.IPage;
016: import com.jofti.btree.LeafNodeEntry;
017: import com.jofti.core.IStoreManager;
018: import com.jofti.exception.JoftiException;
019:
020: /**
021: * @author xenephon
022: *
023: */
024: public class Page implements Cloneable, IPage {
025:
026: private static Log log = LogFactory.getLog(Page.class);
027:
028: public int[] pointers = null;
029: public ByteBuffer buf = null;
030: IStoreManager manager = null;
031: IEntrySerializer serializer = null;
032: int bufSize = 0;
033:
034: int reference = 0;
035:
036: public Page(int[] pointers, ByteBuffer buf, IStoreManager manager,
037: IEntrySerializer serializer) {
038: this .pointers = pointers;
039: this .buf = buf;
040: bufSize = buf.capacity();
041: this .manager = manager;
042: this .serializer = serializer;
043: }
044:
045: public LeafNodeEntry getEntry(int position) {
046: LeafNodeEntry obj = null;
047:
048: if (position >= pointers.length) {
049: log.warn("error in page for position " + position);
050: return null;
051: } else {
052: int pos = pointers[position];
053: if (pos != -1) {
054: ByteBuffer tempBuffer = buf.duplicate();
055: tempBuffer.position(pos);
056: tempBuffer.getInt();
057: try {
058: obj = serializer.convertFromStorage(tempBuffer);
059: } catch (Throwable e) {
060: e.printStackTrace();
061: throw new RuntimeException(e);
062: }
063: // nodeEntries[position]=obj;
064: } else {
065: log.warn("expected entry in page found -1 at pos "
066: + position);
067:
068: for (int i = 0; i < position; i++) {
069: log.warn(i + "[" + pointers[i] + "],");
070: }
071: throw new RuntimeException("expected entry found -1 "
072: + position + " " + this );
073: }
074: if (obj == null) {
075: log.warn("returning null for " + position + " on buf "
076: + buf);
077: }
078: return obj;
079: }
080: }
081:
082: public void setEntry(int position, LeafNodeEntry entry) {
083:
084: byte[] bytes = null;
085: try {
086: bytes = serializer.convertForStorage(entry);
087: } catch (JoftiException e) {
088: throw new RuntimeException(
089: "unable to convert entry to bytes " + entry, e);
090: }
091: //see if we can fit this into the buffer
092: if (buf.capacity() < buf.limit() + (bytes.length + 4)) {
093: // we need to reallocate the buffer
094: ByteBuffer temp = ByteBuffer
095: .allocate((int) (buf.capacity() * 1.5));
096: buf.position(0);
097: temp.put(buf);
098: temp.flip();
099: ByteBuffer oldBuf = buf;
100: //temp.limit(temp.position());
101: buf = temp;
102: log.info("new buffer assigned in page " + buf + " "
103: + oldBuf);
104: }
105:
106: // find out where we put this
107: int pos = pointers[position];
108:
109: //length of insert
110: int length = 4 + bytes.length;
111:
112: // first insert - or at end -
113: if (pos == -1) {
114: //we can just add at end
115: if (position == 0) {
116: pos = 0;
117: } else {
118: pos = buf.limit();
119: }
120: //are we adding at end
121: //reset the limt
122: buf.limit(buf.limit() + length);
123: buf.position(pos);
124: buf.putInt(bytes.length);
125: buf.put(bytes);
126: //new limit and position should match
127:
128: } else {
129: //set where we are going to put the new data
130: buf.position(pos);
131: buf.mark();
132: // create a copy - not a copy of the backing data
133: ByteBuffer copy = buf.duplicate();
134: // reset limit on buffer so we do not overflow
135: buf.limit(buf.capacity());
136: //set the position we are writing to
137: buf.position(buf.position() + length);
138: // copy the moved data
139: try {
140: buf.put(copy);
141: } catch (Throwable t) {
142: log.warn("inserting failure for " + buf, t);
143: throw new RuntimeException("inserting failure for "
144: + buf, t);
145: }
146: // reset the limt to the current position
147: buf.limit(buf.position());
148:
149: // reset back to the previous mark
150: buf.reset();
151:
152: //write the data
153: buf.putInt(bytes.length);
154: buf.put(bytes);
155: }
156:
157: // reset the pointers
158: if (pointers[position] != -1) {
159: System.arraycopy(pointers, position, pointers,
160: position + 1, (pointers.length - 1) - position);
161:
162: for (int i = position + 1; i < pointers.length
163: && pointers[i] != -1; i++) {
164: pointers[i] = pointers[i] + length;
165: }
166: }
167: pointers[position] = pos;
168:
169: }
170:
171: public void removeEntry(int position) {
172:
173: if (position >= pointers.length || pointers[position] == -1) {
174: return;
175: } else {
176:
177: int pos = pointers[position];
178: // set up the start of the next entry
179: int overWriteStart = 0;
180: // if it is not the last entry then use the next entry
181: if (position != pointers.length - 1) {
182: overWriteStart = pointers[position + 1];
183: }
184: if (overWriteStart == -1 || position == pointers.length - 1) {
185: //we can just truncate using the limit
186: buf.position(pos);
187: buf.limit(pos);
188: pointers[position] = -1;
189: } else {
190: // set the position of the buffer to the pos
191: buf.position(pos);
192:
193: // mark where the write is going to be put
194: buf.mark();
195: // duplicate the buffer
196: ByteBuffer temp = buf.duplicate();
197: //get the size of the array plus the
198: int length = temp.getInt() + 4;
199: // set the pos for the overwriteStart
200: temp.position(overWriteStart);
201:
202: // reset back to the mark
203: buf.reset();
204: // put the bytes in
205: try {
206: buf.put(temp);
207: } catch (Exception e) {
208: log.warn("problem moving buffer posoition ", e);
209:
210: }
211:
212: // reset the limt
213: buf.limit(buf.position());
214:
215: //copy them back over the previous entries
216: int start = position + 1;
217: int arrayLength = (pointers.length) - (position + 1);
218: System.arraycopy(pointers, start, pointers, position,
219: arrayLength);
220:
221: // reset the last one to -1 - sort of like bit shift
222:
223: pointers[pointers.length - 1] = -1;
224:
225: // take off the removed entries
226: for (int i = position; i < pointers.length
227: && pointers[i] != -1; i++) {
228: if (position == pointers.length - 1
229: || pointers[i] == -1) {
230: pointers[i] = -1;
231: } else {
232: pointers[i] = pointers[i] - length;
233: }
234: }
235: }
236:
237: }
238: }
239:
240: public void updateEntry(int location, LeafNodeEntry entry) {
241: removeEntry(location);
242: setEntry(location, entry);
243: }
244:
245: public ByteBuffer copyBuffer(ByteBuffer newBuf) {
246:
247: buf.rewind();
248: newBuf.clear();
249: newBuf.put(buf);
250: newBuf.flip();
251: return newBuf;
252: }
253:
254: public void reset() {
255: Arrays.fill(pointers, -1);
256:
257: buf.clear();
258: buf.flip();
259:
260: }
261:
262: /* (non-Javadoc)
263: * @see com.jofti.store.IPage#getBuffer()
264: */
265: public ByteBuffer getBuffer() {
266:
267: return buf;
268: }
269:
270: /* (non-Javadoc)
271: * @see com.jofti.store.IPage#getPointers()
272: */
273: public int[] getPointers() {
274: return pointers;
275: }
276:
277: /* (non-Javadoc)
278: * @see com.jofti.store.IPage#setManager(com.jofti.core.IStoreManager)
279: */
280: public void setManager(IStoreManager manager) {
281: this.manager = manager;
282:
283: }
284:
285: }
|