KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > persist > SubIndex


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

8
9 package com.sleepycat.persist;
10
11 import java.util.Map JavaDoc;
12 import java.util.SortedMap JavaDoc;
13
14 import com.sleepycat.bind.EntityBinding;
15 import com.sleepycat.bind.EntryBinding;
16 import com.sleepycat.collections.StoredSortedMap;
17 import com.sleepycat.je.Cursor;
18 import com.sleepycat.je.CursorConfig;
19 import com.sleepycat.je.DatabaseEntry;
20 import com.sleepycat.je.DatabaseException;
21 import com.sleepycat.je.Environment;
22 import com.sleepycat.je.LockMode;
23 import com.sleepycat.je.OperationStatus;
24 import com.sleepycat.je.SecondaryCursor;
25 import com.sleepycat.je.SecondaryDatabase;
26 import com.sleepycat.je.Transaction;
27 import com.sleepycat.util.keyrange.KeyRange;
28 import com.sleepycat.util.keyrange.RangeCursor;
29
30 /**
31  * The EntityIndex returned by SecondaryIndex.subIndex. A SubIndex, in JE
32  * internal terms, is a duplicates btree for a single key in the main btree.
33  * From the user's viewpoint, the keys are primary keys. This class implements
34  * that viewpoint. In general, getSearchBoth and getSearchBothRange are used
35  * where in a normal index getSearchKey and getSearchRange would be used. The
36  * main tree key is always implied, not passed as a parameter.
37  *
38  * @author Mark Hayes
39  */

