Git Product home page Git Product logo

aerospike-client-java's Introduction

Aerospike Java Client Package

Aerospike Java client. This package contains full source code for these projects.

  • client: Java native client library.
  • proxy: Java proxy client library for dbaas (database as a service).
  • examples: Java client examples.
  • benchmarks: Java client benchmarks.
  • test: Java client unit tests.

Prerequisites:

  • Java 21+
  • Maven 3.9.5+

The source code can be imported into any Java IDE.
Maven build scripts are also provided.

Build instructions:

./build_all

aerospike-client-java's People

Contributors

acmeofmanas avatar aerospikerobertmarks avatar agrgr avatar anandintouch avatar ani94 avatar ashishshinde avatar briannichols avatar dependabot[bot] avatar fpopic avatar hbpatre avatar helipilot50 avatar himanchali avatar jtraver avatar justinlee-aerospike avatar jyotigithub avatar kportertx avatar ksedgwic avatar pr-lawrence avatar pvinh-spike avatar pygupta avatar rahul-aerospike avatar reugn avatar roimenashe avatar sambarker avatar sanjalinagare57 avatar snyk-bot avatar spkesan avatar sud82 avatar sunilvirus avatar wchu-citrusleaf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aerospike-client-java's Issues

Deadlock and other problems

I made some tests with the AsyncClient. Unfortunately there are several problems. I don't have the feeling that this is really ready for production :(

So far I only tested a client.get with a RecordListener.
At first I figured out that all the exceptions in the methods onSuccess and onFailure of a RecordListener will we swallowed. When you want to change it, you should print the exception in
com.aerospike.client.async.SelectorManager line 100.

I set an expiration of -1 but the record shows me an expiration of 0 for the same value. This is a bit inconsistent.

In my tests I closed the client before the RecordListener could return any results of a client.get() call. With aerospike-client-3.0.35.jar this will lead to a deadlock in 100 % of all cases. The java program won't terminate.
With the latest source code a deadlock only occurs in some cases. But this must be fixed. Your client must always shut down gracefully! In my test cases I never used a local Aerospike server. This means there was always a high network latency.

Hopefully this stack will help you:

Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.75-b04 mixed mode):

