func (cmd *serverCommand) parseRecordResults(ifc command, receiveSize int) (bool, error) {
	// Server commands (Query/Execute UDF) should only send back a return code.
	// Keep parsing logic to empty socket buffer just in case server does
	// send records back.
	cmd.dataOffset = 0

	for cmd.dataOffset < receiveSize {
		if err := cmd.readBytes(int(_MSG_REMAINING_HEADER_SIZE)); err != nil {
			return false, err
		}
		resultCode := ResultCode(cmd.dataBuffer[5] & 0xFF)

		if resultCode != 0 {
			if resultCode == KEY_NOT_FOUND_ERROR {
				return false, nil
			}
			return false, NewAerospikeError(resultCode)
		}

		info3 := int(cmd.dataBuffer[3])

		// If cmd is the end marker of the response, do not proceed further
		if (info3 & _INFO3_LAST) == _INFO3_LAST {
			return false, nil
		}

		fieldCount := int(Buffer.BytesToUint16(cmd.dataBuffer, 18))
		opCount := int(Buffer.BytesToUint16(cmd.dataBuffer, 20))

		if _, err := cmd.parseKey(fieldCount); err != nil {
			return false, err
		}

		for i := 0; i < opCount; i++ {
			if err := cmd.readBytes(8); err != nil {
				return false, err
			}
			opSize := int(Buffer.BytesToUint32(cmd.dataBuffer, 0))
			nameSize := int(cmd.dataBuffer[7])

			if err := cmd.readBytes(nameSize); err != nil {
				return false, err
			}

			particleBytesSize := int((opSize - (4 + nameSize)))
			if err := cmd.readBytes(particleBytesSize); err != nil {
				return false, err
			}
		}
	}
	return true, nil
}
// Parse all results in the batch.  Add records to shared list.
// If the record was not found, the bins will be nil.
func (cmd *batchCommandExists) parseRecordResults(ifc command, receiveSize int) (bool, error) {
	//Parse each message response and add it to the result array
	cmd.dataOffset = 0

	for cmd.dataOffset < receiveSize {
		if err := cmd.readBytes(int(_MSG_REMAINING_HEADER_SIZE)); err != nil {
			return false, err
		}

		resultCode := ResultCode(cmd.dataBuffer[5] & 0xFF)

		// The only valid server return codes are "ok" and "not found".
		// If other return codes are received, then abort the batch.
		if resultCode != 0 && resultCode != KEY_NOT_FOUND_ERROR {
			return false, NewAerospikeError(resultCode)
		}

		info3 := cmd.dataBuffer[3]

		// If cmd is the end marker of the response, do not proceed further
		if (int(info3) & _INFO3_LAST) == _INFO3_LAST {
			return false, nil
		}

		fieldCount := int(Buffer.BytesToUint16(cmd.dataBuffer, 18))
		opCount := int(Buffer.BytesToUint16(cmd.dataBuffer, 20))

		if opCount > 0 {
			return false, NewAerospikeError(PARSE_ERROR, "Received bins that were not requested!")
		}

		key, err := cmd.parseKey(fieldCount)
		if err != nil {
			return false, err
		}

		offset := cmd.batchNamespace.offsets[cmd.index]
		cmd.index++

		if bytes.Equal(key.digest[:], cmd.keys[offset].digest[:]) {
			// only set the results to true; as a result, no synchronization is needed
			if resultCode == 0 {
				cmd.existsArray[offset] = true
			}
		} else {
			return false, NewAerospikeError(PARSE_ERROR, "Unexpected batch key returned: "+string(key.namespace)+","+Buffer.BytesToHexString(key.digest[:]))
		}
	}
	return true, nil
}
// Parse all results in the batch.  Add records to shared list.
// If the record was not found, the bins will be nil.
func (cmd *batchCommandGet) parseRecordResults(ifc command, receiveSize int) (bool, error) {
	//Parse each message response and add it to the result array
	cmd.dataOffset = 0

	for cmd.dataOffset < receiveSize {
		if err := cmd.readBytes(int(_MSG_REMAINING_HEADER_SIZE)); err != nil {
			return false, err
		}
		resultCode := ResultCode(cmd.dataBuffer[5] & 0xFF)

		// The only valid server return codes are "ok" and "not found".
		// If other return codes are received, then abort the batch.
		if resultCode != 0 && resultCode != KEY_NOT_FOUND_ERROR {
			return false, NewAerospikeError(resultCode)
		}

		info3 := int(cmd.dataBuffer[3])

		// If cmd is the end marker of the response, do not proceed further
		if (info3 & _INFO3_LAST) == _INFO3_LAST {
			return false, nil
		}

		generation := Buffer.BytesToUint32(cmd.dataBuffer, 6)
		expiration := TTL(Buffer.BytesToUint32(cmd.dataBuffer, 10))
		fieldCount := int(Buffer.BytesToUint16(cmd.dataBuffer, 18))
		opCount := int(Buffer.BytesToUint16(cmd.dataBuffer, 20))
		key, err := cmd.parseKey(fieldCount)
		if err != nil {
			return false, err
		}

		offset := cmd.batchNamespace.offsets[cmd.index] //cmd.keyMap[string(key.digest)]
		cmd.index++

		if bytes.Equal(key.digest[:], cmd.keys[offset].digest[:]) {
			if resultCode == 0 {
				if cmd.records[offset], err = cmd.parseRecord(key, opCount, generation, expiration); err != nil {
					return false, err
				}
			}
		} else {
			return false, NewAerospikeError(PARSE_ERROR, "Unexpected batch key returned: "+string(key.namespace)+","+Buffer.BytesToHexString(key.digest[:]))
		}
	}
	return true, nil
}
示例#4
0
func (upckr *unpacker) UnpackMap() (interface{}, error) {
	if upckr.length <= 0 {
		return nil, nil
	}

	theType := upckr.buffer[upckr.offset] & 0xff
	upckr.offset++
	var count int

	if (theType & 0xf0) == 0x80 {
		count = int(theType & 0x0f)
	} else if theType == 0xde {
		count = int(Buffer.BytesToUint16(upckr.buffer, upckr.offset))
		upckr.offset += 2
	} else if theType == 0xdf {
		count = int(Buffer.BytesToUint32(upckr.buffer, upckr.offset))
		upckr.offset += 4
	} else {
		return make(map[interface{}]interface{}), nil
	}
	return upckr.unpackMap(count)
}
示例#5
0
func (upckr *unpacker) UnpackList() ([]interface{}, error) {
	if upckr.length <= 0 {
		return nil, nil
	}

	theType := upckr.buffer[upckr.offset] & 0xff
	upckr.offset++
	var count int

	if (theType & 0xf0) == 0x90 {
		count = int(theType & 0x0f)
	} else if theType == 0xdc {
		count = int(Buffer.BytesToUint16(upckr.buffer, upckr.offset))
		upckr.offset += 2
	} else if theType == 0xdd {
		count = int(Buffer.BytesToUint32(upckr.buffer, upckr.offset))
		upckr.offset += 4
	} else {
		return nil, nil
	}

	return upckr.unpackList(count)
}
示例#6
0
func (upckr *unpacker) unpackObject(isMapKey bool) (interface{}, error) {
	theType := upckr.buffer[upckr.offset] & 0xff
	upckr.offset++

	switch theType {
	case 0xc0:
		return nil, nil

	case 0xc3:
		return true, nil

	case 0xc2:
		return false, nil

	case 0xca:
		val := Buffer.BytesToFloat32(upckr.buffer, upckr.offset)
		upckr.offset += 4
		return val, nil

	case 0xcb:
		val := Buffer.BytesToFloat64(upckr.buffer, upckr.offset)
		upckr.offset += 8
		return val, nil

	case 0xcc:
		r := upckr.buffer[upckr.offset] & 0xff
		upckr.offset++

		return int(r), nil

	case 0xcd:
		val := uint16(Buffer.BytesToInt16(upckr.buffer, upckr.offset))
		upckr.offset += 2
		return int(val), nil

	case 0xce:
		val := uint32(Buffer.BytesToInt32(upckr.buffer, upckr.offset))
		upckr.offset += 4

		if Buffer.Arch64Bits {
			return int(val), nil
		}
		return int64(val), nil

	case 0xcf:
		val := Buffer.BytesToInt64(upckr.buffer, upckr.offset)
		upckr.offset += 8
		return uint64(val), nil

	case 0xd0:
		r := int8(upckr.buffer[upckr.offset])
		upckr.offset++
		return int(r), nil

	case 0xd1:
		val := Buffer.BytesToInt16(upckr.buffer, upckr.offset)
		upckr.offset += 2
		return int(val), nil

	case 0xd2:
		val := Buffer.BytesToInt32(upckr.buffer, upckr.offset)
		upckr.offset += 4
		return int(val), nil

	case 0xd3:
		val := Buffer.BytesToInt64(upckr.buffer, upckr.offset)
		upckr.offset += 8
		if Buffer.Arch64Bits {
			return int(val), nil
		}
		return int64(val), nil

	case 0xc4, 0xd9:
		count := int(upckr.offset & 0xff)
		upckr.offset++
		return upckr.unpackBlob(count, isMapKey)

	case 0xc5, 0xda:
		count := int(Buffer.BytesToUint16(upckr.buffer, upckr.offset))
		upckr.offset += 2
		return upckr.unpackBlob(count, isMapKey)

	case 0xc6, 0xdb:
		count := int(Buffer.BytesToUint32(upckr.buffer, upckr.offset))
		upckr.offset += 4
		return upckr.unpackBlob(count, isMapKey)

	case 0xdc:
		count := int(Buffer.BytesToUint16(upckr.buffer, upckr.offset))
		upckr.offset += 2
		return upckr.unpackList(count)

	case 0xdd:
		count := int(Buffer.BytesToUint32(upckr.buffer, upckr.offset))
		upckr.offset += 4
		return upckr.unpackList(count)

	case 0xde:
		count := int(Buffer.BytesToUint16(upckr.buffer, upckr.offset))
		upckr.offset += 2
		return upckr.unpackMap(count)

	case 0xdf:
		count := int(Buffer.BytesToUint32(upckr.buffer, upckr.offset))
		upckr.offset += 4
		return upckr.unpackMap(count)

	case 0xd4:
		// Skip over type extension with 1 byte
		upckr.offset += 1 + 1
		return nil, skipHeaderErr

	case 0xd5:
		// Skip over type extension with 2 bytes
		upckr.offset += 1 + 2
		return nil, skipHeaderErr

	case 0xd6:
		// Skip over type extension with 4 bytes
		upckr.offset += 1 + 4
		return nil, skipHeaderErr

	case 0xd7:
		// Skip over type extension with 8 bytes
		upckr.offset += 1 + 8
		return nil, skipHeaderErr

	case 0xd8:
		// Skip over type extension with 16 bytes
		upckr.offset += 1 + 16
		return nil, skipHeaderErr

	case 0xc7: // Skip over type extension with 8 bit header and bytes
		count := int(upckr.buffer[upckr.offset] & 0xff)
		upckr.offset += count + 1 + 1
		return nil, skipHeaderErr

	case 0xc8: // Skip over type extension with 16 bit header and bytes
		count := int(Buffer.BytesToInt16(upckr.buffer, upckr.offset))
		upckr.offset += count + 1 + 2
		return nil, skipHeaderErr

	case 0xc9: // Skip over type extension with 32 bit header and bytes
		count := int(Buffer.BytesToInt32(upckr.buffer, upckr.offset))
		upckr.offset += count + 1 + 4
		return nil, skipHeaderErr

	default:
		if (theType & 0xe0) == 0xa0 {
			return upckr.unpackBlob(int(theType&0x1f), isMapKey)
		}

		if (theType & 0xf0) == 0x80 {
			return upckr.unpackMap(int(theType & 0x0f))
		}

		if (theType & 0xf0) == 0x90 {
			count := int(theType & 0x0f)
			return upckr.unpackList(count)
		}

		if theType < 0x80 {
			return int(theType), nil
		}

		if theType >= 0xe0 {
			return int(int(theType) - 0xe0 - 32), nil
		}
	}

	return nil, NewAerospikeError(SERIALIZE_ERROR)
}
func (cmd *baseMultiCommand) parseRecordResults(ifc command, receiveSize int) (bool, error) {
	// Read/parse remaining message bytes one record at a time.
	cmd.dataOffset = 0

	for cmd.dataOffset < receiveSize {
		if err := cmd.readBytes(int(_MSG_REMAINING_HEADER_SIZE)); err != nil {
			cmd.recordset.Errors <- newNodeError(cmd.node, err)
			return false, err
		}
		resultCode := ResultCode(cmd.dataBuffer[5] & 0xFF)

		if resultCode != 0 {
			if resultCode == KEY_NOT_FOUND_ERROR {
				// consume the rest of the input buffer from the socket
				if cmd.dataOffset < receiveSize {
					if err := cmd.readBytes(receiveSize - cmd.dataOffset); err != nil {
						cmd.recordset.Errors <- newNodeError(cmd.node, err)
						return false, err
					}
				}
				return false, nil
			}
			err := NewAerospikeError(resultCode)
			cmd.recordset.Errors <- newNodeError(cmd.node, err)
			return false, err
		}

		info3 := int(cmd.dataBuffer[3])

		// If cmd is the end marker of the response, do not proceed further
		if (info3 & _INFO3_LAST) == _INFO3_LAST {
			return false, nil
		}

		generation := Buffer.BytesToUint32(cmd.dataBuffer, 6)
		expiration := TTL(Buffer.BytesToUint32(cmd.dataBuffer, 10))
		fieldCount := int(Buffer.BytesToUint16(cmd.dataBuffer, 18))
		opCount := int(Buffer.BytesToUint16(cmd.dataBuffer, 20))

		key, err := cmd.parseKey(fieldCount)
		if err != nil {
			cmd.recordset.Errors <- newNodeError(cmd.node, err)
			return false, err
		}

		// if there is a recordset, process the record traditionally
		// otherwise, it is supposed to be a record channel
		if cmd.selectCases == nil {
			// Parse bins.
			var bins BinMap

			for i := 0; i < opCount; i++ {
				if err := cmd.readBytes(8); err != nil {
					cmd.recordset.Errors <- newNodeError(cmd.node, err)
					return false, err
				}

				opSize := int(Buffer.BytesToUint32(cmd.dataBuffer, 0))
				particleType := int(cmd.dataBuffer[5])
				nameSize := int(cmd.dataBuffer[7])

				if err := cmd.readBytes(nameSize); err != nil {
					cmd.recordset.Errors <- newNodeError(cmd.node, err)
					return false, err
				}
				name := string(cmd.dataBuffer[:nameSize])

				particleBytesSize := int((opSize - (4 + nameSize)))
				if err = cmd.readBytes(particleBytesSize); err != nil {
					cmd.recordset.Errors <- newNodeError(cmd.node, err)
					return false, err
				}
				value, err := bytesToParticle(particleType, cmd.dataBuffer, 0, particleBytesSize)
				if err != nil {
					cmd.recordset.Errors <- newNodeError(cmd.node, err)
					return false, err
				}

				if bins == nil {
					bins = make(BinMap, opCount)
				}
				bins[name] = value
			}

			// If the channel is full and it blocks, we don't want this command to
			// block forever, or panic in case the channel is closed in the meantime.
			select {
			// send back the result on the async channel
			case cmd.recordset.Records <- newRecord(cmd.node, key, bins, generation, expiration):
			case <-cmd.recordset.cancelled:
				return false, NewAerospikeError(cmd.terminationErrorType)
			}
		} else if multiObjectParser != nil {
			obj := reflect.New(cmd.resObjType)
			if err := multiObjectParser(cmd, obj, opCount, fieldCount, generation, expiration); err != nil {
				cmd.recordset.Errors <- newNodeError(cmd.node, err)
				return false, err
			}

			// set the object to send
			cmd.selectCases[0].Send = obj

			chosen, _, _ := reflect.Select(cmd.selectCases)
			switch chosen {
			case 0: // object sent
			case 1: // cancel channel is closed
				return false, NewAerospikeError(cmd.terminationErrorType)
			}
		}
	}

	return true, nil
}