Google format
This commit is contained in:
151
.clang-format
Normal file
151
.clang-format
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: Google
|
||||||
|
AccessModifierOffset: -1
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 80
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: true
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<ext/.*\.h>'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '^<.*\.h>'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^<.*'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 3
|
||||||
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 2
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBinPackProtocolList: Never
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
|
PointerAlignment: Left
|
||||||
|
RawStringFormats:
|
||||||
|
- Language: Cpp
|
||||||
|
Delimiters:
|
||||||
|
- cc
|
||||||
|
- CC
|
||||||
|
- cpp
|
||||||
|
- Cpp
|
||||||
|
- CPP
|
||||||
|
- 'c++'
|
||||||
|
- 'C++'
|
||||||
|
CanonicalDelimiter: ''
|
||||||
|
BasedOnStyle: google
|
||||||
|
- Language: TextProto
|
||||||
|
Delimiters:
|
||||||
|
- pb
|
||||||
|
- PB
|
||||||
|
- proto
|
||||||
|
- PROTO
|
||||||
|
EnclosingFunctions:
|
||||||
|
- EqualsProto
|
||||||
|
- EquivToProto
|
||||||
|
- PARSE_PARTIAL_TEXT_PROTO
|
||||||
|
- PARSE_TEST_PROTO
|
||||||
|
- PARSE_TEXT_PROTO
|
||||||
|
- ParseTextOrDie
|
||||||
|
- ParseTextProtoOrDie
|
||||||
|
CanonicalDelimiter: ''
|
||||||
|
BasedOnStyle: google
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: true
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Auto
|
||||||
|
StatementMacros:
|
||||||
|
- Q_UNUSED
|
||||||
|
- QT_REQUIRE_VERSION
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Never
|
||||||
|
...
|
||||||
|
|
||||||
@@ -1,57 +1,57 @@
|
|||||||
#include <atomic>
|
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <atomic>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
DEFINE_int32(port, 9000, "TCP port to bind");
|
DEFINE_int32(port, 9000, "TCP port to bind");
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
google::InitGoogleLogging(argv[0]);
|
google::InitGoogleLogging(argv[0]);
|
||||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||||
|
|
||||||
std::mutex mu;
|
std::mutex mu;
|
||||||
std::unordered_set<firesse::Stream*> streams;
|
std::unordered_set<firesse::Stream*> streams;
|
||||||
std::atomic<bool> running = true;
|
std::atomic<bool> running = true;
|
||||||
|
|
||||||
std::thread clock([&streams, &mu, &running]() {
|
std::thread clock([&streams, &mu, &running]() {
|
||||||
while (running) {
|
while (running) {
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
||||||
timeval tv;
|
timeval tv;
|
||||||
PCHECK(gettimeofday(&tv, nullptr) == 0);
|
PCHECK(gettimeofday(&tv, nullptr) == 0);
|
||||||
const uint64_t time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
const uint64_t time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
const auto time_str = std::to_string(time_ms);
|
const auto time_str = std::to_string(time_ms);
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard l(mu);
|
std::lock_guard l(mu);
|
||||||
for (auto* stream : streams) {
|
for (auto* stream : streams) {
|
||||||
stream->WriteEvent(time_str, 0, "time");
|
stream->WriteEvent(time_str, 0, "time");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
firesse::Server server(FLAGS_port, [&streams, &mu](firesse::Stream* stream) {
|
firesse::Server server(FLAGS_port, [&streams, &mu](firesse::Stream* stream) {
|
||||||
LOG(INFO) << "new stream: " << stream;
|
LOG(INFO) << "new stream: " << stream;
|
||||||
|
|
||||||
std::lock_guard l(mu);
|
std::lock_guard l(mu);
|
||||||
streams.insert(stream);
|
streams.insert(stream);
|
||||||
stream->OnClose([stream, &streams, &mu]() {
|
stream->OnClose([stream, &streams, &mu]() {
|
||||||
LOG(INFO) << "stream closed: " << stream;
|
LOG(INFO) << "stream closed: " << stream;
|
||||||
|
|
||||||
std::lock_guard l(mu);
|
std::lock_guard l(mu);
|
||||||
streams.erase(stream);
|
streams.erase(stream);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
server.RegisterSignalHandlers();
|
server.RegisterSignalHandlers();
|
||||||
server.Serve();
|
server.Serve();
|
||||||
|
|
||||||
running = false;
|
running = false;
|
||||||
clock.join();
|
clock.join();
|
||||||
|
|
||||||
gflags::ShutDownCommandLineFlags();
|
gflags::ShutDownCommandLineFlags();
|
||||||
google::ShutdownGoogleLogging();
|
google::ShutdownGoogleLogging();
|
||||||
}
|
}
|
||||||
|
|||||||
2
firecgi
2
firecgi
Submodule firecgi updated: a39ef8e25d...f9988beb88
142
index.cc
142
index.cc
@@ -3,92 +3,94 @@
|
|||||||
namespace firesse {
|
namespace firesse {
|
||||||
|
|
||||||
void Index::Add(Stream* stream) {
|
void Index::Add(Stream* stream) {
|
||||||
std::lock_guard l(mu_);
|
std::lock_guard l(mu_);
|
||||||
|
|
||||||
stream->last_message_time_ = std::chrono::steady_clock::now();
|
stream->last_message_time_ = std::chrono::steady_clock::now();
|
||||||
stream->fresher_ = nullptr;
|
stream->fresher_ = nullptr;
|
||||||
stream->staler_ = freshest_;
|
stream->staler_ = freshest_;
|
||||||
if (stream->staler_) {
|
if (stream->staler_) {
|
||||||
stream->staler_->fresher_ = stream;
|
stream->staler_->fresher_ = stream;
|
||||||
}
|
}
|
||||||
freshest_ = stream;
|
freshest_ = stream;
|
||||||
if (!stalest_) {
|
if (!stalest_) {
|
||||||
stalest_ = stream;
|
stalest_ = stream;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Index::Remove(Stream* stream) {
|
void Index::Remove(Stream* stream) {
|
||||||
std::lock_guard l(mu_);
|
std::lock_guard l(mu_);
|
||||||
|
|
||||||
if (freshest_ == stream) {
|
if (freshest_ == stream) {
|
||||||
freshest_ = stream->staler_;
|
freshest_ = stream->staler_;
|
||||||
}
|
}
|
||||||
if (stalest_ == stream) {
|
if (stalest_ == stream) {
|
||||||
stalest_ = stream->fresher_;
|
stalest_ = stream->fresher_;
|
||||||
}
|
}
|
||||||
if (stream->fresher_) {
|
if (stream->fresher_) {
|
||||||
stream->fresher_->staler_ = stream->staler_;
|
stream->fresher_->staler_ = stream->staler_;
|
||||||
stream->fresher_ = nullptr;
|
stream->fresher_ = nullptr;
|
||||||
}
|
}
|
||||||
if (stream->staler_) {
|
if (stream->staler_) {
|
||||||
stream->staler_->fresher_ = stream->fresher_;
|
stream->staler_->fresher_ = stream->fresher_;
|
||||||
stream->staler_ = nullptr;
|
stream->staler_ = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Index::Freshen(Stream* stream) {
|
void Index::Freshen(Stream* stream) {
|
||||||
std::lock_guard l(mu_);
|
std::lock_guard l(mu_);
|
||||||
if (freshest_ == stream) {
|
if (freshest_ == stream) {
|
||||||
// Shortcut
|
// Shortcut
|
||||||
stream->last_message_time_ = std::chrono::steady_clock::now();
|
stream->last_message_time_ = std::chrono::steady_clock::now();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Remove(stream);
|
Remove(stream);
|
||||||
Add(stream);
|
Add(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::chrono::nanoseconds Index::WithStalest(std::function<void(Stream*)> callback, const std::chrono::nanoseconds& min_stale) {
|
std::chrono::nanoseconds Index::WithStalest(
|
||||||
Stream* stalest = nullptr;
|
std::function<void(Stream*)> callback,
|
||||||
std::chrono::nanoseconds ret;
|
const std::chrono::nanoseconds& min_stale) {
|
||||||
const auto now = std::chrono::steady_clock::now();
|
Stream* stalest = nullptr;
|
||||||
const auto latest = now - min_stale;
|
std::chrono::nanoseconds ret;
|
||||||
|
const auto now = std::chrono::steady_clock::now();
|
||||||
|
const auto latest = now - min_stale;
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard l(mu_);
|
std::lock_guard l(mu_);
|
||||||
if (!stalest_) {
|
if (!stalest_) {
|
||||||
return min_stale;
|
return min_stale;
|
||||||
}
|
}
|
||||||
if (stalest_->last_message_time_ > latest) {
|
if (stalest_->last_message_time_ > latest) {
|
||||||
return stalest_->last_message_time_ - latest;
|
return stalest_->last_message_time_ - latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stalest_ is valid for callback
|
// stalest_ is valid for callback
|
||||||
stalest = stalest_;
|
stalest = stalest_;
|
||||||
|
|
||||||
if (stalest->fresher_) {
|
if (stalest->fresher_) {
|
||||||
if (stalest->fresher_->last_message_time_ > latest) {
|
if (stalest->fresher_->last_message_time_ > latest) {
|
||||||
ret = stalest_->fresher_->last_message_time_ - latest;
|
ret = stalest_->fresher_->last_message_time_ - latest;
|
||||||
}
|
}
|
||||||
// Otherwise ret is 0 for immediate cycle
|
// Otherwise ret is 0 for immediate cycle
|
||||||
} else {
|
} else {
|
||||||
ret = min_stale;
|
ret = min_stale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stalest->mu_.try_lock()) {
|
if (!stalest->mu_.try_lock()) {
|
||||||
// We're acquiring mutexes in the wrong order here; normally it's
|
// We're acquiring mutexes in the wrong order here; normally it's
|
||||||
// (Stream, Index), but we're doing (Index, Stream). That means we
|
// (Stream, Index), but we're doing (Index, Stream). That means we
|
||||||
// may deadlock. We take the lower-priority path and fail in case
|
// may deadlock. We take the lower-priority path and fail in case
|
||||||
// of deadlock.
|
// of deadlock.
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Freshen(stalest);
|
Freshen(stalest);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(stalest);
|
callback(stalest);
|
||||||
stalest->mu_.unlock();
|
stalest->mu_.unlock();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace firesse
|
} // namespace firesse
|
||||||
|
|||||||
28
index.h
28
index.h
@@ -11,20 +11,22 @@ namespace firesse {
|
|||||||
// Avoids allocation and folds in iterators by using an intrusive list
|
// Avoids allocation and folds in iterators by using an intrusive list
|
||||||
// inside Stream.
|
// inside Stream.
|
||||||
class Index {
|
class Index {
|
||||||
public:
|
public:
|
||||||
void Add(Stream* stream);
|
void Add(Stream* stream);
|
||||||
void Remove(Stream* stream);
|
void Remove(Stream* stream);
|
||||||
void Freshen(Stream* stream);
|
void Freshen(Stream* stream);
|
||||||
|
|
||||||
// Returns time to sleep until next stalest, or min_stale if none
|
// Returns time to sleep until next stalest, or min_stale if none
|
||||||
// Only calls callback if stalest is at least min_stale
|
// Only calls callback if stalest is at least min_stale
|
||||||
// Handles all locking and marks Stream as fresh after callback
|
// Handles all locking and marks Stream as fresh after callback
|
||||||
std::chrono::nanoseconds WithStalest(std::function<void(Stream*)> callback, const std::chrono::nanoseconds& min_stale);
|
std::chrono::nanoseconds WithStalest(
|
||||||
|
std::function<void(Stream*)> callback,
|
||||||
|
const std::chrono::nanoseconds& min_stale);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::recursive_mutex mu_;
|
std::recursive_mutex mu_;
|
||||||
Stream* freshest_ = nullptr;
|
Stream* freshest_ = nullptr;
|
||||||
Stream* stalest_ = nullptr;
|
Stream* stalest_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace firesse
|
} // namespace firesse
|
||||||
|
|||||||
54
keepalive.cc
54
keepalive.cc
@@ -6,42 +6,38 @@
|
|||||||
namespace firesse {
|
namespace firesse {
|
||||||
|
|
||||||
KeepAlive::KeepAlive(const std::chrono::nanoseconds& max_stale, Index* index)
|
KeepAlive::KeepAlive(const std::chrono::nanoseconds& max_stale, Index* index)
|
||||||
: max_stale_(max_stale),
|
: max_stale_(max_stale), index_(index), shutdown_fd_(eventfd(0, 0)) {
|
||||||
index_(index),
|
PCHECK(shutdown_fd_ >= 0) << "eventfd()";
|
||||||
shutdown_fd_(eventfd(0, 0)) {
|
|
||||||
PCHECK(shutdown_fd_ >= 0) << "eventfd()";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeepAlive::~KeepAlive() {
|
KeepAlive::~KeepAlive() { PCHECK(close(shutdown_fd_) == 0); }
|
||||||
PCHECK(close(shutdown_fd_) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeepAlive::Start() {
|
void KeepAlive::Start() {
|
||||||
thread_ = std::thread([this]() {
|
thread_ = std::thread([this]() {
|
||||||
int timeout = 0;
|
int timeout = 0;
|
||||||
constexpr auto num_fds = 1;
|
constexpr auto num_fds = 1;
|
||||||
pollfd fds[num_fds] = {
|
pollfd fds[num_fds] = {
|
||||||
{
|
{
|
||||||
.fd = shutdown_fd_,
|
.fd = shutdown_fd_,
|
||||||
.events = POLLIN,
|
.events = POLLIN,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
while (running_ && (timeout == 0 || poll(fds, num_fds, timeout) <= 0)) {
|
while (running_ && (timeout == 0 || poll(fds, num_fds, timeout) <= 0)) {
|
||||||
auto sleep = index_->WithStalest([](Stream* stream) {
|
auto sleep = index_->WithStalest(
|
||||||
stream->WriteRaw(":\n");
|
[](Stream* stream) { stream->WriteRaw(":\n"); }, max_stale_);
|
||||||
}, max_stale_);
|
timeout =
|
||||||
timeout = std::chrono::duration_cast<std::chrono::milliseconds>(sleep).count();
|
std::chrono::duration_cast<std::chrono::milliseconds>(sleep).count();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeepAlive::Stop() {
|
void KeepAlive::Stop() {
|
||||||
CHECK(thread_.joinable());
|
CHECK(thread_.joinable());
|
||||||
|
|
||||||
running_ = false;
|
running_ = false;
|
||||||
uint64_t shutdown = 1;
|
uint64_t shutdown = 1;
|
||||||
PCHECK(write(shutdown_fd_, &shutdown, sizeof(shutdown)) == sizeof(shutdown));
|
PCHECK(write(shutdown_fd_, &shutdown, sizeof(shutdown)) == sizeof(shutdown));
|
||||||
thread_.join();
|
thread_.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace firesse
|
} // namespace firesse
|
||||||
|
|||||||
28
keepalive.h
28
keepalive.h
@@ -8,23 +8,23 @@
|
|||||||
namespace firesse {
|
namespace firesse {
|
||||||
|
|
||||||
class KeepAlive {
|
class KeepAlive {
|
||||||
public:
|
public:
|
||||||
KeepAlive(const std::chrono::nanoseconds& max_stale, Index* index);
|
KeepAlive(const std::chrono::nanoseconds& max_stale, Index* index);
|
||||||
~KeepAlive();
|
~KeepAlive();
|
||||||
|
|
||||||
void Start();
|
void Start();
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::chrono::nanoseconds max_stale_;
|
const std::chrono::nanoseconds max_stale_;
|
||||||
Index* index_;
|
Index* index_;
|
||||||
|
|
||||||
// Two shutdown mechanisms, one for if we're in a tight no-syscall loop,
|
// Two shutdown mechanisms, one for if we're in a tight no-syscall loop,
|
||||||
// and one for if we're sleeping in poll()
|
// and one for if we're sleeping in poll()
|
||||||
int shutdown_fd_;
|
int shutdown_fd_;
|
||||||
std::atomic<bool> running_ = true;
|
std::atomic<bool> running_ = true;
|
||||||
|
|
||||||
std::thread thread_;
|
std::thread thread_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace firesse
|
} // namespace firesse
|
||||||
|
|||||||
47
server.cc
47
server.cc
@@ -3,41 +3,38 @@
|
|||||||
namespace firesse {
|
namespace firesse {
|
||||||
|
|
||||||
Server::Server(int port, const std::function<void(Stream*)>& callback)
|
Server::Server(int port, const std::function<void(Stream*)>& callback)
|
||||||
: callback_(callback),
|
: callback_(callback),
|
||||||
keep_alive_(std::chrono::seconds(15), &index_),
|
keep_alive_(std::chrono::seconds(15), &index_),
|
||||||
firecgi_server_(port,
|
firecgi_server_(
|
||||||
[this](firecgi::Request* request) { OnRequest(request); },
|
port, [this](firecgi::Request* request) { OnRequest(request); }, 1) {}
|
||||||
1) {}
|
|
||||||
|
|
||||||
void Server::Serve() {
|
void Server::Serve() {
|
||||||
keep_alive_.Start();
|
keep_alive_.Start();
|
||||||
firecgi_server_.Serve();
|
firecgi_server_.Serve();
|
||||||
keep_alive_.Stop();
|
keep_alive_.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::Shutdown() {
|
void Server::Shutdown() { firecgi_server_.Shutdown(); }
|
||||||
firecgi_server_.Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::RegisterSignalHandlers() {
|
void Server::RegisterSignalHandlers() {
|
||||||
firecgi_server_.RegisterSignalHandlers();
|
firecgi_server_.RegisterSignalHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::OnRequest(firecgi::Request* request) {
|
void Server::OnRequest(firecgi::Request* request) {
|
||||||
request->WriteHeader("Content-Type", "text/event-stream; charset=utf-8");
|
request->WriteHeader("Content-Type", "text/event-stream; charset=utf-8");
|
||||||
request->WriteHeader("Cache-Control", "no-cache");
|
request->WriteHeader("Cache-Control", "no-cache");
|
||||||
request->WriteHeader("X-Accel-Buffering", "no");
|
request->WriteHeader("X-Accel-Buffering", "no");
|
||||||
request->WriteBody("");
|
request->WriteBody("");
|
||||||
auto stream = new Stream(request, &index_);
|
auto stream = new Stream(request, &index_);
|
||||||
|
|
||||||
{
|
{
|
||||||
request->OnClose([stream]() {
|
request->OnClose([stream]() {
|
||||||
stream->Close();
|
stream->Close();
|
||||||
delete stream;
|
delete stream;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
callback_(stream);
|
callback_(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace firesse
|
} // namespace firesse
|
||||||
|
|||||||
24
server.h
24
server.h
@@ -11,19 +11,19 @@
|
|||||||
namespace firesse {
|
namespace firesse {
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
public:
|
public:
|
||||||
Server(int port, const std::function<void(Stream*)>& callback);
|
Server(int port, const std::function<void(Stream*)>& callback);
|
||||||
void Serve();
|
void Serve();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void RegisterSignalHandlers();
|
void RegisterSignalHandlers();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnRequest(firecgi::Request* request);
|
void OnRequest(firecgi::Request* request);
|
||||||
|
|
||||||
std::function<void(Stream*)> callback_;
|
std::function<void(Stream*)> callback_;
|
||||||
Index index_;
|
Index index_;
|
||||||
KeepAlive keep_alive_;
|
KeepAlive keep_alive_;
|
||||||
firecgi::Server firecgi_server_;
|
firecgi::Server firecgi_server_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace firesse
|
} // namespace firesse
|
||||||
|
|||||||
56
stream.cc
56
stream.cc
@@ -5,52 +5,50 @@
|
|||||||
namespace firesse {
|
namespace firesse {
|
||||||
|
|
||||||
Stream::Stream(firecgi::Request* request, Index* index)
|
Stream::Stream(firecgi::Request* request, Index* index)
|
||||||
: request_(request),
|
: request_(request), index_(index) {
|
||||||
index_(index) {
|
index_->Add(this);
|
||||||
index_->Add(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream::~Stream() {
|
Stream::~Stream() {
|
||||||
std::lock_guard l(mu_);
|
std::lock_guard l(mu_);
|
||||||
index_->Remove(this);
|
index_->Remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stream::OnClose(const std::function<void()>& callback) {
|
void Stream::OnClose(const std::function<void()>& callback) {
|
||||||
on_close_ = callback;
|
on_close_ = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Stream::WriteEvent(const std::string_view& data, uint64_t id, const std::string& type) {
|
bool Stream::WriteEvent(const std::string_view& data, uint64_t id,
|
||||||
std::lock_guard l(mu_);
|
const std::string& type) {
|
||||||
|
std::lock_guard l(mu_);
|
||||||
|
|
||||||
index_->Freshen(this);
|
index_->Freshen(this);
|
||||||
|
|
||||||
return request_->InTransaction<bool>([=]() {
|
return request_->InTransaction<bool>([=]() {
|
||||||
if (id) {
|
if (id) {
|
||||||
request_->WriteBody("id: ", std::to_string(id), "\n");
|
request_->WriteBody("id: ", std::to_string(id), "\n");
|
||||||
}
|
}
|
||||||
if (!type.empty()) {
|
if (!type.empty()) {
|
||||||
request_->WriteBody("event: ", type, "\n");
|
request_->WriteBody("event: ", type, "\n");
|
||||||
}
|
}
|
||||||
request_->WriteBody("data: ", data, "\n\n");
|
request_->WriteBody("data: ", data, "\n\n");
|
||||||
return request_->Flush();
|
return request_->Flush();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Stream::WriteRaw(const std::string_view& data) {
|
bool Stream::WriteRaw(const std::string_view& data) {
|
||||||
std::lock_guard l(mu_);
|
std::lock_guard l(mu_);
|
||||||
|
|
||||||
request_->WriteBody(data);
|
request_->WriteBody(data);
|
||||||
return request_->Flush();
|
return request_->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Stream::End() {
|
bool Stream::End() { return request_->End(); }
|
||||||
return request_->End();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Stream::Close() {
|
void Stream::Close() {
|
||||||
if (on_close_) {
|
if (on_close_) {
|
||||||
on_close_();
|
on_close_();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace firesse
|
} // namespace firesse
|
||||||
|
|||||||
39
stream.h
39
stream.h
@@ -9,30 +9,31 @@ namespace firesse {
|
|||||||
class Index;
|
class Index;
|
||||||
|
|
||||||
class Stream {
|
class Stream {
|
||||||
public:
|
public:
|
||||||
Stream(firecgi::Request* request, Index* index);
|
Stream(firecgi::Request* request, Index* index);
|
||||||
~Stream();
|
~Stream();
|
||||||
|
|
||||||
void OnClose(const std::function<void()>& callback);
|
void OnClose(const std::function<void()>& callback);
|
||||||
|
|
||||||
bool WriteEvent(const std::string_view& data, uint64_t id=0, const std::string& type="");
|
bool WriteEvent(const std::string_view& data, uint64_t id = 0,
|
||||||
bool WriteRaw(const std::string_view& data);
|
const std::string& type = "");
|
||||||
bool End();
|
bool WriteRaw(const std::string_view& data);
|
||||||
void Close();
|
bool End();
|
||||||
|
void Close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
firecgi::Request* request_;
|
firecgi::Request* request_;
|
||||||
Index* index_;
|
Index* index_;
|
||||||
|
|
||||||
std::function<void()> on_close_;
|
std::function<void()> on_close_;
|
||||||
|
|
||||||
// TODO: What exactly is this protecting?
|
// TODO: What exactly is this protecting?
|
||||||
std::recursive_mutex mu_;
|
std::recursive_mutex mu_;
|
||||||
std::chrono::steady_clock::time_point last_message_time_;
|
std::chrono::steady_clock::time_point last_message_time_;
|
||||||
Stream* fresher_;
|
Stream* fresher_;
|
||||||
Stream* staler_;
|
Stream* staler_;
|
||||||
|
|
||||||
friend class Index;
|
friend class Index;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace firesse
|
} // namespace firesse
|
||||||
|
|||||||
Reference in New Issue
Block a user