diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml index 717bd8d1a..8a6be85fb 100644 --- a/benchmarks/pom.xml +++ b/benchmarks/pom.xml @@ -6,7 +6,7 @@ com.aerospike aerospike-parent - 8.1.0 + 8.1.2 aerospike-benchmarks jar 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 eacf50df1..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; @@ -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 @@ -1100,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++; } @@ -1143,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 } diff --git a/client/pom.xml b/client/pom.xml index 1d097a072..cef2d4ecd 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -6,7 +6,7 @@ com.aerospike aerospike-parent - 8.1.0 + 8.1.2 aerospike-client-jdk8 jar @@ -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/AerospikeClient.java b/client/src/com/aerospike/client/AerospikeClient.java index 6f5bfe7ae..df7c8dbd2 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); } //------------------------------------------------------- @@ -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 //------------------------------------------------------- @@ -1686,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 { @@ -1702,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); @@ -1744,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); @@ -1759,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); @@ -1796,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()]; @@ -1809,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); @@ -2228,13 +2337,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( @@ -2245,13 +2350,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); @@ -2261,13 +2362,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; } @@ -2345,13 +2442,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); @@ -2361,13 +2454,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; } @@ -2375,13 +2464,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; @@ -2460,13 +2545,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( @@ -2477,13 +2558,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; @@ -2492,13 +2569,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; @@ -4397,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/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/Info.java b/client/src/com/aerospike/client/Info.java index 21c82f417..42f88f822 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,32 @@ 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; + } + + Info.Error error = new Info.Error(response); + + if (error.code >= 0) { + // Server errors return error code. + return error.code; + } + else { + // Client errors result in a exception. + throw new AerospikeException(error.code, "Unrecognized info response: " + response); + } + } + //------------------------------------------------------- // Member variables. //------------------------------------------------------- @@ -820,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/async/AsyncBatch.java b/client/src/com/aerospike/client/async/AsyncBatch.java index abd386dde..22d4fecf6 100644 --- a/client/src/com/aerospike/client/async/AsyncBatch.java +++ b/client/src/com/aerospike/client/async/AsyncBatch.java @@ -16,9 +16,9 @@ */ package com.aerospike.client.async; -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 +62,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 +117,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 +411,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 +500,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/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; 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..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); @@ -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 876e687fe..7ae5e92d1 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; @@ -239,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); @@ -247,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) { @@ -743,12 +738,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; @@ -836,7 +844,13 @@ public final void setBatchOperate(BatchPolicy policy, KeyIter iter) } 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); @@ -851,13 +865,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 +875,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 +887,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; } @@ -1327,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); @@ -1387,6 +1388,7 @@ public final void setScan( // Query //-------------------------------------------------- + @SuppressWarnings("deprecation") public final void setQuery( Cluster cluster, Policy policy, @@ -1578,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); } 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); } } 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
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
 }
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/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/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.
diff --git a/examples/pom.xml b/examples/pom.xml
index 4d1c03e63..b0ca631da 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -6,7 +6,7 @@
   
     com.aerospike
     aerospike-parent
-    8.1.0
+    8.1.2
   
   aerospike-examples
   jar
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/pom.xml b/pom.xml
index b072d70ea..416961f65 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   com.aerospike
   aerospike-parent
   aerospike-parent
-  8.1.0
+  8.1.2
   pom
   https://github.com/aerospike/aerospike-client-java
 
@@ -39,12 +39,12 @@
     2.18.1
     3.2.0
 
-    4.1.107.Final
+    4.1.110.Final
     2.0.62.Final
     1.59.0
     3.0.1
     0.4
-    1.6.0
+    1.8.0
     4.13.1
   
 
diff --git a/proxy/pom.xml b/proxy/pom.xml
index 9155a1832..8d980ca2c 100644
--- a/proxy/pom.xml
+++ b/proxy/pom.xml
@@ -6,7 +6,7 @@
   
     com.aerospike
     aerospike-parent
-    8.1.0
+    8.1.2
   
   aerospike-proxy-client
   jar
diff --git a/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java b/proxy/src/com/aerospike/client/proxy/AerospikeClientProxy.java
index 32305f660..889e1c502 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
 	//-------------------------------------------------------
@@ -1235,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();
 	}
 
@@ -1263,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();
 	}
 
@@ -1521,7 +1625,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();
 	}
 
@@ -1556,7 +1660,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
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) {
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();
diff --git a/test/pom.xml b/test/pom.xml
index c0c8878b0..48de52c7b 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -6,7 +6,7 @@
   
     com.aerospike
     aerospike-parent
-    8.1.0
+    8.1.2
   
   aerospike-client-test
   jar
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/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");
+	}
 }
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);
 		}
 	}
 
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();
+		}
+	}
 }