void Codec20::readNewTopologyAndHash(Transport& transport, HeaderParams& params) const{ // Just consume the header's byte // Do not evaluate new topology right now int newTopologyId = transport.readVInt(); params.topologyId.setId(newTopologyId); //update topologyId reference uint32_t clusterSize = transport.readVInt(); TRACE("Coded20::readNewToplogyAndhash(): clusterSize=%d",clusterSize); std::vector<InetSocketAddress> addresses(clusterSize); for (uint32_t i = 0; i < clusterSize; i++) { std::string host(transport.readString()); int16_t port = transport.readUnsignedShort(); addresses[i] = InetSocketAddress(host, port); } uint8_t hashFunctionVersion = transport.readByte(); uint32_t numSegments = transport.readVInt(); std::vector<std::vector<InetSocketAddress>> segmentOwners(numSegments); if (hashFunctionVersion > 0) { TRACE("Codec20::readNewTopologyAndHash: numSegments=%d", numSegments); for (uint32_t i = 0; i < numSegments; i++) { uint8_t numOwners = transport.readByte(); segmentOwners[i]=std::vector<InetSocketAddress>(numOwners); for (uint8_t j = 0; j < numOwners; j++) { uint32_t memberIndex = transport.readVInt(); segmentOwners[i][j] = addresses[memberIndex]; } } } TransportFactory &tf = transport.getTransportFactory(); bool noTopologyInfo=false; int currentTopology = 0; try { currentTopology = tf.getTopologyId(params.cacheName); } catch (std::exception &e) { noTopologyInfo=true; } int topologyAge = tf.getTopologyAge(); if (noTopologyInfo || (params.topologyAge == topologyAge && currentTopology != newTopologyId)) { params.topologyId = newTopologyId; tf.updateServers(addresses); if (hashFunctionVersion == 0) { TRACE("Not using a consistent hash function (hash function version == 0)."); } else { TRACE("Updating client hash function with %u number of segments", numSegments); } tf.updateHashFunction(segmentOwners, numSegments, hashFunctionVersion, params.cacheName, params.topologyId.getId()); } else { TRACE("Outdated topology received (topology id = %d, topology age = %d), so ignoring it: s", newTopologyId, topologyAge/*, Arrays.toString(addresses)*/); } }
void Codec12::readNewTopologyIfPresent( Transport& transport, const HeaderParams& params) const { uint8_t topologyChangeByte = transport.readByte(); if (topologyChangeByte == 1) readNewTopologyAndHash(transport, params.topologyId); }
uint8_t Codec12::readHeader( Transport& transport, const HeaderParams& params) const { uint8_t magic = transport.readByte(); if (magic != HotRodConstants::RESPONSE_MAGIC) { std::ostringstream message; message << "Invalid magic number. Expected " << HotRodConstants::RESPONSE_MAGIC << " and received " << magic; throw InvalidResponseException(message.str()); } uint64_t receivedMessageId = transport.readVLong(); // TODO: java comment, to be checked // If received id is 0, it could be that a failure was noted before the // message id was detected, so don't consider it to a message id error if (receivedMessageId != params.messageId && receivedMessageId != 0) { std::ostringstream message; message << "Invalid message id. Expected " << params.messageId << " and received " << receivedMessageId; throw InvalidResponseException(message.str()); } uint8_t receivedOpCode = transport.readByte(); // Read both the status and new topology (if present), // before deciding how to react to error situations. uint8_t status = transport.readByte(); readNewTopologyIfPresent(transport, params); // Now that all headers values have been read, check the error responses. // This avoids situations where an exceptional return ends up with // the socket containing data from previous request responses. if (receivedOpCode != params.opRespCode) { if (receivedOpCode == HotRodConstants::ERROR_RESPONSE) { checkForErrorsInResponseStatus(transport, params, status); } std::ostringstream message; message << "Invalid response operation. Expected " << std::hex << (int) params.opRespCode << " and received " << std::hex << (int) receivedOpCode; throw InvalidResponseException(message.str()); } return status; }
std::set<hrbytes> BulkGetKeysOperation::executeOperation(Transport& transport) { hr_scoped_ptr<HeaderParams> params(&(RetryOnFailureOperation<std::set<hrbytes> >::writeHeader(transport, BULK_GET_KEYS_REQUEST))); transport.writeVInt(scope); transport.flush(); RetryOnFailureOperation<std::set<hrbytes> >::readHeaderAndValidate(transport, *params); std::set<hrbytes> result; while (transport.readByte()==1) { result.insert(transport.readArray()); } return result; }
void Codec20::readNewTopologyIfPresent( Transport& transport, HeaderParams& params) const { uint8_t topologyChangeByte = transport.readByte(); if (topologyChangeByte == 1) { TRACE("Topology has changes"); readNewTopologyAndHash(transport, params); } else { TRACE("No topology changes"); } }
std::set<hrbytes> BulkGetKeysOperation::executeOperation(Transport& transport) { TRACE("Execute BulkGetKeys(flags=%u,scope=%d)", flags, scope); hr_scoped_ptr<HeaderParams> params(&(RetryOnFailureOperation<std::set<hrbytes> >::writeHeader(transport, BULK_GET_KEYS_REQUEST))); transport.writeVInt(scope); transport.flush(); RetryOnFailureOperation<std::set<hrbytes> >::readHeaderAndValidate(transport, *params); std::set<hrbytes> result; while (transport.readByte()==1) { result.insert(transport.readArray()); } if (logger.isTraceEnabled()) { for (std::set<hrbytes>::iterator it = result.begin(); it != result.end(); ++it) { TRACEBYTES("return key = ", *it); } if (result.size() == 0) { TRACE("No data in bulk"); } } return result; }