private static Access remove(final byte[] min, final byte[] max) {
   assert min == null || max == null || ByteUtil.compare(min, max) <= 0;
   return new Access("REM", min, max) {
     @Override
     public void apply(KVStore kv) {
       kv.removeRange(min, max);
     }
   };
 }
 private static Access getRange(
     final byte[] min, final byte[] max, final boolean reverse, final KeyRanges removes) {
   assert min == null || max == null || ByteUtil.compare(min, max) <= 0;
   return new Access("GETRNG", min, max, reverse, removes) {
     @Override
     public void apply(KVStore kv) {
       for (Iterator<KVPair> i = kv.getRange(min, max, reverse); i.hasNext(); ) {
         final KVPair pair = i.next();
         if (removes != null && removes.contains(pair.getKey())) i.remove();
       }
     }
   };
 }
  @Override
  public synchronized void mutate(Mutations mutations, boolean sync) {
    Preconditions.checkArgument(mutations != null, "null mutations");
    Preconditions.checkState(this.db != null, "closed");

    // Apply mutations in a batch
    try (WriteBatch batch = this.db.createWriteBatch()) {

      // Apply removes
      final ReadOptions iteratorOptions =
          new ReadOptions().verifyChecksums(this.options.verifyChecksums()).fillCache(false);
      for (KeyRange range : mutations.getRemoveRanges()) {
        final byte[] min = range.getMin();
        final byte[] max = range.getMax();
        if (min != null && max != null && ByteUtil.isConsecutive(min, max)) batch.delete(min);
        else {
          try (LevelDBKVStore.Iterator i =
              this.kv.createIterator(iteratorOptions, min, max, false)) {
            while (i.hasNext()) batch.delete(i.next().getKey());
          }
        }
      }

      // Apply puts
      for (Map.Entry<byte[], byte[]> entry : mutations.getPutPairs())
        batch.put(entry.getKey(), entry.getValue());

      // Convert counter adjustments into puts
      final Function<Map.Entry<byte[], Long>, Map.Entry<byte[], byte[]>> counterPutFunction =
          new Function<Map.Entry<byte[], Long>, Map.Entry<byte[], byte[]>>() {
            @Override
            public Map.Entry<byte[], byte[]> apply(Map.Entry<byte[], Long> adjust) {

              // Decode old value
              final byte[] key = adjust.getKey();
              final long diff = adjust.getValue();
              byte[] oldBytes = LevelDBAtomicKVStore.this.kv.get(key);
              if (oldBytes == null) oldBytes = new byte[8];
              final long oldValue;
              try {
                oldValue = LevelDBAtomicKVStore.this.kv.decodeCounter(oldBytes);
              } catch (IllegalArgumentException e) {
                return null;
              }

              // Add adjustment and re-encode it
              return new AbstractMap.SimpleEntry<byte[], byte[]>(
                  key, LevelDBAtomicKVStore.this.kv.encodeCounter(oldValue + diff));
            }
          };

      // Apply counter adjustments
      for (Map.Entry<byte[], byte[]> entry :
          Iterables.transform(mutations.getAdjustPairs(), counterPutFunction)) {
        if (entry != null) batch.put(entry.getKey(), entry.getValue());
      }

      // Write the batch
      this.db.write(batch, new WriteOptions().sync(sync));
    } catch (IOException e) {
      throw new DBException("error applying changes to LevelDB", e);
    }
  }
  @Test
  public void testRandomWrites() throws Exception {
    KVStore kvstore = new NavigableMapKVStore();
    KVStore expected = new NavigableMapKVStore();
    MutableView mv = new MutableView(kvstore);
    for (int i = 0; i < 100000; i++) {

      // Get key(s) and value
      byte[] minKey;
      byte[] maxKey;
      do {
        minKey = new byte[1 << this.random.nextInt(4)];
        this.random.nextBytes(minKey);
        maxKey = this.random.nextInt(7) != 0 ? new byte[1 << this.random.nextInt(4)] : null;
        if (maxKey != null) this.random.nextBytes(maxKey);
      } while (maxKey != null && ByteUtil.compare(maxKey, minKey) < 0);
      byte[] value = new byte[1 << this.random.nextInt(2)];
      this.random.nextBytes(value);

      // Mutate
      final int choice = this.random.nextInt(85);
      if (choice < 10) {
        value = mv.get(minKey);
        byte[] evalue = expected.get(minKey);
        Assert.assertEquals(value, evalue);
      } else if (choice < 20) {
        KVPair pair = mv.getAtLeast(minKey);
        KVPair epair = expected.getAtLeast(minKey);
        Assert.assertEquals(pair, epair);
      } else if (choice < 30) {
        KVPair pair = mv.getAtMost(minKey);
        KVPair epair = expected.getAtMost(minKey);
        Assert.assertEquals(pair, epair);
      } else if (choice < 40) {
        final boolean reverse = this.random.nextBoolean();
        if (this.random.nextInt(10) == 0) minKey = null;
        if (this.random.nextInt(10) == 0) maxKey = null;
        final List<KVPair> alist = Lists.newArrayList(mv.getRange(minKey, maxKey, reverse));
        final List<KVPair> elist = Lists.newArrayList(expected.getRange(minKey, maxKey, reverse));
        Assert.assertEquals(
            alist, elist, "iterations differ:\n  alist=" + alist + "\n  elist=" + elist + "\n");
      } else if (choice < 60) {
        mv.put(minKey, value);
        expected.put(minKey, value);
        if (this.log.isTraceEnabled())
          this.log.trace("PUT: " + ByteUtil.toString(minKey) + " -> " + ByteUtil.toString(value));
      } else if (choice < 70) {
        mv.remove(minKey);
        expected.remove(minKey);
        if (this.log.isTraceEnabled()) this.log.trace("REMOVE: " + ByteUtil.toString(minKey));
      } else if (choice < 80) {
        mv.removeRange(minKey, maxKey);
        expected.removeRange(minKey, maxKey);
        if (this.log.isTraceEnabled())
          this.log.trace(
              "REMOVE_RANGE: " + ByteUtil.toString(minKey) + ", " + ByteUtil.toString(maxKey));
      } else {
        mv.getWrites().applyTo(kvstore);
        mv = new MutableView(kvstore);
      }

      // Verify
      final boolean reverse = this.random.nextBoolean();
      final List<KVPair> alist = Lists.newArrayList(mv.getRange(null, null, reverse));
      final List<KVPair> elist = Lists.newArrayList(expected.getRange(null, null, reverse));
      Assert.assertEquals(
          alist, elist, "contents differ:\n  alist=" + alist + "\n  elist=" + elist + "\n");
    }
  }
Example #5
0
 @Override
 public void write(ByteWriter writer, Float value) {
   int bits = Float.floatToIntBits(value);
   bits ^= (bits & SIGN_BIT) != 0 ? NEG_XOR : POS_XOR;
   ByteUtil.writeInt(writer, bits);
 }
Example #6
0
 @Override
 public Float read(ByteReader reader) {
   int bits = ByteUtil.readInt(reader);
   bits ^= (bits & SIGN_BIT) == 0 ? NEG_XOR : POS_XOR;
   return Float.intBitsToFloat(bits);
 }