/** * Writes the given 16-bit Short to the given ArrayView at the given offset. * * @param target The ArrayView to write to. * @param offset The offset within the ArrayView to write at. * @param value The value to write. * @return The number of bytes written. */ public static int writeShort(ArrayView target, int offset, short value) { return writeShort(target.array(), target.arrayOffset() + offset, value); }
private WireCommands.TableEntries getTableEntries(List<TableEntry> updateData) { List<Map.Entry<WireCommands.TableKey, WireCommands.TableValue>> entries = updateData.stream().map(te -> { if (te == null) { return new AbstractMap.SimpleImmutableEntry<>(WireCommands.TableKey.EMPTY, WireCommands.TableValue.EMPTY); } else { val tableKey = new WireCommands.TableKey(ByteBuffer.wrap(te.getKey().getKey().array()), te.getKey().getVersion()); val tableValue = new WireCommands.TableValue(ByteBuffer.wrap(te.getValue().array())); return new AbstractMap.SimpleImmutableEntry<>(tableKey, tableValue); } }).collect(toList()); return new WireCommands.TableEntries(entries); }
/** * Writes the given 32-bit Integer to the given ArrayView at the given offset. * * @param target The ArrayView to write to. * @param offset The offset within the ArrayView to write at. * @param value The value to write. * @return The number of bytes written. */ public static int writeInt(ArrayView target, int offset, int value) { return writeInt(target.array(), target.arrayOffset() + offset, value); }
WireCommands.TableKey key = new WireCommands.TableKey(ByteBuffer.wrap(e1.getKey().getKey().array()), 0L); processor.removeTableKeys(new WireCommands.RemoveTableKeys(3, streamSegmentName, "", singletonList(key))); order.verify(connection).send(new WireCommands.TableKeysRemoved(3, streamSegmentName)); key = new WireCommands.TableKey(ByteBuffer.wrap(e1.getKey().getKey().array()), 0L); processor.removeTableKeys(new WireCommands.RemoveTableKeys(4, streamSegmentName, "", singletonList(key))); order.verify(connection).send(new WireCommands.TableKeyBadVersion(4, streamSegmentName, "" ));
/** * Writes the given 64-bit Long to the given ArrayView at the given offset. * * @param target The ArrayView to write to. * @param offset The offset within the ArrayView to write at. * @param value The value to write. * @return The number of bytes written. */ public static int writeLong(ArrayView target, int offset, long value) { return writeLong(target.array(), target.arrayOffset() + offset, value); }
Entry(ArrayView inputData) { this.data = new byte[inputData.getLength()]; System.arraycopy(inputData.array(), inputData.arrayOffset(), this.data, 0, this.data.length); }
/** * Creates a new instance of the HashedArray class. * * @param array An {@link ArrayView} to wrap. */ public HashedArray(ArrayView array) { super(array.array(), array.arrayOffset(), array.getLength()); this.hashCode = hashCode(array); }
/** * Calculates a Hash Code for the given {@link ArrayView}. * * @param array The {@link ArrayView} to calculate the hash for. * @return The hash code. */ public static int hashCode(ArrayView array) { return HASH.hash(array.array(), array.arrayOffset(), array.getLength()); }
/** * Determines if the given {@link ArrayView} instances contain the same data. * * @param av1 The first instance. * @param av2 The second instance. * @return True if both instances have the same length and contain the same data. */ public static boolean arrayEquals(ArrayView av1, ArrayView av2) { int len = av1.getLength(); if (len != av2.getLength()) { return false; } byte[] a1 = av1.array(); int o1 = av1.arrayOffset(); byte[] a2 = av2.array(); int o2 = av2.arrayOffset(); for (int i = 0; i < len; i++) { if (a1[o1 + i] != a2[o2 + i]) { return false; } } return true; } }
public int hashToBucket(ArrayView array, int numBuckets) { return Hashing.consistentHash(hash.hashBytes(array.array(), array.arrayOffset(), array.getLength()), numBuckets); }
@Override public CompletableFuture<Void> append(String streamName, Event event, Duration timeout) { ensureRunning(); ArrayView s = event.getSerialization(); byte[] payload = s.arrayOffset() == 0 ? s.array() : Arrays.copyOfRange(s.array(), s.arrayOffset(), s.getLength()); return this.streamSegmentStore.append(streamName, payload, null, timeout) .exceptionally(ex -> attemptReconcile(ex, streamName, timeout)); }
@Override public UUID hash(@NonNull ArrayView key) { byte[] rawHash = new byte[HASH_SIZE_BYTES]; int c = HASH.hashBytes(key.array(), key.arrayOffset(), key.getLength()).writeBytesTo(rawHash, 0, rawHash.length); assert c == rawHash.length; return toUUID(rawHash); } }
private WireCommands.TableEntries getTableEntries(final List<ArrayView> inputKeys, final List<TableEntry> resultEntries) { Preconditions.checkArgument(resultEntries.size() == inputKeys.size(), "Number of input keys should match result entry count."); final List<Map.Entry<WireCommands.TableKey, WireCommands.TableValue>> entries = IntStream.range(0, resultEntries.size()) .mapToObj(i -> { TableEntry resultTableEntry = resultEntries.get(i); if (resultTableEntry == null) { // no entry for key at index i. ArrayView k = inputKeys.get(i); // key for which the read result was null. val keyWireCommand = new WireCommands.TableKey(ByteBuffer.wrap(k.array(), k.arrayOffset(), k.getLength()), TableKey.NO_VERSION); return new AbstractMap.SimpleImmutableEntry<>(keyWireCommand, WireCommands.TableValue.EMPTY); } else { TableEntry te = resultEntries.get(i); TableKey k = te.getKey(); val keyWireCommand = new WireCommands.TableKey(ByteBuffer.wrap(k.getKey().array(), k.getKey().arrayOffset(), k.getKey().getLength()), k.getVersion()); ArrayView v = te.getValue(); val valueWireCommand = new WireCommands.TableValue(ByteBuffer.wrap(v.array(), v.arrayOffset(), v.getLength())); return new AbstractMap.SimpleImmutableEntry<>(keyWireCommand, valueWireCommand); } }).collect(toList()); return new WireCommands.TableEntries(entries); }
/** * Serializes the given {@link TableEntry} to the given byte array. * * @param entry The {@link TableEntry} to serialize. * @param target The byte array to serialize to. * @param targetOffset The first offset within the byte array to serialize at. * @return The first offset in the given byte array after the serialization. */ private int serializeUpdate(@NonNull TableEntry entry, byte[] target, int targetOffset) { val key = entry.getKey().getKey(); val value = entry.getValue(); Preconditions.checkArgument(key.getLength() <= MAX_KEY_LENGTH, "Key too large."); int serializationLength = getUpdateLength(entry); Preconditions.checkArgument(serializationLength <= MAX_SERIALIZATION_LENGTH, "Key+Value serialization too large."); Preconditions.checkElementIndex(targetOffset + serializationLength - 1, target.length, "serialization does not fit in target buffer"); // Serialize Header. target[targetOffset] = CURRENT_SERIALIZATION_VERSION; targetOffset++; targetOffset += BitConverter.writeInt(target, targetOffset, key.getLength()); targetOffset += BitConverter.writeInt(target, targetOffset, value.getLength()); // Key System.arraycopy(key.array(), key.arrayOffset(), target, targetOffset, key.getLength()); targetOffset += key.getLength(); // Value. System.arraycopy(value.array(), value.arrayOffset(), target, targetOffset, value.getLength()); targetOffset += value.getLength(); return targetOffset; }
/** * Serializes the given {@link TableKey} for removal into the given array. * * @param tableKey The {@link TableKey} to serialize. * @param target The byte array to serialize to. * @param targetOffset The first offset within the byte array to serialize at. * @return The first offset in the given byte array after the serialization. */ private int serializeRemoval(@NonNull TableKey tableKey, byte[] target, int targetOffset) { val key = tableKey.getKey(); Preconditions.checkArgument(key.getLength() <= MAX_KEY_LENGTH, "Key too large."); int serializationLength = getRemovalLength(tableKey); Preconditions.checkElementIndex(targetOffset + serializationLength - 1, target.length, "serialization does not fit in target buffer"); // Serialize Header. target[targetOffset] = CURRENT_SERIALIZATION_VERSION; targetOffset++; targetOffset += BitConverter.writeInt(target, targetOffset, key.getLength()); targetOffset += BitConverter.writeInt(target, targetOffset, NO_VALUE); // Key System.arraycopy(key.array(), key.arrayOffset(), target, targetOffset, key.getLength()); return targetOffset + key.getLength(); }
w.getWriteLedger().ledger.asyncAddEntry(w.data.array(), w.data.arrayOffset(), w.data.getLength(), this::addCallback, w); } catch (Throwable ex) {
@Override public CompletableFuture<Void> append(String streamName, Event event, Duration timeout) { ensureRunning(); ArrayView s = event.getSerialization(); byte[] payload = s.arrayOffset() == 0 ? s.array() : Arrays.copyOfRange(s.array(), s.arrayOffset(), s.getLength()); String routingKey = Integer.toString(event.getRoutingKey()); String parentName = StreamSegmentNameUtils.getParentStreamSegmentName(streamName); if (isTransaction(streamName, parentName)) { // Dealing with a Transaction. return CompletableFuture.runAsync(() -> { try { UUID txnId = getTransactionId(streamName); getTransactionalWriter(parentName, event.getRoutingKey()).getTxn(txnId).writeEvent(routingKey, payload); } catch (Exception ex) { this.transactionIds.remove(streamName); throw new CompletionException(ex); } }, this.testExecutor); } else { try { return getWriter(streamName, event.getRoutingKey()).writeEvent(routingKey, payload); } catch (Exception ex) { return Futures.failedFuture(ex); } } }
/** * Tests the ability to read a key. */ @Test public void testReadKey() throws Exception { val testItems = generateTestItems(); for (val e : testItems) { val keyReader = AsyncTableEntryReader.readKey(1L, SERIALIZER, new TimeoutTimer(TIMEOUT)); @Cleanup val rr = new ReadResultMock(e.serialization, e.serialization.length, 1); AsyncReadResultProcessor.process(rr, keyReader, executorService()); // Get the result and compare it with the original key. val result = keyReader.getResult().get(BASE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); val expectedVersion = e.isRemoval ? TableKey.NOT_EXISTS : 1L; Assert.assertEquals("Unexpected version.", expectedVersion, result.getVersion()); AssertExtensions.assertArrayEquals("Unexpected key read back.", e.key, 0, result.getKey().array(), result.getKey().arrayOffset(), e.key.length); } }
@Test public void testRemoval() throws Exception { val keys = generateKeys(); val s = new EntrySerializer(); val length = keys.stream().map(s::getRemovalLength).mapToInt(i -> i).sum(); byte[] serialization = new byte[length]; s.serializeRemoval(keys, serialization); int offset = 0; for (val key : keys) { val headerStream = s.readHeader(new ByteArrayInputStream(serialization, offset, serialization.length - offset)); val headerArray = s.readHeader(new ByteArraySegment(serialization, offset, serialization.length - offset)); Assert.assertEquals("Unexpected key length (stream).", key.getKey().getLength(), headerStream.getKeyLength()); Assert.assertEquals("Unexpected key length (array).", key.getKey().getLength(), headerArray.getKeyLength()); Assert.assertTrue("Unexpected value from isDeletion().", headerStream.isDeletion() && headerArray.isDeletion()); AssertExtensions.assertArrayEquals("Unexpected serialized key.", serialization, offset + headerStream.getKeyOffset(), key.getKey().array(), key.getKey().arrayOffset(), headerStream.getKeyLength()); AssertExtensions.assertThrows( "Able to retrieve value for deletion header.", headerStream::getValueOffset, ex -> ex instanceof IllegalStateException); offset += headerArray.getTotalLength(); } Assert.assertEquals("Did not read the entire serialization.", serialization.length, offset); }
/** * Tests the ability to serialize updates. */ @Test public void testUpdate() throws Exception { val entries = generateEntries(); val s = new EntrySerializer(); val length = entries.stream().map(s::getUpdateLength).mapToInt(i -> i).sum(); byte[] serialization = new byte[length]; s.serializeUpdate(entries, serialization); int offset = 0; for (val e : entries) { val headerStream = s.readHeader(new ByteArrayInputStream(serialization, offset, serialization.length - offset)); val headerArray = s.readHeader(new ByteArraySegment(serialization, offset, serialization.length - offset)); Assert.assertEquals("Unexpected key length (stream).", e.getKey().getKey().getLength(), headerStream.getKeyLength()); Assert.assertEquals("Unexpected key length (array).", e.getKey().getKey().getLength(), headerArray.getKeyLength()); Assert.assertEquals("Unexpected value length (stream).", e.getValue().getLength(), headerStream.getValueLength()); Assert.assertEquals("Unexpected value length (array).", e.getValue().getLength(), headerArray.getValueLength()); Assert.assertFalse("Unexpected value from isDeletion().", headerStream.isDeletion() || headerArray.isDeletion()); AssertExtensions.assertArrayEquals("Unexpected serialized key.", serialization, offset + headerStream.getKeyOffset(), e.getKey().getKey().array(), e.getKey().getKey().arrayOffset(), headerStream.getKeyLength()); AssertExtensions.assertArrayEquals("Unexpected serialized value.", serialization, offset + headerStream.getValueOffset(), e.getValue().array(), e.getValue().arrayOffset(), headerStream.getValueLength()); offset += headerArray.getTotalLength(); } Assert.assertEquals("Did not read the entire serialization.", serialization.length, offset); }