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 types 16 17import ( 18 "errors" 19 "strings" 20) 21 22// AerospikeError implements error interface for aerospike specific errors. 23// All errors returning from the library are of this type. 24// Errors resulting from Go's stdlib are not translated to this type, unless 25// they are a net.Timeout error. 26type AerospikeError struct { 27 error 28 29 resultCode ResultCode 30 inDoubt bool 31} 32 33// ResultCode returns the ResultCode from AerospikeError object. 34func (ase AerospikeError) ResultCode() ResultCode { 35 return ase.resultCode 36} 37 38// InDoubt determines if a write transaction may have completed or not. 39func (ase AerospikeError) InDoubt() bool { 40 return ase.inDoubt 41} 42 43// SetInDoubt sets whether it is possible that the write transaction may have completed 44// even though this error was generated. This may be the case when a 45// client error occurs (like timeout) after the command was sent to the server. 46func (ase *AerospikeError) SetInDoubt(isRead bool, commandSentCounter int) { 47 if !isRead && (commandSentCounter > 1 || (commandSentCounter == 1 && (ase.resultCode == TIMEOUT || ase.resultCode <= 0))) { 48 ase.inDoubt = true 49 } 50} 51 52// MarkInDoubt marks an error as in doubt. 53func (ase *AerospikeError) MarkInDoubt() { 54 ase.inDoubt = true 55} 56 57// NewAerospikeError generates a new AerospikeError instance. 58// If no message is provided, the result code will be translated into the default 59// error message automatically. 60// To be able to check for error type, you could use the following: 61// if aerr, ok := err.(AerospikeError); ok { 62// errCode := aerr.ResultCode() 63// errMessage := aerr.Error() 64// } 65func NewAerospikeError(code ResultCode, messages ...string) error { 66 if len(messages) == 0 { 67 messages = []string{ResultCodeToString(code)} 68 } 69 70 err := errors.New(strings.Join(messages, " ")) 71 return AerospikeError{error: err, resultCode: code} 72} 73 74var ErrServerNotAvailable = NewAerospikeError(SERVER_NOT_AVAILABLE) 75var ErrKeyNotFound = NewAerospikeError(KEY_NOT_FOUND_ERROR) 76var ErrRecordsetClosed = NewAerospikeError(RECORDSET_CLOSED) 77var ErrConnectionPoolEmpty = NewAerospikeError(NO_AVAILABLE_CONNECTIONS_TO_NODE, "Connection pool is empty. This happens when either all connection are in-use already, or no connections were available") 78var ErrTooManyConnectionsForNode = NewAerospikeError(NO_AVAILABLE_CONNECTIONS_TO_NODE, "Connection limit reached for this node. This value is controlled via ClientPolicy.LimitConnectionsToQueueSize") 79var ErrTooManyOpeningConnections = NewAerospikeError(NO_AVAILABLE_CONNECTIONS_TO_NODE, "Too many connections are trying to open at once. This value is controlled via ClientPolicy.OpeningConnectionThreshold") 80var ErrTimeout = NewAerospikeError(TIMEOUT, "command execution timed out on client: See `Policy.Timeout`") 81var ErrUDFBadResponse = NewAerospikeError(UDF_BAD_RESPONSE, "Invalid UDF return value") 82var ErrNoOperationsSpecified = NewAerospikeError(INVALID_COMMAND, "No operations were passed to QueryExecute") 83var ErrNoBinNamesAlloedInQueryExecute = NewAerospikeError(INVALID_COMMAND, "Statement.BinNames must be empty for QueryExecute") 84var ErrFilteredOut = NewAerospikeError(FILTERED_OUT) 85