1 8 9 package com.sleepycat.persist; 10 11 import java.util.Map ; 12 import java.util.SortedMap ; 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 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 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 <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 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 <PK,E> map() { 316 return sortedMap(); 317 } 318 319 public synchronized SortedMap <PK,E> sortedMap() { 320 if (map == null) { 321 map = (SortedMap ) ((StoredSortedMap) secIndex.sortedMap()). 322 duplicatesMap(keyObject, pkeyBinding); 323 } 324 return map; 325 } 326 } 327 | Popular Tags |