How can i use mutate in Java Client

i want to code cas operation in mutate

  public void testCAS() throws InterruptedException {
    Database db = fdb.open();
    try (Transaction tr = db.createTransaction()) {
      tr.clear(Tuple.from("count").pack());
      tr.commit().join();
    }
    CountDownLatch countDownLatch = new CountDownLatch(10);
    for (int i = 0; i < 10; i++) {
      new Thread(
              () -> {
                db.run(
                    tr -> {
                      incrementCounter1(tr);
                      return null;
                    });
                countDownLatch.countDown();
              })
          .start();
    }
    countDownLatch.await();
    try (Transaction tr1 = db.createTransaction()) {
      byte[] join = tr1.snapshot().get(Tuple.from("count").pack()).join();
      System.out.println(Tuple.fromBytes(join).getLong(0));
    }
  }

  private void incrementCounter1(Transaction tr) {
    byte[] join = tr.snapshot().get(Tuple.from("count").pack()).join();
    long counterValue = 0;
    if (join != null) {
      counterValue = Tuple.fromBytes(join).getLong(0);
    }
    tr.mutate(MutationType.ADD, Tuple.from("count").pack(), Tuple.from(counterValue + 1).pack());
  }

Actually,I have some problems…
Finally, I want to get the value of count, but the returned byte array is [-46,10]

java.lang.IllegalArgumentException: Unknown tuple data type -46 at index 0

	at com.apple.foundationdb.tuple.TupleUtil.decode(TupleUtil.java:588)
	at com.apple.foundationdb.tuple.TupleUtil.unpack(TupleUtil.java:676)
	at com.apple.foundationdb.tuple.Tuple.fromBytes(Tuple.java:552)
	at com.apple.foundationdb.tuple.Tuple.fromBytes(Tuple.java:527)
	at com.trz.CRUDTest.testCAS(CRUDTest.java:229)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

MutationType.ADD Javadoc:

Performs an addition of little-endian integers.

There is no atomic mutation for Tuple-encoded integers.

You can see an example of how to use the ADD mutation in the multimap sample code: Multimaps — FoundationDB 7.1

It’s a bit unfortunate that the atomic mutation uses a different serialization format from Tuples, and perhaps there’s space for some kind of syntactic sugar in the Java API to do the conversion for you (for example, some kind of void tr.add(byte[] key, long value) and then I guess long tr.getLong(byte[] key)), but the sample code linked above uses a ByteBuffer to encode and decode in a compatible format.

1 Like