@Override public Boolean call() throws Exception { manager.mutateMany(subMutations, tx); return true; }
@Override public void mutateMany(Map<String, Map<StaticBuffer, KCVMutation>> mutations, StoreTransaction txh) throws BackendException { manager.mutateMany(mutations,txh); }
@Override public void mutateMany(Map<String, Map<StaticBuffer, KCVMutation>> mutations, StoreTransaction txh) throws BackendException { ExpectedValueCheckingTransaction etx = (ExpectedValueCheckingTransaction)txh; boolean hasAtLeastOneLock = etx.prepareForMutations(); if (hasAtLeastOneLock) { // Force all mutations on this transaction to use strong consistency log.debug("Transaction {} holds one or more locks: writing using consistent transaction {} due to held locks", etx, etx.getConsistentTx()); manager.mutateMany(mutations, etx.getConsistentTx()); } else { log.debug("Transaction {} holds no locks: writing mutations using store transaction {}", etx, etx.getInconsistentTx()); manager.mutateMany(mutations, etx.getInconsistentTx()); } }
@Test public void testMutateManyWithoutLockUsesInconsistentTx() throws BackendException { final ImmutableList<Entry> adds = ImmutableList.of(StaticArrayEntry.of(DATA_COL, DATA_VAL)); final ImmutableList<StaticBuffer> deletions = ImmutableList.of(); Map<String, Map<StaticBuffer, KCVMutation>> mutations = ImmutableMap.of(STORE_NAME, ImmutableMap.of(DATA_KEY, new KCVMutation(adds, deletions))); // Run mutateMany backingManager.mutateMany(mutations, inconsistentTx); // consistency level is unconstrained w/o locks ctrl.replay(); // Run mutateMany expectManager.mutateMany(mutations, expectTx); } }
@Override public void mutateMany(Map<String, Map<StaticBuffer, KCVMutation>> mutations, StoreTransaction txh) throws BackendException { if (!txh.getConfiguration().hasGroupName()) { backend.mutateMany(mutations,txh); } String prefix = txh.getConfiguration().getGroupName(); final MetricManager mgr = MetricManager.INSTANCE; mgr.getCounter(prefix, managerMetricsName, M_MUTATE, M_CALLS).inc(); final Timer.Context tc = mgr.getTimer(prefix, managerMetricsName, M_MUTATE, M_TIME).time(); try { backend.mutateMany(mutations,txh); } catch (BackendException | RuntimeException e) { mgr.getCounter(prefix, managerMetricsName, M_MUTATE, M_EXCEPTIONS).inc(); throw e; } finally { tc.stop(); } }
@Override public void mutateMany(Map<String, Map<StaticBuffer, KCVMutation>> mutations, StoreTransaction txh) throws BackendException { if (!manager.getFeatures().hasStoreTTL()) { assert manager.getFeatures().hasCellTTL(); for (Map.Entry<String,Map<StaticBuffer, KCVMutation>> sentry : mutations.entrySet()) { Integer ttl = ttlEnabledStores.get(sentry.getKey()); if (null != ttl && 0 < ttl) { for (KCVMutation mut : sentry.getValue().values()) { if (mut.hasAdditions()) applyTTL(mut.getAdditions(), ttl); } } } } manager.mutateMany(mutations,txh); }
@Test public void testMutateManyWithLockUsesConsistentTx() throws BackendException { final ImmutableList<Entry> adds = ImmutableList.of(StaticArrayEntry.of(DATA_COL, DATA_VAL)); final ImmutableList<StaticBuffer> deletions = ImmutableList.of(); Map<String, Map<StaticBuffer, KCVMutation>> mutations = ImmutableMap.of(STORE_NAME, ImmutableMap.of(DATA_KEY, new KCVMutation(adds, deletions))); final KeyColumn kc = new KeyColumn(LOCK_KEY, LOCK_COL); // Acquire a lock backingLocker.writeLock(kc, consistentTx); // 2. Run mutateMany // 2.1. Check locks & expected values before mutating data backingLocker.checkLocks(consistentTx); StaticBuffer nextBuf = BufferUtil.nextBiggerBuffer(kc.getColumn()); KeySliceQuery expectedValueQuery = new KeySliceQuery(kc.getKey(), kc.getColumn(), nextBuf); expect(backingStore.getSlice(expectedValueQuery, consistentTx)) // expected value read must use strong consistency .andReturn(StaticArrayEntryList.of(StaticArrayEntry.of(LOCK_COL, LOCK_VAL))); // 2.2. Run mutateMany on backing manager to modify data backingManager.mutateMany(mutations, consistentTx); // writes by txs with locks must use strong consistency ctrl.replay(); // Lock acquisition expectStore.acquireLock(LOCK_KEY, LOCK_COL, LOCK_VAL, expectTx); // Mutate expectManager.mutateMany(mutations, expectTx); }
@Test public void mutateManyWritesSameKeyOnMultipleCFs() throws BackendException { final long arbitraryLong = 42; //must be greater than 0 final StaticBuffer key = KeyColumnValueStoreUtil.longToByteBuffer(arbitraryLong * arbitraryLong); final StaticBuffer val = KeyColumnValueStoreUtil.longToByteBuffer(arbitraryLong * arbitraryLong * arbitraryLong); final StaticBuffer col = KeyColumnValueStoreUtil.longToByteBuffer(arbitraryLong); final StaticBuffer nextCol = KeyColumnValueStoreUtil.longToByteBuffer(arbitraryLong + 1); final StoreTransaction directTx = manager.beginTransaction(getTxConfig()); KCVMutation km = new KCVMutation( Lists.newArrayList(StaticArrayEntry.of(col, val)), Lists.newArrayList()); Map<StaticBuffer, KCVMutation> keyColumnAndValue = ImmutableMap.of(key, km); Map<String, Map<StaticBuffer, KCVMutation>> mutations = ImmutableMap.of( storeName1, keyColumnAndValue, storeName2, keyColumnAndValue); manager.mutateMany(mutations, directTx); directTx.commit(); KeySliceQuery query = new KeySliceQuery(key, col, nextCol); List<Entry> expected = ImmutableList.of(StaticArrayEntry.of(col, val)); Assert.assertEquals(expected, store1.getSlice(query, tx)); Assert.assertEquals(expected, store2.getSlice(query, tx)); }