private void removeLob(int tableId, long lobId) { if (TRACE) { trace("remove " + tableId + "/" + lobId); } Object[] value = lobMap.remove(lobId); if (value == null) { // already removed return; } byte[] streamStoreId = (byte[]) value[0]; Object[] key = new Object[] {streamStoreId, lobId}; refMap.remove(key); // check if there are more entries for this streamStoreId key = new Object[] {streamStoreId, 0L}; value = refMap.ceilingKey(key); boolean hasMoreEntries = false; if (value != null) { byte[] s2 = (byte[]) value[0]; if (Arrays.equals(streamStoreId, s2)) { hasMoreEntries = true; } } if (!hasMoreEntries) { streamStore.remove(streamStoreId); } }
/** * Remove a key-value pair if the value matches the stored one. * * @param key the key (may not be null) * @param value the expected value * @return true if the item was removed */ public synchronized boolean remove(Object key, Object value) { V old = get(key); if (areValuesEqual(old, value)) { remove(key); return true; } return false; }
/** * Rollback to an old savepoint. * * @param t the transaction * @param maxLogId the last log id * @param toLogId the log id to roll back to */ void rollbackTo(Transaction t, long maxLogId, long toLogId) { for (long logId = maxLogId - 1; logId >= toLogId; logId--) { Object[] op = undoLog.get(new long[] {t.getId(), logId}); int mapId = ((Integer) op[1]).intValue(); Map<String, String> meta = store.getMetaMap(); String m = meta.get("map." + mapId); String mapName = DataUtils.parseMap(m).get("name"); MVMap<Object, Object[]> map = store.openMap(mapName); Object key = op[2]; Object[] oldValue = (Object[]) op[3]; if (oldValue == null) { // this transaction added the value map.remove(key); } else { // this transaction updated the value map.put(key, oldValue); } undoLog.remove(op); } }
@Override public void setTable(ValueLobDb lob, int tableId) { init(); long lobId = lob.getLobId(); Object[] value = lobMap.remove(lobId); if (TRACE) { trace("move " + lob.getTableId() + "/" + lob.getLobId() + " > " + tableId + "/" + lobId); } value[1] = tableId; lobMap.put(lobId, value); }
@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); } }
/** Test the concurrent map implementation. */ private void testConcurrentMap() throws InterruptedException { final MVStore s = openStore(null); final MVMap<Integer, Integer> m = s.openMap("data", new MVMapConcurrent.Builder<Integer, Integer>()); final int size = 20; final Random rand = new Random(1); Task task = new Task() { @Override public void call() throws Exception { try { while (!stop) { if (rand.nextBoolean()) { m.put(rand.nextInt(size), 1); } else { m.remove(rand.nextInt(size)); } m.get(rand.nextInt(size)); m.firstKey(); m.lastKey(); m.ceilingKey(5); m.floorKey(5); m.higherKey(5); m.lowerKey(5); for (Iterator<Integer> it = m.keyIterator(null); it.hasNext(); ) { it.next(); } } } catch (Exception e) { e.printStackTrace(); } } }; task.execute(); Thread.sleep(1); for (int j = 0; j < 100; j++) { for (int i = 0; i < 100; i++) { if (rand.nextBoolean()) { m.put(rand.nextInt(size), 2); } else { m.remove(rand.nextInt(size)); } m.get(rand.nextInt(size)); } s.commit(); Thread.sleep(1); } task.get(); s.close(); }
/** * Commit a transaction. * * @param t the transaction * @param maxLogId the last log id */ void commit(Transaction t, long maxLogId) { for (long logId = 0; logId < maxLogId; logId++) { long[] undoKey = new long[] {t.getId(), logId}; Object[] op = undoLog.get(undoKey); int opType = (Integer) op[0]; if (opType == Transaction.OP_REMOVE) { int mapId = (Integer) op[1]; Map<String, String> meta = store.getMetaMap(); String m = meta.get("map." + mapId); String mapName = DataUtils.parseMap(m).get("name"); MVMap<Object, Object[]> map = store.openMap(mapName); Object key = op[2]; Object[] value = map.get(key); // possibly the entry was added later on // so we have to check if (value[2] == null) { // remove the value map.remove(key); } } undoLog.remove(undoKey); } endTransaction(t); }
private void endTransaction(Transaction t) { openTransactions.remove(t.getId()); openTransactionMap.remove(t.getId()); }
private void testConcurrentWrite(final AtomicInteger detected, final AtomicInteger notDetected) throws InterruptedException { final MVStore s = openStore(null); final MVMap<Integer, Integer> m = s.openMap("data"); final int size = 20; final Random rand = new Random(1); Task task = new Task() { @Override public void call() throws Exception { while (!stop) { try { if (rand.nextBoolean()) { m.put(rand.nextInt(size), 1); } else { m.remove(rand.nextInt(size)); } m.get(rand.nextInt(size)); } catch (ConcurrentModificationException e) { detected.incrementAndGet(); } catch (NegativeArraySizeException e) { notDetected.incrementAndGet(); } catch (ArrayIndexOutOfBoundsException e) { notDetected.incrementAndGet(); } catch (IllegalArgumentException e) { notDetected.incrementAndGet(); } catch (NullPointerException e) { notDetected.incrementAndGet(); } } } }; task.execute(); Thread.sleep(1); for (int j = 0; j < 10; j++) { for (int i = 0; i < 10; i++) { try { if (rand.nextBoolean()) { m.put(rand.nextInt(size), 2); } else { m.remove(rand.nextInt(size)); } m.get(rand.nextInt(size)); } catch (ConcurrentModificationException e) { detected.incrementAndGet(); } catch (NegativeArraySizeException e) { notDetected.incrementAndGet(); } catch (ArrayIndexOutOfBoundsException e) { notDetected.incrementAndGet(); } catch (IllegalArgumentException e) { notDetected.incrementAndGet(); } catch (NullPointerException e) { notDetected.incrementAndGet(); } } s.commit(); Thread.sleep(1); } task.get(); s.close(); }
void removeMovieSetFromDb(MovieSet movieSet) throws Exception { movieSetMap.remove(movieSet.getDbId()); }
void removeMovieFromDb(Movie movie) throws Exception { movieMap.remove(movie.getDbId()); }