KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > tree > BINDelta


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: BINDelta.java,v 1.43 2006/10/30 21:14:25 bostic Exp $
7  */

8
9 package com.sleepycat.je.tree;
10
11 import java.nio.ByteBuffer JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.List JavaDoc;
14
15 import com.sleepycat.je.DatabaseException;
16 import com.sleepycat.je.dbi.DatabaseId;
17 import com.sleepycat.je.dbi.DatabaseImpl;
18 import com.sleepycat.je.dbi.EnvironmentImpl;
19 import com.sleepycat.je.log.LogEntryType;
20 import com.sleepycat.je.log.LogException;
21 import com.sleepycat.je.log.LogReadable;
22 import com.sleepycat.je.log.LogUtils;
23 import com.sleepycat.je.log.LoggableObject;
24 import com.sleepycat.je.utilint.DbLsn;
25
26 /**
27  * BINDelta contains the information needed to create a partial (delta) BIN log
28  * entry. It also knows how to combine a full BIN log entry and a delta to
29  * generate a new BIN.
30  */

31 public class BINDelta implements LoggableObject, LogReadable {
32         
33     private DatabaseId dbId; // owning db for this bin.
34
private long lastFullLsn; // location of last full version
35
private List JavaDoc deltas; // list of key/action changes
36
private LogEntryType logEntryType; // type of log entry to use
37
// when writing to the log.
38

39     /**
40      * Read a BIN and create the deltas.
41      */

42     public BINDelta(BIN bin) {
43         lastFullLsn = bin.getLastFullVersion();
44         dbId = bin.getDatabaseId();
45         deltas = new ArrayList JavaDoc();
46         logEntryType = bin.getBINDeltaType();
47
48         /*
49          * Save every entry that has been modified since the last full version.
50          * Note that we must rely on the dirty bit, and we can't infer any
51          * dirtiness by comparing the last full version LSN and the child
52          * reference LSN. That's because the ChildReference LSN may be earlier
53          * than the full version LSN because of aborts.
54          */

55         for (int i = 0; i < bin.getNEntries(); i++) {
56             if (bin.isDirty(i)) {
57                 deltas.add(new DeltaInfo(bin.getKey(i),
58                                          bin.getLsn(i),
59                                          bin.getState(i)));
60             }
61         }
62     }
63         
64     /**
65      * For instantiating from the log.
66      */

67     public BINDelta() {
68         dbId = new DatabaseId();
69         lastFullLsn = DbLsn.NULL_LSN;
70         deltas = new ArrayList JavaDoc();
71     }
72         
73     /**
74      * @return a count of deltas for this BIN.
75      */

76     int getNumDeltas() {
77         return deltas.size();
78     }
79         
80     /**
81      * @return the dbId for this BIN.
82      */

83     public DatabaseId getDbId() {
84         return dbId;
85     }
86
87     /**
88      * @return the last full version of this BIN
89      */

90     public long getLastFullLsn() {
91         return lastFullLsn;
92     }
93
94     /**
95      * Create a BIN by starting with the full version and applying the deltas.
96      */

97     public BIN reconstituteBIN(EnvironmentImpl env)
98         throws DatabaseException {
99                 
100         /* Get the last full version of this BIN. */
101         BIN fullBIN = (BIN) env.getLogManager().get(lastFullLsn);
102         DatabaseImpl db = env.getDbMapTree().getDb(dbId);
103
104     /*
105      * In effect, call fullBIN.postFetchInit(db) here. But we don't want
106      * to do that since it will put fullBIN on the INList. Since this is
107      * either recovery or during the Cleaner run, we don't want it on the
108      * INList.
109      */

110     fullBIN.setDatabase(db);
111         fullBIN.setLastFullLsn(lastFullLsn);
112         
113         /* Process each delta. */
114         fullBIN.latch();
115         for (int i = 0; i < deltas.size(); i++) {
116             DeltaInfo info = (DeltaInfo) deltas.get(i);
117
118         /*
119          * The BINDelta holds the authoritative version of each entry. In
120          * all cases, its entry should supercede the entry in the full
121          * BIN. This is true even if the BIN Delta's entry is knownDeleted
122          * or if the full BIN's version is knownDeleted. Therefore we use
123          * the flavor of findEntry that will return a knownDeleted entry if
124          * the entry key matches (i.e. true, false) but still indicates
125          * exact matches with the return index. findEntry only returns
126          * deleted entries if third arg is false, but we still need to know
127          * if it's an exact match or not so indicateExact is true.
128          */

129             int foundIndex = fullBIN.findEntry(info.getKey(), true, false);
130             if (foundIndex >= 0 &&
131         (foundIndex & IN.EXACT_MATCH) != 0) {
132         foundIndex &= ~IN.EXACT_MATCH;
133
134                 /*
135                  * The entry exists in the full version, update it with the
136                  * delta info.
137                  */

138                 if (info.isKnownDeleted()) {
139                     fullBIN.setKnownDeleted(foundIndex);
140                 } else {
141                     fullBIN.updateEntry
142                         (foundIndex, info.getLsn(), info.getState());
143                 }
144             } else {
145                 /* The entry doesn't exist, add a new entry from the delta. */
146         if (!info.isKnownDeleted()) {
147             ChildReference entry =
148             new ChildReference(null,
149                                            info.getKey(),
150                        info.getLsn(),
151                        info.getState());
152             boolean insertOk = fullBIN.insertEntry(entry);
153             assert insertOk;
154         }
155             }
156         }
157
158         /*
159          * Reset the generation to 0, all this manipulation might have driven
160          * it up.
161          */

162         fullBIN.setGeneration(0);
163         fullBIN.releaseLatch();
164         return fullBIN;
165     }
166         
167     /*
168      * Logging support
169      */

170
171     /*
172      * @see com.sleepycat.je.log.LoggableObject#getLogType()
173      */

174     public LogEntryType getLogType() {
175         return logEntryType;
176     }
177
178     /**
179      * @see LoggableObject#marshallOutsideWriteLatch
180      * Can be marshalled outside the log write latch.
181      */

182     public boolean marshallOutsideWriteLatch() {
183         return true;
184     }
185
186     /**
187      * @see LoggableObject#countAsObsoleteWhenLogged
188      */

189     public boolean countAsObsoleteWhenLogged() {
190         return false;
191     }
192
193     /*
194      * Nothing to do after the act of logging this entry.
195      * @see com.sleepycat.je.log.LoggableObject#postLogWork(
196      * com.sleepycat.je.util.DbLsn)
197      */

198     public void postLogWork(long justLoggedLsn) {
199     }
200
201     /*
202      * @see com.sleepycat.je.log.LogReadable#readFromLog(
203      * java.nio.ByteBuffer)
204      */

205     public void readFromLog(ByteBuffer JavaDoc itemBuffer,byte entryTypeVersion)
206     throws LogException {
207
208         dbId.readFromLog(itemBuffer, entryTypeVersion); // database id
209
lastFullLsn = LogUtils.readLong(itemBuffer); // last version
210
int numDeltas = LogUtils.readInt(itemBuffer);
211
212         for (int i=0; i < numDeltas; i++) { // deltas
213
DeltaInfo info = new DeltaInfo();
214             info.readFromLog(itemBuffer, entryTypeVersion);
215             deltas.add(info);
216         }
217     }
218
219     /*
220      * @see com.sleepycat.je.log.LoggableObject#getLogSize()
221      */

222     public int getLogSize() {
223         int size =
224             dbId.getLogSize() + // database id
225
LogUtils.LONG_BYTES + // last version
226
LogUtils.INT_BYTES; // num deltas
227

228         for (int i = 0; i < deltas.size(); i++) { // deltas
229
DeltaInfo info = (DeltaInfo) deltas.get(i);
230             size += info.getLogSize();
231         }
232         
233         return size;
234     }
235
236     /*
237      * @see com.sleepycat.je.log.LoggableObject#writeToLog
238      * (java.nio.ByteBuffer)
239      */

240     public void writeToLog(ByteBuffer JavaDoc logBuffer) {
241         dbId.writeToLog(logBuffer); // database id
242
LogUtils.writeLong(logBuffer, lastFullLsn); // last version
243
LogUtils.writeInt(logBuffer, deltas.size()); // num deltas
244

245         for (int i = 0; i < deltas.size(); i++) { // deltas
246
DeltaInfo info = (DeltaInfo) deltas.get(i);
247             info.writeToLog(logBuffer);
248         }
249     }
250
251     /*
252      * @see LogReadable#dumpLog(java.lang.StringBuffer)
253      */

254     public void dumpLog(StringBuffer JavaDoc sb, boolean verbose) {
255         dbId.dumpLog(sb, verbose);
256         sb.append("<lastFullLsn>");
257     sb.append(DbLsn.toString(lastFullLsn));
258         sb.append("</lastFullLsn>");
259         sb.append("<deltas size=\"").append(deltas.size()).append("\"/>");
260         for (int i = 0; i < deltas.size(); i++) { // deltas
261
DeltaInfo info = (DeltaInfo) deltas.get(i);
262             info.dumpLog(sb, verbose);
263         }
264     }
265
266     /**
267      * @see LogReadable#logEntryIsTransactional
268      */

269     public boolean logEntryIsTransactional() {
270     return false;
271     }
272
273     /**
274      * @see LogReadable#getTransactionId
275      */

276     public long getTransactionId() {
277     return 0;
278     }
279 }
280
Popular Tags