void Stream::SetConnected(const StreamSettings* remote_settings) { bthread_mutex_lock(&_connect_mutex); if (_closed) { bthread_mutex_unlock(&_connect_mutex); return; } if (_connected) { CHECK(false); bthread_mutex_unlock(&_connect_mutex); return; } CHECK(_host_socket != NULL); if (remote_settings != NULL) { CHECK(!_remote_settings.IsInitialized()); _remote_settings.MergeFrom(*remote_settings); } else { CHECK(_remote_settings.IsInitialized()); } CHECK(_host_socket != NULL); RPC_VLOG << "stream=" << id() << " is connected to stream_id=" << _remote_settings.stream_id() << " at host_socket=" << *_host_socket; _connected = true; _connect_meta.ec = 0; TriggerOnConnectIfNeed(); if (remote_settings == NULL) { // Start the timer at server-side // Client-side timer would triggered in Consume after received the first // message which is the very RPC response StartIdleTimer(); } }
int Stream::Connect(Socket* ptr, const timespec*, int (*on_connect)(int, int, void *), void *data) { CHECK_EQ(ptr->id(), _id); bthread_mutex_lock(&_connect_mutex); if (_connect_meta.on_connect != NULL) { CHECK(false) << "Connect is supposed to be called once"; bthread_mutex_unlock(&_connect_mutex); return -1; } _connect_meta.on_connect = on_connect; _connect_meta.arg = data; if (_connected) { ConnectMeta* meta = new ConnectMeta; meta->on_connect = _connect_meta.on_connect; meta->arg = _connect_meta.arg; meta->ec = _connect_meta.ec; bthread_mutex_unlock(&_connect_mutex); bthread_t tid; if (bthread_start_urgent(&tid, &BTHREAD_ATTR_NORMAL, RunOnConnect, meta) != 0) { LOG(FATAL) << "Fail to start bthread, " << berror(); RunOnConnect(meta); } return 0; } bthread_mutex_unlock(&_connect_mutex); return 0; }
int bthread_cond_wait(bthread_cond_t *c, bthread_mutex_t *m) { c->waiters[vcore_id()] = 1; bthread_mutex_unlock(m); volatile int* poll = &c->waiters[vcore_id()]; while(*poll); bthread_mutex_lock(m); return 0; }
void Stream::Close() { _fake_socket_weak_ref->SetFailed(); bthread_mutex_lock(&_connect_mutex); if (_closed) { bthread_mutex_unlock(&_connect_mutex); return; } _closed = true; if (_connected) { bthread_mutex_unlock(&_connect_mutex); return; } _connect_meta.ec = ECONNRESET; // Trigger on connect to release the reference of socket return TriggerOnConnectIfNeed(); }
void Stream::Wait(void (*on_writable)(StreamId, void*, int), void* arg, const timespec* due_time, bool new_thread, bthread_id_t *join_id) { WritableMeta *wm = new WritableMeta; wm->on_writable = on_writable; wm->id = id(); wm->arg = arg; wm->new_thread = new_thread; wm->has_timer = false; bthread_id_t wait_id; const int rc = bthread_id_create(&wait_id, wm, TriggerOnWritable); if (rc != 0) { CHECK(false) << "Fail to create bthread_id, " << berror(rc); wm->error_code = rc; RunOnWritable(wm); return; } if (join_id) { *join_id = wait_id; } CHECK_EQ(0, bthread_id_lock(wait_id, NULL)); if (due_time != NULL) { wm->has_timer = true; const int rc = bthread_timer_add(&wm->timer, *due_time, OnTimedOut, reinterpret_cast<void*>(wait_id.value)); if (rc != 0) { LOG(ERROR) << "Fail to add timer, " << berror(rc); CHECK_EQ(0, TriggerOnWritable(wait_id, wm, rc)); } } bthread_mutex_lock(&_congestion_control_mutex); if (_options.max_buf_size <= 0 || _produced < _remote_consumed + (size_t)_options.max_buf_size) { bthread_mutex_unlock(&_congestion_control_mutex); CHECK_EQ(0, TriggerOnWritable(wait_id, wm, 0)); return; } else { bthread_id_list_add(&_writable_wait_list, wait_id); bthread_mutex_unlock(&_congestion_control_mutex); } CHECK_EQ(0, bthread_id_unlock(wait_id)); }
void Stream::SetRemoteConsumed(size_t new_remote_consumed) { CHECK(_options.max_buf_size > 0); bthread_id_list_t tmplist; bthread_id_list_init(&tmplist, 0, 0); bthread_mutex_lock(&_congestion_control_mutex); if (_remote_consumed >= new_remote_consumed) { bthread_mutex_unlock(&_congestion_control_mutex); return; } const bool was_full = _produced >= _remote_consumed + (size_t)_options.max_buf_size; _remote_consumed = new_remote_consumed; const bool is_full = _produced >= _remote_consumed + (size_t)_options.max_buf_size; if (was_full && !is_full) { bthread_id_list_swap(&tmplist, &_writable_wait_list); } bthread_mutex_unlock(&_congestion_control_mutex); // broadcast bthread_id_list_reset(&tmplist, 0); bthread_id_list_destroy(&tmplist); }