From 58c0032dead55fe51e2d9af9a16c3788a4f5c8fe Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Tue, 26 Mar 2024 15:14:19 -0400 Subject: [PATCH 01/18] CLIENT-2839 Add methods for copying default policies: copyReadPolicyDefault() copyWritePolicyDefault() copyScanPolicyDefault() copyQueryPolicyDefault() copyBatchPolicyDefault() copyBatchParentPolicyWriteDefault() copyBatchWritePolicyDefault() copyBatchDeletePolicyDefault() copyBatchUDFPolicyDefault() copyInfoPolicyDefault() Also, suppress internal deprecation warnings for shortQuery. --- .../com/aerospike/client/AerospikeClient.java | 100 ++++++++++++++++++ .../aerospike/client/IAerospikeClient.java | 91 +++++++++++++++- .../com/aerospike/client/command/Command.java | 1 + .../src/com/aerospike/examples/QueryExp.java | 8 +- .../client/proxy/AerospikeClientProxy.java | 100 ++++++++++++++++++ .../client/proxy/grpc/GrpcConversions.java | 1 + 6 files changed, 296 insertions(+), 5 deletions(-) diff --git a/client/src/com/aerospike/client/AerospikeClient.java b/client/src/com/aerospike/client/AerospikeClient.java index 6f5bfe7ae..b055fbdb7 100644 --- a/client/src/com/aerospike/client/AerospikeClient.java +++ b/client/src/com/aerospike/client/AerospikeClient.java @@ -339,46 +339,146 @@ protected AerospikeClient(ClientPolicy policy) { // Default Policies //------------------------------------------------------- + /** + * Return read policy default. Use when the policy will not be modified. + */ public final Policy getReadPolicyDefault() { return readPolicyDefault; } + /** + * Copy read policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final Policy copyReadPolicyDefault() { + return new Policy(readPolicyDefault); + } + + /** + * Return write policy default. Use when the policy will not be modified. + */ public final WritePolicy getWritePolicyDefault() { return writePolicyDefault; } + /** + * Copy write policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final WritePolicy copyWritePolicyDefault() { + return new WritePolicy(writePolicyDefault); + } + + /** + * Return scan policy default. Use when the policy will not be modified. + */ public final ScanPolicy getScanPolicyDefault() { return scanPolicyDefault; } + /** + * Copy scan policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final ScanPolicy copyScanPolicyDefault() { + return new ScanPolicy(scanPolicyDefault); + } + + /** + * Return query policy default. Use when the policy will not be modified. + */ public final QueryPolicy getQueryPolicyDefault() { return queryPolicyDefault; } + /** + * Copy query policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final QueryPolicy copyQueryPolicyDefault() { + return new QueryPolicy(queryPolicyDefault); + } + + /** + * Return batch header read policy default. Use when the policy will not be modified. + */ public final BatchPolicy getBatchPolicyDefault() { return batchPolicyDefault; } + /** + * Copy batch header read policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final BatchPolicy copyBatchPolicyDefault() { + return new BatchPolicy(batchPolicyDefault); + } + + /** + * Return batch header write policy default. Use when the policy will not be modified. + */ public final BatchPolicy getBatchParentPolicyWriteDefault() { return batchParentPolicyWriteDefault; } + /** + * Copy batch header write policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final BatchPolicy copyBatchParentPolicyWriteDefault() { + return new BatchPolicy(batchParentPolicyWriteDefault); + } + + /** + * Return batch detail write policy default. Use when the policy will not be modified. + */ public final BatchWritePolicy getBatchWritePolicyDefault() { return batchWritePolicyDefault; } + /** + * Copy batch detail write policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final BatchWritePolicy copyBatchWritePolicyDefault() { + return new BatchWritePolicy(batchWritePolicyDefault); + } + + /** + * Return batch detail delete policy default. Use when the policy will not be modified. + */ public final BatchDeletePolicy getBatchDeletePolicyDefault() { return batchDeletePolicyDefault; } + /** + * Copy batch detail delete policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final BatchDeletePolicy copyBatchDeletePolicyDefault() { + return new BatchDeletePolicy(batchDeletePolicyDefault); + } + + /** + * Return batch detail UDF policy default. Use when the policy will not be modified. + */ public final BatchUDFPolicy getBatchUDFPolicyDefault() { return batchUDFPolicyDefault; } + /** + * Copy batch detail UDF policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final BatchUDFPolicy copyBatchUDFPolicyDefault() { + return new BatchUDFPolicy(batchUDFPolicyDefault); + } + + /** + * Return info command policy default. Use when the policy will not be modified. + */ public final InfoPolicy getInfoPolicyDefault() { return infoPolicyDefault; } + /** + * Copy info command policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final InfoPolicy copyInfoPolicyDefault() { + return new InfoPolicy(infoPolicyDefault); + } + //------------------------------------------------------- // Cluster Connection Management //------------------------------------------------------- diff --git a/client/src/com/aerospike/client/IAerospikeClient.java b/client/src/com/aerospike/client/IAerospikeClient.java index f6ce767fb..161ea58bb 100644 --- a/client/src/com/aerospike/client/IAerospikeClient.java +++ b/client/src/com/aerospike/client/IAerospikeClient.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. @@ -77,17 +77,106 @@ public interface IAerospikeClient extends Closeable { // Default Policies //------------------------------------------------------- + /** + * Return read policy default. Use when the policy will not be modified. + */ public Policy getReadPolicyDefault(); + + /** + * Copy read policy default. Use when the policy will be modified for use in a specific transaction. + */ + public Policy copyReadPolicyDefault(); + + /** + * Return write policy default. Use when the policy will not be modified. + */ public WritePolicy getWritePolicyDefault(); + + /** + * Copy write policy default. Use when the policy will be modified for use in a specific transaction. + */ + public WritePolicy copyWritePolicyDefault(); + + /** + * Return scan policy default. Use when the policy will not be modified. + */ public ScanPolicy getScanPolicyDefault(); + + /** + * Copy scan policy default. Use when the policy will be modified for use in a specific transaction. + */ + public ScanPolicy copyScanPolicyDefault(); + + /** + * Return query policy default. Use when the policy will not be modified. + */ public QueryPolicy getQueryPolicyDefault(); + + /** + * Copy query policy default. Use when the policy will be modified for use in a specific transaction. + */ + public QueryPolicy copyQueryPolicyDefault(); + + /** + * Return batch header read policy default. Use when the policy will not be modified. + */ public BatchPolicy getBatchPolicyDefault(); + + /** + * Copy batch header read policy default. Use when the policy will be modified for use in a specific transaction. + */ + public BatchPolicy copyBatchPolicyDefault(); + + /** + * Return batch header write policy default. Use when the policy will not be modified. + */ public BatchPolicy getBatchParentPolicyWriteDefault(); + + /** + * Copy batch header write policy default. Use when the policy will be modified for use in a specific transaction. + */ + public BatchPolicy copyBatchParentPolicyWriteDefault(); + + /** + * Return batch detail write policy default. Use when the policy will not be modified. + */ public BatchWritePolicy getBatchWritePolicyDefault(); + + /** + * Copy batch detail write policy default. Use when the policy will be modified for use in a specific transaction. + */ + public BatchWritePolicy copyBatchWritePolicyDefault(); + + /** + * Return batch detail delete policy default. Use when the policy will not be modified. + */ public BatchDeletePolicy getBatchDeletePolicyDefault(); + + /** + * Copy batch detail delete policy default. Use when the policy will be modified for use in a specific transaction. + */ + public BatchDeletePolicy copyBatchDeletePolicyDefault(); + + /** + * Return batch detail UDF policy default. Use when the policy will not be modified. + */ public BatchUDFPolicy getBatchUDFPolicyDefault(); + + /** + * Copy batch detail UDF policy default. Use when the policy will be modified for use in a specific transaction. + */ + public BatchUDFPolicy copyBatchUDFPolicyDefault(); + + /** + * Return info command policy default. Use when the policy will not be modified. + */ public InfoPolicy getInfoPolicyDefault(); + /** + * Copy info command policy default. Use when the policy will be modified for use in a specific transaction. + */ + public InfoPolicy copyInfoPolicyDefault(); + //------------------------------------------------------- // Cluster Connection Management //------------------------------------------------------- diff --git a/client/src/com/aerospike/client/command/Command.java b/client/src/com/aerospike/client/command/Command.java index 876e687fe..a053fec5c 100644 --- a/client/src/com/aerospike/client/command/Command.java +++ b/client/src/com/aerospike/client/command/Command.java @@ -1387,6 +1387,7 @@ public final void setScan( // Query //-------------------------------------------------- + @SuppressWarnings("deprecation") public final void setQuery( Cluster cluster, Policy policy, diff --git a/examples/src/com/aerospike/examples/QueryExp.java b/examples/src/com/aerospike/examples/QueryExp.java index c0a9d3a54..f0895dfec 100644 --- a/examples/src/com/aerospike/examples/QueryExp.java +++ b/examples/src/com/aerospike/examples/QueryExp.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. @@ -132,7 +132,7 @@ private void runQuery1( // Predicates are applied on query results on server side. // Predicates can reference any bin. - QueryPolicy policy = new QueryPolicy(client.getQueryPolicyDefault()); + QueryPolicy policy = client.copyQueryPolicyDefault(); policy.filterExp = Exp.build( Exp.or( Exp.and( @@ -171,7 +171,7 @@ private void runQuery2( stmt.setSetName(params.set); stmt.setFilter(Filter.range(binName, begin, end)); - QueryPolicy policy = new QueryPolicy(client.getQueryPolicyDefault()); + QueryPolicy policy = client.copyQueryPolicyDefault(); policy.filterExp = Exp.build( Exp.and( Exp.ge(Exp.lastUpdate(), Exp.val(beginTime)), @@ -206,7 +206,7 @@ private void runQuery3( stmt.setSetName(params.set); stmt.setFilter(Filter.range(binName, begin, end)); - QueryPolicy policy = new QueryPolicy(client.getQueryPolicyDefault()); + QueryPolicy policy = client.copyQueryPolicyDefault(); policy.filterExp = Exp.build( Exp.regexCompare("prefix.*suffix", RegexFlag.ICASE | RegexFlag.NEWLINE, Exp.stringBin("bin3"))); diff --git a/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java b/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java index 32305f660..1a75cd3be 100644 --- a/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java +++ b/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java @@ -334,46 +334,146 @@ private static String getVersion() { // Default Policies //------------------------------------------------------- + /** + * Return read policy default. Use when the policy will not be modified. + */ public final Policy getReadPolicyDefault() { return readPolicyDefault; } + /** + * Copy read policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final Policy copyReadPolicyDefault() { + return new Policy(readPolicyDefault); + } + + /** + * Return write policy default. Use when the policy will not be modified. + */ public final WritePolicy getWritePolicyDefault() { return writePolicyDefault; } + /** + * Copy write policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final WritePolicy copyWritePolicyDefault() { + return new WritePolicy(writePolicyDefault); + } + + /** + * Return scan policy default. Use when the policy will not be modified. + */ public final ScanPolicy getScanPolicyDefault() { return scanPolicyDefault; } + /** + * Copy scan policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final ScanPolicy copyScanPolicyDefault() { + return new ScanPolicy(scanPolicyDefault); + } + + /** + * Return query policy default. Use when the policy will not be modified. + */ public final QueryPolicy getQueryPolicyDefault() { return queryPolicyDefault; } + /** + * Copy query policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final QueryPolicy copyQueryPolicyDefault() { + return new QueryPolicy(queryPolicyDefault); + } + + /** + * Return batch header read policy default. Use when the policy will not be modified. + */ public final BatchPolicy getBatchPolicyDefault() { return batchPolicyDefault; } + /** + * Copy batch header read policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final BatchPolicy copyBatchPolicyDefault() { + return new BatchPolicy(batchPolicyDefault); + } + + /** + * Return batch header write policy default. Use when the policy will not be modified. + */ public final BatchPolicy getBatchParentPolicyWriteDefault() { return batchParentPolicyWriteDefault; } + /** + * Copy batch header write policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final BatchPolicy copyBatchParentPolicyWriteDefault() { + return new BatchPolicy(batchParentPolicyWriteDefault); + } + + /** + * Return batch detail write policy default. Use when the policy will not be modified. + */ public final BatchWritePolicy getBatchWritePolicyDefault() { return batchWritePolicyDefault; } + /** + * Copy batch detail write policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final BatchWritePolicy copyBatchWritePolicyDefault() { + return new BatchWritePolicy(batchWritePolicyDefault); + } + + /** + * Return batch detail delete policy default. Use when the policy will not be modified. + */ public final BatchDeletePolicy getBatchDeletePolicyDefault() { return batchDeletePolicyDefault; } + /** + * Copy batch detail delete policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final BatchDeletePolicy copyBatchDeletePolicyDefault() { + return new BatchDeletePolicy(batchDeletePolicyDefault); + } + + /** + * Return batch detail UDF policy default. Use when the policy will not be modified. + */ public final BatchUDFPolicy getBatchUDFPolicyDefault() { return batchUDFPolicyDefault; } + /** + * Copy batch detail UDF policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final BatchUDFPolicy copyBatchUDFPolicyDefault() { + return new BatchUDFPolicy(batchUDFPolicyDefault); + } + + /** + * Return info command policy default. Use when the policy will not be modified. + */ public final InfoPolicy getInfoPolicyDefault() { return infoPolicyDefault; } + /** + * Copy info command policy default. Use when the policy will be modified for use in a specific transaction. + */ + public final InfoPolicy copyInfoPolicyDefault() { + return new InfoPolicy(infoPolicyDefault); + } + //------------------------------------------------------- // Client Management //------------------------------------------------------- diff --git a/proxy/src/com/aerospike/client/proxy/grpc/GrpcConversions.java b/proxy/src/com/aerospike/client/proxy/grpc/GrpcConversions.java index 3e7019139..33c7fa1c3 100644 --- a/proxy/src/com/aerospike/client/proxy/grpc/GrpcConversions.java +++ b/proxy/src/com/aerospike/client/proxy/grpc/GrpcConversions.java @@ -106,6 +106,7 @@ public static Kvs.ScanPolicy toGrpc(ScanPolicy scanPolicy) { return scanPolicyBuilder.build(); } + @SuppressWarnings("deprecation") public static Kvs.QueryPolicy toGrpc(QueryPolicy queryPolicy) { // Base policy fields. Kvs.QueryPolicy.Builder queryPolicyBuilder = Kvs.QueryPolicy.newBuilder(); From c95dd9121700c62a3c2123232aaa4b1124ec203f Mon Sep 17 00:00:00 2001 From: agrgr Date: Thu, 28 Mar 2024 12:48:45 -0400 Subject: [PATCH 02/18] CLIENT-2843 Add getKeyRecord() in RecordSet and RecordSequenceRecordSet. --- client/src/com/aerospike/client/query/RecordSet.java | 11 +++++++++-- .../client/proxy/RecordSequenceRecordSet.java | 9 +++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/client/src/com/aerospike/client/query/RecordSet.java b/client/src/com/aerospike/client/query/RecordSet.java index ad36a5e65..7796db2b9 100644 --- a/client/src/com/aerospike/client/query/RecordSet.java +++ b/client/src/com/aerospike/client/query/RecordSet.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. @@ -131,6 +131,13 @@ public Record getRecord() { return record.record; } + /** + * Get key and record. + */ + public KeyRecord getKeyRecord() { + return record; + } + //------------------------------------------------------- // Methods for internal use only. //------------------------------------------------------- @@ -206,7 +213,7 @@ public boolean hasNext() { @Override public KeyRecord next() { - KeyRecord kr = recordSet.record; + KeyRecord kr = recordSet.getKeyRecord(); more = recordSet.next(); return kr; } diff --git a/proxy/src/com/aerospike/client/proxy/RecordSequenceRecordSet.java b/proxy/src/com/aerospike/client/proxy/RecordSequenceRecordSet.java index 0da743a84..b782cb447 100644 --- a/proxy/src/com/aerospike/client/proxy/RecordSequenceRecordSet.java +++ b/proxy/src/com/aerospike/client/proxy/RecordSequenceRecordSet.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. @@ -34,7 +34,7 @@ public class RecordSequenceRecordSet extends RecordSet implements RecordSequence private final long taskId; private volatile boolean valid = true; private final BlockingQueue queue; - private volatile KeyRecord record; + protected volatile KeyRecord record; private volatile AerospikeException exception; public RecordSequenceRecordSet(long taskId, int capacity) { @@ -114,6 +114,11 @@ public Key getKey() { return record.key; } + @Override + public KeyRecord getKeyRecord() { + return record; + } + @Override public void onRecord(Key key, Record record) throws AerospikeException { if (!valid) { From b2102be124b73db7b51de1cbeb6f344c9d613685 Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Thu, 28 Mar 2024 17:47:11 -0400 Subject: [PATCH 03/18] CLIENT-2842 Use default batch policy (ClientPolicy batchWritePolicyDefault, batchUDFPolicyDefault or batchDeletePolicyDefault) when the record level batch policy is null. --- .../com/aerospike/client/AerospikeClient.java | 74 +++++-------------- .../aerospike/client/async/AsyncBatch.java | 13 +++- .../com/aerospike/client/cluster/Cluster.java | 7 +- .../com/aerospike/client/command/Batch.java | 7 +- .../aerospike/client/command/BatchAttr.java | 33 --------- .../com/aerospike/client/command/Command.java | 46 ++++++------ .../client/proxy/AerospikeClientProxy.java | 4 +- .../aerospike/client/proxy/BatchProxy.java | 20 +++-- 8 files changed, 80 insertions(+), 124 deletions(-) diff --git a/client/src/com/aerospike/client/AerospikeClient.java b/client/src/com/aerospike/client/AerospikeClient.java index b055fbdb7..f5ffee2c7 100644 --- a/client/src/com/aerospike/client/AerospikeClient.java +++ b/client/src/com/aerospike/client/AerospikeClient.java @@ -296,7 +296,7 @@ public AerospikeClient(ClientPolicy policy, Host... hosts) this.infoPolicyDefault = policy.infoPolicyDefault; this.operatePolicyReadDefault = new WritePolicy(this.readPolicyDefault); - cluster = new Cluster(policy, hosts); + cluster = new Cluster(this, policy, hosts); } //------------------------------------------------------- @@ -2328,13 +2328,9 @@ public final boolean operate(BatchPolicy policy, List records) case BATCH_WRITE: { BatchWrite bw = (BatchWrite)record; BatchAttr attr = new BatchAttr(); + BatchWritePolicy bwp = (bw.policy != null)? bw.policy : this.batchWritePolicyDefault; - if (bw.policy != null) { - attr.setWrite(bw.policy); - } - else { - attr.setWrite(policy); - } + attr.setWrite(bwp); attr.adjustWrite(bw.ops); attr.setOpSize(bw.ops); commands[count++] = new BatchSingle.OperateBatchRecord( @@ -2345,13 +2341,9 @@ public final boolean operate(BatchPolicy policy, List records) case BATCH_UDF: { BatchUDF bu = (BatchUDF)record; BatchAttr attr = new BatchAttr(); + BatchUDFPolicy bup = (bu.policy != null)? bu.policy : this.batchUDFPolicyDefault; - if (bu.policy != null) { - attr.setUDF(bu.policy); - } - else { - attr.setUDF(policy); - } + attr.setUDF(bup); commands[count++] = new BatchSingle.UDF( cluster, policy, bu.packageName, bu.functionName, bu.functionArgs, attr, record, status, bn.node); @@ -2361,13 +2353,9 @@ public final boolean operate(BatchPolicy policy, List records) case BATCH_DELETE: { BatchDelete bd = (BatchDelete)record; BatchAttr attr = new BatchAttr(); + BatchDeletePolicy bdp = (bd.policy != null)? bd.policy : this.batchDeletePolicyDefault; - if (bd.policy != null) { - attr.setDelete(bd.policy); - } - else { - attr.setDelete(policy); - } + attr.setDelete(bdp); commands[count++] = new BatchSingle.Delete(cluster, policy, attr, record, status, bn.node); break; } @@ -2445,13 +2433,9 @@ public final void operate( case BATCH_WRITE: { BatchWrite bw = (BatchWrite)record; BatchAttr attr = new BatchAttr(); + BatchWritePolicy bwp = (bw.policy != null)? bw.policy : this.batchWritePolicyDefault; - if (bw.policy != null) { - attr.setWrite(bw.policy); - } - else { - attr.setWrite(policy); - } + attr.setWrite(bwp); attr.adjustWrite(bw.ops); attr.setOpSize(bw.ops); commands[count++] = new AsyncBatchSingle.Write(executor, cluster, policy, attr, bw, bn.node); @@ -2461,13 +2445,9 @@ public final void operate( case BATCH_UDF: { BatchUDF bu = (BatchUDF)record; BatchAttr attr = new BatchAttr(); + BatchUDFPolicy bup = (bu.policy != null)? bu.policy : this.batchUDFPolicyDefault; - if (bu.policy != null) { - attr.setUDF(bu.policy); - } - else { - attr.setUDF(policy); - } + attr.setUDF(bup); commands[count++] = new AsyncBatchSingle.UDF(executor, cluster, policy, attr, bu, bn.node); break; } @@ -2475,13 +2455,9 @@ public final void operate( case BATCH_DELETE: { BatchDelete bd = (BatchDelete)record; BatchAttr attr = new BatchAttr(); + BatchDeletePolicy bdp = (bd.policy != null)? bd.policy : this.batchDeletePolicyDefault; - if (bd.policy != null) { - attr.setDelete(bd.policy); - } - else { - attr.setDelete(policy); - } + attr.setDelete(bdp); commands[count++] = new AsyncBatchSingle.Delete(executor, cluster, policy, attr, record, bn.node); break; @@ -2560,13 +2536,9 @@ public final void operate( case BATCH_WRITE: { BatchWrite bw = (BatchWrite)record; BatchAttr attr = new BatchAttr(); + BatchWritePolicy bwp = (bw.policy != null)? bw.policy : this.batchWritePolicyDefault; - if (bw.policy != null) { - attr.setWrite(bw.policy); - } - else { - attr.setWrite(policy); - } + attr.setWrite(bwp); attr.adjustWrite(bw.ops); attr.setOpSize(bw.ops); commands[count++] = new AsyncBatchSingle.WriteSequence( @@ -2577,13 +2549,9 @@ public final void operate( case BATCH_UDF: { BatchUDF bu = (BatchUDF)record; BatchAttr attr = new BatchAttr(); + BatchUDFPolicy bup = (bu.policy != null)? bu.policy : this.batchUDFPolicyDefault; - if (bu.policy != null) { - attr.setUDF(bu.policy); - } - else { - attr.setUDF(policy); - } + attr.setUDF(bup); commands[count++] = new AsyncBatchSingle.UDFSequence( executor, cluster, policy, attr, bu, bn.node, listener, i); break; @@ -2592,13 +2560,9 @@ public final void operate( case BATCH_DELETE: { BatchDelete bd = (BatchDelete)record; BatchAttr attr = new BatchAttr(); + BatchDeletePolicy bdp = (bd.policy != null)? bd.policy : this.batchDeletePolicyDefault; - if (bd.policy != null) { - attr.setDelete(bd.policy); - } - else { - attr.setDelete(policy); - } + attr.setDelete(bdp); commands[count++] = new AsyncBatchSingle.DeleteSequence( executor, cluster, policy, attr, bd, bn.node, listener, i); break; diff --git a/client/src/com/aerospike/client/async/AsyncBatch.java b/client/src/com/aerospike/client/async/AsyncBatch.java index abd386dde..5893e06ae 100644 --- a/client/src/com/aerospike/client/async/AsyncBatch.java +++ b/client/src/com/aerospike/client/async/AsyncBatch.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; +import com.aerospike.client.AerospikeClient; import com.aerospike.client.AerospikeException; import com.aerospike.client.BatchRead; import com.aerospike.client.BatchRecord; @@ -62,7 +63,7 @@ public ReadListCommand( @Override protected void writeBuffer() { if (batch.node.hasBatchAny()) { - setBatchOperate(batchPolicy, records, batch); + setBatchOperate(batchPolicy, null, null, null, records, batch); } else { setBatchRead(batchPolicy, records, batch); @@ -117,7 +118,7 @@ public ReadSequenceCommand( @Override protected void writeBuffer() { if (batch.node.hasBatchAny()) { - setBatchOperate(batchPolicy, records, batch); + setBatchOperate(batchPolicy, null, null, null, records, batch); } else { setBatchRead(batchPolicy, records, batch); @@ -411,7 +412,9 @@ protected boolean isWrite() { @Override protected void writeBuffer() { - setBatchOperate(batchPolicy, records, batch); + AerospikeClient client = parent.cluster.client; + setBatchOperate(batchPolicy, client.batchWritePolicyDefault, client.batchUDFPolicyDefault, + client.batchDeletePolicyDefault, records, batch); } @Override @@ -498,7 +501,9 @@ protected boolean isWrite() { @Override protected void writeBuffer() { - setBatchOperate(batchPolicy, records, batch); + AerospikeClient client = parent.cluster.client; + setBatchOperate(batchPolicy, client.batchWritePolicyDefault, client.batchUDFPolicyDefault, + client.batchDeletePolicyDefault, records, batch); } @Override diff --git a/client/src/com/aerospike/client/cluster/Cluster.java b/client/src/com/aerospike/client/cluster/Cluster.java index d8fbf22cd..7bb55ad3d 100644 --- a/client/src/com/aerospike/client/cluster/Cluster.java +++ b/client/src/com/aerospike/client/cluster/Cluster.java @@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReferenceArray; +import com.aerospike.client.AerospikeClient; import com.aerospike.client.AerospikeException; import com.aerospike.client.Host; import com.aerospike.client.Log; @@ -59,6 +60,9 @@ import com.aerospike.client.util.Util; public class Cluster implements Runnable, Closeable { + // Client back pointer. + public final AerospikeClient client; + // Expected cluster name. protected final String clusterName; @@ -206,7 +210,8 @@ public class Cluster implements Runnable, Closeable { private final AtomicLong tranCount = new AtomicLong(); private final AtomicLong delayQueueTimeoutCount = new AtomicLong(); - public Cluster(ClientPolicy policy, Host[] hosts) { + public Cluster(AerospikeClient client, ClientPolicy policy, Host[] hosts) { + this.client = client; this.clusterName = policy.clusterName; this.validateClusterName = policy.validateClusterName; this.tlsPolicy = policy.tlsPolicy; diff --git a/client/src/com/aerospike/client/command/Batch.java b/client/src/com/aerospike/client/command/Batch.java index 993206f48..fecf05ed4 100644 --- a/client/src/com/aerospike/client/command/Batch.java +++ b/client/src/com/aerospike/client/command/Batch.java @@ -18,6 +18,7 @@ import java.util.List; +import com.aerospike.client.AerospikeClient; import com.aerospike.client.AerospikeException; import com.aerospike.client.BatchRead; import com.aerospike.client.BatchRecord; @@ -53,7 +54,7 @@ public ReadListCommand( @Override protected void writeBuffer() { if (batch.node.hasBatchAny()) { - setBatchOperate(batchPolicy, records, batch); + setBatchOperate(batchPolicy, null, null, null, records, batch); } else { setBatchRead(batchPolicy, records, batch); @@ -232,7 +233,9 @@ protected boolean isWrite() { @Override protected void writeBuffer() { - setBatchOperate(batchPolicy, records, batch); + AerospikeClient client = cluster.client; + setBatchOperate(batchPolicy, client.batchWritePolicyDefault, client.batchUDFPolicyDefault, + client.batchDeletePolicyDefault, records, batch); } @Override diff --git a/client/src/com/aerospike/client/command/BatchAttr.java b/client/src/com/aerospike/client/command/BatchAttr.java index 9f48e3dbb..487a742d0 100644 --- a/client/src/com/aerospike/client/command/BatchAttr.java +++ b/client/src/com/aerospike/client/command/BatchAttr.java @@ -191,17 +191,6 @@ public void adjustRead(boolean readAllBins) { } } - public void setWrite(Policy wp) { - filterExp = null; - readAttr = 0; - writeAttr = Command.INFO2_WRITE | Command.INFO2_RESPOND_ALL_OPS; - infoAttr = 0; - expiration = 0; - generation = 0; - hasWrite = true; - sendKey = wp.sendKey; - } - public void setWrite(BatchWritePolicy wp) { filterExp = wp.filterExp; readAttr = 0; @@ -271,17 +260,6 @@ else if (op.type == Operation.Type.READ_HEADER) { } } - public void setUDF(Policy up) { - filterExp = null; - readAttr = 0; - writeAttr = Command.INFO2_WRITE; - infoAttr = 0; - expiration = 0; - generation = 0; - hasWrite = true; - sendKey = up.sendKey; - } - public void setUDF(BatchUDFPolicy up) { filterExp = up.filterExp; readAttr = 0; @@ -301,17 +279,6 @@ public void setUDF(BatchUDFPolicy up) { } } - public void setDelete(Policy dp) { - filterExp = null; - readAttr = 0; - writeAttr = Command.INFO2_WRITE | Command.INFO2_RESPOND_ALL_OPS | Command.INFO2_DELETE; - infoAttr = 0; - expiration = 0; - generation = 0; - hasWrite = true; - sendKey = dp.sendKey; - } - public void setDelete(BatchDeletePolicy dp) { filterExp = dp.filterExp; readAttr = 0; diff --git a/client/src/com/aerospike/client/command/Command.java b/client/src/com/aerospike/client/command/Command.java index a053fec5c..0e573594c 100644 --- a/client/src/com/aerospike/client/command/Command.java +++ b/client/src/com/aerospike/client/command/Command.java @@ -36,8 +36,11 @@ import com.aerospike.client.Value; import com.aerospike.client.cluster.Cluster; import com.aerospike.client.exp.Expression; +import com.aerospike.client.policy.BatchDeletePolicy; import com.aerospike.client.policy.BatchPolicy; import com.aerospike.client.policy.BatchReadPolicy; +import com.aerospike.client.policy.BatchUDFPolicy; +import com.aerospike.client.policy.BatchWritePolicy; import com.aerospike.client.policy.CommitLevel; import com.aerospike.client.policy.Policy; import com.aerospike.client.policy.QueryDuration; @@ -743,12 +746,25 @@ else if (ops != null) { // Batch Read/Write Operations //-------------------------------------------------- - public final void setBatchOperate(BatchPolicy policy, List records, BatchNode batch) { + public final void setBatchOperate( + BatchPolicy policy, + BatchWritePolicy writePolicy, + BatchUDFPolicy udfPolicy, + BatchDeletePolicy deletePolicy, + List records, + BatchNode batch + ) { final BatchRecordIterNative iter = new BatchRecordIterNative(records, batch); - setBatchOperate(policy, iter); + setBatchOperate(policy, writePolicy, udfPolicy, deletePolicy, iter); } - public final void setBatchOperate(BatchPolicy policy, KeyIter iter) { + public final void setBatchOperate( + BatchPolicy policy, + BatchWritePolicy writePolicy, + BatchUDFPolicy udfPolicy, + BatchDeletePolicy deletePolicy, + KeyIter iter + ) { BatchRecord record; BatchRecord prev = null; @@ -851,13 +867,9 @@ else if (br.ops != null) { case BATCH_WRITE: { BatchWrite bw = (BatchWrite)record; + BatchWritePolicy bwp = (bw.policy != null)? bw.policy : writePolicy; - if (bw.policy != null) { - attr.setWrite(bw.policy); - } - else { - attr.setWrite(policy); - } + attr.setWrite(bwp); attr.adjustWrite(bw.ops); writeBatchOperations(key, bw.ops, attr, attr.filterExp); break; @@ -865,13 +877,9 @@ else if (br.ops != null) { case BATCH_UDF: { BatchUDF bu = (BatchUDF)record; + BatchUDFPolicy bup = (bu.policy != null)? bu.policy : udfPolicy; - if (bu.policy != null) { - attr.setUDF(bu.policy); - } - else { - attr.setUDF(policy); - } + attr.setUDF(bup); writeBatchWrite(key, attr, attr.filterExp, 3, 0); writeField(bu.packageName, FieldType.UDF_PACKAGE_NAME); writeField(bu.functionName, FieldType.UDF_FUNCTION); @@ -881,13 +889,9 @@ else if (br.ops != null) { case BATCH_DELETE: { BatchDelete bd = (BatchDelete)record; + BatchDeletePolicy bdp = (bd.policy != null)? bd.policy : deletePolicy; - if (bd.policy != null) { - attr.setDelete(bd.policy); - } - else { - attr.setDelete(policy); - } + attr.setDelete(bdp); writeBatchWrite(key, attr, attr.filterExp, 0, 0); break; } diff --git a/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java b/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java index 1a75cd3be..7274c0f5f 100644 --- a/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java +++ b/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java @@ -1621,7 +1621,7 @@ public void operate( policy = batchParentPolicyWriteDefault; } - CommandProxy command = new BatchProxy.OperateListCommand(executor, policy, listener, records); + CommandProxy command = new BatchProxy.OperateListCommand(this, executor, policy, listener, records); command.execute(); } @@ -1656,7 +1656,7 @@ public void operate( policy = batchParentPolicyWriteDefault; } - CommandProxy command = new BatchProxy.OperateSequenceCommand(executor, policy, listener, records); + CommandProxy command = new BatchProxy.OperateSequenceCommand(this, executor, policy, listener, records); command.execute(); } diff --git a/proxy/src/com/aerospike/client/proxy/BatchProxy.java b/proxy/src/com/aerospike/client/proxy/BatchProxy.java index cef64b9da..c4ce06f8d 100644 --- a/proxy/src/com/aerospike/client/proxy/BatchProxy.java +++ b/proxy/src/com/aerospike/client/proxy/BatchProxy.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. @@ -75,7 +75,7 @@ public ReadListCommandSync( @Override void writeCommand(Command command) { BatchRecordIterProxy iter = new BatchRecordIterProxy(records); - command.setBatchOperate(batchPolicy, iter); + command.setBatchOperate(batchPolicy, null, null, null, iter); } @Override @@ -120,7 +120,7 @@ public ReadListCommand( @Override void writeCommand(Command command) { BatchRecordIterProxy iter = new BatchRecordIterProxy(records); - command.setBatchOperate(batchPolicy, iter); + command.setBatchOperate(batchPolicy, null, null, null, iter); } @Override @@ -164,7 +164,7 @@ public ReadSequenceCommand( @Override void writeCommand(Command command) { BatchRecordIterProxy iter = new BatchRecordIterProxy(records); - command.setBatchOperate(batchPolicy, iter); + command.setBatchOperate(batchPolicy, null, null, null, iter); } @Override @@ -417,17 +417,20 @@ void onFailure(AerospikeException ae) { //------------------------------------------------------- public static final class OperateListCommand extends BaseCommand { + private final AerospikeClientProxy client; private final BatchOperateListListener listener; private final List records; private boolean status; public OperateListCommand( + AerospikeClientProxy client, GrpcCallExecutor executor, BatchPolicy batchPolicy, BatchOperateListListener listener, List records ) { super(executor, batchPolicy, true, records.size()); + this.client = client; this.listener = listener; this.records = records; this.status = true; @@ -436,7 +439,8 @@ public OperateListCommand( @Override void writeCommand(Command command) { BatchRecordIterProxy iter = new BatchRecordIterProxy(records); - command.setBatchOperate(batchPolicy, iter); + command.setBatchOperate(batchPolicy, client.batchWritePolicyDefault, client.batchUDFPolicyDefault, + client.batchDeletePolicyDefault, iter); } @Override @@ -485,16 +489,19 @@ void onFailure(AerospikeException ae) { } public static final class OperateSequenceCommand extends BaseCommand { + private final AerospikeClientProxy client; private final BatchRecordSequenceListener listener; private final List records; public OperateSequenceCommand( + AerospikeClientProxy client, GrpcCallExecutor executor, BatchPolicy batchPolicy, BatchRecordSequenceListener listener, List records ) { super(executor, batchPolicy, true, records.size()); + this.client = client; this.listener = listener; this.records = records; } @@ -502,7 +509,8 @@ public OperateSequenceCommand( @Override void writeCommand(Command command) { BatchRecordIterProxy iter = new BatchRecordIterProxy(records); - command.setBatchOperate(batchPolicy, iter); + command.setBatchOperate(batchPolicy, client.batchWritePolicyDefault, client.batchUDFPolicyDefault, + client.batchDeletePolicyDefault, iter); } @Override From 5ffd6fb1afc4ac0fdd3974a187c14f567ebb8572 Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Fri, 5 Apr 2024 14:43:05 -0400 Subject: [PATCH 04/18] CLIENT-2868 Add readTouchTtlPercent command line option to benchmarks. --- .../src/com/aerospike/benchmarks/Main.java | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/benchmarks/src/com/aerospike/benchmarks/Main.java b/benchmarks/src/com/aerospike/benchmarks/Main.java index eacf50df1..5ee9c00ea 100644 --- a/benchmarks/src/com/aerospike/benchmarks/Main.java +++ b/benchmarks/src/com/aerospike/benchmarks/Main.java @@ -221,6 +221,11 @@ public Main(String[] commandLineArgs) throws Exception { " 0: Default to namespace expiration time\n" + " >0: Actual given expiration time" ); + options.addOption("rt", "readTouchTtlPercent", true, + "Read touch TTL percent is expressed as a percentage of the TTL (or expiration) sent on the most\n" + + "recent write such that a read within this interval of the record’s end of life will generate a touch.\n" + + "Range: 0 - 100" + ); options.addOption("g", "throughput", true, "Set a target transactions per second for the client. The client should not exceed this " + "average throughput." @@ -395,6 +400,14 @@ public Main(String[] commandLineArgs) throws Exception { } } + if (line.hasOption("readTouchTtlPercent")) { + args.readPolicy.readTouchTtlPercent = Integer.parseInt(line.getOptionValue("readTouchTtlPercent")); + if (args.readPolicy.readTouchTtlPercent < 0 || args.readPolicy.readTouchTtlPercent > 100) { + throw new Exception("Invalid readTouchTtlPercent: " + args.readPolicy.readTouchTtlPercent + + " Range: 0 - 100"); + } + } + if (line.hasOption("port")) { this.port = Integer.parseInt(line.getOptionValue("port")); } @@ -1053,19 +1066,21 @@ else if (! level.equals("all")) { if (args.workload != Workload.INITIALIZE) { System.out.println("read policy:"); System.out.println( - " connectTimeout: " + args.readPolicy.connectTimeout - + ", socketTimeout: " + args.readPolicy.socketTimeout - + ", totalTimeout: " + args.readPolicy.totalTimeout - + ", timeoutDelay: " + args.readPolicy.timeoutDelay - + ", maxRetries: " + args.readPolicy.maxRetries - + ", sleepBetweenRetries: " + args.readPolicy.sleepBetweenRetries - ); + " connectTimeout: " + args.readPolicy.connectTimeout + + ", socketTimeout: " + args.readPolicy.socketTimeout + + ", totalTimeout: " + args.readPolicy.totalTimeout + + ", timeoutDelay: " + args.readPolicy.timeoutDelay + + ", maxRetries: " + args.readPolicy.maxRetries + + ", sleepBetweenRetries: " + args.readPolicy.sleepBetweenRetries + ); System.out.println( - " readModeAP: " + args.readPolicy.readModeAP - + ", readModeSC: " + args.readPolicy.readModeSC - + ", replica: " + args.readPolicy.replica - + ", reportNotFound: " + args.reportNotFound); + " readModeAP: " + args.readPolicy.readModeAP + + ", readModeSC: " + args.readPolicy.readModeSC + + ", replica: " + args.readPolicy.replica + + ", readTouchTtlPercent: " + args.readPolicy.readTouchTtlPercent + + ", reportNotFound: " + args.reportNotFound + ); } System.out.println("write policy:"); @@ -1078,7 +1093,10 @@ else if (! level.equals("all")) { + ", sleepBetweenRetries: " + args.writePolicy.sleepBetweenRetries ); - System.out.println(" commitLevel: " + args.writePolicy.commitLevel); + System.out.println( + " commitLevel: " + args.writePolicy.commitLevel + + ", expiration: " + args.writePolicy.expiration + ); if (args.batchSize > 1) { System.out.println("batch size: " + args.batchSize From 8b11ca7ce80e19b56ff1ebe964d135f7adf313ea Mon Sep 17 00:00:00 2001 From: Kateryna Kanivets Date: Fri, 5 Apr 2024 16:05:42 -0400 Subject: [PATCH 05/18] Code cleanup in benchmarks. --- .../aerospike/benchmarks/InsertTaskSync.java | 18 +++----- .../src/com/aerospike/benchmarks/KeyType.java | 4 +- .../aerospike/benchmarks/LatencyManager.java | 12 ++--- .../benchmarks/LatencyManagerYcsb.java | 26 +++++------ .../src/com/aerospike/benchmarks/Main.java | 40 ++++++++-------- .../src/com/aerospike/benchmarks/RWTask.java | 46 +++++++++---------- .../com/aerospike/benchmarks/RWTaskSync.java | 33 ++++++------- .../benchmarks/TransactionalItem.java | 7 +-- .../benchmarks/TransactionalType.java | 10 ++-- .../benchmarks/TransactionalWorkload.java | 6 +-- .../com/aerospike/benchmarks/Workload.java | 4 +- 11 files changed, 100 insertions(+), 106 deletions(-) diff --git a/benchmarks/src/com/aerospike/benchmarks/InsertTaskSync.java b/benchmarks/src/com/aerospike/benchmarks/InsertTaskSync.java index 0046dc511..992ed2d75 100644 --- a/benchmarks/src/com/aerospike/benchmarks/InsertTaskSync.java +++ b/benchmarks/src/com/aerospike/benchmarks/InsertTaskSync.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,9 +16,6 @@ */ package com.aerospike.benchmarks; -import java.util.HashMap; -import java.util.Map; - import com.aerospike.client.AerospikeException; import com.aerospike.client.Bin; import com.aerospike.client.IAerospikeClient; @@ -87,11 +84,11 @@ private void runCommand(long keyCurrent, RandomShift random) { private void put(Key key, Bin[] bins) { if (counters.write.latency != null) { long begin = System.nanoTime(); - + if (! skipKey(key)) { client.put(args.writePolicy, key, bins); } - + long elapsed = System.nanoTime() - begin; counters.write.count.getAndIncrement(); counters.write.latency.add(elapsed); @@ -103,11 +100,8 @@ private void put(Key key, Bin[] bins) { counters.write.count.getAndIncrement(); } } - + private boolean skipKey(Key key) { - if (args.partitionIds != null && !args.partitionIds.contains(Partition.getPartitionId(key.digest))) { - return true; - } - return false; - } + return args.partitionIds != null && !args.partitionIds.contains(Partition.getPartitionId(key.digest)); + } } diff --git a/benchmarks/src/com/aerospike/benchmarks/KeyType.java b/benchmarks/src/com/aerospike/benchmarks/KeyType.java index 885e79846..24daf4326 100644 --- a/benchmarks/src/com/aerospike/benchmarks/KeyType.java +++ b/benchmarks/src/com/aerospike/benchmarks/KeyType.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. @@ -17,5 +17,5 @@ package com.aerospike.benchmarks; public enum KeyType { - STRING, INTEGER; + STRING, INTEGER } diff --git a/benchmarks/src/com/aerospike/benchmarks/LatencyManager.java b/benchmarks/src/com/aerospike/benchmarks/LatencyManager.java index 0b157016b..ec13c9bf0 100644 --- a/benchmarks/src/com/aerospike/benchmarks/LatencyManager.java +++ b/benchmarks/src/com/aerospike/benchmarks/LatencyManager.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. @@ -20,9 +20,9 @@ public interface LatencyManager { - public void add(long elapsed); + void add(long elapsed); - public void printHeader(PrintStream stream); + void printHeader(PrintStream stream); /** * Print latency percents for specified cumulative ranges. @@ -32,9 +32,9 @@ public interface LatencyManager { * affects performance. Fortunately, the values will even out over time * (ie. no double counting). */ - public void printResults(PrintStream stream, String prefix); + void printResults(PrintStream stream, String prefix); - public void printSummaryHeader(PrintStream stream); + void printSummaryHeader(PrintStream stream); - public void printSummary(PrintStream stream, String prefix); + void printSummary(PrintStream stream, String prefix); } diff --git a/benchmarks/src/com/aerospike/benchmarks/LatencyManagerYcsb.java b/benchmarks/src/com/aerospike/benchmarks/LatencyManagerYcsb.java index 50498bf82..351abad9a 100644 --- a/benchmarks/src/com/aerospike/benchmarks/LatencyManagerYcsb.java +++ b/benchmarks/src/com/aerospike/benchmarks/LatencyManagerYcsb.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. @@ -25,21 +25,21 @@ public class LatencyManagerYcsb implements LatencyManager { public static final String BUCKETS = "histogram.buckets"; public static final String BUCKETS_DEFAULT = "1000"; - private AtomicInteger _buckets; - private AtomicLongArray histogram; - private AtomicLong histogramoverflow; - private AtomicInteger operations; - private AtomicLong totallatency; - private AtomicInteger warmupCount; + private final AtomicInteger _buckets; + private final AtomicLongArray histogram; + private final AtomicLong histogramoverflow; + private final AtomicInteger operations; + private final AtomicLong totallatency; + private final AtomicInteger warmupCount; private volatile boolean warmupComplete = false; //keep a windowed version of these stats for printing status - private AtomicInteger windowoperations; - private AtomicLong windowtotallatency; + private final AtomicInteger windowoperations; + private final AtomicLong windowtotallatency; - private AtomicLong min; - private AtomicLong max; - private String name; + private final AtomicLong min; + private final AtomicLong max; + private final String name; public LatencyManagerYcsb(String name, int warmupCount) { this.name = name; @@ -125,7 +125,7 @@ public void printResults(PrintStream exporter, String prefix) { } } buffer.append(']'); - exporter.println(buffer.toString()); + exporter.println(buffer); windowoperations.set(0); windowtotallatency.set(0); } diff --git a/benchmarks/src/com/aerospike/benchmarks/Main.java b/benchmarks/src/com/aerospike/benchmarks/Main.java index 5ee9c00ea..1107393fc 100644 --- a/benchmarks/src/com/aerospike/benchmarks/Main.java +++ b/benchmarks/src/com/aerospike/benchmarks/Main.java @@ -96,8 +96,8 @@ public static void main(String[] args) { } } - private Arguments args = new Arguments(); - private Host[] hosts; + private final Arguments args = new Arguments(); + private final Host[] hosts; private EventLoopType eventLoopType = EventLoopType.DIRECT_NIO; private int port = 3000; private long nKeys; @@ -112,8 +112,8 @@ public static void main(String[] args) { private String filepath; private EventLoops eventLoops; - private ClientPolicy clientPolicy = new ClientPolicy(); - private CounterStore counters = new CounterStore(); + private final ClientPolicy clientPolicy = new ClientPolicy(); + private final CounterStore counters = new CounterStore(); public Main(String[] commandLineArgs) throws Exception { boolean hasTxns = false; @@ -1118,25 +1118,25 @@ else if (! level.equals("all")) { System.out.print("bin[" + binCount + "]: "); switch (spec.type) { - case INTEGER: - System.out.println("integer"); - break; + case INTEGER: + System.out.println("integer"); + break; - case STRING: - System.out.println("string[" + spec.size + "]"); - break; + case STRING: + System.out.println("string[" + spec.size + "]"); + break; - case BYTES: - System.out.println("byte[" + spec.size + "]"); - break; + case BYTES: + System.out.println("byte[" + spec.size + "]"); + break; - case RANDOM: - System.out.println("random[" + (spec.size * 8) + "]"); - break; + case RANDOM: + System.out.println("random[" + (spec.size * 8) + "]"); + break; - case TIMESTAMP: - System.out.println("timestamp"); - break; + case TIMESTAMP: + System.out.println("timestamp"); + break; } binCount++; } @@ -1161,7 +1161,7 @@ private static void logUsage(Options options) { String syntax = Main.class.getName() + " []"; formatter.printHelp(pw, 100, syntax, "options:", options, 0, 2, null); - System.out.println(sw.toString()); + System.out.println(sw); } private static String getLatencyUsage(String latencyString) { diff --git a/benchmarks/src/com/aerospike/benchmarks/RWTask.java b/benchmarks/src/com/aerospike/benchmarks/RWTask.java index c4e592976..3cbd59550 100644 --- a/benchmarks/src/com/aerospike/benchmarks/RWTask.java +++ b/benchmarks/src/com/aerospike/benchmarks/RWTask.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. @@ -59,33 +59,33 @@ public void stop() { protected void runCommand(RandomShift random) { try { switch (args.workload) { - case READ_UPDATE: - case READ_REPLACE: - readUpdate(random); - break; + case READ_UPDATE: + case READ_REPLACE: + readUpdate(random); + break; - case READ_MODIFY_UPDATE: - readModifyUpdate(random); - break; + case READ_MODIFY_UPDATE: + readModifyUpdate(random); + break; - case READ_MODIFY_INCREMENT: - readModifyIncrement(random); - break; + case READ_MODIFY_INCREMENT: + readModifyIncrement(random); + break; - case READ_MODIFY_DECREMENT: - readModifyDecrement(random); - break; + case READ_MODIFY_DECREMENT: + readModifyDecrement(random); + break; - case READ_FROM_FILE: - readFromFile(random); - break; + case READ_FROM_FILE: + readFromFile(random); + break; - case TRANSACTION: - runTransaction(random); - break; + case TRANSACTION: + runTransaction(random); + break; - default: - break; + default: + break; } } catch (Exception e) { @@ -93,7 +93,7 @@ protected void runCommand(RandomShift random) { e.printStackTrace(); } else { - System.out.println("Exception - " + e.toString()); + System.out.println("Exception - " + e); } } } diff --git a/benchmarks/src/com/aerospike/benchmarks/RWTaskSync.java b/benchmarks/src/com/aerospike/benchmarks/RWTaskSync.java index ba573bdcd..b59ae553b 100644 --- a/benchmarks/src/com/aerospike/benchmarks/RWTaskSync.java +++ b/benchmarks/src/com/aerospike/benchmarks/RWTaskSync.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. @@ -75,7 +75,7 @@ protected void put(WritePolicy writePolicy, Key key, Bin[] bins) { counters.write.count.getAndIncrement(); return; } - + if (counters.write.latency != null) { long begin = System.nanoTime(); client.put(writePolicy, key, bins); @@ -95,7 +95,7 @@ protected void add(Key key, Bin[] bins) { counters.write.count.getAndIncrement(); return; } - + if (counters.write.latency != null) { long begin = System.nanoTime(); client.add(writePolicyGeneration, key, bins); @@ -115,7 +115,7 @@ protected void get(Key key, String binName) { processRead(key, new Object()); return; } - + Record record; if (counters.read.latency != null) { @@ -136,7 +136,7 @@ protected void get(Key key) { processRead(key, new Object()); return; } - + Record record; if (counters.read.latency != null) { @@ -157,12 +157,12 @@ protected void get(Key key, String udfPackageName, String udfFunctionName, Value processRead(key, new Object()); return; } - + Object udfReturnObj; if (counters.read.latency != null) { long begin = System.nanoTime(); - + udfReturnObj = client.execute(args.writePolicy, key, udfPackageName, udfFunctionName, udfValues); long elapsed = System.nanoTime() - begin; counters.read.latency.add(elapsed); @@ -178,7 +178,7 @@ protected void get(Key[] keys, String binName) { if (args.partitionIds != null) { keys = getFilteredKeys(keys); } - + Record[] records; if (counters.read.latency != null) { @@ -202,7 +202,7 @@ protected void get(Key[] keys) { if (args.partitionIds != null) { keys = getFilteredKeys(keys); } - + Record[] records; if (counters.read.latency != null) { @@ -220,23 +220,20 @@ protected void get(Key[] keys) { } processBatchRead(); } - + private boolean skipKey(Key key) { - if (args.partitionIds != null && !args.partitionIds.contains(Partition.getPartitionId(key.digest))) { - return true; - } - return false; - } - + return args.partitionIds != null && !args.partitionIds.contains(Partition.getPartitionId(key.digest)); + } + private Key[] getFilteredKeys(Key[] keys) { List filteredKeys = new ArrayList<>(); - + for (Key key : keys) { if (! skipKey(key)) { filteredKeys.add(key); } } - + return filteredKeys.toArray(new Key[0]); } } diff --git a/benchmarks/src/com/aerospike/benchmarks/TransactionalItem.java b/benchmarks/src/com/aerospike/benchmarks/TransactionalItem.java index 1bce61121..d29c48c65 100644 --- a/benchmarks/src/com/aerospike/benchmarks/TransactionalItem.java +++ b/benchmarks/src/com/aerospike/benchmarks/TransactionalItem.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. @@ -17,8 +17,9 @@ package com.aerospike.benchmarks; public class TransactionalItem { - private TransactionalType type; - private int repetitions; + private final TransactionalType type; + private final int repetitions; + public TransactionalItem(TransactionalType type, int repetitions) { super(); this.type = type; diff --git a/benchmarks/src/com/aerospike/benchmarks/TransactionalType.java b/benchmarks/src/com/aerospike/benchmarks/TransactionalType.java index 81e3545f6..0c74b4935 100644 --- a/benchmarks/src/com/aerospike/benchmarks/TransactionalType.java +++ b/benchmarks/src/com/aerospike/benchmarks/TransactionalType.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. @@ -29,14 +29,16 @@ public enum TransactionalType { MULTI_BIN_REPLACE('P', false), MULTI_BIN_WRITE('W', false); - private char code; - private boolean read; - private boolean batch; + private final char code; + private final boolean read; + private final boolean batch; + private TransactionalType(char code, boolean isRead, boolean isBatch) { this.code = code; this.read = isRead; this.batch = isBatch; } + private TransactionalType(char code, boolean isRead) { this(code, isRead, false); } diff --git a/benchmarks/src/com/aerospike/benchmarks/TransactionalWorkload.java b/benchmarks/src/com/aerospike/benchmarks/TransactionalWorkload.java index b54287307..c8912678e 100644 --- a/benchmarks/src/com/aerospike/benchmarks/TransactionalWorkload.java +++ b/benchmarks/src/com/aerospike/benchmarks/TransactionalWorkload.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. @@ -32,7 +32,7 @@ public class TransactionalWorkload implements Iterable{ private enum VariationType { PLUS, MINUS - }; + } // These options are derived and should not be set private int minReads; @@ -166,7 +166,7 @@ else if (varianceStr.matches("^\\d+$")) { private class WorkloadIterator implements Iterator { private int reads = 0; private int writes = 0; - private RandomShift random; + private final RandomShift random; private int fixedSequenceIndex = 0; public WorkloadIterator(RandomShift random) { diff --git a/benchmarks/src/com/aerospike/benchmarks/Workload.java b/benchmarks/src/com/aerospike/benchmarks/Workload.java index 8c049cb59..350c2c137 100644 --- a/benchmarks/src/com/aerospike/benchmarks/Workload.java +++ b/benchmarks/src/com/aerospike/benchmarks/Workload.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. @@ -58,5 +58,5 @@ public enum Workload { /** * Form business transactions */ - TRANSACTION; + TRANSACTION } From d5edebcf5f9e3bdb53f52c7098cc63fd8f1a1213 Mon Sep 17 00:00:00 2001 From: John Griffin Date: Mon, 15 Apr 2024 11:20:45 -0400 Subject: [PATCH 06/18] Propagate the original LuaC compile() exception details in AerospikeExceptions thrown by LuaCache. (#316) Co-authored-by: griffinjm --- client/src/com/aerospike/client/lua/LuaCache.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/com/aerospike/client/lua/LuaCache.java b/client/src/com/aerospike/client/lua/LuaCache.java index 51e080f5f..499fcf40c 100644 --- a/client/src/com/aerospike/client/lua/LuaCache.java +++ b/client/src/com/aerospike/client/lua/LuaCache.java @@ -63,7 +63,7 @@ public static final Prototype loadPackageFromFile(String packageName) { Packages.put(packageName, prototype); } catch (Throwable e) { - throw new AerospikeException("Failed to read file: " + source.getAbsolutePath()); + throw new AerospikeException("Failed to read file: " + source.getAbsolutePath(), e); } } return prototype; @@ -81,7 +81,7 @@ public static final Prototype loadPackageFromResource(ClassLoader resourceLoader Packages.put(packageName, prototype); } catch (Throwable e) { - throw new AerospikeException("Failed to read resource: " + resourcePath); + throw new AerospikeException("Failed to read resource: " + resourcePath, e); } } return prototype; @@ -94,7 +94,7 @@ private static Prototype compile(String packageName, InputStream is) { return LuaC.instance.compile(bis, packageName); } catch (Throwable e) { - throw new AerospikeException("Failed to compile: " + packageName); + throw new AerospikeException("Failed to compile: " + packageName, e); } } From e0dc58b1321020ddbdfd90ab36be5793893795ef Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Thu, 25 Apr 2024 18:37:46 -0400 Subject: [PATCH 07/18] CLIENT-2902 Only validate error code instead of entire error string in createDrop() index test. --- client/src/com/aerospike/client/Info.java | 43 ++++++++++++++++++- .../aerospike/test/sync/query/TestIndex.java | 5 ++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/client/src/com/aerospike/client/Info.java b/client/src/com/aerospike/client/Info.java index 21c82f417..1bcf83198 100644 --- a/client/src/com/aerospike/client/Info.java +++ b/client/src/com/aerospike/client/Info.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. @@ -306,6 +306,47 @@ public static HashMap request(Connection conn) return info.parseMultiResponse(); } + //------------------------------------------------------- + // Parse Methods + //------------------------------------------------------- + + /** + * Parse info response string and return the result code for info commands + * that only return OK or an error string. Info commands that return other + * data are not handled by this method. + */ + public static int parseResultCode(String response) { + if (response.regionMatches(true, 0, "OK", 0, 2)) { + 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)) { + + 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; + } + catch (Throwable t) { + throw new AerospikeException("Unrecognized info response: " + response, t); + } + } + //------------------------------------------------------- // Member variables. //------------------------------------------------------- diff --git a/test/src/com/aerospike/test/sync/query/TestIndex.java b/test/src/com/aerospike/test/sync/query/TestIndex.java index 404dc484c..ca97c54ba 100644 --- a/test/src/com/aerospike/test/sync/query/TestIndex.java +++ b/test/src/com/aerospike/test/sync/query/TestIndex.java @@ -26,7 +26,6 @@ import com.aerospike.client.Value; import com.aerospike.client.cdt.CTX; import com.aerospike.client.cluster.Node; -import com.aerospike.client.policy.Policy; import com.aerospike.client.query.IndexType; import com.aerospike.client.task.IndexTask; import com.aerospike.test.sync.TestSync; @@ -62,7 +61,9 @@ public void createDrop() { for (Node node : nodes) { String response = Info.request(node, cmd); - assertEquals(response, "FAIL:201:no-index"); + int code = Info.parseResultCode(response); + + assertEquals(code, 201); } } From c136578b588e9c57b46f7d2ad5e728c9d8fd2a8a Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Tue, 7 May 2024 09:56:21 -0400 Subject: [PATCH 08/18] Upgrade to netty 4.1.108.Final and commons-cli 1.7.0 per snyk. --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b072d70ea..e2fa560b1 100644 --- a/pom.xml +++ b/pom.xml @@ -39,12 +39,12 @@ 2.18.1 3.2.0 - 4.1.107.Final + 4.1.108.Final 2.0.62.Final 1.59.0 3.0.1 0.4 - 1.6.0 + 1.7.0 4.13.1 From 1f8ffa948817e5e91f2f4a613ba2fdb7c87e8d93 Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Tue, 7 May 2024 10:04:03 -0400 Subject: [PATCH 09/18] Update version 8.1.1 --- 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 717bd8d1a..c85ef456c 100644 --- a/benchmarks/pom.xml +++ b/benchmarks/pom.xml @@ -6,7 +6,7 @@ com.aerospike aerospike-parent - 8.1.0 + 8.1.1 aerospike-benchmarks jar diff --git a/client/pom.xml b/client/pom.xml index 1d097a072..675aabef8 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -6,7 +6,7 @@ com.aerospike aerospike-parent - 8.1.0 + 8.1.1 aerospike-client-jdk8 jar diff --git a/examples/pom.xml b/examples/pom.xml index 4d1c03e63..ad3807c82 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -6,7 +6,7 @@ com.aerospike aerospike-parent - 8.1.0 + 8.1.1 aerospike-examples jar diff --git a/pom.xml b/pom.xml index e2fa560b1..6c462c20b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.aerospike aerospike-parent aerospike-parent - 8.1.0 + 8.1.1 pom https://github.com/aerospike/aerospike-client-java diff --git a/proxy/pom.xml b/proxy/pom.xml index 9155a1832..84c64ea2d 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -6,7 +6,7 @@ com.aerospike aerospike-parent - 8.1.0 + 8.1.1 aerospike-proxy-client jar diff --git a/test/pom.xml b/test/pom.xml index c0c8878b0..796c09656 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -6,7 +6,7 @@ com.aerospike aerospike-parent - 8.1.0 + 8.1.1 aerospike-client-test jar From 5081d4781902be71bf2fce8b91d3a10251f1a99b Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Wed, 8 May 2024 15:43:16 -0400 Subject: [PATCH 10/18] Update copyright year in Crypto.java. --- client/src/com/aerospike/client/util/Crypto.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/com/aerospike/client/util/Crypto.java b/client/src/com/aerospike/client/util/Crypto.java index 22037c7c3..63ca13556 100644 --- a/client/src/com/aerospike/client/util/Crypto.java +++ b/client/src/com/aerospike/client/util/Crypto.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. From 155391ed1924464621d878248a3711ae4de9fb09 Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Mon, 13 May 2024 17:37:26 -0400 Subject: [PATCH 11/18] 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 0e573594c..e1506f481 100644 --- a/client/src/com/aerospike/client/command/Command.java +++ b/client/src/com/aerospike/client/command/Command.java @@ -242,7 +242,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); @@ -250,45 +260,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) { @@ -852,7 +844,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 7274c0f5f..889e1c502 100644 --- a/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java +++ b/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java @@ -1335,7 +1335,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(); } @@ -1363,7 +1365,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 3657d7987eaeda7238231ffb0230f1514786c4f0 Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Tue, 21 May 2024 14:07:00 -0400 Subject: [PATCH 12/18] CLIENT-2962 Remove unnecessary imports. --- client/src/com/aerospike/client/async/AsyncBatch.java | 1 - client/src/com/aerospike/client/cluster/Connection.java | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) 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 1a420177f..0ed06c28a 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; From b9831bf42b126a3d9f2466e18dac613041062e16 Mon Sep 17 00:00:00 2001 From: Brian Nichols Date: Tue, 28 May 2024 17:48:32 -0400 Subject: [PATCH 13/18] 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 675aabef8..1e190aac2 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -125,6 +125,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 d604732c393d62867e6b10a8bb8594b56081e44d Mon Sep 17 00:00:00 2001
From: Brian Nichols 
Date: Wed, 29 May 2024 18:29:00 -0400
Subject: [PATCH 14/18] 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 e1506f481..7ae5e92d1 100644
--- a/client/src/com/aerospike/client/command/Command.java
+++ b/client/src/com/aerospike/client/command/Command.java
@@ -1329,9 +1329,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);
@@ -1581,7 +1580,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 fddac7e768c1bf0442313426eb1ed4597486501d Mon Sep 17 00:00:00 2001
From: Brian Nichols 
Date: Thu, 30 May 2024 15:20:28 -0400
Subject: [PATCH 15/18] 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 1bcf83198..42f88f822 100644
--- a/client/src/com/aerospike/client/Info.java
+++ b/client/src/com/aerospike/client/Info.java
@@ -320,30 +320,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);
 		}
 	}
 
@@ -861,4 +846,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 524b74aeaedb217928ee6f68136674c8b0199ce8 Mon Sep 17 00:00:00 2001
From: Brian Nichols 
Date: Fri, 14 Jun 2024 11:55:11 -0400
Subject: [PATCH 16/18] 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 df263d2f26df92e65360622b4d900188bf0283d2 Mon Sep 17 00:00:00 2001
From: Brian Nichols 
Date: Mon, 24 Jun 2024 16:05:50 -0400
Subject: [PATCH 17/18] 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 6c462c20b..abc91397d 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 97a654f5cd0d9b1688f195ec49ddf94632b5e469 Mon Sep 17 00:00:00 2001
From: Brian Nichols 
Date: Tue, 25 Jun 2024 12:37:57 -0400
Subject: [PATCH 18/18] 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 c85ef456c..8a6be85fb 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 1e190aac2..cef2d4ecd 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-jdk8
   jar
diff --git a/examples/pom.xml b/examples/pom.xml
index ad3807c82..b0ca631da 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 abc91397d..416961f65 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 84c64ea2d..8d980ca2c 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 796c09656..48de52c7b 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