@Override
 public void init() {
   if (init) {
     return;
   }
   init = true;
   Store s = database.getMvStore();
   MVStore mvStore;
   if (s == null) {
     // in-memory database
     mvStore = MVStore.open(null);
   } else {
     mvStore = s.getStore();
   }
   lobMap = mvStore.openMap("lobMap");
   refMap = mvStore.openMap("lobRef");
   dataMap = mvStore.openMap("lobData");
   streamStore = new StreamStore(dataMap);
   // garbage collection of the last blocks
   if (database.isReadOnly()) {
     return;
   }
   if (dataMap.isEmpty()) {
     return;
   }
   // search the last referenced block
   // (a lob may not have any referenced blocks if data is kept inline,
   // so we need to loop)
   long lastUsedKey = -1;
   Long lobId = lobMap.lastKey();
   while (lobId != null) {
     Object[] v = lobMap.get(lobId);
     byte[] id = (byte[]) v[0];
     lastUsedKey = streamStore.getMaxBlockKey(id);
     if (lastUsedKey >= 0) {
       break;
     }
     lobId = lobMap.lowerKey(lobId);
   }
   // delete all blocks that are newer
   while (true) {
     Long last = dataMap.lastKey();
     if (last == null || last <= lastUsedKey) {
       break;
     }
     dataMap.remove(last);
   }
   // don't re-use block ids, except at the very end
   Long last = dataMap.lastKey();
   if (last != null) {
     streamStore.setNextKey(last + 1);
   }
 }
 /**
  * Get the largest key that is smaller than the given key, or null if no such key exists.
  *
  * @param key the key (may not be null)
  * @return the result
  */
 public K lowerKey(K key) {
   // TODO Auto-generated method stub
   return map.lowerKey(key);
 }