public static <E> Entry ofBytes(E element, StaticArrayEntry.GetColVal<E,byte[]> getter) { return of(element, getter, ByteArrayHandler.INSTANCE); }
public static <E> Entry ofStaticBuffer(E element, StaticArrayEntry.GetColVal<E,StaticBuffer> getter) { return of(element, getter, StaticBufferHandler.INSTANCE); }
public static <E> Entry of(StaticBuffer column, StaticBuffer value) { return of(column, value, StaticBufferHandler.INSTANCE); }
public static <E> Entry ofByteBuffer(E element, StaticArrayEntry.GetColVal<E,ByteBuffer> getter) { return of(element, getter, ByteBufferHandler.INSTANCE); }
int getIndex(StaticBuffer column) { return Arrays.binarySearch(array, 0, size, StaticArrayEntry.of(column)); }
@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]); }
@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); }
@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); } }
private void writeSetting(String identifier, final StaticBuffer column, long value) { final StaticBuffer key = getSettingKey(identifier); final Entry add = StaticArrayEntry.of(column, BufferUtil.getLongBuffer(value)); Boolean status = BackendOperation.execute(new BackendOperation.Transactional<Boolean>() { @Override public Boolean call(StoreTransaction txh) throws BackendException { store.mutate(key,ImmutableList.of(add),KeyColumnValueStore.NO_DELETIONS,txh); return Boolean.TRUE; } @Override public String toString() { return "writingLogSetting"; } },this, times, maxWriteTime); Preconditions.checkState(status); }
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); }
public int checkThatDeletionsApplied(Map<StaticBuffer, KCVEntryMutation> changes, KeyColumnValueStore store, int round) throws BackendException { int checked = 0; int skipped = 0; for (StaticBuffer key : changes.keySet()) { KCVEntryMutation m = changes.get(key); if (!m.hasDeletions()) continue; List<Entry> deletions = m.getDeletions(); List<Entry> additions = m.getAdditions(); for (Entry entry : deletions) { StaticBuffer col = entry.getColumn(); if (null != additions && additions.contains(StaticArrayEntry.of(col, col))) { skipped++; continue; } Assert.assertNull(KCVSUtil.get(store, key, col, tx)); checked++; } } log.debug("Checked absence of {} key-column-value deletions on round {} (skipped {})", checked, round, skipped); return checked; }
@Test public void getSliceRespectsAllBoundsInclusionArguments() throws Exception { // Test case where endColumn=startColumn+1 StaticBuffer key = KeyColumnValueStoreUtil.longToByteBuffer(0); StaticBuffer columnBeforeStart = KeyColumnValueStoreUtil.longToByteBuffer(776); StaticBuffer columnStart = KeyColumnValueStoreUtil.longToByteBuffer(777); StaticBuffer columnEnd = KeyColumnValueStoreUtil.longToByteBuffer(778); StaticBuffer columnAfterEnd = KeyColumnValueStoreUtil.longToByteBuffer(779); // First insert four test Entries List<Entry> entries = Arrays.asList( StaticArrayEntry.of(columnBeforeStart, columnBeforeStart), StaticArrayEntry.of(columnStart, columnStart), StaticArrayEntry.of(columnEnd, columnEnd), StaticArrayEntry.of(columnAfterEnd, columnAfterEnd)); store.mutate(key, entries, KeyColumnValueStore.NO_DELETIONS, tx); tx.commit(); // getSlice() with only start inclusive tx = startTx(); List<Entry> result = store.getSlice(new KeySliceQuery(key, columnStart, columnEnd), tx); Assert.assertEquals(1, result.size()); Assert.assertEquals(777, KeyColumnValueStoreUtil.bufferToLong(result.get(0).getColumn())); }
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])); }
@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); }
private static <E,D> Entry of(E element, StaticArrayEntry.GetColVal<E,D> getter, StaticArrayEntry.DataHandler<D> dataHandler) { StaticArrayEntry entry = of(getter.getColumn(element),getter.getValue(element),dataHandler); //Add meta data if exists if (getter.getMetaSchema(element).length>0) { for (EntryMetaData meta : getter.getMetaSchema(element)) { entry.setMetaData(meta,getter.getMetaData(element,meta)); } } return entry; }
@Test public void testMutateWithLockUsesConsistentTx() throws BackendException { final ImmutableList<Entry> adds = ImmutableList.of(StaticArrayEntry.of(DATA_COL, DATA_VAL)); final ImmutableList<StaticBuffer> deletions = ImmutableList.of(); final KeyColumn kc = new KeyColumn(LOCK_KEY, LOCK_COL); // 1. Acquire a lock backingLocker.writeLock(kc, consistentTx); // 2. Run a mutation // N.B. mutation coordinates do not overlap with the lock, but consistentTx should be used anyway // 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. Mutate data backingStore.mutate(DATA_KEY, adds, deletions, consistentTx); // writes by txs with locks must use strong consistency ctrl.replay(); // 1. Lock acquisition expectStore.acquireLock(LOCK_KEY, LOCK_COL, LOCK_VAL, expectTx); // 2. Mutate expectStore.mutate(DATA_KEY, adds, deletions, expectTx); }
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(); }