"RMI TCP Connection(2)-" daemon prio=6 tid=0x000000000a70f000 nid=0x1770 runnable [0x000000000ba7e000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
- locked <0x00000000eb333e68> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.access$400(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Locked ownable synchronizers:
- <0x00000000eb042fe8> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"JMX server connection timeout 15" daemon prio=6 tid=0x000000000a5c0800 nid=0x16c8 in Object.wait() [0x000000000b96f000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000eb18d518> (a [I)
at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(Unknown Source)
- locked <0x00000000eb18d518> (a [I)
at java.lang.Thread.run(Unknown Source)

Locked ownable synchronizers:
- None

"RMI Scheduler(0)" daemon prio=6 tid=0x00000000095d0000 nid=0x7f4 waiting on condition [0x000000000b73e000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000eaf9a980> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Locked ownable synchronizers:
- None

"RMI TCP Connection(1)-" daemon prio=6 tid=0x00000000095cf800 nid=0x1648 runnable [0x000000000b54e000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
- locked <0x00000000eb0e47b0> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.access$400(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Locked ownable synchronizers:
- <0x00000000eb03fb00> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"RMI TCP Accept-0" daemon prio=6 tid=0x00000000098c8000 nid=0x1618 runnable [0x000000000b2ce000]
java.lang.Thread.State: RUNNABLE
at java.net.DualStackPlainSocketImpl.accept0(Native Method)
at java.net.DualStackPlainSocketImpl.socketAccept(Unknown Source)
at java.net.AbstractPlainSocketImpl.accept(Unknown Source)
at java.net.PlainSocketImpl.accept(Unknown Source)
- locked <0x00000000eaf9e748> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(Unknown Source)
at java.net.ServerSocket.accept(Unknown Source)
at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Locked ownable synchronizers:
- None

"selector0" daemon prio=6 tid=0x000000000989d800 nid=0xc10 waiting for monitor entry [0x000000000a0af000]
java.lang.Thread.State: BLOCKED (on object monitor)
at sun.nio.ch.WindowsSelectorImpl.putEventOps(Unknown Source)
- waiting to lock <0x00000000eab790d8> (a java.lang.Object)
at sun.nio.ch.SocketChannelImpl.translateAndSetInterestOps(Unknown Source)
at sun.nio.ch.SelectionKeyImpl.nioInterestOps(Unknown Source)
at sun.nio.ch.SelectionKeyImpl.interestOps(Unknown Source)
at sun.nio.ch.SelectorImpl.register(Unknown Source)
at java.nio.channels.spi.AbstractSelectableChannel.register(Unknown Source)
- locked <0x00000000eacf6c00> (a java.lang.Object)
- locked <0x00000000eacf6c10> (a java.lang.Object)
at com.aerospike.client.async.AsyncConnection.register(AsyncConnection.java:86)
at com.aerospike.client.async.SelectorManager.registerCommands(SelectorManager.java:129)
at com.aerospike.client.async.SelectorManager.runCommands(SelectorManager.java:85)
at com.aerospike.client.async.SelectorManager.run(SelectorManager.java:69)

Locked ownable synchronizers:
- None

"Service Thread" daemon prio=6 tid=0x0000000007df0000 nid=0x106c runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"C2 CompilerThread1" daemon prio=10 tid=0x0000000007ded000 nid=0xa04 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"C2 CompilerThread0" daemon prio=10 tid=0x0000000007dde800 nid=0x1488 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Attach Listener" daemon prio=10 tid=0x0000000007ddd000 nid=0x1624 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Signal Dispatcher" daemon prio=10 tid=0x0000000007ddb800 nid=0x10e8 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Finalizer" daemon prio=8 tid=0x0000000007d89800 nid=0x7d8 in Object.wait() [0x0000000008c3f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000eaa84858> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
- locked <0x00000000eaa84858> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)

Locked ownable synchronizers:
- None

"Reference Handler" daemon prio=10 tid=0x0000000001d2c000 nid=0x1540 in Object.wait() [0x000000000890f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000eaa84470> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
- locked <0x00000000eaa84470> (a java.lang.ref.Reference$Lock)

Locked ownable synchronizers:
- None

"main" prio=6 tid=0x0000000001d5d800 nid=0x1420 waiting for monitor entry [0x000000000208f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.nio.channels.spi.AbstractSelectableChannel.removeKey(Unknown Source)
- waiting to lock <0x00000000eacf6c00> (a java.lang.Object)
at java.nio.channels.spi.AbstractSelector.deregister(Unknown Source)
at sun.nio.ch.WindowsSelectorImpl.implClose(Unknown Source)
- locked <0x00000000eab790d8> (a java.lang.Object)
at sun.nio.ch.SelectorImpl.implCloseSelector(Unknown Source)
- locked <0x00000000eab78e58> (a sun.nio.ch.Util$2)
- locked <0x00000000eab78df0> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000eab78bd8> (a sun.nio.ch.WindowsSelectorImpl)
at java.nio.channels.spi.AbstractSelector.close(Unknown Source)
at com.aerospike.client.async.SelectorManager.close(SelectorManager.java:201)
at com.aerospike.client.async.SelectorManagers.close(SelectorManagers.java:65)
at com.aerospike.client.async.AsyncCluster.close(AsyncCluster.java:86)
at com.aerospike.client.AerospikeClient.close(AerospikeClient.java:233)
at Test.main(Test.java:130)

Locked ownable synchronizers:
- None

"VM Thread" prio=10 tid=0x0000000007d82000 nid=0x1734 runnable

"GC task thread#0 (ParallelGC)" prio=6 tid=0x0000000001c64000 nid=0x1144 runnable

"GC task thread#1 (ParallelGC)" prio=6 tid=0x0000000001c66000 nid=0x15d0 runnable

"VM Periodic Task Thread" prio=10 tid=0x0000000007df9800 nid=0x15d8 waiting on condition

JNI global references: 167

Found one Java-level deadlock:

"selector0":
waiting to lock monitor 0x0000000007d896d8 (object 0x00000000eab790d8, a java.lang.Object),
which is held by "main"
"main":
waiting to lock monitor 0x0000000007d88028 (object 0x00000000eacf6c00, a java.lang.Object),
which is held by "selector0"

Java stack information for the threads listed above:

"selector0":
at sun.nio.ch.WindowsSelectorImpl.putEventOps(Unknown Source)
- waiting to lock <0x00000000eab790d8> (a java.lang.Object)
at sun.nio.ch.SocketChannelImpl.translateAndSetInterestOps(Unknown Source)
at sun.nio.ch.SelectionKeyImpl.nioInterestOps(Unknown Source)
at sun.nio.ch.SelectionKeyImpl.interestOps(Unknown Source)
at sun.nio.ch.SelectorImpl.register(Unknown Source)
at java.nio.channels.spi.AbstractSelectableChannel.register(Unknown Source)
- locked <0x00000000eacf6c00> (a java.lang.Object)
- locked <0x00000000eacf6c10> (a java.lang.Object)
at com.aerospike.client.async.AsyncConnection.register(AsyncConnection.java:86)
at com.aerospike.client.async.SelectorManager.registerCommands(SelectorManager.java:129)
at com.aerospike.client.async.SelectorManager.runCommands(SelectorManager.java:85)
at com.aerospike.client.async.SelectorManager.run(SelectorManager.java:69)
"main":
at java.nio.channels.spi.AbstractSelectableChannel.removeKey(Unknown Source)
- waiting to lock <0x00000000eacf6c00> (a java.lang.Object)
at java.nio.channels.spi.AbstractSelector.deregister(Unknown Source)
at sun.nio.ch.WindowsSelectorImpl.implClose(Unknown Source)
- locked <0x00000000eab790d8> (a java.lang.Object)
at sun.nio.ch.SelectorImpl.implCloseSelector(Unknown Source)
- locked <0x00000000eab78e58> (a sun.nio.ch.Util$2)
- locked <0x00000000eab78df0> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000eab78bd8> (a sun.nio.ch.WindowsSelectorImpl)
at java.nio.channels.spi.AbstractSelector.close(Unknown Source)
at com.aerospike.client.async.SelectorManager.close(SelectorManager.java:201)
at com.aerospike.client.async.SelectorManagers.close(SelectorManagers.java:65)
at com.aerospike.client.async.AsyncCluster.close(AsyncCluster.java:86)
at com.aerospike.client.AerospikeClient.close(AerospikeClient.java:233)
at Test.main(Test.java:130)

Found 1 deadlock.

Error Code 4: Parameter error when using round-robin reverse-proxy

We have an Aerospike installation with a round-robin reverse-proxy in front of the nodes (this is in practice a Kubernetes service).

This sometimes works, but for the same request often returns:
com.aerospike.client.AerospikeException: Error Code 4: Parameter error
at com.aerospike.client.command.MultiCommand.parseGroup(MultiCommand.java:96)
at com.aerospike.client.command.MultiCommand.parseResult(MultiCommand.java:71)
at com.aerospike.client.command.SyncCommand.execute(SyncCommand.java:57)
at com.aerospike.client.query.QueryExecutor$QueryThread.run(QueryExecutor.java:137)

If I reconfigure it so that the Kubernetes service only points to a single node then it works fine.

I am using version 3.2.4 of the Java client and 3.9.1 of the server. This is very similar to this issue:
aerospike/aerospike-client-go#97

Support asynchronous aggregate queries

It would be very helpful to have an asynchronous equivalent to AerospikeClient.queryAggregate(). This feature gap prevents the use of AsyncClient in applications which require aggregation.

removeUdf method for AerospikeClient is missing

Not sure if its an issue or intended but removeUdf method in the API is missing. I'm currently using a self-made tool to generate lua UDFs and register them in Aerospike, but I cannot remove them in a "development way" unless I do it manually.

This operation already exists in Ruby and Go clients and I think it is odd to have inconsistency for different language bindings (http://www.aerospike.com/docs/client/go/usage/udf/remove.html and http://www.aerospike.com/docs/client/ruby/usage/udf/remove.html) even more given the fact I can register indexes and UDFs but cannot remove them.

EDIT: C bindings also have remove options http://www.aerospike.com/docs/client/c/usage/udf/register.html

Provide a way to change default policy when using IAerospikeClient/IAsyncClient

Scenario: I want to put a value using client's default write policy, but I want to set expiration time for the record. If I use the AerospikeClient class I can do that like this:

AerospikeClient client = getClient();
WritePolicy policy = new WritePolicy(client.writePolicyDefault);
policy.expiration = 10;
client.put(policy, key, bin);

But I cannot access writePolicyDefault if I use the IAerospikeClient interface.
Please either create getters for default policies in the interfaces or provide another way to apply a modified default policy for an operation.

Java client ERROR: /opt/aerospike/sys/udf/lua/ldt/lib_lmap.lua:868 LDT-Bin Does Not Exist

Client cannot execute "scan", "config" and the exception com.aerospike.client.AerospikeException: Error Code 1417: /opt/aerospike/sys/udf/lua/ldt/lib_lmap.lua:868 LDT-Bin Does Not Exist is flow

WritePolicy policy = new WritePolicy();
policy.sendKey= true;
Key key = new Key(SystemVariable.DEFAULT_NAME_SPACE, Account.class, uuid);
LargeMap lg= ((LargeMap)aerospikeClient.getLargeMap(policy, key, "userGroupMap", null));
Map map = lg.getConfig(); //ERROR Map<String,String>
if (lg.size()>0){ //ERROR

}

com.aerospike.client.AerospikeException: Error Code 1417: /opt/aerospike/sys/udf/lua/ldt/lib_lmap.lua:868 LDT-Bin Does Not Exist
at com.aerospike.client.command.ReadCommand.handleUdfError(ReadCommand.java:157)
at com.aerospike.client.command.ReadCommand.parseResult(ReadCommand.java:118)
at com.aerospike.client.command.SyncCommand.execute(SyncCommand.java:56)
at com.aerospike.client.AerospikeClient.execute(AerospikeClient.java:1145)
at com.aerospike.client.large.LargeMap.getConfig(LargeMap.java:145)

Adding a Byte Array to a Large List throws an exception

Calling LargeList.add(Value value) with a byte array Value throws an exception:

Example Call:
list.add(Value.get("testhello".getBytes())

Exception:
AerospikeException: Error Code 100: /opt/aerospike/sys/udf/lua/ldt/lib_llist.lua:1243: bad argument #2 to '?' (number expected, got string) (ReadCommand.java:142)
[error] com.aerospike.client.command.ReadCommand.handleUdfError(ReadCommand.java:142)
[error] com.aerospike.client.command.ReadCommand.parseResult(ReadCommand.java:106)
[error] com.aerospike.client.command.SyncCommand.execute(SyncCommand.java:56)
[error] com.aerospike.client.AerospikeClient.execute(AerospikeClient.java:926)

Support set udf path

there is a function to set udf path in aerospike-client-c,but i cann't find the same function in aerospike-client-java.

it seem that not allow to modify the lua path
image

Aerospike java client may not trigger callback on nested async calls

When creating an async aerospike client and explicitly creating an asyncTaskThreadPool (i.e. not running on the same thread as the selector) and the client policy asyncSelectorTimeout is not explicitly set, the aerospike client may occasionally not issue a callback when executing nested reads (seems to be a race condition)

The code below illustrates an example of when the nested bulk call may sometimes hang:

public static void main(String[] args) throws Exception {
    AsyncClientPolicy asyncClientPolicy = new AsyncClientPolicy();
    asyncClientPolicy.asyncMaxCommands = 200;
    asyncClientPolicy.asyncSelectorThreads = 1;
    asyncClientPolicy.asyncTaskThreadPool = Executors.newFixedThreadPool(10);

    // NOTE: Adding selector timeout seems to prevent the nested bulk call from hanging
    //asyncClientPolicy.asyncSelectorTimeout = 1;

    AsyncClient client = new AsyncClient(asyncClientPolicy, AEROSPIKE_HOST, AEROSPIKE_PORT);

    client.get(new ReadPolicy(), new RecordListener() {
        public void onSuccess(Key key, final Record record) {
             // Bulk call below may never notify listener of success or error
             client.get(new ReadPolicy(), new RecordArrayListener() {
             ... 
             keys);
       }

       public void onFailure(AerospikeException e) {
            ...
       }
    }, key);
   }
}

The aerospike client selector seems to block when no timeout is specified and async tasks may not notify listeners of completion events.

Question is, is this expected behaviour and what is the recommended setting for the asyncSelectorTimeout variable (low or high value)?

Full code example:

    import java.util.concurrent.Executors;
    import com.aerospike.client.AerospikeException;
    import com.aerospike.client.Key;
    import com.aerospike.client.Record;
    import com.aerospike.client.async.AsyncClient;
    import com.aerospike.client.async.AsyncClientPolicy;
    import com.aerospike.client.listener.RecordArrayListener;
    import com.aerospike.client.listener.RecordListener;
    import com.aerospike.client.policy.Policy;
    public class AerospikeAsyncTest {

    private static final String NAMESPACE = "default"; 
    private static final String AEROSPIKE_HOST = "<HOST>";
    private static final int AEROSPIKE_PORT = 3000;

    private static final String PRIMARY_KEY = "<KEY>";
    private static final String[] SECONDARY_KEYS = {"<KEY>", "<KEY>",
      "<KEY>", "<KEY>", "<KEY>", "<KEY>",
      "<KEY>", "<KEY>", "<KEY>", "<KEY>"};

    private static class ReadPolicy extends Policy {
      public int timeout = 500;
      public int maxRetries = 0;
      public int sleepBetweenRetries = 0;
    }

    public static void main(String[] args) throws Exception {
      AsyncClientPolicy asyncClientPolicy = new AsyncClientPolicy();
      asyncClientPolicy.asyncMaxCommands = 200;
      asyncClientPolicy.asyncSelectorThreads = 1;

      // NOTE: Un-commenting this timeout setting seems to prevent the bulk call from hanging
      //asyncClientPolicy.asyncSelectorTimeout = 2;

      // NOTE: Commenting out this thread pool also seems to prevent the bulk call from hanging
      asyncClientPolicy.asyncTaskThreadPool = Executors.newFixedThreadPool(10);

      AsyncClient client = new AsyncClient(asyncClientPolicy, AEROSPIKE_HOST,   AEROSPIKE_PORT);

      for (int i = 0; i < 10; i++) {
        System.out.println("Running iteration " + i);
        // The runExample call will pass sometimes and hang other times
        // Seems to be a race condition in the aerospike client library
        // When race condition occurs, test will hang when making the bulk get call
        new AerospikeAsyncTest().runExample(client);
      }
    }

    private boolean completed;

    public void runExample(AsyncClient client) throws Exception {
      run(client);
      waitTillComplete();
    }

    private void run(final AsyncClient client) throws AerospikeException {

      Key key = new Key(NAMESPACE, (String) null, PRIMARY_KEY);
      System.out.println("Running initial get...");
      client.get(new ReadPolicy(), new RecordListener() {

        public void onSuccess(Key key, final Record record) {
          try {
            System.out.println("Initial get completed successfully");
            Key[] keys = new Key[SECONDARY_KEYS.length];
            int i = 0;
            for (String secondaryKey : SECONDARY_KEYS) {
              keys[i++] = new Key(NAMESPACE, (String) null, secondaryKey);
            }

            System.out.println("Running bulk get...");
            // Client seems to get stuck here, listener is never notified of success or failure when
            // race condition occurs
            client.get(new ReadPolicy(), new RecordArrayListener() {

              @Override
              public void onSuccess(final Key[] keys, final Record[] records) {
                System.out.println("Bulk get completed successfully: " + records);
                notifyCompleted();
              }

              public void onFailure(AerospikeException e) {
                e.printStackTrace();
                notifyCompleted();
              }
            }, keys);
          } catch (Exception e) {
            e.printStackTrace();
          }
        }

        public void onFailure(AerospikeException e) {
          e.printStackTrace();
          notifyCompleted();
        }
      }, key);
    }


    private synchronized void waitTillComplete() {
      while (!completed) {
        try {
          super.wait();
        } catch (InterruptedException ie) {
        }
      }
    }

    private synchronized void notifyCompleted() {
      completed = true;
      super.notify();
    }

    }

Null pointer in LList exists

This is the exists method. When corresponding key or llist is missing in Aerospike, list object at the 2nd line is null & hence list.size() at 3rd line throws Null Pointer exception.

public List<Boolean> exists(List<Value> keyValues) throws AerospikeException {
        List<?> list = (List<?>)client.execute(policy, key, PackageName, "exists", binName, Value.get(keyValues));
        List<Boolean> target = new ArrayList<Boolean>(list.size());

        for (Object obj : list) {
            target.add(Util.toBoolean(obj));
        }
        return target;
    }

Not sure if similar issues are there for other methods too.

Batch write and delete

When i do some benchmarks, inserting a lot of records (a key and a bin of 1 kbytes), i see all my indicators (CPU, IO network and disk) at a very low level. But the result is not so good (20000 records/sec ==> 25 Mbytes/sec). I think it's due to network and client/server latency. So with methods for a batch write (and batch delete) , i'm sure i could go more faster!

Support for get_all

I see lib_lmap.lua contains a function called llist.get_all(), but I don't see support for that in the LargeMap class here. Is there a particular reason this has been left out, such as scan() being better, or would it be possible to get support for it?

Batch get() with null policy results in Null Pointer Exception

AerospikeClient#get(Policy policy, Key[] keys, String... binNames) operation throws a null pointer exception when I pass in a null policy. This behaviour seems to conflict with its documentation:

@param policy               generic configuration parameters, pass in null for defaults

This behaviour may be present in other batch operations using the BatchExecutor:

  • exists(Policy policy, Key[] keys)
  • get(Policy policy, Key[] keys)
  • getHeader(Policy policy, Key[] keys)

The Exception:
com.aerospike.client.AerospikeException: java.lang.NullPointerException at com.aerospike.client.command.BatchExecutor.<init>(BatchExecutor.java:86)

Creating record from Clojure results into "Cannot cast com.aerospike.client.Bin to [Lcom.aerospike.client.Bin;"

Trying to create aerospike records, using the client e.g. version [com.aerospike/aerospike-client "3.0.34"] or [com.aerospike/aerospike-client "3.0.20"]
results in the following error:
ClassCastException Cannot cast com.aerospike.client.Bin to [Lcom.aerospike.client.Bin; java.lang.Class.cast (Class.java:3133)

(ns todo-aerospike.domain.utils.db
  (:import [com.aerospike.client Bin AerospikeClient Key Record Info]
           [com.aerospike.client.cluster Node]
           [com.aerospike.client.policy WritePolicy]))

(def key-namespace "todo-aerospike")
(def write-policy (new WritePolicy))

(defn uuid []
  (str (java.util.UUID/randomUUID)))

(defn create [conn data]
  "[C]RUD creates a record  "
  (let [bin (new Bin (:column-name data) (:value data))
        key (new Key key-namespace (:set-name data) (uuid))]
        (println (.getClass bin)) ; for Debug
        (. conn put write-policy key bin)))

trying to create a record from the repl, results in the mentioned error

โžœ  todo-aerospike git:(master) โœ— lein repl
nREPL server started on port 53426 on host 127.0.0.1 - nrepl://127.0.0.1:53426
REPL-y 0.3.5, nREPL 0.2.6
Clojure 1.6.0
Java HotSpot(TM) 64-Bit Server VM 1.7.0_67-b01
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

=> (in-ns 'todo-aerospike.domain.utils.db)
=> (def conn (new AerospikeClient "localhost" 3000))
=> (first (.getNodes conn))
#<Node BB976C89B270008 127.0.0.1:3000>
=>  (create conn { :column-name "test" :value "work you client" :set-name "test" })
com.aerospike.client.Bin

ClassCastException Cannot cast com.aerospike.client.Bin to [Lcom.aerospike.client.Bin;  java.lang.Class.cast (Class.java:3133)

and this is the stacktrace

java.lang.ClassCastException: Cannot cast com.aerospike.client.Bin to [Lcom.aerospike.client.Bin;
        at java.lang.Class.cast(Class.java:3133)
        at clojure.lang.Reflector.boxArg(Reflector.java:427)
        at clojure.lang.Reflector.boxArgs(Reflector.java:460)
        at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:58)
        at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28)
        at todo_aerospike.domain.utils.db$eval6145.invoke(form-init4786145880839548089.clj:1)
        at clojure.lang.Compiler.eval(Compiler.java:6703)
        at clojure.lang.Compiler.eval(Compiler.java:6666)
        at clojure.core$eval.invoke(core.clj:2927)
        at clojure.main$repl$read_eval_print__6625$fn__6628.invoke(main.clj:239)
        at clojure.main$repl$read_eval_print__6625.invoke(main.clj:239)
        at clojure.main$repl$fn__6634.invoke(main.clj:257)
        at clojure.main$repl.doInvoke(main.clj:257)
        at clojure.lang.RestFn.invoke(RestFn.java:1523)
        at clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__5548.invoke(interruptible_eval.clj:67)
        at clojure.lang.AFn.applyToHelper(AFn.java:152)
        at clojure.lang.AFn.applyTo(AFn.java:144)
        at clojure.core$apply.invoke(core.clj:624)
        at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1862)
        at clojure.lang.RestFn.invoke(RestFn.java:425)
        at clojure.tools.nrepl.middleware.interruptible_eval$evaluate.invoke(interruptible_eval.clj:51)
        at clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__5590$fn__5593.invoke(interruptible_eval.clj:183)
        at clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__5583.invoke(interruptible_eval.clj:152)
        at clojure.lang.AFn.run(AFn.java:22)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)

I want to creat an aerospike todo app to showcase the client API.
here is the github repo https://github.com/andreiursan/todo-aerospike

Parameter Error when making Aerospike Query with multiple equal filters

I am using version 3.1.2 of the client and am trying to make a query which contains the following code

Statement stmt = new Statement();
stmt.setNamespace("ns");
stmt.setSetName("set");
stmt.setFilters( Filter.equal("foo", "someFoo"), Filter.equal("bar", "someBar") );

RecordSet rs = asClient.query(null, stmt);
while (rs.next()) {
  // etc..
}

So the corresponding aql would be something like

SELECT * FROM ns.set WHERE foo = 'someFoo' AND bar = 'someBar'

Both foo and bar have a secondary index and the corresponding aql statement works as expected. There's also nothing in the logs regarding any indication of any error. When I only use one filter, the query works fine.

However, when I execute that statement and try and retrieve the records I get an AerospikeException saying Error Code 4: Parameter Error.

I could not find anything in the Java Client Documentation or in the JavaDocs about this issue. The only thing I could find was a response to a question from almost a year ago saying that multiple equal filters were not supported. I also couldn't find a changelog between clients so I'm not sure if this is still the case. If it's not the case, is there any way I can get more visibility into what it is I'm doing wrong? If it is still the case, could you maybe please make that fact more apparent in the documentation?

findFrom(Value begin, int count) causes SIGSEGV when count ~ Integer.MAX_VALUE

Bit of an edge condition and looks like something that should probably be caught closer to aerospike-server but putting it here as we are using the Java client.

When using an LLIST on Aerospike build 3.5.15, issuing the method above with very large values for count causes a SIGSEGV on the server.

(signal.c::160) SIGSEGV received, aborting Aerospike Community Edition build 3.5.15
(signal.c::162) stacktrace: found 17 frames
(signal.c::162) stacktrace: frame 0: /usr/bin/asd(as_sig_handle_segv+0x54) [0x478115]
(signal.c::162) stacktrace: frame 1: /lib/x86_64-linux-gnu/libc.so.6(+0x321e0) [0x7f2088a5c1e0]
(signal.c::162) stacktrace: frame 2: /usr/bin/asd(as_arraylist_insert+0x82) [0x531e6b]
(signal.c::162) stacktrace: frame 3: /usr/bin/asd() [0x52b816]
(signal.c::162) stacktrace: frame 4: /usr/bin/asd() [0x54f798]
(signal.c::162) stacktrace: frame 5: /usr/bin/asd(lua_pcall+0x30) [0x53f440]
(signal.c::162) stacktrace: frame 6: /usr/bin/asd() [0x528491]
(signal.c::162) stacktrace: frame 7: /usr/bin/asd() [0x52940c]
(signal.c::162) stacktrace: frame 8: /usr/bin/asd(udf_apply_record+0x106) [0x4d1dfb]
(signal.c::162) stacktrace: frame 9: /usr/bin/asd(udf_rw_local+0x1a4) [0x4d2101]
(signal.c::162) stacktrace: frame 10: /usr/bin/asd() [0x4bc7bf]
(signal.c::162) stacktrace: frame 11: /usr/bin/asd(as_rw_start+0x28b) [0x4bf503]
(signal.c::162) stacktrace: frame 12: /usr/bin/asd(process_transaction+0xcfd) [0x4c8db0]
(signal.c::162) stacktrace: frame 13: /usr/bin/asd(thr_tsvc_process_or_enqueue+0x3e) [0x4c91f1]
(signal.c::162) stacktrace: frame 14: /usr/bin/asd(thr_demarshal+0x402) [0x48d47d]
(signal.c::162) stacktrace: frame 15: /lib/x86_64-linux-gnu/libpthread.so.0(+0x6b50) [0x7f2089876b50]
(signal.c::162) stacktrace: frame 16: /lib/x86_64-linux-gnu/libc.so.6(clone+0x6d) [0x7f2088b0595d]

This is with a 1GB memory based storage-engine namespace.

AerospikeClient does not play well in unit testing

My company is using the Java Aerospike client to connect from our jvm-based apps to various clusters. In an attempt to get good unit test coverage around our applications code, we tried to use Mockito to mock our code interaction with the AerospikeClient class. However since ALL methods of AerospikeClient are final, this is not possible without the use of PowerMockito or some other "more brute force" framework - which usually points out code-smell (IMHO).

So my issue is more of a question as to WHY all of these methods are final?

Thanks in advance...

Returned type of the same operation expands from Integer to Long type

Hello,
I'm trying to use increment and get operation like the following:

Record record = client.operate(
        null,
        new Key("foo", "bar", "keyValue"),
        Operation.add(new Bin("test", 1L)),
        Operation.get("test")
    );

Returned Record contains entry with Integer value type. Everything goes well until Integer overflows.
So after integer overflows like the following:

record = client.operate(
        null,
        new Key("foo", "bar", "keyValue"),
        Operation.add(new Bin("test", Integer.MAX_VALUE)),
        Operation.get("test")
    );

Returned Record will contain entry with Long value type.

In my opinion it's a little bit confusing and makes me write redundant code in a "switch case" manner.
I think it will be much more better to support the single returned type for such kind of operations.

Document how to do batch writes

I looked at the Batch example:

https://github.com/aerospike/aerospike-client-java/blob/master/examples/src/com/aerospike/examples/Batch.java

and it seems to do individual writes.

It is not clear from the docs or the examples how to do large batch saves (e.g. update 5000 different records in a single call, instead of 5000 separate saves).

It is possible to update different sets in the same batch?

E.g. save 5000 records in one set, plus an audit trail record for each of them in a separate set, as part of the same operation?

LargeMap.get throws an exception when a key does not exist

The LargeMap.get function should return an empty Map.
It would also be nice if an "exists(key)" function was created otherwise there should be a function that can be used to determine if a key exists in the LargeMap without throwing an exception.

The following is the exception:

[error] AerospikeException: Error Code 1401: /opt/aerospike/sys/udf/lua/ldt/lib_lmap.lua:2976 LDT-Item Not Found (ReadCommand.java:137)
[error] com.aerospike.client.command.ReadCommand.handleUdfError(ReadCommand.java:137)
[error] com.aerospike.client.command.ReadCommand.parseResult(ReadCommand.java:106)
[error] com.aerospike.client.command.SyncCommand.execute(SyncCommand.java:56)
[error] com.aerospike.client.AerospikeClient.execute(AerospikeClient.java:848)
[error] com.aerospike.client.large.LargeMap.get(LargeMap.java:82)

Support reading/writing Direct Buffer value with zero copy

for now there is only com.aerospike.client.Value.BytesValue that store a byte[]. byte[] resides in JVM heap. for cases data create inside the JVM, it doesn't matter. but for many cases such as feeding data from the network, the bytes do not need to go into the JVM heap to be represented as byte[]. The Java app pass the DirectBuffer reference (pointer) to AeroSpike client.

I notice it is using old socket write to outputstream for now
https://github.com/aerospike/aerospike-client-java/blob/master/client/src/com/aerospike/client/cluster/Connection.java

it needs to be changed to use: SocketChannel.write(ByteBuffer src)

Change AerospikeException to be a RuntimeException

Trying to use the client for the first time. Already I got bitten by the checked exception that is AerospikeException.

nearly everyone agrees today that checked exceptions in Java were a bad idea and all new libraries try to avoid.

All this will do is force us to do the same code over and over again:

    try {
        return new AerospikeClient(config.getHost(),config.getPort());
    } catch (AerospikeException e) {
        throw new RuntimeException(e);
    }

We had to deal with the same issues when using Astyanax Cassandra client and it was really annoying.

Please consider changing all your exceptions to be regular unchecked runtime exceptions/

MultiCommand.MAX_BUFFER_SIZE limit

Last week I faced the following exception:
java.lang.IllegalArgumentException: Invalid readBytes length: 33554432.

I used aerospike-helper to fetch some data.
The source of the exception is the following code:

public abstract class MultiCommand extends SyncCommand {
	private static final int MAX_BUFFER_SIZE = 1024 * 1024 * 10;  // 10 MB

	...

	protected final void readBytes(int length) throws IOException {
		if (length > dataBuffer.length) {
			// Corrupted data streams can result in a huge length.
			// Do a sanity check here.
			if (length > MAX_BUFFER_SIZE) {
				throw new IllegalArgumentException("Invalid readBytes length: " + length);
			}
			dataBuffer = new byte[length];
		}

		int pos = 0;

		while (pos < length) {
			int count = bis.read(dataBuffer, pos, length - pos);

			if (count < 0) {
		    	throw new EOFException();
			}
			pos += count;
		}
		dataOffset += length;
	}

	...

}

According to the comment, data might be corrupted. But then I removed this limit and my data was successfully deserialized. Nothing was corrupted at all.

So I am wondering, is there any reason for this restriction? Or maybe it is some sort of legacy code?

As far as I know C client does not contain this limit. Could it be just removed for java client?

Error Registering LUA file

I simply want to add a value onto the end of a list. It does not appear that I can do this via the regular api so I am trying to write a lua function that will do it for me.

Every time I try to register my lua file I get this error --

Exception in thread "main" com.aerospike.client.AerospikeException: Registration failed: invalid_content_len
File: null
Line: null
Message: null
at com.aerospike.client.AerospikeClient.registerContent(AerospikeClient.java:1014)
at com.aerospike.client.AerospikeClient.register(AerospikeClient.java:951)
at com.alianza.aerospiketest.Main.main(Main.java:36)

Here is my example code

import com.aerospike.client.AerospikeClient;
import com.aerospike.client.policy.ClientPolicy;

public class Main {
    private static final String HOST = "host";
    private static final String NAMESPACE = "namespace";

    private static AerospikeClient client;
    private static ClientPolicy policy;

    public static void main(String[] args) {
        client = new AerospikeClient(HOST, 3000);
        policy = new ClientPolicy();

        client.register(policy.readPolicyDefault, "/tmp/list_functions.lua", "list_functions.lua", com.aerospike.client.Language.LUA);
    }
}

lua file -- list_functions.lua

function add_to_list(record, binname, value)
  if record.MAIN == null then
    record.MAIN = list()
  end

  list.append(record.MAIN, value)
  aerospike:update(record)
end

Cannot mock query results

I am trying to write unit tests for some code of mine which is calling AerospikeClient.queryAggregate. I have mocked the AerospikeClient via the IAerospikeClient interface using Mockito. So far, so good.

Where I run into trouble is that I cannot mock the result. Mockito cannot mock ResultSet because that class is final. Its dependency, QueryAggregateExecutor is also final, which would lead me to mock Cluster. That is possible, but leads down a very complicated rabbit hole.

RecordSet might be more practical to mock since it depends on a QueryExecutor, which is the abstract parent class. However, many of QueryExecutor's method are final, so it may still be difficult.

I think the most expedient solution would be to make RecordSet and ResultSet non-final. I understand making classes final is good practice, but I believe making the code mock-able so it can be unit tested is considerably more valuable. I am certainly open to other suggestions.

By the way, the ExecutionTask returned from AerospikeClient.execute has a similar problem, so you may wish to apply the same solution. I was able to work around that case like so:

ExecuteTask task = client.execute(...); // When client is a mock, will return null
if (task != null) task.waitTillComplete();

Expose low level API

I want to avoid data convertions that happen when client converts policy, namespaces, set names, keys to byte array. I.e. in Command and in Key
Instead I want to see something like

public byte[] get(byte[] policy, byte[] key) throws AerospikeException;
// or
public byte[] get(byte[] policy, byte[] namespace, byte[] set, byte[] keyHash) throws AerospikeException;

Whant do you think?

Bin values returned as String irrespective of the store type

I am performing this for a record which has binvalues of types double and list.

Key key = new Key(namespace,set,recordKey);
Record record = aerospikeClient.get(null, key);

The value for record.bins.get("binName").getClass() is always class java.lang.String irrespective of the bin value. Is this the expected behavior?

3.1.0 AerospikeClient.register in war does not work

I tried upgrading to the latest aerospike client version and had an error trying to use the new register function from within a war.

AerospikeClient.register(readPolicy, contextLoader, resourcePath, name, Language.LUA)

Caused by: java.io.FileNotFoundException: /content/mywar.war/WEB-INF/lib/myjar.jar/udf/list_functions.lua (No such file or directory)
at java.io.FileInputStream.open(Native Method) [rt.jar:1.7.0_71]

Make IAerospikeClient extend Closeable

Make IAerospikeClient interface extend Closeable so it can be used in try-with-resources block.

try (IAerospikeClient client = new AerospikeClient(host, port)) {
    ...
}

getDouble(String) throws ClassCastException if record in table is int

Sometimes there is a need to have Double values mixed with Integer values in Aerospike. E.g. some job inserts double values, but when it comes to 0 or other integer it simply inserts 0 instead of 0.0 or 5 instead of 5.0. But in Aerospike client it's not convenient to try-cast value to any type. Java is OK to convert int to double, so there should be no problem to do that in Aerospike driver.

Steps to reproduce:

  1. Insert some integer value to any bin (e.g. named "value") in Aerospike. E.g. 0 or 5.
  2. Try to get this value via record.getDouble("value").

Expected:
3. There's a value converted to double, e.g. 0.0 or 5.0

Actual:
3.

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
      at com.aerospike.client.Record.getDouble(Record.java:77)
      ....

Short test to reproduce:

    @Test
    public void testGetDoubleWhenIntInserted() {
        Map<String, Object> vals = new HashMap<>();
        vals.put("value", 5);
        Record record = new Record(vals, 1, 1);
        record.getDouble("value");
    }

Aerospike client version:
3.3.0

isConnected() always return true even if there is no available nodes

Hi,

During my local investigation I found that isConnected() always return true, if there is no nodes available.

My setup is done in a way that I have just one Aerospike instance.
After startup of my application I manually shutdown Aerospike instance and I expect that this method will return false (since there is no instance to connect to).
Instead it always returns true.

As I can see from sources this method could return false only in two cases:

  • if client has been closed (tendValid is false)
  • if there is no nodes

Problem is that Tend thread never deletes last node even if it is unavailable.
from com.aerospike.client.cluster.Cluster:

            switch (nodes.length) {
            case 1:
                // Single node clusters rely on whether it responded to info requests.
                if (node.failures >= 5) {
                    // 5 consecutive info requests failed. Try seeds.
                    if (seedNodes(false)) { // <--- Is negation missed here ? it always return false in my case
                        removeList.add(node);
                    }
                }
                break;

seedNodes(false) return false in my case and It prevents thread from removing this last node.
And this is the root of this problem.

Is it correct behavior or I understood semantics of this method incorrectly ?

Broken fault tolerance in the AsyncClient

We are using at out company the asynchronous application framework Vert.x to implement a high-performance web application. We decided to give the AsyncClient a try instead of implementing ourselves the asynchronous calls to Aerospike.

Unfortunately, this didn't work out for us because of a severe bug in the implementation of the AsyncClient, namely its inability to handle failures in one or more of the Aerospike nodes in our cluster. The problem can be reproduced as follows.

There are two Aerospike nodes in our cluster: srvaer01 and srvaer02. The replication factor is 2. We instantiate the AsyncClient like this:

final AsyncClientPolicy clientPolicy = new AsyncClientPolicy();
clientPolicy.failIfNotConnected = true;

final List<Host> hosts = new LinkedList<>();
hosts.add(new Host("srvaer01", 3000));
hosts.add(new Host("srvaer02", 3000));

AsyncClient client = new AsyncClient(clientPolicy, hosts);

We then use the asynchronous methods of the AsyncClient to retrieve data from Aerospike, e.g.:

final Key key = new Key(namespace, storeName, keyName);

client.get(new Policy(), handler, key);

The behavior we observed is the following:

  • If both nodes are up and running, the AsyncClient works fine.
  • If only one node is running and the other one is down at the moment of instantiating the AsyncClient, then the AsyncClient works fine.
  • If both nodes are running at the moment of instantiating the AsyncClient, and after that we stop one of the nodes, the AsyncClient blocks completely (stops all threads) within 1-2 minutes and does not process any more requests.

A thread dump of the blocked AsyncClient instance shows the following:

Thread 11346: (state = BLOCKED)
 - sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
 - java.util.concurrent.locks.LockSupport.park(java.lang.Object) @bci=14, line=175 (Compiled frame)
 - java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await() @bci=42, line=2039 (Compiled frame)
 - java.util.concurrent.ArrayBlockingQueue.take() @bci=20, line=403 (Interpreted frame)
 - com.aerospike.client.async.AsyncCluster$BlockBufferQueue.getByteBuffer() @bci=4, line=114 (Interpreted frame)
 - com.aerospike.client.async.AsyncCluster.getByteBuffer() @bci=4, line=68 (Interpreted frame)
 - com.aerospike.client.async.AsyncCommand.execute() @bci=38, line=58 (Interpreted frame)
 - com.aerospike.client.async.AsyncClient.get(com.aerospike.client.policy.Policy, com.aerospike.client.listener.RecordListener, com.aerospike.client.Key) @bci=28, line=447 (Compiled frame)
...

We were able to reproduce this undesired behavior multiple times. As a workaround to this problem, we changed the AsyncClient with its synchronous counterpart, which works correctly.

Cannot call lua method load

This lua method is not available in this client, while other clients, like the node.js one, do. We use this method to dynamically generate aggregation functions.

I was able to use this method by previously registering it manually so that Aerospike gets an instance with the method loaded. (This is a hacky way, probably there is a better one):

final LuaInstance instance = LuaCache.getInstance();
instance.registerPackage("load", LuaTable.tableOf(new LuaValue[] {
    LuaValue.valueOf("loadLib"), JsePlatform.standardGlobals().get("load") }));
LuaCache.putInstance(instance);

and then in lua

local load = load or loadLib.load
local foo = load("return 'hi'");
info(foo()); -- Prints 'hi'

But this doesn't solve the problem if Aerospike decides it needs more instances than what the pool currently has.

unboxed double value comes back as Long

package com.aerospike.examples;

import com.aerospike.client.*;

public class DoubleBinTest {

  public static void main(String[] args) throws Exception {
    String host = "localhost";
    int    port = 3000;
    AerospikeClient client = new AerospikeClient(null, host, port);

    String namespace = "test";
    String set       = "putget";
    Key    key       = new Key(namespace, set, "foo");

    Bin testBin1  = new Bin("Double", new Double(0.5)); // works
    Bin testBin2  = new Bin("double", 0.5);  // fails
    client.put(null, key, testBin1, testBin2);

    Record record1 = client.get(null, key);

    Object result1 = record1.getValue("Double");
    System.out.println("Result Double bin value is " + result1);

    Object result2 = record1.getValue("double");
    if (result2 != null) {
      System.out.println("Result double bin type should be java.lang.Double");
      System.out.println("Result double bin type  is " + result2.getClass()); // class java.lang.Long
      System.out.println("Result double bin value is " + result2);            // 4602678819172646912
    }

    client.delete(null, key);
  }
}

gives this result:

Result double bin value is 0.5
Result Double bin type should be java.lang.Double
Result Double bin type  is class java.lang.Long
Result Double bin value is 4602678819172646912

Get all indexes

Can we have some method in aerospike java client which can provide us all indexes present in all namespaces or in a particular namespace.

Unable to reconnect

Hi,

Suppose one of my aerospike node is down. In that case the java client should be able to reconnect when the node is up.Presently the client keeps the old connection object cached .Please let me know if we can approach to this problem somehow.

Potential connection leak in NodeValidator

Hello,

In NodeValidator#validateAlias method, the Connection constructor is called and it can throw an AerospikeException.Connection exception. The connection is closed in the catch block, but only for exceptions thrown inside the try block. Unfortunately, the connection constructor isn't called inside the try block, so if it throws an exception we will have a connection leak.

I made a pull request that fixes this issue, you can take a look.
#56

We encountered this issue while using aerospike at Thinknear, because we were seeding a host that had a number of aliases, one of them was unreachable and caused that connection leak in our application.

Thanks

Filter.range Javadoc doesn't specify inclusive or exclusive

The javadoc comments on com.aerospike.client.query.Filter.range (two methods) don't specify whether the begin and end parameters are inclusive or exclusive. Assuming the wrong meaning is an easy way to introduce subtle bugs into an application.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.