public BatchCommand(Executor parent, BatchNode batch, BatchPolicy policy) : base(batch.node, false) { this.parent = parent; this.batch = batch; this.policy = policy; }
public AsyncBatchCommand(AsyncBatchExecutor parent, AsyncCluster cluster, BatchNode batch, BatchPolicy batchPolicy) : base(parent, cluster, batchPolicy, (AsyncNode)batch.node) { this.parent = parent; this.batch = batch; this.batchPolicy = batchPolicy; }
public static void Main(string[] args) { var client = Connect(); var policy = new Policy(); var writePolicy = new WritePolicy(); var batchPolicy = new BatchPolicy(); //NOTE: adjust the timeout value depending on your demo machine writePolicy.timeout = 1000; var key = new Key("test", "myset", "mykey"); WriteSingleValue(client, writePolicy, key); CheckKeyExists(client, policy, key); AddSingleValue(client, writePolicy); WriteMultipleValues(client, writePolicy, key); WriteValueWithTtl(client); ReadAllValuesForKey(client, policy, key); ReadSomeValuesForKey(client, policy, key); DeleteValue(client, writePolicy, key); DeleteRecord(client, writePolicy, key); AddRecords(client, writePolicy); BatchReadRecords(client, batchPolicy); MultiOps(client, writePolicy, key); client.Close(); }
public AsyncBatchExistsArrayExecutor ( AsyncCluster cluster, BatchPolicy policy, Key[] keys, ExistsArrayListener listener ) { this.keys = keys; this.existsArray = new bool[keys.Length]; this.listener = listener; // Create commands. List <BatchNode> batchNodes = BatchNode.GenerateList(cluster, policy, keys); AsyncBatchCommand[] commands = new AsyncBatchCommand[batchNodes.Count]; int count = 0; foreach (BatchNode batchNode in batchNodes) { commands[count++] = new AsyncBatchExistsArrayCommand(this, cluster, batchNode, policy, keys, existsArray); } // Dispatch commands to nodes. Execute(commands); }
public AsyncBatchReadListExecutor ( AsyncCluster cluster, BatchPolicy policy, BatchListListener listener, List <BatchRead> records ) { this.listener = listener; this.records = records; // Create commands. List <BatchNode> batchNodes = BatchNode.GenerateList(cluster, policy, records); AsyncMultiCommand[] tasks = new AsyncMultiCommand[batchNodes.Count]; int count = 0; foreach (BatchNode batchNode in batchNodes) { if (!batchNode.node.hasBatchIndex) { throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Requested command requires a server that supports new batch index protocol."); } tasks[count++] = new AsyncBatchReadListCommand(this, cluster, batchNode, policy, records); } // Dispatch commands to nodes. Execute(tasks, policy.maxConcurrentThreads); }
public AsyncBatchExistsArrayCommand(AsyncBatchExistsArrayCommand other) : base(other) { this.batch = other.batch; this.batchPolicy = other.batchPolicy; this.keys = other.keys; this.existsArray = other.existsArray; }
public BatchCommand(Cluster cluster, Executor parent, BatchNode batch, BatchPolicy batchPolicy) : base(cluster, batchPolicy, batch.node, false) { this.parent = parent; this.batch = batch; this.batchPolicy = batchPolicy; }
public AsyncBatchExistsSequenceExecutor ( AsyncCluster cluster, BatchPolicy policy, Key[] keys, ExistsSequenceListener listener ) : base(cluster, policy, keys) { this.listener = listener; // Create commands. AsyncMultiCommand[] tasks = new AsyncMultiCommand[base.taskSize]; int count = 0; foreach (BatchNode batchNode in batchNodes) { if (batchNode.node.UseNewBatch(policy)) { // New batch tasks[count++] = new AsyncBatchExistsSequenceCommand(this, cluster, batchNode, policy, keys, listener); } else { // Old batch only allows one namespace per call. foreach (BatchNode.BatchNamespace batchNamespace in batchNode.batchNamespaces) { tasks[count++] = new AsyncBatchExistsSequenceDirect(this, cluster, (AsyncNode)batchNode.node, batchNamespace, policy, keys, listener); } } } // Dispatch commands to nodes. Execute(tasks, policy.maxConcurrentThreads); }
public AsyncBatchGetSequenceExecutor ( AsyncCluster cluster, BatchPolicy policy, RecordSequenceListener listener, Key[] keys, string[] binNames, int readAttr ) { this.listener = listener; // Create commands. List <BatchNode> batchNodes = BatchNode.GenerateList(cluster, policy, keys); AsyncBatchCommand[] commands = new AsyncBatchCommand[batchNodes.Count]; int count = 0; foreach (BatchNode batchNode in batchNodes) { commands[count++] = new AsyncBatchGetSequenceCommand(this, cluster, batchNode, policy, keys, binNames, listener, readAttr); } // Dispatch commands to nodes. Execute(commands); }
public static List <BatchNode> GenerateList(Cluster cluster, BatchPolicy policy, Key[] keys) { Node[] nodes = cluster.Nodes; if (nodes.Length == 0) { throw new AerospikeException(ResultCode.SERVER_NOT_AVAILABLE, "Command failed because cluster is empty."); } int nodeCount = nodes.Length; int keysPerNode = keys.Length / nodeCount + 10; // Split keys by server node. List <BatchNode> batchNodes = new List <BatchNode>(nodeCount + 1); for (int i = 0; i < keys.Length; i++) { Key key = keys[i]; Partition partition = new Partition(key); BatchNode batchNode; Node node = cluster.GetReadNode(partition, policy.replica); batchNode = FindBatchNode(batchNodes, node); if (batchNode == null) { batchNodes.Add(new BatchNode(node, keysPerNode, key.ns, i)); } else { batchNode.AddKey(key.ns, i); } } return(batchNodes); }
/// <summary> /// Copy client policy from another client policy. /// </summary> public ClientPolicy(ClientPolicy other) { this.user = other.user; this.password = other.password; this.clusterName = other.clusterName; this.authMode = other.authMode; this.timeout = other.timeout; this.loginTimeout = other.loginTimeout; this.maxConnsPerNode = other.maxConnsPerNode; this.connPoolsPerNode = other.connPoolsPerNode; this.maxSocketIdle = other.maxSocketIdle; this.tendInterval = other.tendInterval; this.failIfNotConnected = other.failIfNotConnected; this.readPolicyDefault = new Policy(other.readPolicyDefault); this.writePolicyDefault = new WritePolicy(other.writePolicyDefault); this.scanPolicyDefault = new ScanPolicy(other.scanPolicyDefault); this.queryPolicyDefault = new QueryPolicy(other.queryPolicyDefault); this.batchPolicyDefault = new BatchPolicy(other.batchPolicyDefault); this.infoPolicyDefault = new InfoPolicy(other.infoPolicyDefault); this.tlsPolicy = (other.tlsPolicy != null) ? new TlsPolicy(other.tlsPolicy) : null; this.ipMap = other.ipMap; this.useServicesAlternate = other.useServicesAlternate; this.rackAware = other.rackAware; this.rackId = other.rackId; }
public AsyncBatchExistsSequenceCommand(AsyncBatchExistsSequenceCommand other) : base(other) { this.batch = other.batch; this.batchPolicy = other.batchPolicy; this.keys = other.keys; this.listener = other.listener; }
public BatchReadListCommand(BatchNode batch, BatchPolicy policy, List <BatchRead> records) : base(batch.node, false) { this.batch = batch; this.policy = policy; this.records = records; }
public AsyncBatchCommand(AsyncBatchCommand other) : base(other) { this.batch = other.batch; this.batchPolicy = other.batchPolicy; this.sequenceAP = other.sequenceAP; this.sequenceSC = other.sequenceSC; }
public AsyncBatchExistsArrayExecutor( AsyncCluster cluster, BatchPolicy policy, Key[] keys, ExistsArrayListener listener ) : base(cluster, policy, keys) { this.existsArray = new bool[keys.Length]; this.listener = listener; // Create commands. AsyncMultiCommand[] tasks = new AsyncMultiCommand[base.taskSize]; int count = 0; foreach (BatchNode batchNode in batchNodes) { if (batchNode.node.UseNewBatch(policy)) { // New batch tasks[count++] = new AsyncBatchExistsArrayCommand(this, cluster, batchNode, policy, keys, existsArray); } else { // Old batch only allows one namespace per call. foreach (BatchNode.BatchNamespace batchNamespace in batchNode.batchNamespaces) { tasks[count++] = new AsyncBatchExistsArrayDirect(this, cluster, (AsyncNode)batchNode.node, batchNamespace, policy, keys, existsArray); } } } // Dispatch commands to nodes. Execute(tasks, policy.maxConcurrentThreads); }
public AsyncBatchExecutor(AsyncCluster cluster, BatchPolicy policy, Key[] keys, bool stopOnFailure) : base(cluster, stopOnFailure) { this.keys = keys; this.batchNodes = BatchNode.GenerateList(cluster, policy, keys); this.taskSize = batchNodes.Count; }
public AsyncBatchReadSequenceCommand(AsyncBatchReadSequenceCommand other) : base(other) { this.batch = other.batch; this.batchPolicy = other.batchPolicy; this.listener = other.listener; this.records = other.records; }
public AsyncBatchExistsArrayExecutor ( AsyncCluster cluster, BatchPolicy policy, Key[] keys, ExistsArrayListener listener ) : base(cluster, policy, keys) { this.existsArray = new bool[keys.Length]; this.listener = listener; // Create commands. AsyncMultiCommand[] tasks = new AsyncMultiCommand[base.taskSize]; int count = 0; foreach (BatchNode batchNode in batchNodes) { if (batchNode.node.UseNewBatch(policy)) { // New batch tasks[count++] = new AsyncBatchExistsArrayCommand(this, cluster, batchNode, policy, keys, existsArray); } else { // Old batch only allows one namespace per call. foreach (BatchNode.BatchNamespace batchNamespace in batchNode.batchNamespaces) { tasks[count++] = new AsyncBatchExistsArrayDirect(this, cluster, (AsyncNode)batchNode.node, batchNamespace, policy, keys, existsArray); } } } // Dispatch commands to nodes. Execute(tasks, 0); }
public BatchReadListCommand(Executor parent, BatchNode batch, BatchPolicy policy, List <BatchRead> records) : base(false) { this.parent = parent; this.batch = batch; this.policy = policy; this.records = records; }
public AsyncBatchGetSequenceCommand(AsyncBatchGetSequenceCommand other) : base(other) { this.batch = other.batch; this.batchPolicy = other.batchPolicy; this.keys = other.keys; this.binNames = other.binNames; this.listener = other.listener; this.readAttr = other.readAttr; }
public AsyncBatchGetArrayCommand(AsyncBatchGetArrayCommand other) : base(other) { this.batch = other.batch; this.batchPolicy = other.batchPolicy; this.keys = other.keys; this.binNames = other.binNames; this.records = other.records; this.readAttr = other.readAttr; }
public AsyncBatchReadListCommand ( AsyncMultiExecutor parent, AsyncCluster cluster, BatchNode batch, BatchPolicy batchPolicy, List <BatchRead> records ) : base(parent, cluster, batch, batchPolicy) { this.records = records; }
public BatchReadListCommand ( Cluster cluster, Executor parent, BatchNode batch, BatchPolicy policy, List <BatchRead> records ) : base(cluster, parent, batch, policy) { this.records = records; }
private static void BatchReadRecords(AerospikeClient client, BatchPolicy batchPolicy) { Console.WriteLine("Batch Reads"); const int size = 1024; var keys = new Key[size]; for (var i = 0; i < keys.Length; i++) { keys[i] = new Key("test", "myset", (i + 1)); } var records = client.Get(batchPolicy, keys); Console.WriteLine("Read " + records.Length + " records"); }
public BatchExistsArrayCommand ( Executor parent, BatchNode batch, BatchPolicy policy, Key[] keys, bool[] existsArray ) : base(parent, batch, policy) { this.keys = keys; this.existsArray = existsArray; }
public static List <BatchNode> GenerateList ( Cluster cluster, BatchPolicy policy, Key[] keys, uint sequenceAP, uint sequenceSC, BatchNode batchSeed ) { Node[] nodes = cluster.Nodes; if (nodes.Length == 0) { throw new AerospikeException(ResultCode.SERVER_NOT_AVAILABLE, "Command failed because cluster is empty."); } // Create initial key capacity for each node as average + 25%. int keysPerNode = batchSeed.offsetsSize / nodes.Length; keysPerNode += (int)((uint)keysPerNode >> 2); // The minimum key capacity is 10. if (keysPerNode < 10) { keysPerNode = 10; } Replica replica = policy.replica; Replica replicaSC = Partition.GetReplicaSC(policy); // Split keys by server node. List <BatchNode> batchNodes = new List <BatchNode>(nodes.Length); for (int i = 0; i < batchSeed.offsetsSize; i++) { int offset = batchSeed.offsets[i]; Node node = Partition.GetNodeBatchRead(cluster, keys[offset], replica, replicaSC, sequenceAP, sequenceSC); BatchNode batchNode = FindBatchNode(batchNodes, node); if (batchNode == null) { batchNodes.Add(new BatchNode(node, keysPerNode, offset)); } else { batchNode.AddKey(offset); } } return(batchNodes); }
public AsyncBatchExistsSequenceCommand ( AsyncMultiExecutor parent, AsyncCluster cluster, BatchNode batch, BatchPolicy batchPolicy, Key[] keys, ExistsSequenceListener listener ) : base(parent, cluster, batch, batchPolicy) { this.keys = keys; this.listener = listener; }
public AsyncBatchExistsArrayCommand ( AsyncMultiExecutor parent, AsyncCluster cluster, BatchNode batch, BatchPolicy batchPolicy, Key[] keys, bool[] existsArray ) : base(parent, cluster, batch, batchPolicy) { this.keys = keys; this.existsArray = existsArray; }
public AsyncBatchReadSequenceCommand ( AsyncMultiExecutor parent, AsyncCluster cluster, BatchNode batch, BatchPolicy batchPolicy, BatchSequenceListener listener, List <BatchRead> records ) : base(parent, cluster, batch, batchPolicy) { this.listener = listener; this.records = records; }
public BatchExistsArrayCommand( BatchNode batch, BatchPolicy policy, Key[] keys, bool[] existsArray ) : base(batch.node, false) { this.batch = batch; this.policy = policy; this.keys = keys; this.existsArray = existsArray; }
private static void ExecuteNode(Cluster cluster, BatchNode batchNode, BatchPolicy policy, Key[] keys, bool[] existsArray, Record[] records, string[] binNames, int readAttr) { if (records != null) { MultiCommand command = new BatchGetArrayCommand(cluster, null, batchNode, policy, keys, binNames, records, readAttr); command.Execute(); } else { MultiCommand command = new BatchExistsArrayCommand(cluster, null, batchNode, policy, keys, existsArray); command.Execute(); } }
public BatchExistsArrayCommand ( BatchNode batch, BatchPolicy policy, Key[] keys, bool[] existsArray ) : base(batch.node, false) { this.batch = batch; this.policy = policy; this.keys = keys; this.existsArray = existsArray; }
public AsyncBatchReadListCommand ( AsyncMultiExecutor parent, AsyncCluster cluster, BatchNode batch, BatchPolicy policy, List <BatchRead> records ) : base(parent, cluster, (AsyncNode)batch.node, false) { this.batch = batch; this.policy = policy; this.records = records; }
public AsyncBatchExecutor(Cluster cluster, BatchPolicy policy, Key[] keys) { this.keys = keys; this.batchNodes = BatchNode.GenerateList(cluster, policy, keys); // Count number of asynchronous commands needed. int size = 0; foreach (BatchNode batchNode in batchNodes) { size += batchNode.batchNamespaces.Count; } completedSize = size; }
public static List<BatchNode> GenerateList(Cluster cluster, BatchPolicy policy, Key[] keys) { Node[] nodes = cluster.Nodes; if (nodes.Length == 0) { throw new AerospikeException(ResultCode.SERVER_NOT_AVAILABLE, "Command failed because cluster is empty."); } // Create initial key capacity for each node as average + 25%. int keysPerNode = keys.Length / nodes.Length; keysPerNode += (int)((uint)keysPerNode >> 2); // The minimum key capacity is 10. if (keysPerNode < 10) { keysPerNode = 10; } // Split keys by server node. List<BatchNode> batchNodes = new List<BatchNode>(nodes.Length); for (int i = 0; i < keys.Length; i++) { Partition partition = new Partition(keys[i]); Node node = cluster.GetReadNode(partition, policy.replica); BatchNode batchNode = FindBatchNode(batchNodes, node); if (batchNode == null) { batchNodes.Add(new BatchNode(node, keysPerNode, i)); } else { batchNode.AddKey(i); } } return batchNodes; }
/// <summary> /// Initialize large stack operator. /// </summary> /// <param name="client">client</param> /// <param name="policy">generic configuration parameters, pass in null for defaults</param> /// <param name="key">unique record identifier</param> /// <param name="binName">bin name</param> /// <param name="headBinName">Bin name for the head counter, null for default</param> public LargeStack(AerospikeClient client, WritePolicy policy, Key key, string binName, string headBinName) { this.client = client; this.policy = policy; this.key = key; this.lockKey = new Key(this.key.ns, LOCK_SET_NAME, this.key.digest); this.binName = binName; if (headBinName == null) this.headBinName = DEFAULT_HEAD_BIN_NAME; else this.headBinName = headBinName; if (this.policy == null){ this.lockPolicy = new WritePolicy(); } else { this.lockPolicy = new WritePolicy(this.policy); } if (this.policy != null) this.batchPolicy = new BatchPolicy(policy); else this.batchPolicy = new BatchPolicy(this.client.batchPolicyDefault); }
public AsyncBatchExecutor(Cluster cluster, BatchPolicy policy, Key[] keys) { this.keys = keys; this.batchNodes = BatchNode.GenerateList(cluster, policy, keys); // Count number of asynchronous commands needed. int size = 0; foreach (BatchNode batchNode in batchNodes) { if (batchNode.node.UseNewBatch(policy)) { // New batch size++; } else { // Old batch only allows one namespace per call. batchNode.SplitByNamespace(keys); size += batchNode.batchNamespaces.Count; } } this.taskSize = size; }
public static void Execute(Cluster cluster, BatchPolicy policy, Key[] keys, bool[] existsArray, Record[] records, string[] binNames, int readAttr) { if (keys.Length == 0) { return; } if (policy.allowProleReads) { // Send all requests to a single node chosen in round-robin fashion in this transaction thread. Node node = cluster.GetRandomNode(); BatchNode batchNode = new BatchNode(node, keys); ExecuteNode(batchNode, policy, keys, existsArray, records, binNames, readAttr); return; } List<BatchNode> batchNodes = BatchNode.GenerateList(cluster, policy, keys); if (policy.maxConcurrentThreads == 1 || batchNodes.Count <= 1) { // Run batch requests sequentially in same thread. foreach (BatchNode batchNode in batchNodes) { ExecuteNode(batchNode, policy, keys, existsArray, records, binNames, readAttr); } } else { // Run batch requests in parallel in separate threads. // // Multiple threads write to the record/exists array, so one might think that // volatile or memory barriers are needed on the write threads and this read thread. // This should not be necessary here because it happens in Executor which does a // volatile write (Interlocked.Increment(ref completedCount)) at the end of write threads // and a synchronized WaitTillComplete() in this thread. Executor executor = new Executor(batchNodes.Count * 2); // Initialize threads. foreach (BatchNode batchNode in batchNodes) { if (batchNode.node.UseNewBatch(policy)) { // New batch if (records != null) { MultiCommand command = new BatchGetArrayCommand(batchNode, policy, keys, binNames, records, readAttr); executor.AddCommand(command); } else { MultiCommand command = new BatchExistsArrayCommand(batchNode, policy, keys, existsArray); executor.AddCommand(command); } } else { // There may be multiple threads for a single node because the // wire protocol only allows one namespace per command. Multiple namespaces // require multiple threads per node. batchNode.SplitByNamespace(keys); foreach (BatchNode.BatchNamespace batchNamespace in batchNode.batchNamespaces) { if (records != null) { MultiCommand command = new BatchGetArrayDirect(batchNode.node, batchNamespace, policy, keys, binNames, records, readAttr); executor.AddCommand(command); } else { MultiCommand command = new BatchExistsArrayDirect(batchNode.node, batchNamespace, policy, keys, existsArray); executor.AddCommand(command); } } } } executor.Execute(policy.maxConcurrentThreads); } }
private static void ExecuteNode(BatchNode batchNode, BatchPolicy policy, Key[] keys, bool[] existsArray, Record[] records, string[] binNames, int readAttr) { if (batchNode.node.UseNewBatch(policy)) { // New batch if (records != null) { MultiCommand command = new BatchGetArrayCommand(batchNode, policy, keys, binNames, records, readAttr); command.Execute(); } else { MultiCommand command = new BatchExistsArrayCommand(batchNode, policy, keys, existsArray); command.Execute(); } } else { // Old batch only allows one namespace per call. batchNode.SplitByNamespace(keys); foreach (BatchNode.BatchNamespace batchNamespace in batchNode.batchNamespaces) { if (records != null) { MultiCommand command = new BatchGetArrayDirect(batchNode.node, batchNamespace, policy, keys, binNames, records, readAttr); command.Execute(); } else { MultiCommand command = new BatchExistsArrayDirect(batchNode.node, batchNamespace, policy, keys, existsArray); command.Execute(); } } } }
/// <summary> /// Asynchronously read multiple records for specified batch keys in one batch call. /// This method allows different namespaces/bins to be requested for each key in the batch. /// The returned records are located in the same list. /// If the BatchRecord key field is not found, the corresponding record field will be null. /// <para> /// This method schedules the get command with a channel selector and returns. /// Another thread will process the command and send the results to the listener in a single call. /// This method requires Aerospike Server version >= 3.6.0. /// </para> /// </summary> /// <param name="policy">batch configuration parameters, pass in null for defaults</param> /// <param name="listener">where to send results</param> /// <param name="records">list of unique record identifiers and the bins to retrieve.</param> /// <exception cref="AerospikeException">if read fails</exception> public void Get(BatchPolicy policy, BatchSequenceListener listener, List<BatchRead> records) { if (records.Count == 0) { listener.OnSuccess(); return; } if (policy == null) { policy = batchPolicyDefault; } new AsyncBatchReadSequenceExecutor(cluster, policy, listener, records); }
/// <summary> /// Asynchronously check if multiple record keys exist in one batch call. /// Create listener, call asynchronous array exists and return task monitor. /// <para> /// The policy can be used to specify timeouts. /// </para> /// </summary> /// <param name="policy">generic configuration parameters, pass in null for defaults</param> /// <param name="token">cancellation token</param> /// <param name="keys">array of unique record identifiers</param> /// <exception cref="AerospikeException">if queue is full</exception> public Task<bool[]> Exists(BatchPolicy policy, CancellationToken token, Key[] keys) { ExistsArrayListenerAdapter listener = new ExistsArrayListenerAdapter(token); Exists(policy, listener, keys); return listener.Task; }
public AsyncBatchGetArrayCommand( AsyncMultiExecutor parent, AsyncCluster cluster, BatchNode batch, BatchPolicy policy, Key[] keys, string[] binNames, Record[] records, int readAttr ) : base(parent, cluster, (AsyncNode)batch.node, false) { this.batch = batch; this.policy = policy; this.keys = keys; this.binNames = binNames; this.records = records; this.readAttr = readAttr; }
public AsyncBatchExistsArrayCommand( AsyncMultiExecutor parent, AsyncCluster cluster, BatchNode batch, BatchPolicy policy, Key[] keys, bool[] existsArray ) : base(parent, cluster, (AsyncNode)batch.node, false) { this.batch = batch; this.policy = policy; this.keys = keys; this.existsArray = existsArray; }
/// <summary> /// Use new batch protocol if server supports it and useBatchDirect is not set. /// </summary> public bool UseNewBatch(BatchPolicy policy) { return !policy.useBatchDirect && hasBatchIndex; }
public void SetBatchRead(BatchPolicy policy, List<BatchRead> records, BatchNode batch) { // Estimate full row size int[] offsets = batch.offsets; int max = batch.offsetsSize; BatchRead prev = null; Begin(); dataOffset += FIELD_HEADER_SIZE + 5; for (int i = 0; i < max; i++) { BatchRead record = records[offsets[i]]; Key key = record.key; string[] binNames = record.binNames; dataOffset += key.digest.Length + 4; // Avoid relatively expensive full equality checks for performance reasons. // Use reference equality only in hope that common namespaces/bin names are set from // fixed variables. It's fine if equality not determined correctly because it just // results in more space used. The batch will still be correct. if (prev != null && prev.key.ns == key.ns && prev.binNames == binNames && prev.readAllBins == record.readAllBins) { // Can set repeat previous namespace/bin names to save space. dataOffset++; } else { // Estimate full header, namespace and bin names. dataOffset += ByteUtil.EstimateSizeUtf8(key.ns) + FIELD_HEADER_SIZE + 6; if (binNames != null) { foreach (string binName in binNames) { EstimateOperationSize(binName); } } prev = record; } } SizeBuffer(); WriteHeader(policy, Command.INFO1_READ | Command.INFO1_BATCH, 0, 1, 0); int fieldSizeOffset = dataOffset; WriteFieldHeader(0, FieldType.BATCH_INDEX); // Need to update size at end ByteUtil.IntToBytes((uint)max, dataBuffer, dataOffset); dataOffset += 4; dataBuffer[dataOffset++] = (policy.allowInline) ? (byte)1 : (byte)0; prev = null; for (int i = 0; i < max; i++) { int index = offsets[i]; ByteUtil.IntToBytes((uint)index, dataBuffer, dataOffset); dataOffset += 4; BatchRead record = records[index]; Key key = record.key; string[] binNames = record.binNames; byte[] digest = key.digest; Array.Copy(digest, 0, dataBuffer, dataOffset, digest.Length); dataOffset += digest.Length; // Avoid relatively expensive full equality checks for performance reasons. // Use reference equality only in hope that common namespaces/bin names are set from // fixed variables. It's fine if equality not determined correctly because it just // results in more space used. The batch will still be correct. if (prev != null && prev.key.ns == key.ns && prev.binNames == binNames && prev.readAllBins == record.readAllBins) { // Can set repeat previous namespace/bin names to save space. dataBuffer[dataOffset++] = 1; // repeat } else { // Write full header, namespace and bin names. dataBuffer[dataOffset++] = 0; // do not repeat if (binNames != null && binNames.Length != 0) { dataBuffer[dataOffset++] = (byte)Command.INFO1_READ; dataBuffer[dataOffset++] = 0; // pad dataBuffer[dataOffset++] = 0; // pad ByteUtil.ShortToBytes((ushort)binNames.Length, dataBuffer, dataOffset); dataOffset += 2; WriteField(key.ns, FieldType.NAMESPACE); foreach (string binName in binNames) { WriteOperation(binName, Operation.Type.READ); } } else { dataBuffer[dataOffset++] = (byte)(Command.INFO1_READ | (record.readAllBins ? Command.INFO1_GET_ALL : Command.INFO1_NOBINDATA)); dataBuffer[dataOffset++] = 0; // pad dataBuffer[dataOffset++] = 0; // pad ByteUtil.ShortToBytes(0, dataBuffer, dataOffset); dataOffset += 2; WriteField(key.ns, FieldType.NAMESPACE); } prev = record; } } // Write real field size. ByteUtil.IntToBytes((uint)(dataOffset - MSG_TOTAL_HEADER_SIZE - 4), dataBuffer, fieldSizeOffset); End(); }
public void SetBatchRead(BatchPolicy policy, Key[] keys, BatchNode batch, string[] binNames, int readAttr) { // Estimate full row size int[] offsets = batch.offsets; int max = batch.offsetsSize; int rowSize = 30 + FIELD_HEADER_SIZE + 31; // Row's header(30) + max namespace(31). int operationCount = 0; if (binNames != null) { foreach (string binName in binNames) { EstimateOperationSize(binName); } rowSize += dataOffset; operationCount = binNames.Length; } // Estimate buffer size. Begin(); dataOffset += FIELD_HEADER_SIZE + 5; string prevNamespace = null; for (int i = 0; i < max; i++) { Key key = keys[offsets[i]]; // Try reference equality in hope that namespace for all keys is set from a fixed variable. if (key.ns == prevNamespace || (prevNamespace != null && prevNamespace.Equals(key.ns))) { // Can set repeat previous namespace/bin names to save space. dataOffset += 25; } else { // Must write full header and namespace/bin names. dataOffset += rowSize; prevNamespace = key.ns; } } SizeBuffer(); WriteHeader(policy, readAttr | Command.INFO1_BATCH, 0, 1, 0); int fieldSizeOffset = dataOffset; WriteFieldHeader(0, FieldType.BATCH_INDEX); // Need to update size at end ByteUtil.IntToBytes((uint)max, dataBuffer, dataOffset); dataOffset += 4; dataBuffer[dataOffset++] = (policy.allowInline) ? (byte)1 : (byte)0; prevNamespace = null; for (int i = 0; i < max; i++) { int index = offsets[i]; ByteUtil.IntToBytes((uint)index, dataBuffer, dataOffset); dataOffset += 4; Key key = keys[index]; byte[] digest = key.digest; Array.Copy(digest, 0, dataBuffer, dataOffset, digest.Length); dataOffset += digest.Length; // Try reference equality in hope that namespace for all keys is set from a fixed variable. if (key.ns == prevNamespace || (prevNamespace != null && prevNamespace.Equals(key.ns))) { // Can set repeat previous namespace/bin names to save space. dataBuffer[dataOffset++] = 1; // repeat } else { // Write full header, namespace and bin names. dataBuffer[dataOffset++] = 0; // do not repeat dataBuffer[dataOffset++] = (byte)readAttr; dataBuffer[dataOffset++] = 0; // pad dataBuffer[dataOffset++] = 0; // pad ByteUtil.ShortToBytes((ushort)operationCount, dataBuffer, dataOffset); dataOffset += 2; WriteField(key.ns, FieldType.NAMESPACE); if (binNames != null) { foreach (string binName in binNames) { WriteOperation(binName, Operation.Type.READ); } } prevNamespace = key.ns; } } // Write real field size. ByteUtil.IntToBytes((uint)(dataOffset - MSG_TOTAL_HEADER_SIZE - 4), dataBuffer, fieldSizeOffset); End(); }
public void Read(AerospikeClient client, BatchPolicy policy, string ns, string set, string accountId) { Record record = client.Join(policy, new Key(ns, set, accountId), new Join("tickers", ns, set)); if (record == null) { throw new Exception("Failed to read: " + accountId); } this.accountId = accountId; byte[] positionsBytes = (byte[])record.GetValue("positions"); Record[] records = (Record[])record.GetValue("tickers"); if (positionsBytes != null) { MemoryStream ms = new MemoryStream(positionsBytes); BinaryReader reader = new BinaryReader(ms); int count = reader.ReadInt32(); positions = new List<Position>(count); for (int i = 0; i < count; i++) { positions.Add(new Position(reader, records[i])); } } else { positions = new List<Position>(0); } }
/// <summary> /// Asynchronously read multiple record header data for specified keys in one batch call. /// Create listener, call asynchronous batch header get and return task monitor. /// <para> /// If a key is not found, the record will be null. /// The policy can be used to specify timeouts. /// </para> /// </summary> /// <param name="policy">generic configuration parameters, pass in null for defaults</param> /// <param name="token">cancellation token</param> /// <param name="keys">array of unique record identifiers</param> /// <exception cref="AerospikeException">if queue is full</exception> public Task<Record[]> GetHeader(BatchPolicy policy, CancellationToken token, Key[] keys) { RecordArrayListenerAdapter listener = new RecordArrayListenerAdapter(token); GetHeader(policy, listener, keys); return listener.Task; }
/// <summary> /// Asynchronously read multiple record header data for specified keys in one batch call. /// Schedule the batch get header command with a channel selector and return. /// Another thread will process the command and send the results to the listener in a single call. /// <para> /// If a key is not found, the record will be null. /// The policy can be used to specify timeouts. /// </para> /// </summary> /// <param name="policy">generic configuration parameters, pass in null for defaults</param> /// <param name="listener">where to send results</param> /// <param name="keys">array of unique record identifiers</param> /// <exception cref="AerospikeException">if queue is full</exception> public void GetHeader(BatchPolicy policy, RecordArrayListener listener, Key[] keys) { if (keys.Length == 0) { listener.OnSuccess(keys, new Record[0]); return; } if (policy == null) { policy = batchPolicyDefault; } new AsyncBatchGetArrayExecutor(cluster, policy, listener, keys, null, Command.INFO1_READ | Command.INFO1_NOBINDATA); }
public AsyncBatchReadSequenceCommand( AsyncMultiExecutor parent, AsyncCluster cluster, BatchNode batch, BatchPolicy policy, BatchSequenceListener listener, List<BatchRead> records ) : base(parent, cluster, (AsyncNode)batch.node, false) { this.batch = batch; this.policy = policy; this.listener = listener; this.records = records; }
public AsyncBatchGetSequenceExecutor( AsyncCluster cluster, BatchPolicy policy, RecordSequenceListener listener, Key[] keys, string[] binNames, int readAttr ) : base(cluster, policy, keys) { this.listener = listener; // Create commands. AsyncMultiCommand[] tasks = new AsyncMultiCommand[base.taskSize]; int count = 0; foreach (BatchNode batchNode in batchNodes) { if (batchNode.node.UseNewBatch(policy)) { // New batch tasks[count++] = new AsyncBatchGetSequenceCommand(this, cluster, batchNode, policy, keys, binNames, listener, readAttr); } else { // Old batch only allows one namespace per call. foreach (BatchNode.BatchNamespace batchNamespace in batchNode.batchNamespaces) { tasks[count++] = new AsyncBatchGetSequenceDirect(this, cluster, (AsyncNode)batchNode.node, batchNamespace, policy, keys, binNames, listener, readAttr); } } } // Dispatch commands to nodes. Execute(tasks, policy.maxConcurrentThreads); }
//------------------------------------------------------- // Batch Read Operations //------------------------------------------------------- /// <summary> /// Asynchronously read multiple records for specified batch keys in one batch call. /// This method allows different namespaces/bins to be requested for each key in the batch. /// The returned records are located in the same list. /// <para> /// Create listener, call asynchronous batch get and return task monitor. /// This method requires Aerospike Server version >= 3.6.0. /// </para> /// </summary> /// <param name="policy">batch configuration parameters, pass in null for defaults</param> /// <param name="token">cancellation token</param> /// <param name="records">list of unique record identifiers and the bins to retrieve.</param> /// <exception cref="AerospikeException">if read fails</exception> public Task<List<BatchRead>> Get(BatchPolicy policy, CancellationToken token, List<BatchRead> records) { BatchListListenerAdapter listener = new BatchListListenerAdapter(token); Get(policy, listener, records); return listener.Task; }
public AsyncBatchReadSequenceExecutor( AsyncCluster cluster, BatchPolicy policy, BatchSequenceListener listener, List<BatchRead> records ) { this.listener = listener; // Create commands. List<BatchNode> batchNodes = BatchNode.GenerateList(cluster, policy, records); AsyncMultiCommand[] tasks = new AsyncMultiCommand[batchNodes.Count]; int count = 0; foreach (BatchNode batchNode in batchNodes) { if (!batchNode.node.hasBatchIndex) { throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Requested command requires a server that supports new batch index protocol."); } tasks[count++] = new AsyncBatchReadSequenceCommand(this, cluster, batchNode, policy, listener, records); } // Dispatch commands to nodes. Execute(tasks, policy.maxConcurrentThreads); }
public AsyncBatchGetSequenceCommand( AsyncMultiExecutor parent, AsyncCluster cluster, BatchNode batch, BatchPolicy policy, Key[] keys, string[] binNames, RecordSequenceListener listener, int readAttr ) : base(parent, cluster, (AsyncNode)batch.node, false) { this.batch = batch; this.policy = policy; this.keys = keys; this.binNames = binNames; this.listener = listener; this.readAttr = readAttr; }
public AsyncBatchExistsSequenceCommand( AsyncMultiExecutor parent, AsyncCluster cluster, BatchNode batch, BatchPolicy policy, Key[] keys, ExistsSequenceListener listener ) : base(parent, cluster, (AsyncNode)batch.node, false) { this.batch = batch; this.policy = policy; this.keys = keys; this.listener = listener; }
/// <summary> /// Asynchronously read multiple records for specified keys in one batch call. /// Schedule the get command with a channel selector and return. /// Another thread will process the command and send the results to the listener in multiple unordered calls. /// <para> /// If a key is not found, the record will be null. /// The policy can be used to specify timeouts. /// </para> /// </summary> /// <param name="policy">generic configuration parameters, pass in null for defaults</param> /// <param name="listener">where to send results</param> /// <param name="keys">array of unique record identifiers</param> /// <exception cref="AerospikeException">if queue is full</exception> public void Get(BatchPolicy policy, RecordSequenceListener listener, Key[] keys) { if (keys.Length == 0) { listener.OnSuccess(); return; } if (policy == null) { policy = batchPolicyDefault; } new AsyncBatchGetSequenceExecutor(cluster, policy, listener, keys, null, Command.INFO1_READ | Command.INFO1_GET_ALL); }
public BatchReadListCommand(BatchNode batch, BatchPolicy policy, List<BatchRead> records) : base(batch.node, false) { this.batch = batch; this.policy = policy; this.records = records; }
/// <summary> /// Asynchronously check if multiple record keys exist in one batch call. /// Schedule the exists command with a channel selector and return. /// Another thread will process the command and send the results to the listener in multiple unordered calls. /// <para> /// The policy can be used to specify timeouts. /// </para> /// </summary> /// <param name="policy">generic configuration parameters, pass in null for defaults</param> /// <param name="listener">where to send results</param> /// <param name="keys">array of unique record identifiers</param> /// <exception cref="AerospikeException">if queue is full</exception> public void Exists(BatchPolicy policy, ExistsSequenceListener listener, Key[] keys) { if (keys.Length == 0) { listener.OnSuccess(); return; } if (policy == null) { policy = batchPolicyDefault; } new AsyncBatchExistsSequenceExecutor(cluster, policy, keys, listener); }
/// <summary> /// Asynchronously read multiple record headers and bins for specified keys in one batch call. /// Schedule the batch get command with a channel selector and return. /// Another thread will process the command and send the results to the listener in multiple unordered calls. /// <para> /// If a key is not found, the record will be null. /// The policy can be used to specify timeouts. /// </para> /// </summary> /// <param name="policy">generic configuration parameters, pass in null for defaults</param> /// <param name="listener">where to send results</param> /// <param name="keys">array of unique record identifiers</param> /// <param name="binNames">array of bins to retrieve</param> /// <exception cref="AerospikeException">if queue is full</exception> public void Get(BatchPolicy policy, RecordSequenceListener listener, Key[] keys, params string[] binNames) { if (keys.Length == 0) { listener.OnSuccess(); return; } if (policy == null) { policy = batchPolicyDefault; } new AsyncBatchGetSequenceExecutor(cluster, policy, listener, keys, binNames, Command.INFO1_READ); }
/// <summary> /// Asynchronously read multiple record headers and bins for specified keys in one batch call. /// Create listener, call asynchronous batch get and return task monitor. /// <para> /// If a key is not found, the record will be null. /// The policy can be used to specify timeouts. /// </para> /// </summary> /// <param name="policy">generic configuration parameters, pass in null for defaults</param> /// <param name="token">cancellation token</param> /// <param name="keys">array of unique record identifiers</param> /// <param name="binNames">array of bins to retrieve</param> /// <exception cref="AerospikeException">if queue is full</exception> public Task<Record[]> Get(BatchPolicy policy, CancellationToken token, Key[] keys, params string[] binNames) { RecordArrayListenerAdapter listener = new RecordArrayListenerAdapter(token); Get(policy, listener, keys, binNames); return listener.Task; }