1// Copyright 2013-2020 Aerospike, Inc. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package aerospike 16 17import ( 18 "fmt" 19 20 . "github.com/aerospike/aerospike-client-go/logger" 21 . "github.com/aerospike/aerospike-client-go/types" 22 Buffer "github.com/aerospike/aerospike-client-go/utils/buffer" 23) 24 25// guarantee touchCommand implements command interface 26var _ command = &touchCommand{} 27 28type touchCommand struct { 29 singleCommand 30 31 policy *WritePolicy 32} 33 34func newTouchCommand(cluster *Cluster, policy *WritePolicy, key *Key) (touchCommand, error) { 35 partition, err := PartitionForWrite(cluster, &policy.BasePolicy, key) 36 if err != nil { 37 return touchCommand{}, err 38 } 39 40 newTouchCmd := touchCommand{ 41 singleCommand: newSingleCommand(cluster, key, partition), 42 policy: policy, 43 } 44 45 return newTouchCmd, nil 46} 47 48func (cmd *touchCommand) getPolicy(ifc command) Policy { 49 return cmd.policy 50} 51 52func (cmd *touchCommand) writeBuffer(ifc command) error { 53 return cmd.setTouch(cmd.policy, cmd.key) 54} 55 56func (cmd *touchCommand) getNode(ifc command) (*Node, error) { 57 return cmd.partition.GetNodeWrite(cmd.cluster) 58} 59 60func (cmd *touchCommand) prepareRetry(ifc command, isTimeout bool) bool { 61 cmd.partition.PrepareRetryWrite(isTimeout) 62 return true 63} 64 65func (cmd *touchCommand) parseResult(ifc command, conn *Connection) error { 66 // Read header. 67 _, err := conn.Read(cmd.dataBuffer, 8) 68 if err != nil { 69 return err 70 } 71 72 if compressedSize := cmd.compressedSize(); compressedSize > 0 { 73 // Read compressed size 74 _, err = conn.Read(cmd.dataBuffer, compressedSize) 75 if err != nil { 76 Logger.Debug("Connection error reading data for TouchCommand: %s", err.Error()) 77 return err 78 } 79 80 // Read compressed size 81 _, err = conn.Read(cmd.dataBuffer, 8) 82 if err != nil { 83 Logger.Debug("Connection error reading data for TouchCommand: %s", err.Error()) 84 return err 85 } 86 87 if err := cmd.conn.initInflater(true, compressedSize); err != nil { 88 return NewAerospikeError(PARSE_ERROR, fmt.Sprintf("Error setting up zlib inflater for size `%d`: %s", compressedSize, err.Error())) 89 } 90 91 // Read header. 92 _, err = conn.Read(cmd.dataBuffer, int(_MSG_TOTAL_HEADER_SIZE)) 93 if err != nil { 94 Logger.Debug("Connection error reading data for TouchCommand: %s", err.Error()) 95 return err 96 } 97 } else { 98 // Read header. 99 _, err = conn.Read(cmd.dataBuffer[8:], int(_MSG_TOTAL_HEADER_SIZE)-8) 100 if err != nil { 101 Logger.Debug("Connection error reading data for TouchCommand: %s", err.Error()) 102 return err 103 } 104 } 105 106 // Read header. 107 header := Buffer.BytesToInt64(cmd.dataBuffer, 0) 108 109 // Validate header to make sure we are at the beginning of a message 110 if err := cmd.validateHeader(header); err != nil { 111 return err 112 } 113 114 resultCode := cmd.dataBuffer[13] & 0xFF 115 116 if resultCode != 0 { 117 if resultCode == byte(KEY_NOT_FOUND_ERROR) { 118 return ErrKeyNotFound 119 } else if ResultCode(resultCode) == FILTERED_OUT { 120 return ErrFilteredOut 121 } 122 123 return NewAerospikeError(ResultCode(resultCode)) 124 } 125 if err := cmd.emptySocket(conn); err != nil { 126 return err 127 } 128 return nil 129} 130 131func (cmd *touchCommand) Execute() error { 132 return cmd.execute(cmd, false) 133} 134