-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
ServerIdleSessionController.cpp
88 lines (77 loc) · 2.8 KB
/
ServerIdleSessionController.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <proxygen/lib/http/connpool/ServerIdleSessionController.h>
namespace proxygen {
folly::Future<HTTPSessionBase*> ServerIdleSessionController::getIdleSession() {
folly::Promise<HTTPSessionBase*> promise;
folly::Future<HTTPSessionBase*> future = promise.getFuture();
SessionPool* maxPool = nullptr;
{
std::lock_guard<std::mutex> lock(lock_);
maxPool = popBestIdlePool();
if (markedForDeath_ || !maxPool || !maxPool->getEventBase()) {
return folly::makeFuture<HTTPSessionBase*>(nullptr);
}
}
if (maxPool->getEventBase()->isInEventBaseThread()) {
LOG(ERROR) << "Idle session already belongs to current thread!";
return folly::makeFuture<HTTPSessionBase*>(nullptr);
}
maxPool->getEventBase()->runInEventBaseThread(
[this, maxPool, promise = std::move(promise)]() mutable {
// Caller (in this case Server::getTransaction()) needs to guarantee
// that 'this' still exists.
HTTPSessionBase* session =
isMarkedForDeath() ? nullptr : maxPool->removeOldestIdleSession();
if (session) {
session->detachThreadLocals(true);
}
promise.setValue(session);
});
return future;
}
void ServerIdleSessionController::addIdleSession(const HTTPSessionBase* session,
SessionPool* sessionPool) {
std::lock_guard<std::mutex> lock(lock_);
if (sessionMap_.find(session) != sessionMap_.end()) {
// removeIdleSession should've been called before re-adding
LOG(ERROR) << "Session " << session << " already exists!";
return;
}
if (sessionsByIdleAge_.size() < maxIdleCount_) {
auto newIt = sessionsByIdleAge_.insert(sessionsByIdleAge_.end(),
{session, sessionPool});
sessionMap_[session] = newIt;
}
}
void ServerIdleSessionController::removeIdleSession(
const HTTPSessionBase* session) {
std::lock_guard<std::mutex> lock(lock_);
auto it = sessionMap_.find(session);
if (it != sessionMap_.end()) {
sessionsByIdleAge_.erase(it->second);
sessionMap_.erase(it);
}
}
void ServerIdleSessionController::markForDeath() {
std::lock_guard<std::mutex> lock(lock_);
markedForDeath_ = true;
sessionMap_.clear();
sessionsByIdleAge_.clear();
}
// must be called under lock_
SessionPool* FOLLY_NULLABLE ServerIdleSessionController::popBestIdlePool() {
if (!sessionsByIdleAge_.empty()) {
auto ret = *sessionsByIdleAge_.begin();
sessionsByIdleAge_.erase(sessionsByIdleAge_.begin());
sessionMap_.erase(ret.session);
return ret.sessionPool;
}
return nullptr;
}
} // namespace proxygen