@Override public void mutate(StaticBuffer key, List<Entry> additions, List<StaticBuffer> deletions, StoreTransaction txh) throws BackendException { store.mutate(key,additions,deletions,txh); }
@Override public void mutate(final StaticBuffer key, final List<Entry> additions, final List<StaticBuffer> deletions, final StoreTransaction txh) throws BackendException { runWithMetrics(txh, metricsStoreName, M_MUTATE, (StorageCallable<Void>) () -> { backend.mutate(key, additions, deletions, txh); return null; }); }
@Override public void mutate(StaticBuffer key, List<Entry> additions, List<StaticBuffer> deletions, StoreTransaction txh) throws BackendException { store.mutate(key, additions, deletions, unwrapTx(txh)); }
@Override public void mutateMany(Map<String, Map<StaticBuffer, KCVMutation>> mutations, StoreTransaction txh) throws BackendException { for (Map.Entry<String, Map<StaticBuffer, KCVMutation>> storeMut : mutations.entrySet()) { KeyColumnValueStore store = stores.get(storeMut.getKey()); Preconditions.checkNotNull(store); for (Map.Entry<StaticBuffer, KCVMutation> keyMut : storeMut.getValue().entrySet()) { store.mutate(keyMut.getKey(), keyMut.getValue().getAdditions(), keyMut.getValue().getDeletions(), txh); } } }
@Test public void testMutateWithoutLockUsesInconsistentTx() throws BackendException { // Run a mutation final ImmutableList<Entry> adds = ImmutableList.of(StaticArrayEntry.of(DATA_COL, DATA_VAL)); final ImmutableList<StaticBuffer> deletions = ImmutableList.of(); backingStore.mutate(DATA_KEY, adds, deletions, inconsistentTx); // consistency level is unconstrained w/o locks ctrl.replay(); expectStore.mutate(DATA_KEY, adds, deletions, expectTx); }
public Set<Integer> deleteKeys(int every) throws BackendException { final Set<Integer> removed = new HashSet<>(); for (int i = 0; i < numKeys; i++) { if (i % every == 0) { removed.add(i); final List<StaticBuffer> deletions = new ArrayList<>(); for (int j = 0; j < numColumns; j++) { deletions.add(KeyValueStoreUtil.getBuffer(j)); } store.mutate(KeyValueStoreUtil.getBuffer(i), KeyColumnValueStore.NO_ADDITIONS, deletions, tx); } } return removed; }
public static void delete(KeyColumnValueStore store, StoreTransaction txn, long key, String col) throws BackendException { StaticBuffer k = longToByteBuffer(key); StaticBuffer c = stringToByteBuffer(col); store.mutate(k, KeyColumnValueStore.NO_ADDITIONS, Collections.singletonList(c), txn); }
/** * {@inheritDoc} * <p> * This implementation supports locking when {@code lockStore} is non-null. */ @Override public void mutate(StaticBuffer key, List<Entry> additions, List<StaticBuffer> deletions, StoreTransaction txh) throws BackendException { ExpectedValueCheckingTransaction etx = (ExpectedValueCheckingTransaction)txh; boolean hasAtLeastOneLock = etx.prepareForMutations(); if (hasAtLeastOneLock) { // Force all mutations on this transaction to use strong consistency store.mutate(key, additions, deletions, getConsistentTx(txh)); } else { store.mutate(key, additions, deletions, unwrapTx(txh)); } }
@Override public void mutate(StaticBuffer key, List<Entry> additions, List<StaticBuffer> deletions, StoreTransaction txh) throws BackendException { TTLKCVSManager.applyTTL(additions, ttl); store.mutate(key, additions, deletions, unwrapTx(txh)); }
public Set<KeyColumn> deleteValues(int every) throws BackendException { final Set<KeyColumn> removed = new HashSet<>(); int counter = 0; for (int i = 0; i < numKeys; i++) { final List<StaticBuffer> deletions = new ArrayList<>(); for (int j = 0; j < numColumns; j++) { counter++; if (counter % every == 0) { //remove removed.add(new KeyColumn(i, j)); deletions.add(KeyValueStoreUtil.getBuffer(j)); } } store.mutate(KeyValueStoreUtil.getBuffer(i), KeyColumnValueStore.NO_ADDITIONS, deletions, tx); } return removed; }
@Test(expected = PermanentLockingException.class) public void expectedValueMismatchCausesMutateFailure() throws BackendException { store[0].acquireLock(k, c1, v1, tx[0][0]); store[0].mutate(k, Collections.singletonList(StaticArrayEntry.of(c1, v1)), NO_DELETIONS, tx[0][0]); }
public static void insert(KeyColumnValueStore store, StoreTransaction txn, long key, String col, String val) throws BackendException { StaticBuffer k = longToByteBuffer(key); StaticBuffer c = stringToByteBuffer(col); StaticBuffer v = stringToByteBuffer(val); store.mutate(k, Collections.singletonList(StaticArrayEntry.of(c, v)), KeyColumnValueStore.NO_DELETIONS, txn); }
@Override protected void deleteSingleLock(KeyColumn kc, ConsistentKeyLockStatus ls, StoreTransaction tx) { List<StaticBuffer> deletions = ImmutableList.of(serializer.toLockCol(ls.getWriteTimestamp(), rid, times)); for (int i = 0; i < lockRetryCount; i++) { try { StoreTransaction newTx = overrideTimestamp(tx, times.getTime()); store.mutate(serializer.toLockKey(kc.getKey(), kc.getColumn()), ImmutableList.of(), deletions, newTx); return; } catch (TemporaryBackendException e) { log.warn("Temporary storage exception while deleting lock", e); // don't return -- iterate and retry } catch (BackendException e) { log.error("Storage exception while deleting lock", e); return; // give up on this lock } } }
private void runWithExceptions() throws BackendException { StaticBuffer lockKey = serializer.toLockKey(target.getKey(), target.getColumn()); List<Entry> locks = store.getSlice(new KeySliceQuery(lockKey, LOCK_COL_START, LOCK_COL_END), tx); // TODO reduce LOCK_COL_END based on cutoff ImmutableList.Builder<StaticBuffer> b = ImmutableList.builder(); for (Entry lc : locks) { TimestampRid tr = serializer.fromLockColumn(lc.getColumn(), times); if (tr.getTimestamp().isBefore(cutoff)) { log.info("Deleting expired lock on {} by rid {} with timestamp {} (before or at cutoff {})", target, tr.getRid(), tr.getTimestamp(), cutoff); b.add(lc.getColumn()); } else { log.debug("Ignoring lock on {} by rid {} with timestamp {} (timestamp is after cutoff {})", target, tr.getRid(), tr.getTimestamp(), cutoff); } } List<StaticBuffer> deletions = b.build(); if (!deletions.isEmpty()) { store.mutate(lockKey, ImmutableList.of(), deletions, tx); log.info("Deleted {} expired locks (before or at cutoff {})", deletions.size(), cutoff); } }
private WriteResult tryDeleteLockOnce(StaticBuffer key, StaticBuffer col, StoreTransaction txh) { Throwable t = null; final Timer delTimer = times.getTimer().start(); try { final StoreTransaction newTx = overrideTimestamp(txh, delTimer.getStartTime()); store.mutate(key, ImmutableList.of(), Collections.singletonList(col), newTx); } catch (BackendException e) { t = e; } delTimer.stop(); return new WriteResult(delTimer.elapsed(), delTimer.getStartTime(), null, t); }
private void tryLocks(KeyColumnValueStore s1, StoreTransaction tx1, KeyColumnValueStore s2, StoreTransaction tx2, boolean detectLocally) throws BackendException, InterruptedException { s1.acquireLock(k, k, null, tx1); // Require local lock contention, if requested by our caller // Remote lock contention is checked by separate cases if (detectLocally) { try { s2.acquireLock(k, k, null, tx2); Assert.fail("Expected lock contention between transactions did not occur"); } catch (BackendException e) { Assert.assertTrue(e instanceof PermanentLockingException || e instanceof TemporaryLockingException); } } // Let the original lock expire Thread.sleep(EXPIRE_MS + 100L); // This should succeed now that the original lock is expired s2.acquireLock(k, k, null, tx2); // Mutate to check for remote contention s2.mutate(k, Collections.singletonList(StaticArrayEntry.of(c2, v2)), NO_DELETIONS, tx2); }
@Test public void singleLockAndUnlock() throws BackendException { store[0].acquireLock(k, c1, null, tx[0][0]); store[0].mutate(k, Collections.singletonList(StaticArrayEntry.of(c1, v1)), NO_DELETIONS, tx[0][0]); tx[0][0].commit(); tx[0][0] = newTransaction(manager[0]); Assert.assertEquals(v1, KCVSUtil.get(store[0], k, c1, tx[0][0])); }
private WriteResult tryWriteLockOnce(StaticBuffer key, StaticBuffer del, StoreTransaction txh) { Throwable t = null; final Timer writeTimer = times.getTimer().start(); StaticBuffer newLockCol = serializer.toLockCol(writeTimer.getStartTime(), rid, times); Entry newLockEntry = StaticArrayEntry.of(newLockCol, zeroBuf); try { final StoreTransaction newTx = overrideTimestamp(txh, writeTimer.getStartTime()); store.mutate(key, Collections.singletonList(newLockEntry), null == del ? KeyColumnValueStore.NO_DELETIONS : Collections.singletonList(del), newTx); } catch (BackendException e) { log.debug("Lock write attempt failed with exception", e); t = e; } writeTimer.stop(); return new WriteResult(writeTimer.elapsed(), writeTimer.getStartTime(), newLockCol, t); }
@Test public void transactionMayReenterLock() throws BackendException { store[0].acquireLock(k, c1, null, tx[0][0]); store[0].acquireLock(k, c1, null, tx[0][0]); store[0].acquireLock(k, c1, null, tx[0][0]); store[0].mutate(k, Collections.singletonList(StaticArrayEntry.of(c1, v1)), NO_DELETIONS, tx[0][0]); tx[0][0].commit(); tx[0][0] = newTransaction(manager[0]); Assert.assertEquals(v1, KCVSUtil.get(store[0], k, c1, tx[0][0])); }
private void tryWrites(KeyColumnValueStore store1, KeyColumnValueStoreManager keyColumnValueStoreManager, StoreTransaction tx1, KeyColumnValueStore store2, StoreTransaction tx2) throws BackendException { Assert.assertNull(KCVSUtil.get(store1, k, c1, tx1)); Assert.assertNull(KCVSUtil.get(store2, k, c2, tx2)); store1.acquireLock(k, c1, null, tx1); store2.acquireLock(k, c2, null, tx2); store1.mutate(k, Collections.singletonList(StaticArrayEntry.of(c1, v1)), NO_DELETIONS, tx1); store2.mutate(k, Collections.singletonList(StaticArrayEntry.of(c2, v2)), NO_DELETIONS, tx2); tx1.commit(); if (tx2 != tx1) tx2.commit(); StoreTransaction transaction = newTransaction(keyColumnValueStoreManager); Assert.assertEquals(v1, KCVSUtil.get(store1, k, c1, transaction)); Assert.assertEquals(v2, KCVSUtil.get(store2, k, c2, transaction)); transaction.commit(); }