From 2cda4a412c993fdd791bffa8f04545f3e8ab7d50 Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Mon, 13 May 2024 17:37:26 -0400 Subject: [PATCH 1/9] CLIENT-2933 If binNames array is specified and empty, read all bins. Add tests for that scenario. --- .../com/aerospike/client/AerospikeClient.java | 15 ++++- .../aerospike/client/command/BatchAttr.java | 2 +- .../com/aerospike/client/command/Command.java | 58 +++++++++---------- .../client/proxy/AerospikeClientProxy.java | 8 ++- .../aerospike/test/sync/basic/TestBatch.java | 28 ++++++++- .../aerospike/test/sync/basic/TestPutGet.java | 7 ++- .../aerospike/test/sync/basic/TestScan.java | 6 +- .../test/sync/query/TestQueryString.java | 29 ++++++++++ 8 files changed, 113 insertions(+), 40 deletions(-) diff --git a/client/src/com/aerospike/client/AerospikeClient.java b/client/src/com/aerospike/client/AerospikeClient.java index f5ffee2c7..9f6e7a992 100644 --- a/client/src/com/aerospike/client/AerospikeClient.java +++ b/client/src/com/aerospike/client/AerospikeClient.java @@ -1786,6 +1786,9 @@ public final Record[] get(BatchPolicy policy, Key[] keys, String... binNames) policy = batchPolicyDefault; } + int readAttr = (binNames == null || binNames.length == 0)? + Command.INFO1_READ | Command.INFO1_GET_ALL : Command.INFO1_READ; + Record[] records = new Record[keys.length]; try { @@ -1802,7 +1805,7 @@ public final Record[] get(BatchPolicy policy, Key[] keys, String... binNames) } else { commands[count++] = new Batch.GetArrayCommand( - cluster, bn, policy, keys, binNames, null, records, Command.INFO1_READ, false, status); + cluster, bn, policy, keys, binNames, null, records, readAttr, false, status); } } BatchExecutor.execute(cluster, policy, commands, status); @@ -1844,6 +1847,9 @@ public final void get(EventLoop eventLoop, RecordArrayListener listener, BatchPo policy = batchPolicyDefault; } + int readAttr = (binNames == null || binNames.length == 0)? + Command.INFO1_READ | Command.INFO1_GET_ALL : Command.INFO1_READ; + Record[] records = new Record[keys.length]; AsyncBatchExecutor.GetArray executor = new AsyncBatchExecutor.GetArray( eventLoop, cluster, listener, keys, records); @@ -1859,7 +1865,7 @@ public final void get(EventLoop eventLoop, RecordArrayListener listener, BatchPo } else { commands[count++] = new AsyncBatch.GetArrayCommand( - executor, bn, policy, keys, binNames, null, records, Command.INFO1_READ, false); + executor, bn, policy, keys, binNames, null, records, readAttr, false); } } executor.execute(commands); @@ -1896,6 +1902,9 @@ public final void get(EventLoop eventLoop, RecordSequenceListener listener, Batc policy = batchPolicyDefault; } + int readAttr = (binNames == null || binNames.length == 0)? + Command.INFO1_READ | Command.INFO1_GET_ALL : Command.INFO1_READ; + AsyncBatchExecutor.GetSequence executor = new AsyncBatchExecutor.GetSequence(eventLoop, cluster, listener); List bns = BatchNodeList.generate(cluster, policy, keys, null, false, executor); AsyncCommand[] commands = new AsyncCommand[bns.size()]; @@ -1909,7 +1918,7 @@ public final void get(EventLoop eventLoop, RecordSequenceListener listener, Batc } else { commands[count++] = new AsyncBatch.GetSequenceCommand( - executor, bn, policy, keys, binNames, null, listener, Command.INFO1_READ, false); + executor, bn, policy, keys, binNames, null, listener, readAttr, false); } } executor.execute(commands); diff --git a/client/src/com/aerospike/client/command/BatchAttr.java b/client/src/com/aerospike/client/command/BatchAttr.java index 487a742d0..7f063537e 100644 --- a/client/src/com/aerospike/client/command/BatchAttr.java +++ b/client/src/com/aerospike/client/command/BatchAttr.java @@ -48,7 +48,7 @@ public BatchAttr(Policy policy, int rattr) { public BatchAttr(Policy policy, int rattr, Operation[] ops) { setRead(policy); - this.readAttr |= rattr; + this.readAttr = rattr; if (ops != null) { adjustRead(ops); diff --git a/client/src/com/aerospike/client/command/Command.java b/client/src/com/aerospike/client/command/Command.java index efda4be76..ceb2e8a83 100644 --- a/client/src/com/aerospike/client/command/Command.java +++ b/client/src/com/aerospike/client/command/Command.java @@ -241,7 +241,17 @@ public final void setExists(Policy policy, Key key) { end(); } - private final void setRead(Policy policy, Key key) { + public final void setRead(Policy policy, Key key, String[] binNames) { + int readAttr = Command.INFO1_READ; + int opCount = 0; + + if (binNames != null && binNames.length > 0) { + opCount = binNames.length; + } + else { + readAttr |= Command.INFO1_GET_ALL; + } + begin(); int fieldCount = estimateKeySize(policy, key); @@ -249,45 +259,27 @@ private final void setRead(Policy policy, Key key) { dataOffset += policy.filterExp.size(); fieldCount++; } + + if (opCount != 0) { + for (String binName : binNames) { + estimateOperationSize(binName); + } + } + sizeBuffer(); - writeHeaderRead(policy, serverTimeout, Command.INFO1_READ | Command.INFO1_GET_ALL, 0, 0, fieldCount, 0); + writeHeaderRead(policy, serverTimeout, readAttr, 0, 0, fieldCount, opCount); writeKey(policy, key); if (policy.filterExp != null) { policy.filterExp.write(this); } - end(); - } - - public final void setRead(Policy policy, Key key, String[] binNames) { - if (binNames != null) { - begin(); - int fieldCount = estimateKeySize(policy, key); - - if (policy.filterExp != null) { - dataOffset += policy.filterExp.size(); - fieldCount++; - } - - for (String binName : binNames) { - estimateOperationSize(binName); - } - sizeBuffer(); - writeHeaderRead(policy, serverTimeout, Command.INFO1_READ, 0, 0, fieldCount, binNames.length); - writeKey(policy, key); - - if (policy.filterExp != null) { - policy.filterExp.write(this); - } + if (opCount != 0) { for (String binName : binNames) { writeOperation(binName, Operation.Type.READ); } - end(); - } - else { - setRead(policy, key); } + end(); } public final void setRead(Policy policy, BatchRead br) { @@ -851,7 +843,13 @@ public final void setBatchOperate( } if (br.binNames != null) { - writeBatchBinNames(key, br.binNames, attr, attr.filterExp); + if (br.binNames.length > 0) { + writeBatchBinNames(key, br.binNames, attr, attr.filterExp); + } + else { + attr.adjustRead(true); + writeBatchRead(key, attr, attr.filterExp, 0); + } } else if (br.ops != null) { attr.adjustRead(br.ops); diff --git a/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java b/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java index 46a051d91..eca2fe93a 100644 --- a/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java +++ b/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java @@ -1289,7 +1289,9 @@ public void get(EventLoop eventLoop, RecordArrayListener listener, BatchPolicy p policy = batchPolicyDefault; } - CommandProxy command = new BatchProxy.GetArrayCommand(executor, policy, listener, keys, binNames, null, Command.INFO1_READ, false); + int readAttr = (binNames == null || binNames.length == 0)? Command.INFO1_READ | Command.INFO1_GET_ALL : Command.INFO1_READ; + + CommandProxy command = new BatchProxy.GetArrayCommand(executor, policy, listener, keys, binNames, null, readAttr, false); command.execute(); } @@ -1317,7 +1319,9 @@ public void get(EventLoop eventLoop, RecordSequenceListener listener, BatchPolic policy = batchPolicyDefault; } - CommandProxy command = new BatchProxy.GetSequenceCommand(executor, policy, listener, keys, binNames, null, Command.INFO1_READ, false); + int readAttr = (binNames == null || binNames.length == 0)? Command.INFO1_READ | Command.INFO1_GET_ALL : Command.INFO1_READ; + + CommandProxy command = new BatchProxy.GetSequenceCommand(executor, policy, listener, keys, binNames, null, readAttr, false); command.execute(); } diff --git a/test/src/com/aerospike/test/sync/basic/TestBatch.java b/test/src/com/aerospike/test/sync/basic/TestBatch.java index 90afd5765..82b7083ed 100644 --- a/test/src/com/aerospike/test/sync/basic/TestBatch.java +++ b/test/src/com/aerospike/test/sync/basic/TestBatch.java @@ -144,6 +144,30 @@ public void batchReads () { } } + @Test + public void batchReadsEmptyBinNames() { + Key[] keys = new Key[Size]; + for (int i = 0; i < Size; i++) { + keys[i] = new Key(args.namespace, args.set, KeyPrefix + (i + 1)); + } + + String[] binNames = new String[] {}; + Record[] records = client.get(null, keys, binNames); + assertEquals(Size, records.length); + + for (int i = 0; i < records.length; i++) { + Key key = keys[i]; + Record record = records[i]; + + if (i != 5) { + assertBinEqual(key, record, BinName, ValuePrefix + (i + 1)); + } + else { + assertBinEqual(key, record, BinName, i + 1); + } + } + } + @Test public void batchReadHeaders () { Key[] keys = new Key[Size]; @@ -168,7 +192,7 @@ public void batchReadHeaders () { } @Test - public void batchReadComplex () { + public void batchReadComplex() { // Batch allows multiple namespaces in one call, but example test environment may only have one namespace. // bin * 8 @@ -179,7 +203,7 @@ public void batchReadComplex () { List records = new ArrayList(); records.add(new BatchRead(new Key(args.namespace, args.set, KeyPrefix + 1), bins)); records.add(new BatchRead(new Key(args.namespace, args.set, KeyPrefix + 2), true)); - records.add(new BatchRead(new Key(args.namespace, args.set, KeyPrefix + 3), true)); + records.add(new BatchRead(new Key(args.namespace, args.set, KeyPrefix + 3), new String[] {})); records.add(new BatchRead(new Key(args.namespace, args.set, KeyPrefix + 4), false)); records.add(new BatchRead(new Key(args.namespace, args.set, KeyPrefix + 5), true)); records.add(new BatchRead(new Key(args.namespace, args.set, KeyPrefix + 6), ops)); diff --git a/test/src/com/aerospike/test/sync/basic/TestPutGet.java b/test/src/com/aerospike/test/sync/basic/TestPutGet.java index e2f99cd42..58830abee 100644 --- a/test/src/com/aerospike/test/sync/basic/TestPutGet.java +++ b/test/src/com/aerospike/test/sync/basic/TestPutGet.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 Aerospike, Inc. + * Copyright 2012-2024 Aerospike, Inc. * * Portions may be licensed to Aerospike, Inc. under one or more contributor * license agreements WHICH ARE COMPATIBLE WITH THE APACHE LICENSE, VERSION 2.0. @@ -41,6 +41,11 @@ public void putGet() { Record record = client.get(null, key); assertBinEqual(key, record, bin1); assertBinEqual(key, record, bin2); + + // Test empty binNames array. + record = client.get(null, key, new String[] {}); + assertBinEqual(key, record, bin1); + assertBinEqual(key, record, bin2); } @Test diff --git a/test/src/com/aerospike/test/sync/basic/TestScan.java b/test/src/com/aerospike/test/sync/basic/TestScan.java index d0b3e1762..c6a29289f 100644 --- a/test/src/com/aerospike/test/sync/basic/TestScan.java +++ b/test/src/com/aerospike/test/sync/basic/TestScan.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 Aerospike, Inc. + * Copyright 2012-2024 Aerospike, Inc. * * Portions may be licensed to Aerospike, Inc. under one or more contributor * license agreements WHICH ARE COMPATIBLE WITH THE APACHE LICENSE, VERSION 2.0. @@ -35,6 +35,10 @@ public class TestScan extends TestSync implements ScanCallback { public void scanParallel() { ScanPolicy policy = new ScanPolicy(); client.scanAll(policy, args.namespace, args.set, this); + + // Test empty binNames. + String[] binNames = new String[] {}; + client.scanAll(policy, args.namespace, args.set, this, binNames); } @Test diff --git a/test/src/com/aerospike/test/sync/query/TestQueryString.java b/test/src/com/aerospike/test/sync/query/TestQueryString.java index 92a2ea96a..8ef779f0c 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryString.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryString.java @@ -95,4 +95,33 @@ public void queryString() { rs.close(); } } + + @Test + public void queryStringEmptyBinName() { + String filter = valuePrefix + 3; + + Statement stmt = new Statement(); + stmt.setNamespace(args.namespace); + stmt.setSetName(args.set); + stmt.setBinNames(new String[] {}); + stmt.setFilter(Filter.equal(binName, filter)); + + RecordSet rs = client.query(null, stmt); + + try { + int count = 0; + + while (rs.next()) { + Record record = rs.getRecord(); + String result = record.getString(binName); + assertEquals(filter, result); + count++; + } + + assertNotEquals(0, count); + } + finally { + rs.close(); + } + } } From e3bb34870d6af09ea13e31b5c8ac4e1bceca1712 Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Tue, 21 May 2024 14:04:13 -0400 Subject: [PATCH 2/9] CLIENT-2962 Remove unnecessary imports. --- client/src/com/aerospike/client/async/AsyncBatch.java | 1 - client/src/com/aerospike/client/cluster/Connection.java | 2 ++ client/src/com/aerospike/client/command/BatchExecutor.java | 3 --- .../src/com/aerospike/client/query/QueryAggregateExecutor.java | 2 -- client/src/com/aerospike/client/query/QueryExecutor.java | 3 --- 5 files changed, 2 insertions(+), 9 deletions(-) diff --git a/client/src/com/aerospike/client/async/AsyncBatch.java b/client/src/com/aerospike/client/async/AsyncBatch.java index 5893e06ae..22d4fecf6 100644 --- a/client/src/com/aerospike/client/async/AsyncBatch.java +++ b/client/src/com/aerospike/client/async/AsyncBatch.java @@ -16,7 +16,6 @@ */ package com.aerospike.client.async; -import java.util.ArrayList; import java.util.List; import com.aerospike.client.AerospikeClient; diff --git a/client/src/com/aerospike/client/cluster/Connection.java b/client/src/com/aerospike/client/cluster/Connection.java index 73a36bdad..276214ffa 100644 --- a/client/src/com/aerospike/client/cluster/Connection.java +++ b/client/src/com/aerospike/client/cluster/Connection.java @@ -327,6 +327,8 @@ public void close() { } public static final class ReadTimeout extends RuntimeException { + private static final long serialVersionUID = 1L; + public final byte[] buffer; public final int offset; public final int length; diff --git a/client/src/com/aerospike/client/command/BatchExecutor.java b/client/src/com/aerospike/client/command/BatchExecutor.java index 704e32ac0..dbd5f9f9d 100644 --- a/client/src/com/aerospike/client/command/BatchExecutor.java +++ b/client/src/com/aerospike/client/command/BatchExecutor.java @@ -18,9 +18,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; import com.aerospike.client.AerospikeException; import com.aerospike.client.cluster.Cluster; diff --git a/client/src/com/aerospike/client/query/QueryAggregateExecutor.java b/client/src/com/aerospike/client/query/QueryAggregateExecutor.java index 614d6aa26..b4860c401 100644 --- a/client/src/com/aerospike/client/query/QueryAggregateExecutor.java +++ b/client/src/com/aerospike/client/query/QueryAggregateExecutor.java @@ -18,8 +18,6 @@ import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import org.luaj.vm2.LuaInteger; import org.luaj.vm2.LuaValue; diff --git a/client/src/com/aerospike/client/query/QueryExecutor.java b/client/src/com/aerospike/client/query/QueryExecutor.java index fd2a21251..a50693429 100644 --- a/client/src/com/aerospike/client/query/QueryExecutor.java +++ b/client/src/com/aerospike/client/query/QueryExecutor.java @@ -16,9 +16,6 @@ */ package com.aerospike.client.query; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; From bb14def83b2af274d741e0843b4423b118235bec Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Tue, 21 May 2024 15:08:43 -0400 Subject: [PATCH 3/9] CLIENT-2962 Remove unnecessary imports in test. --- test/src/com/aerospike/test/async/TestAsyncQuery.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryAverage.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryBlob.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryCollection.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryContext.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryExecute.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryFilter.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryFilterExp.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryGeo.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryInteger.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryKey.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryRPS.java | 1 - test/src/com/aerospike/test/sync/query/TestQueryString.java | 1 - test/src/com/aerospike/test/sync/query/TestQuerySum.java | 1 - 14 files changed, 14 deletions(-) diff --git a/test/src/com/aerospike/test/async/TestAsyncQuery.java b/test/src/com/aerospike/test/async/TestAsyncQuery.java index fe4a8199a..daa34e49d 100644 --- a/test/src/com/aerospike/test/async/TestAsyncQuery.java +++ b/test/src/com/aerospike/test/async/TestAsyncQuery.java @@ -29,7 +29,6 @@ import com.aerospike.client.ResultCode; import com.aerospike.client.listener.RecordSequenceListener; import com.aerospike.client.listener.WriteListener; -import com.aerospike.client.policy.Policy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.client.query.Statement; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryAverage.java b/test/src/com/aerospike/test/sync/query/TestQueryAverage.java index 02c47ab89..98060d825 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryAverage.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryAverage.java @@ -30,7 +30,6 @@ import com.aerospike.client.Key; import com.aerospike.client.Language; import com.aerospike.client.ResultCode; -import com.aerospike.client.policy.Policy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.client.query.ResultSet; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryBlob.java b/test/src/com/aerospike/test/sync/query/TestQueryBlob.java index d7f1587bb..5362799b4 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryBlob.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryBlob.java @@ -32,7 +32,6 @@ import com.aerospike.client.Key; import com.aerospike.client.Record; import com.aerospike.client.command.Buffer; -import com.aerospike.client.policy.Policy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexCollectionType; import com.aerospike.client.query.IndexType; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryCollection.java b/test/src/com/aerospike/test/sync/query/TestQueryCollection.java index 5736a8391..78bc92a8e 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryCollection.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryCollection.java @@ -32,7 +32,6 @@ import com.aerospike.client.Language; import com.aerospike.client.Record; import com.aerospike.client.ResultCode; -import com.aerospike.client.policy.Policy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexCollectionType; import com.aerospike.client.query.IndexType; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryContext.java b/test/src/com/aerospike/test/sync/query/TestQueryContext.java index cbc1e448c..b921c5439 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryContext.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryContext.java @@ -32,7 +32,6 @@ import com.aerospike.client.Record; import com.aerospike.client.ResultCode; import com.aerospike.client.cdt.CTX; -import com.aerospike.client.policy.Policy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexCollectionType; import com.aerospike.client.query.IndexType; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryExecute.java b/test/src/com/aerospike/test/sync/query/TestQueryExecute.java index 470af26a7..84b2d35e1 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryExecute.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryExecute.java @@ -35,7 +35,6 @@ import com.aerospike.client.exp.ExpOperation; import com.aerospike.client.exp.ExpWriteFlags; import com.aerospike.client.exp.Expression; -import com.aerospike.client.policy.Policy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.client.query.RecordSet; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryFilter.java b/test/src/com/aerospike/test/sync/query/TestQueryFilter.java index f49e9cf94..198e0877b 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryFilter.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryFilter.java @@ -31,7 +31,6 @@ import com.aerospike.client.Language; import com.aerospike.client.ResultCode; import com.aerospike.client.Value; -import com.aerospike.client.policy.Policy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.client.query.ResultSet; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryFilterExp.java b/test/src/com/aerospike/test/sync/query/TestQueryFilterExp.java index 94d1653b7..b3f6ff862 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryFilterExp.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryFilterExp.java @@ -37,7 +37,6 @@ import com.aerospike.client.exp.Exp; import com.aerospike.client.exp.ListExp; import com.aerospike.client.exp.MapExp; -import com.aerospike.client.policy.Policy; import com.aerospike.client.policy.QueryPolicy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryGeo.java b/test/src/com/aerospike/test/sync/query/TestQueryGeo.java index 692941066..4bf7f5c0f 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryGeo.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryGeo.java @@ -27,7 +27,6 @@ import com.aerospike.client.Key; import com.aerospike.client.ResultCode; import com.aerospike.client.exp.Exp; -import com.aerospike.client.policy.Policy; import com.aerospike.client.policy.QueryPolicy; import com.aerospike.client.query.IndexType; import com.aerospike.client.query.RecordSet; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryInteger.java b/test/src/com/aerospike/test/sync/query/TestQueryInteger.java index 186ef6f42..57c467b83 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryInteger.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryInteger.java @@ -26,7 +26,6 @@ import com.aerospike.client.Bin; import com.aerospike.client.Key; import com.aerospike.client.ResultCode; -import com.aerospike.client.policy.Policy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.client.query.RecordSet; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryKey.java b/test/src/com/aerospike/test/sync/query/TestQueryKey.java index c986c70ac..d06dc5f72 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryKey.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryKey.java @@ -27,7 +27,6 @@ import com.aerospike.client.Bin; import com.aerospike.client.Key; import com.aerospike.client.ResultCode; -import com.aerospike.client.policy.Policy; import com.aerospike.client.policy.WritePolicy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryRPS.java b/test/src/com/aerospike/test/sync/query/TestQueryRPS.java index 59bca48fe..d2cac77b1 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryRPS.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryRPS.java @@ -30,7 +30,6 @@ import com.aerospike.client.ResultCode; import com.aerospike.client.Value; import com.aerospike.client.cluster.Node; -import com.aerospike.client.policy.Policy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.client.query.RecordSet; diff --git a/test/src/com/aerospike/test/sync/query/TestQueryString.java b/test/src/com/aerospike/test/sync/query/TestQueryString.java index 8ef779f0c..4803a5a8c 100644 --- a/test/src/com/aerospike/test/sync/query/TestQueryString.java +++ b/test/src/com/aerospike/test/sync/query/TestQueryString.java @@ -28,7 +28,6 @@ import com.aerospike.client.Key; import com.aerospike.client.Record; import com.aerospike.client.ResultCode; -import com.aerospike.client.policy.Policy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; import com.aerospike.client.query.RecordSet; diff --git a/test/src/com/aerospike/test/sync/query/TestQuerySum.java b/test/src/com/aerospike/test/sync/query/TestQuerySum.java index ce7042095..0ba4247d4 100644 --- a/test/src/com/aerospike/test/sync/query/TestQuerySum.java +++ b/test/src/com/aerospike/test/sync/query/TestQuerySum.java @@ -30,7 +30,6 @@ import com.aerospike.client.Language; import com.aerospike.client.ResultCode; import com.aerospike.client.Value; -import com.aerospike.client.policy.Policy; import com.aerospike.client.policy.QueryPolicy; import com.aerospike.client.query.Filter; import com.aerospike.client.query.IndexType; From 2d17ca985664e841bde6bea98512564804c722df Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Tue, 28 May 2024 17:48:32 -0400 Subject: [PATCH 4/9] CLIENT-2971 Make metrics classes public in javadoc. --- client/pom.xml | 1 + client/src/com/aerospike/client/metrics/LatencyBuckets.java | 4 ++-- client/src/com/aerospike/client/metrics/LatencyType.java | 5 ++++- client/src/com/aerospike/client/metrics/MetricsPolicy.java | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index f575c3e25..a554a9163 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -129,6 +129,7 @@ com/aerospike/client/listener/* com/aerospike/client/command/ParticleType.java com/aerospike/client/exp/* + com/aerospike/client/metrics/* com/aerospike/client/operation/* com/aerospike/client/policy/* com/aerospike/client/task/* diff --git a/client/src/com/aerospike/client/metrics/LatencyBuckets.java b/client/src/com/aerospike/client/metrics/LatencyBuckets.java index db61b2089..ca1b9df3e 100644 --- a/client/src/com/aerospike/client/metrics/LatencyBuckets.java +++ b/client/src/com/aerospike/client/metrics/LatencyBuckets.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 Aerospike, Inc. + * Copyright 2012-2024 Aerospike, Inc. * * Portions may be licensed to Aerospike, Inc. under one or more contributor * license agreements WHICH ARE COMPATIBLE WITH THE APACHE LICENSE, VERSION 2.0. @@ -33,7 +33,7 @@ public final class LatencyBuckets { * * @param latencyColumns number of latency buckets * @param latencyShift power of 2 multiple between each range bucket in latency histograms starting at bucket 3. - * The first 2 buckets are "<=1ms" and ">1ms". + * The first 2 buckets are "<=1ms" and ">1ms". */ public LatencyBuckets(int latencyColumns, int latencyShift) { this.latencyShift = latencyShift; diff --git a/client/src/com/aerospike/client/metrics/LatencyType.java b/client/src/com/aerospike/client/metrics/LatencyType.java index 01fda6aa2..625a9ef07 100644 --- a/client/src/com/aerospike/client/metrics/LatencyType.java +++ b/client/src/com/aerospike/client/metrics/LatencyType.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 Aerospike, Inc. + * Copyright 2012-2024 Aerospike, Inc. * * Portions may be licensed to Aerospike, Inc. under one or more contributor * license agreements WHICH ARE COMPATIBLE WITH THE APACHE LICENSE, VERSION 2.0. @@ -16,6 +16,9 @@ */ package com.aerospike.client.metrics; +/** + * Latency group type. + */ public enum LatencyType { CONN, WRITE, diff --git a/client/src/com/aerospike/client/metrics/MetricsPolicy.java b/client/src/com/aerospike/client/metrics/MetricsPolicy.java index df6e285a3..b6119027e 100644 --- a/client/src/com/aerospike/client/metrics/MetricsPolicy.java +++ b/client/src/com/aerospike/client/metrics/MetricsPolicy.java @@ -69,7 +69,7 @@ public final class MetricsPolicy { /** * Power of 2 multiple between each range bucket in latency histograms starting at column 3. The bucket units - * are in milliseconds. The first 2 buckets are "<=1ms" and ">1ms". Examples: + * are in milliseconds. The first 2 buckets are "<=1ms" and ">1ms". Examples: *
{@code
 	 * // latencyColumns=7 latencyShift=1
 	 * <=1ms >1ms >2ms >4ms >8ms >16ms >32ms

From 9016d0f95ad0c344312ff0ccb027f5391a82ab06 Mon Sep 17 00:00:00 2001
From: Brian Nichols 
Date: Wed, 29 May 2024 18:35:48 -0400
Subject: [PATCH 5/9] CLIENT-2972 Allow scan to work in a mixed cluster of
 server 5.7 and 6.4 nodes.

---
 client/src/com/aerospike/client/command/Command.java | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/client/src/com/aerospike/client/command/Command.java b/client/src/com/aerospike/client/command/Command.java
index ceb2e8a83..56130f26c 100644
--- a/client/src/com/aerospike/client/command/Command.java
+++ b/client/src/com/aerospike/client/command/Command.java
@@ -1328,9 +1328,8 @@ public final void setScan(
 		}
 
 		// Clusters that support partition queries also support not sending partition done messages.
-		int infoAttr = cluster.hasPartitionQuery? Command.INFO3_PARTITION_DONE : 0;
 		int operationCount = (binNames == null)? 0 : binNames.length;
-		writeHeaderRead(policy, totalTimeout, readAttr, 0, infoAttr, fieldCount, operationCount);
+		writeHeaderRead(policy, totalTimeout, readAttr, 0, Command.INFO3_PARTITION_DONE, fieldCount, operationCount);
 
 		if (namespace != null) {
 			writeField(namespace, FieldType.NAMESPACE);
@@ -1580,7 +1579,7 @@ else if (qp.expectedDuration == QueryDuration.LONG_RELAX_AP) {
 				writeAttr |= Command.INFO2_RELAX_AP_LONG_QUERY;
 			}
 
-			int infoAttr = isNew? Command.INFO3_PARTITION_DONE : 0;
+			int infoAttr = (isNew || filter == null)? Command.INFO3_PARTITION_DONE : 0;
 
 			writeHeaderRead(policy, totalTimeout, readAttr, writeAttr, infoAttr, fieldCount, operationCount);
 		}

From 39bd799248c4746aff9d876e80d41d0109cef3c2 Mon Sep 17 00:00:00 2001
From: Brian Nichols 
Date: Thu, 30 May 2024 15:20:28 -0400
Subject: [PATCH 6/9] CLIENT-2978 Support new server 7.1 info command error
 response strings.

Server 7.1 now returns some error strings with "ERROR" instead of "FAIL".
Both cases are handled to preserve compatibility with older servers.
---
 .../com/aerospike/client/AerospikeClient.java | 18 +---
 client/src/com/aerospike/client/Info.java     | 86 ++++++++++++++-----
 .../com/aerospike/client/task/IndexTask.java  | 14 +--
 .../test/sync/basic/TestServerInfo.java       | 33 ++++++-
 4 files changed, 107 insertions(+), 44 deletions(-)

diff --git a/client/src/com/aerospike/client/AerospikeClient.java b/client/src/com/aerospike/client/AerospikeClient.java
index 9f6e7a992..df7c8dbd2 100644
--- a/client/src/com/aerospike/client/AerospikeClient.java
+++ b/client/src/com/aerospike/client/AerospikeClient.java
@@ -4470,21 +4470,7 @@ public void onFailure(AerospikeException ae) {
 	}
 
 	private static int parseIndexErrorCode(String response) {
-		int code = 0;
-
-		try {
-			String[] list = response.split(":");
-
-			if (list.length >= 2 && list[0].equals("FAIL")) {
-				code = Integer.parseInt(list[1]);
-			}
-		}
-		catch (Throwable e) {
-		}
-
-		if (code == 0) {
-			code = ResultCode.SERVER_ERROR;
-		}
-		return code;
+		Info.Error error = new Info.Error(response);
+		return (error.code == 0)? ResultCode.SERVER_ERROR : error.code;
 	}
 }
diff --git a/client/src/com/aerospike/client/Info.java b/client/src/com/aerospike/client/Info.java
index 402ed015c..c9d4793b1 100644
--- a/client/src/com/aerospike/client/Info.java
+++ b/client/src/com/aerospike/client/Info.java
@@ -319,30 +319,15 @@ public static int parseResultCode(String response) {
 			return ResultCode.OK;
 		}
 
-		// Error format: ERROR|FAIL[:][:]
-		try {
-			String[] list = response.split(":");
-			String s = list[0];
-
-			if (s.regionMatches(true, 0, "FAIL", 0, 4) ||
-				s.regionMatches(true, 0, "ERROR", 0, 5)) {
+		Info.Error error = new Info.Error(response);
 
-				if (list.length > 1) {
-					s = list[1].trim();
-
-					if (! s.isEmpty()) {
-						return Integer.parseInt(s);
-					}
-				}
-				return ResultCode.SERVER_ERROR;
-			}
-			throw new AerospikeException("Unrecognized info response: " + response);
-		}
-		catch (AerospikeException ae) {
-			throw ae;
+		if (error.code >= 0) {
+			// Server errors return error code.
+			return error.code;
 		}
-		catch (Throwable t) {
-			throw new AerospikeException("Unrecognized info response: " + response, t);
+		else {
+			// Client errors result in a exception.
+			throw new AerospikeException(error.code, "Unrecognized info response: " + response);
 		}
 	}
 
@@ -828,4 +813,61 @@ public String getStringBase64() {
 			return Buffer.utf8ToString(bytes, 0, bytes.length);
 		}
 	}
+
+	/**
+	 * Info command error response.
+	 */
+	public static class Error {
+		public final int code;
+		public final String message;
+
+		/**
+		 * Parse info command response into code and message.
+		 * If the response is not a recognized error format, the code is set to
+		 * {@link ResultCode#CLIENT_ERROR} and the message is set to the full
+		 * response string.
+		 */
+		public Error(String response) {
+			// Error format: ERROR|FAIL[:][:]
+			int rc = ResultCode.CLIENT_ERROR;
+			String msg = response;
+
+			try {
+				String[] list = response.split(":");
+				String s = list[0];
+
+				if (s.regionMatches(true, 0, "FAIL", 0, 4) ||
+					s.regionMatches(true, 0, "ERROR", 0, 5)) {
+
+					if (list.length >= 3) {
+						msg = list[2].trim();
+						s = list[1].trim();
+
+						if (! s.isEmpty()) {
+							rc = Integer.parseInt(s);
+						}
+					}
+					else if (list.length == 2) {
+						s = list[1].trim();
+
+						if (! s.isEmpty()) {
+							try {
+								rc = Integer.parseInt(s);
+							}
+							catch (Throwable t) {
+								// Some error strings omit the code and just have a message.
+								msg = s;
+							}
+						}
+					}
+				}
+			}
+			catch (Throwable t) {
+			}
+			finally {
+				this.code = rc;
+				this.message = msg;
+			}
+		}
+	}
 }
diff --git a/client/src/com/aerospike/client/task/IndexTask.java b/client/src/com/aerospike/client/task/IndexTask.java
index 98852e603..bdc469127 100644
--- a/client/src/com/aerospike/client/task/IndexTask.java
+++ b/client/src/com/aerospike/client/task/IndexTask.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2021 Aerospike, Inc.
+ * Copyright 2012-2024 Aerospike, Inc.
  *
  * Portions may be licensed to Aerospike, Inc. under one or more contributor
  * license agreements WHICH ARE COMPATIBLE WITH THE APACHE LICENSE, VERSION 2.0.
@@ -18,6 +18,7 @@
 
 import com.aerospike.client.AerospikeException;
 import com.aerospike.client.Info;
+import com.aerospike.client.ResultCode;
 import com.aerospike.client.cluster.Cluster;
 import com.aerospike.client.cluster.Node;
 import com.aerospike.client.policy.Policy;
@@ -92,13 +93,14 @@ public static int parseStatusResponse(String command, String response, boolean i
 			int index = response.indexOf(find);
 
 			if (index < 0) {
-				if (response.indexOf("FAIL:201") >= 0 || response.indexOf("FAIL:203") >= 0) {
-					// Index not found or not readable.
+				Info.Error error = new Info.Error(response);
+
+				if (error.code == ResultCode.INDEX_NOTFOUND || error.code == ResultCode.INDEX_NOTREADABLE) {
 					return Task.NOT_FOUND;
 				}
 				else {
 					// Throw exception immediately.
-					throw new AerospikeException(command + " failed: " + response);
+					throw new AerospikeException(error.code, command + " failed: " + error.message);
 				}
 			}
 
@@ -113,7 +115,9 @@ public static int parseStatusResponse(String command, String response, boolean i
 		}
 		else {
 			// Check if index has been dropped.
-			if (response.indexOf("FAIL:201") < 0) {
+			Info.Error error = new Info.Error(response);
+
+			if (error.code != ResultCode.INDEX_NOTFOUND) {
 				// Index still exists.
 				return Task.IN_PROGRESS;
 			}
diff --git a/test/src/com/aerospike/test/sync/basic/TestServerInfo.java b/test/src/com/aerospike/test/sync/basic/TestServerInfo.java
index f3f52424a..2d39bf2bf 100644
--- a/test/src/com/aerospike/test/sync/basic/TestServerInfo.java
+++ b/test/src/com/aerospike/test/sync/basic/TestServerInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2023 Aerospike, Inc.
+ * Copyright 2012-2024 Aerospike, Inc.
  *
  * Portions may be licensed to Aerospike, Inc. under one or more contributor
  * license agreements WHICH ARE COMPATIBLE WITH THE APACHE LICENSE, VERSION 2.0.
@@ -17,9 +17,11 @@
 package com.aerospike.test.sync.basic;
 
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
 
 import java.util.Map;
 
+import com.aerospike.client.ResultCode;
 import org.junit.Test;
 
 import com.aerospike.client.Info;
@@ -76,4 +78,33 @@ private void LogNameValueTokens(String tokens) {
 			assertNotNull(value);
 		}
 	}
+
+	@Test
+	public void errorResponse() {
+		Info.Error error;
+
+		error = new Info.Error("FaIL:201:index not found");
+		assertEquals(error.code, 201);
+		assertEquals(error.message, "index not found");
+
+		error = new Info.Error("ERRor:201:index not found");
+		assertEquals(error.code, 201);
+		assertEquals(error.message, "index not found");
+
+		error = new Info.Error("error::index not found ");
+		assertEquals(error.code, ResultCode.CLIENT_ERROR);
+		assertEquals(error.message, "index not found");
+
+		error = new Info.Error("error: index not found ");
+		assertEquals(error.code, ResultCode.CLIENT_ERROR);
+		assertEquals(error.message, "index not found");
+
+		error = new Info.Error("error:99");
+		assertEquals(error.code, 99);
+		assertEquals(error.message, "error:99");
+
+		error = new Info.Error("generic message");
+		assertEquals(error.code, ResultCode.CLIENT_ERROR);
+		assertEquals(error.message, "generic message");
+	}
 }

From e808c2ce74f7a7fcc6bcdd3d33089787152f5f2c Mon Sep 17 00:00:00 2001
From: Brian Nichols 
Date: Fri, 14 Jun 2024 11:55:11 -0400
Subject: [PATCH 7/9] CLIENT-3002 Change ReadModeSC doc from server to client
 perspective.

---
 .../com/aerospike/client/policy/ReadModeSC.java    | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/client/src/com/aerospike/client/policy/ReadModeSC.java b/client/src/com/aerospike/client/policy/ReadModeSC.java
index ff2c6dbd3..eed429b13 100644
--- a/client/src/com/aerospike/client/policy/ReadModeSC.java
+++ b/client/src/com/aerospike/client/policy/ReadModeSC.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2021 Aerospike, Inc.
+ * Copyright 2012-2024 Aerospike, Inc.
  *
  * Portions may be licensed to Aerospike, Inc. under one or more contributor
  * license agreements WHICH ARE COMPATIBLE WITH THE APACHE LICENSE, VERSION 2.0.
@@ -24,25 +24,25 @@
 public enum ReadModeSC {
 	/**
 	 * Ensures this client will only see an increasing sequence of record versions.
-	 * Server only reads from master.  This is the default.
+	 * Client only reads from master. This is the default.
 	 */
 	SESSION,
 
 	/**
-	 * Ensures ALL clients will only see an increasing sequence of record versions.
-	 * Server only reads from master.
+	 * Ensures all clients will only see an increasing sequence of record versions.
+	 * Client only reads from master.
 	 */
 	LINEARIZE,
 
 	/**
-	 * Server may read from master or any full (non-migrating) replica.
+	 * Client may read from master or any full (non-migrating) replica.
 	 * Increasing sequence of record versions is not guaranteed.
 	 */
 	ALLOW_REPLICA,
 
 	/**
-	 * Server may read from master or any full (non-migrating) replica or from unavailable
-	 * partitions.  Increasing sequence of record versions is not guaranteed.
+	 * Client may read from master or any full (non-migrating) replica or from unavailable
+	 * partitions. Increasing sequence of record versions is not guaranteed.
 	 */
 	ALLOW_UNAVAILABLE
 }

From 1062c185255c4da7fbf0c9ee0f8aac65420bc239 Mon Sep 17 00:00:00 2001
From: Brian Nichols 
Date: Mon, 24 Jun 2024 16:05:50 -0400
Subject: [PATCH 8/9] Upgrade to netty 4.1.110.Final and commons-cli 1.8.0 per
 snyk.

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index f22dbf19c..a36cd82e8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,12 +39,12 @@
     2.18.1
     3.2.0
 
-    4.1.108.Final
+    4.1.110.Final
     2.0.62.Final
     1.59.0
     3.0.1
     0.4
-    1.7.0
+    1.8.0
     4.13.1
   
 

From 4dac236ce2d823d29925e1a33d9f45cfac81ce77 Mon Sep 17 00:00:00 2001
From: Brian Nichols 
Date: Tue, 25 Jun 2024 12:50:28 -0400
Subject: [PATCH 9/9] Update version 8.1.2

---
 benchmarks/pom.xml | 2 +-
 client/pom.xml     | 2 +-
 examples/pom.xml   | 2 +-
 pom.xml            | 2 +-
 proxy/pom.xml      | 2 +-
 test/pom.xml       | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml
index d142e8dfb..e5d0d7575 100644
--- a/benchmarks/pom.xml
+++ b/benchmarks/pom.xml
@@ -6,7 +6,7 @@
   
     com.aerospike
     aerospike-parent
-    8.1.1
+    8.1.2
   
   aerospike-benchmarks
   jar
diff --git a/client/pom.xml b/client/pom.xml
index a554a9163..95525ba34 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -6,7 +6,7 @@
   
     com.aerospike
     aerospike-parent
-    8.1.1
+    8.1.2
   
   aerospike-client-jdk21
   jar
diff --git a/examples/pom.xml b/examples/pom.xml
index 318c231be..c3f381888 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -6,7 +6,7 @@
   
     com.aerospike
     aerospike-parent
-    8.1.1
+    8.1.2
   
   aerospike-examples
   jar
diff --git a/pom.xml b/pom.xml
index a36cd82e8..3f9c5ddea 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   com.aerospike
   aerospike-parent
   aerospike-parent
-  8.1.1
+  8.1.2
   pom
   https://github.com/aerospike/aerospike-client-java
 
diff --git a/proxy/pom.xml b/proxy/pom.xml
index 0c269eb7f..b458324de 100644
--- a/proxy/pom.xml
+++ b/proxy/pom.xml
@@ -6,7 +6,7 @@
   
     com.aerospike
     aerospike-parent
-    8.1.1
+    8.1.2
   
   aerospike-proxy-client
   jar
diff --git a/test/pom.xml b/test/pom.xml
index 218b6c7ba..e7c55b8ee 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -6,7 +6,7 @@
   
     com.aerospike
     aerospike-parent
-    8.1.1
+    8.1.2
   
   aerospike-client-test
   jar