40 class SubIndex<PK,E> implements EntityIndex<PK,E> {
41
42     private SecondaryIndex<?,PK,E> secIndex;
43     private SecondaryDatabase db;
44     private boolean transactional;
45     private DatabaseEntry keyEntry;
46     private Object JavaDoc keyObject;
47     private KeyRange singleKeyRange;
48     private EntryBinding pkeyBinding;
49     private KeyRange emptyPKeyRange;
50     private EntityBinding entityBinding;
51     private ValueAdapter<PK> keyAdapter;
52     private ValueAdapter<E> entityAdapter;
53     private SortedMap JavaDoc<PK,E> map;
54
55     <SK> SubIndex(SecondaryIndex<SK,PK,E> secIndex,
56                   EntityBinding entityBinding,
57                   SK key) {
58
59         this.secIndex = secIndex;
60         db = secIndex.getDatabase();
61         transactional = secIndex.transactional;
62
63         keyObject = key;
64         keyEntry = new DatabaseEntry();
65         secIndex.keyBinding.objectToEntry(key, keyEntry);
66         singleKeyRange = secIndex.emptyRange.subRange(keyEntry);
67
68         PrimaryIndex<PK,E> priIndex = secIndex.getPrimaryIndex();
69         pkeyBinding = priIndex.keyBinding;
70         emptyPKeyRange = priIndex.emptyRange;
71         this.entityBinding = entityBinding;
72
73         keyAdapter = new PrimaryKeyValueAdapter<PK>
74             (priIndex.keyClass, priIndex.keyBinding);
75         entityAdapter = secIndex.entityAdapter;
76     }
77
78     public boolean contains(PK key)
79         throws DatabaseException {
80
81         return contains(null, key, null);
82     }
83
84     public boolean contains(Transaction txn, PK key, LockMode lockMode)
85         throws DatabaseException {
86
87         DatabaseEntry pkeyEntry = new DatabaseEntry();
88         DatabaseEntry dataEntry = BasicIndex.NO_RETURN_ENTRY;
89         pkeyBinding.objectToEntry(key, pkeyEntry);
90
91         OperationStatus status =
92             db.getSearchBoth(txn, keyEntry, pkeyEntry, dataEntry, lockMode);
93         return (status == OperationStatus.SUCCESS);
94     }
95
96     public E get(PK key)
97         throws DatabaseException {
98
99         return get(null, key, null);
100     }
101
102     public E get(Transaction txn, PK key, LockMode lockMode)
103         throws DatabaseException {
104
105         DatabaseEntry pkeyEntry = new DatabaseEntry();
106         DatabaseEntry dataEntry = new DatabaseEntry();
107         pkeyBinding.objectToEntry(key, pkeyEntry);
108
109         OperationStatus status =
110             db.getSearchBoth(txn, keyEntry, pkeyEntry, dataEntry, lockMode);
111
112         if (status == OperationStatus.SUCCESS) {
113             return (E) entityBinding.entryToObject(pkeyEntry, dataEntry);
114         } else {
115             return null;
116         }
117     }
118
119     public long count()
120         throws DatabaseException {
121
122         EntityCursor<PK> cursor = keys(null, CursorConfig.READ_UNCOMMITTED);
123         try {
124             if (cursor.next() != null) {
125                 return cursor.count();
126             } else {
127                 return 0;
128             }
129         } finally {
130             cursor.close();
131         }
132     }
133
134     public boolean delete(PK key)
135         throws DatabaseException {
136
137         return delete(null, key);
138     }
139
140     public boolean delete(Transaction txn, PK key)
141         throws DatabaseException {
142
143         DatabaseEntry pkeyEntry = new DatabaseEntry();
144         DatabaseEntry dataEntry = BasicIndex.NO_RETURN_ENTRY;
145         pkeyBinding.objectToEntry(key, pkeyEntry);
146
147         boolean autoCommit = false;
148     Environment env = db.getEnvironment();
149         if (transactional &&
150         txn == null &&
151         env.getThreadTransaction() == null) {
152             txn = env.beginTransaction(null, null);
153             autoCommit = true;
154         }
155
156         boolean failed = true;
157         OperationStatus status;
158         SecondaryCursor cursor = db.openSecondaryCursor(txn, null);
159         try {
160             status = cursor.getSearchBoth
161                 (keyEntry, pkeyEntry, dataEntry, LockMode.RMW);
162             if (status == OperationStatus.SUCCESS) {
163                 status = cursor.delete();
164             }
165             failed = false;
166         } finally {
167             cursor.close();
168             if (autoCommit) {
169                 if (failed) {
170                     txn.abort();
171                 } else {
172                     txn.commit();
173                 }
174             }
175         }
176
177         return (status == OperationStatus.SUCCESS);
178     }
179
180     public EntityCursor<PK> keys()
181         throws DatabaseException {
182
183         return keys(null, null);
184     }
185
186     public EntityCursor<PK> keys(Transaction txn, CursorConfig config)
187         throws DatabaseException {
188
189         return cursor(txn, null, keyAdapter, config);
190     }
191
192     public EntityCursor<E> entities()
193         throws DatabaseException {
194
195         return cursor(null, null, entityAdapter, null);
196     }
197
198     public EntityCursor<E> entities(Transaction txn,
199                                     CursorConfig config)
200         throws DatabaseException {
201         
202         return cursor(txn, null, entityAdapter, config);
203     }
204
205     public EntityCursor<PK> keys(PK fromKey,
206                                  boolean fromInclusive,
207                                  PK toKey,
208                                  boolean toInclusive)
209         throws DatabaseException {
210
211         return cursor(null, fromKey, fromInclusive, toKey, toInclusive,
212                       keyAdapter, null);
213     }
214
215     public EntityCursor<PK> keys(Transaction txn,
216                                  PK fromKey,
217                                  boolean fromInclusive,
218                                  PK toKey,
219                                  boolean toInclusive,
220                                  CursorConfig config)
221         throws DatabaseException {
222
223         return cursor(txn, fromKey, fromInclusive, toKey, toInclusive,
224                       keyAdapter, config);
225     }
226
227     public EntityCursor<E> entities(PK fromKey,
228                                     boolean fromInclusive,
229                                     PK toKey,
230                                     boolean toInclusive)
231         throws DatabaseException {
232
233         return cursor(null, fromKey, fromInclusive, toKey, toInclusive,
234                       entityAdapter, null);
235     }
236
237     public EntityCursor<E> entities(Transaction txn,
238                                     PK fromKey,
239                                     boolean fromInclusive,
240                                     PK toKey,
241                                     boolean toInclusive,
242                                     CursorConfig config)
243         throws DatabaseException {
244
245         return cursor(txn, fromKey, fromInclusive, toKey, toInclusive,
246                       entityAdapter, config);
247     }
248
249     /*
250     public ForwardCursor<PK> unsortedKeys(KeySelector<PK> selector)
251         throws DatabaseException {
252
253         return unsortedKeys(null, selector, null);
254     }
255
256     public ForwardCursor<PK> unsortedKeys(Transaction txn,
257                                           KeySelector<PK> selector,
258                                           CursorConfig config)
259         throws DatabaseException {
260         
261         throw new UnsupportedOperationException();
262     }
263
264     public ForwardCursor<E> unsortedEntities(KeySelector<PK> selector)
265         throws DatabaseException {
266             
267         return unsortedEntities(null, selector, null);
268     }
269
270     public ForwardCursor<E> unsortedEntities(Transaction txn,
271                                              KeySelector<PK> selector,
272                                              CursorConfig config)
273         throws DatabaseException {
274         
275         throw new UnsupportedOperationException();
276     }
277     */

278
279     private <V> EntityCursor<V> cursor(Transaction txn,
280                                        PK fromKey,
281                                        boolean fromInclusive,
282                                        PK toKey,
283                                        boolean toInclusive,
284                                        ValueAdapter<V> adapter,
285                                        CursorConfig config)
286         throws DatabaseException {
287
288         DatabaseEntry fromEntry = null;
289         if (fromKey != null) {
290             fromEntry = new DatabaseEntry();
291             pkeyBinding.objectToEntry(fromKey, fromEntry);
292         }
293         DatabaseEntry toEntry = null;
294         if (toKey != null) {
295             toEntry = new DatabaseEntry();
296             pkeyBinding.objectToEntry(toKey, toEntry);
297         }
298         KeyRange pkeyRange = emptyPKeyRange.subRange
299             (fromEntry, fromInclusive, toEntry, toInclusive);
300         return cursor(txn, pkeyRange, adapter, config);
301     }
302
303     private <V> EntityCursor<V> cursor(Transaction txn,
304                                        KeyRange pkeyRange,
305                                        ValueAdapter<V> adapter,
306                                        CursorConfig config)
307         throws DatabaseException {
308
309         Cursor cursor = db.openCursor(txn, config);
310         RangeCursor rangeCursor =
311             new RangeCursor(singleKeyRange, pkeyRange, cursor);
312         return new SubIndexCursor<V>(rangeCursor, adapter);
313     }
314
315     public Map JavaDoc<PK,E> map() {
316         return sortedMap();
317     }
318
319     public synchronized SortedMap JavaDoc<PK,E> sortedMap() {
320         if (map == null) {
321             map = (SortedMap JavaDoc) ((StoredSortedMap) secIndex.sortedMap()).
322                 duplicatesMap(keyObject, pkeyBinding);
323         }
324         return map;
325     }
326 }
327
Popular Tags