001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: INLogEntry.java,v 1.37.2.3 2008/01/07 15:14:13 cwl Exp $
007: */
008:
009: package com.sleepycat.je.log.entry;
010:
011: import java.nio.ByteBuffer;
012:
013: import com.sleepycat.je.DatabaseException;
014: import com.sleepycat.je.dbi.DatabaseId;
015: import com.sleepycat.je.dbi.EnvironmentImpl;
016: import com.sleepycat.je.log.LogEntryHeader;
017: import com.sleepycat.je.log.LogEntryType;
018: import com.sleepycat.je.log.LogUtils;
019: import com.sleepycat.je.tree.IN;
020: import com.sleepycat.je.utilint.DbLsn;
021:
022: /**
023: * INLogEntry embodies all IN log entries.
024: * On disk, an IN log entry contains:
025: * <pre>
026: * IN
027: * database id
028: * obsolete LSN -- in version 2
029: * </pre>
030: */
031: public class INLogEntry extends BaseEntry implements LogEntry,
032: NodeLogEntry, INContainingEntry {
033:
034: /*
035: * Persistent fields in an IN entry.
036: */
037: private IN in;
038: private DatabaseId dbId;
039: /*
040: * obsoleteFile was added in version 1, and changed to obsoleteLsn in
041: * version 2. If the offset is zero in the LSN, we read a version 1 entry
042: * since only the file number was stored.
043: */
044: private long obsoleteLsn;
045:
046: /*
047: * Transient fields
048: *
049: * Save the node id when we read the log entry from disk. Do so explicitly
050: * instead of merely returning in.getNodeId(), because we don't always
051: * instantiate the IN.
052: */
053: private long nodeId;
054:
055: /**
056: * Construct a log entry for reading.
057: */
058: public INLogEntry(Class INClass) {
059: super (INClass);
060: }
061:
062: /**
063: * Construct a log entry for writing to the log.
064: */
065: public INLogEntry(IN in) {
066: setLogType(in.getLogType());
067: this .in = in;
068: this .dbId = in.getDatabase().getId();
069: this .nodeId = in.getNodeId();
070: this .obsoleteLsn = in.getLastFullVersion();
071: }
072:
073: /*
074: * Read support
075: */
076:
077: /**
078: * Read in an IN entry.
079: */
080: public void readEntry(LogEntryHeader header,
081: ByteBuffer entryBuffer, boolean readFullItem)
082: throws DatabaseException {
083:
084: byte entryTypeVersion = LogEntryType.getVersionValue(header
085: .getVersion());
086: try {
087: if (readFullItem) {
088: /* Read IN and get node ID. */
089: in = (IN) logClass.newInstance();
090: in.readFromLog(entryBuffer, entryTypeVersion);
091: nodeId = in.getNodeId();
092: } else {
093: /* Calculate position following IN. */
094: int position = entryBuffer.position()
095: + header.getItemSize();
096: if (entryTypeVersion == 1) {
097: /* Subtract size of obsoleteFile */
098: position -= LogUtils.UNSIGNED_INT_BYTES;
099: } else if (entryTypeVersion >= 2) {
100: /* Subtract size of obsoleteLsn */
101: position -= LogUtils.LONG_BYTES;
102: }
103: /* Subtract size of dbId */
104: position -= LogUtils.INT_BYTES;
105: /* Read node ID and position after IN. */
106: nodeId = LogUtils.readLong(entryBuffer);
107: entryBuffer.position(position);
108: in = null;
109: }
110: dbId = new DatabaseId();
111: dbId.readFromLog(entryBuffer, entryTypeVersion);
112: if (entryTypeVersion < 1) {
113: obsoleteLsn = DbLsn.NULL_LSN;
114: } else if (entryTypeVersion == 1) {
115: long fileNum = LogUtils.getUnsignedInt(entryBuffer);
116: if (fileNum == 0xffffffffL) {
117: obsoleteLsn = DbLsn.NULL_LSN;
118: } else {
119: obsoleteLsn = DbLsn.makeLsn(fileNum, 0);
120: }
121: } else {
122: obsoleteLsn = LogUtils.readLong(entryBuffer);
123: }
124: } catch (IllegalAccessException e) {
125: throw new DatabaseException(e);
126: } catch (InstantiationException e) {
127: throw new DatabaseException(e);
128: }
129: }
130:
131: /**
132: * Returns the LSN of the prior version of this node. Used for counting
133: * the prior version as obsolete. If the offset of the LSN is zero, only
134: * the file number is known because we read a version 1 log entry.
135: */
136: public long getObsoleteLsn() {
137:
138: return obsoleteLsn;
139: }
140:
141: /**
142: * Print out the contents of an entry.
143: */
144: public StringBuffer dumpEntry(StringBuffer sb, boolean verbose) {
145: in.dumpLog(sb, verbose);
146: dbId.dumpLog(sb, verbose);
147: return sb;
148: }
149:
150: /**
151: * @return the item in the log entry
152: */
153: public Object getMainItem() {
154: return in;
155: }
156:
157: public Object clone() throws CloneNotSupportedException {
158:
159: return super .clone();
160: }
161:
162: /**
163: * @see LogEntry#getTransactionId
164: */
165: public long getTransactionId() {
166: return 0;
167: }
168:
169: /*
170: * Writing support
171: */
172:
173: /**
174: */
175: public int getSize() {
176: return (in.getLogSize() + dbId.getLogSize() + LogUtils.LONG_BYTES);
177: }
178:
179: /**
180: * @see LogEntry#writeEntry
181: */
182: public void writeEntry(LogEntryHeader header, ByteBuffer destBuffer) {
183: in.writeToLog(destBuffer);
184: dbId.writeToLog(destBuffer);
185: LogUtils.writeLong(destBuffer, obsoleteLsn);
186: }
187:
188: /*
189: * Access the in held within the entry.
190: * @see INContainingEntry#getIN()
191: */
192: public IN getIN(EnvironmentImpl env) throws DatabaseException {
193:
194: return in;
195: }
196:
197: /**
198: * @see NodeLogEntry#getNodeId
199: */
200: public long getNodeId() {
201: return nodeId;
202: }
203:
204: /**
205: * @see INContainingEntry#getDbId()
206: */
207: public DatabaseId getDbId() {
208:
209: return dbId;
210: }
211:
212: /**
213: * @return the LSN that represents this IN. For a vanilla IN entry, it's
214: * the last lsn read by the log reader.
215: */
216: public long getLsnOfIN(long lastReadLsn) {
217: return lastReadLsn;
218: }
219: }
|