static void unknown_rsp(const void *data, uint8_t size) { const struct bt_ll_unknown_rsp *pdu = data; print_field("Unknown type: %s (0x%2.2x)", opcode_to_string(pdu->type), pdu->type); }
bool Connection::write(Handler* handler, bool flush_immediately) { int8_t stream = stream_manager_.acquire_stream(handler); if (stream < 0) { return false; } handler->inc_ref(); // Connection reference handler->set_connection(this); handler->set_stream(stream); if (pending_writes_.is_empty() || pending_writes_.back()->is_flushed()) { if (ssl_session_) { pending_writes_.add_to_back(new PendingWriteSsl(this)); } else { pending_writes_.add_to_back(new PendingWrite(this)); } } PendingWriteBase* pending_write = pending_writes_.back(); int32_t request_size = pending_write->write(handler); if (request_size < 0) { stream_manager_.release_stream(stream); if (request_size == Request::ENCODE_ERROR_BATCH_WITH_NAMED_VALUES) { handler->on_error(CASS_ERROR_LIB_MESSAGE_ENCODE, "Batches cannot contain queries with named values"); } else { handler->on_error(CASS_ERROR_LIB_MESSAGE_ENCODE, "Operation unsupported by this protocol version"); } handler->dec_ref(); return true; // Don't retry } pending_writes_size_ += request_size; if (pending_writes_size_ > config_.write_bytes_high_water_mark()) { LOG_WARN("Exceeded write bytes water mark (current: %u water mark: %u) on connection to host %s", static_cast<unsigned int>(pending_writes_size_), config_.write_bytes_high_water_mark(), addr_string_.c_str()); metrics_->exceeded_write_bytes_water_mark.inc(); set_is_available(false); } LOG_TRACE("Sending message type %s with stream %d", opcode_to_string(handler->request()->opcode()).c_str(), stream); handler->set_state(Handler::REQUEST_STATE_WRITING); handler->start_timer(loop_, config_.request_timeout_ms(), handler, Connection::on_timeout); if (flush_immediately) { pending_write->flush(); } return true; }
std::string operation::to_string() const { std::ostringstream ss; if (data.empty()) ss << opcode_to_string(code); else ss << "[ " << encode_base16(data) << " ]"; return ss.str(); }
std::string script::string_repr() const { std::ostringstream ss; for (const operation op: operations_) { if (op.data.size() == 0) ss << opcode_to_string(op.code) << " "; else { ss << "[ "; for (byte b: op.data) ss << std::hex << int(b) << " "; ss << "] "; } } return ss.str(); }
bool check_error_or_invalid_response(const std::string& prefix, uint8_t expected_opcode, Response* response) { if (response->opcode() == expected_opcode) { return false; } std::ostringstream ss; if (response->opcode() == CQL_OPCODE_ERROR) { ss << prefix << ": Error response " << static_cast<ErrorResponse*>(response)->error_message(); } else { ss << prefix << ": Unexpected opcode " << opcode_to_string(response->opcode()); } LOG_ERROR("%s", ss.str().c_str()); return true; }
bool script::run(const message::transaction& parent_tx, uint32_t input_index) { stack_.clear(); for (const operation oper: operations_) { log_debug() << "Run: " << opcode_to_string(oper.code); if (!run_operation(oper, parent_tx, input_index)) return false; if (oper.data.size() > 0) { BITCOIN_ASSERT(oper.code == opcode::special || oper.code == opcode::pushdata1 || oper.code == opcode::pushdata2 || oper.code == opcode::pushdata4); stack_.push_back(oper.data); } } if (stack_.size() != 0) { log_error() << "Script left junk on top of the stack"; return false; } return true; }
void Connection::consume(char* input, size_t size) { char* buffer = input; size_t remaining = size; // A successful read means the connection is still responsive restart_terminate_timer(); while (remaining != 0) { ssize_t consumed = response_->decode(buffer, remaining); if (consumed <= 0) { notify_error("Error consuming message"); remaining = 0; continue; } if (response_->is_body_ready()) { ScopedPtr<ResponseMessage> response(response_.release()); response_.reset(new ResponseMessage()); LOG_TRACE("Consumed message type %s with stream %d, input %u, remaining %u on host %s", opcode_to_string(response->opcode()).c_str(), static_cast<int>(response->stream()), static_cast<unsigned int>(size), static_cast<unsigned int>(remaining), host_->address_string().c_str()); if (response->stream() < 0) { if (response->opcode() == CQL_OPCODE_EVENT) { listener_->on_event(static_cast<EventResponse*>(response->response_body().get())); } else { notify_error("Invalid response opcode for event stream: " + opcode_to_string(response->opcode())); } } else { Handler* handler = NULL; if (stream_manager_.get_pending_and_release(response->stream(), handler)) { switch (handler->state()) { case Handler::REQUEST_STATE_READING: maybe_set_keyspace(response.get()); pending_reads_.remove(handler); handler->stop_timer(); handler->set_state(Handler::REQUEST_STATE_DONE); handler->on_set(response.get()); handler->dec_ref(); break; case Handler::REQUEST_STATE_WRITING: // There are cases when the read callback will happen // before the write callback. If this happens we have // to allow the write callback to cleanup. maybe_set_keyspace(response.get()); handler->set_state(Handler::REQUEST_STATE_READ_BEFORE_WRITE); handler->on_set(response.get()); break; case Handler::REQUEST_STATE_TIMEOUT: pending_reads_.remove(handler); handler->set_state(Handler::REQUEST_STATE_DONE); handler->dec_ref(); break; case Handler::REQUEST_STATE_TIMEOUT_WRITE_OUTSTANDING: // We must wait for the write callback before we can do the cleanup handler->set_state(Handler::REQUEST_STATE_READ_BEFORE_WRITE); break; default: assert(false && "Invalid request state after receiving response"); break; } } else { notify_error("Invalid stream ID"); } } } remaining -= consumed; buffer += consumed; } }
bool Connection::internal_write(Handler* handler, bool flush_immediately) { int stream = stream_manager_.acquire(handler); if (stream < 0) { return false; } handler->inc_ref(); // Connection reference handler->set_connection(this); handler->set_stream(stream); if (pending_writes_.is_empty() || pending_writes_.back()->is_flushed()) { if (ssl_session_) { pending_writes_.add_to_back(new PendingWriteSsl(this)); } else { pending_writes_.add_to_back(new PendingWrite(this)); } } PendingWriteBase *pending_write = pending_writes_.back(); int32_t request_size = pending_write->write(handler); if (request_size < 0) { stream_manager_.release(stream); switch (request_size) { case Request::ENCODE_ERROR_BATCH_WITH_NAMED_VALUES: case Request::ENCODE_ERROR_PARAMETER_UNSET: // Already handled break; default: handler->on_error(CASS_ERROR_LIB_MESSAGE_ENCODE, "Operation unsupported by this protocol version"); break; } handler->dec_ref(); return true; // Don't retry } pending_writes_size_ += request_size; if (pending_writes_size_ > config_.write_bytes_high_water_mark()) { LOG_WARN("Exceeded write bytes water mark (current: %u water mark: %u) on connection to host %s", static_cast<unsigned int>(pending_writes_size_), config_.write_bytes_high_water_mark(), host_->address_string().c_str()); metrics_->exceeded_write_bytes_water_mark.inc(); set_state(CONNECTION_STATE_OVERWHELMED); } LOG_TRACE("Sending message type %s with stream %d", opcode_to_string(handler->request()->opcode()).c_str(), stream); handler->set_state(Handler::REQUEST_STATE_WRITING); uint64_t request_timeout_ms = handler->request_timeout_ms(config_); if (request_timeout_ms > 0) { // 0 means no timeout handler->start_timer(loop_, request_timeout_ms, handler, Connection::on_timeout); } if (flush_immediately) { pending_write->flush(); } return true; }