proxygen
AsyncFileWriterTest.cpp File Reference

Go to the source code of this file.

Classes

class  ReadStats
 
struct  ReadStats::ReaderData
 
struct  ReadStats::WriterData
 

Functions

 DEFINE_int64 (async_discard_num_normal_writers, 30,"number of threads to use to generate normal log messages during ""the AsyncFileWriter.discard test")
 
 DEFINE_int64 (async_discard_num_nodiscard_writers, 2,"number of threads to use to generate non-discardable log messages during ""the AsyncFileWriter.discard test")
 
 DEFINE_int64 (async_discard_read_sleep_usec, 500,"how long the read thread should sleep between reads in ""the AsyncFileWriter.discard test")
 
 DEFINE_int64 (async_discard_timeout_msec, 10000,"A timeout for the AsyncFileWriter.discard test if it cannot generate ""enough discards")
 
 DEFINE_int64 (async_discard_num_events, 10,"The number of discard events to wait for in the AsyncFileWriter.discard ""test")
 
 TEST (AsyncFileWriter, noMessages)
 
 TEST (AsyncFileWriter, simpleMessages)
 
 TEST (AsyncFileWriter, ioError)
 
 TEST (AsyncFileWriter, flush)
 
void readThread (folly::File &&file, ReadStats *stats)
 
void writeThread (AsyncFileWriter *writer, size_t id, uint32_t flags, ReadStats *readStats)
 
 TEST (AsyncFileWriter, discard)
 
 TEST (AsyncFileWriter, fork)
 
 TEST (AsyncFileWriter, crazyForks)
 

Variables

static constexpr StringPiece kMsgSuffix
 

Function Documentation

DEFINE_int64 ( async_discard_num_normal_writers  ,
30  ,
"number of threads to use to generate normal log messages during ""the AsyncFileWriter.discard test  
)
DEFINE_int64 ( async_discard_num_nodiscard_writers  ,
,
"number of threads to use to generate non-discardable log messages during ""the AsyncFileWriter.discard test  
)
DEFINE_int64 ( async_discard_read_sleep_usec  ,
500  ,
"how long the read thread should sleep between reads in ""the AsyncFileWriter.discard test  
)
DEFINE_int64 ( async_discard_timeout_msec  ,
10000  ,
"A timeout for the AsyncFileWriter.discard test if it cannot generate ""enough discards"   
)
DEFINE_int64 ( async_discard_num_events  ,
10  ,
"The number of discard events to wait for in the AsyncFileWriter.discard ""test  
)
void readThread ( folly::File &&  file,
ReadStats stats 
)

readThread() reads messages slowly from a pipe. This helps test the AsyncFileWriter behavior when I/O is slow.

Definition at line 506 of file AsyncFileWriterTest.cpp.

References buffer(), folly::Range< Iter >::data(), folly::DBG2, folly::test::end(), folly::ERR, ReadStats::getSleepUS(), ReadStats::messageReceived(), folly::Range< const char * >::npos, folly::readNoInt(), ReadStats::trailingData(), and XLOG.

Referenced by TEST().

506  {
507  std::vector<char> buffer;
508  buffer.resize(1024);
509 
510  size_t bufferIdx = 0;
511  while (true) {
512  /* sleep override */
513  std::this_thread::sleep_for(stats->getSleepUS());
514 
515  auto readResult = folly::readNoInt(
516  file.fd(), buffer.data() + bufferIdx, buffer.size() - bufferIdx);
517  if (readResult < 0) {
518  XLOG(ERR, "error reading from pipe: ", errno);
519  return;
520  }
521  if (readResult == 0) {
522  XLOG(DBG2, "read EOF");
523  break;
524  }
525 
526  auto logDataLen = bufferIdx + readResult;
527  StringPiece logData{buffer.data(), logDataLen};
528  auto idx = 0;
529  while (true) {
530  auto end = logData.find('\n', idx);
531  if (end == StringPiece::npos) {
532  bufferIdx = logDataLen - idx;
533  memmove(buffer.data(), buffer.data() + idx, bufferIdx);
534  break;
535  }
536 
537  StringPiece logMsg{logData.data() + idx, end - idx};
538  stats->messageReceived(logMsg);
539  idx = end + 1;
540  }
541  }
542 
543  if (bufferIdx != 0) {
544  stats->trailingData(StringPiece{buffer.data(), bufferIdx});
545  }
546 }
std::vector< uint8_t > buffer(kBufferSize+16)
std::chrono::microseconds getSleepUS() const
ssize_t readNoInt(int fd, void *buf, size_t count)
Definition: FileUtil.cpp:102
int fd() const
Definition: File.h:85
auto end(TestAdlIterable &instance)
Definition: ForeachTest.cpp:62
constexpr Iter data() const
Definition: Range.h:446
void messageReceived(StringPiece msg)
void trailingData(StringPiece data)
#define XLOG(level,...)
Definition: xlog.h:57
TEST ( AsyncFileWriter  ,
noMessages   
)

Definition at line 75 of file AsyncFileWriterTest.cpp.

References folly::File::fd().

75  {
76  TemporaryFile tmpFile{"logging_test"};
77 
78  // Test the simple construction and destruction of an AsyncFileWriter
79  // without ever writing any messages. This still exercises the I/O
80  // thread start-up and shutdown code.
81  AsyncFileWriter writer{folly::File{tmpFile.fd(), false}};
82 }
int fd() const
Definition: File.h:85
TEST ( AsyncFileWriter  ,
simpleMessages   
)

Definition at line 84 of file AsyncFileWriterTest.cpp.

References ASSERT_TRUE, folly::data(), EXPECT_EQ, folly::File::fd(), folly::gen::move, folly::readFile(), string, and folly::fibers::yield().

84  {
85  TemporaryFile tmpFile{"logging_test"};
86 
87  {
88  AsyncFileWriter writer{folly::File{tmpFile.fd(), false}};
89  for (int n = 0; n < 10; ++n) {
90  writer.writeMessage(folly::to<std::string>("message ", n, "\n"));
92  }
93  }
94  tmpFile.close();
95 
97  auto ret = folly::readFile(tmpFile.path().string().c_str(), data);
98  ASSERT_TRUE(ret);
99 
100  std::string expected =
101  "message 0\n"
102  "message 1\n"
103  "message 2\n"
104  "message 3\n"
105  "message 4\n"
106  "message 5\n"
107  "message 6\n"
108  "message 7\n"
109  "message 8\n"
110  "message 9\n";
111  EXPECT_EQ(expected, data);
112 }
bool readFile(int fd, Container &out, size_t num_bytes=std::numeric_limits< size_t >::max())
Definition: FileUtil.h:125
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
int fd() const
Definition: File.h:85
const char * string
Definition: Conv.cpp:212
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
TEST ( AsyncFileWriter  ,
ioError   
)

Definition at line 125 of file AsyncFileWriterTest.cpp.

References folly::checkUnixError(), folly::netops::close(), testing::ContainsRegex(), folly::data(), folly::DBG1, EXPECT_GT, EXPECT_LE, EXPECT_THAT, pipe(), folly::LoggerDB::setInternalWarningHandler(), string, folly::throwSystemError(), folly::writeNoInt(), XLOG, and folly::fibers::yield().

125  {
126  // Set the LoggerDB internal warning handler so we can record the messages
127  std::vector<std::string> logErrors;
128  internalWarnings = &logErrors;
129  LoggerDB::setInternalWarningHandler(handleLoggingError);
130 
131  // Create an AsyncFileWriter that refers to a pipe whose read end is closed
132  std::array<int, 2> fds;
133  auto rc = pipe(fds.data());
134  folly::checkUnixError(rc, "failed to create pipe");
135 #ifndef _WIN32
136  signal(SIGPIPE, SIG_IGN);
137 #endif
138  ::close(fds[0]);
139 
140  // Log a bunch of messages to the writer
141  size_t numMessages = 100;
142  {
143  AsyncFileWriter writer{folly::File{fds[1], true}};
144  for (size_t n = 0; n < numMessages; ++n) {
145  writer.writeMessage(folly::to<std::string>("message ", n, "\n"));
147  }
148  }
149 
150  LoggerDB::setInternalWarningHandler(nullptr);
151 
152  // AsyncFileWriter should have some internal warning messages about the
153  // log failures. This will generally be many fewer than the number of
154  // messages we wrote, though, since it performs write batching.
155  //
156  // GTest on Windows doesn't support alternation in the regex syntax -_-....
157  const std::string kExpectedErrorMessage =
158 #if _WIN32
159  // The `pipe` call above is actually implemented via sockets, so we get
160  // a different error message.
161  "An established connection was aborted by the software in your host machine\\.";
162 #else
163  "Broken pipe";
164 #endif
165 
166  for (const auto& msg : logErrors) {
167  EXPECT_THAT(
168  msg,
170  "error writing to log file .* in AsyncFileWriter.*: " +
171  kExpectedErrorMessage));
172  }
173  EXPECT_GT(logErrors.size(), 0);
174  EXPECT_LE(logErrors.size(), numMessages);
175 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
PolymorphicMatcher< internal::MatchesRegexMatcher > ContainsRegex(const internal::RE *regex)
void checkUnixError(ssize_t ret, Args &&...args)
Definition: Exception.h:101
#define EXPECT_THAT(value, matcher)
const char * string
Definition: Conv.cpp:212
int close(NetworkSocket s)
Definition: NetOps.cpp:90
void pipe(CPUExecutor cpu, IOExecutor io)
#define EXPECT_GT(val1, val2)
Definition: gtest.h:1934
TEST ( AsyncFileWriter  ,
flush   
)

Definition at line 215 of file AsyncFileWriterTest.cpp.

References folly::checkUnixError(), EXPECT_EQ, EXPECT_FALSE, folly::Promise< T >::getFuture(), folly::makeTryWith(), folly::gen::move, pipe(), folly::readFull(), folly::Promise< T >::setTry(), and string.

215  {
216  // Set up a pipe(), then write data to the write endpoint until it fills up
217  // and starts blocking.
218  std::array<int, 2> fds;
219  auto rc = pipe(fds.data());
220  folly::checkUnixError(rc, "failed to create pipe");
221  File readPipe{fds[0], true};
222  File writePipe{fds[1], true};
223 
224  auto paddingSize = fillUpPipe(writePipe.fd());
225 
226  // Now set up an AsyncFileWriter pointing at the write end of the pipe
227  AsyncFileWriter writer{std::move(writePipe)};
228 
229  // Write a message
230  writer.writeMessage("test message: " + std::string(200, 'x'));
231 
232  // Call flush(). Use a separate thread, since this should block until we
233  // consume data from the pipe.
234  Promise<Unit> promise;
235  auto future = promise.getFuture();
236  auto flushFunction = [&] { writer.flush(); };
237  std::thread flushThread{
238  [&]() { promise.setTry(makeTryWith(flushFunction)); }};
239  // Detach the flush thread now rather than joining it at the end of the
240  // function. This way if something goes wrong during the test we will fail
241  // with the real error, rather than crashing due to the std::thread
242  // destructor running on a still-joinable thread.
243  flushThread.detach();
244 
245  // Sleep briefly, and make sure flush() still hasn't completed.
246  // If it has completed this doesn't necessarily indicate a bug in
247  // AsyncFileWriter, but instead indicates that our test code failed to
248  // successfully cause a blocking write.
249  /* sleep override */
250  std::this_thread::sleep_for(10ms);
251  EXPECT_FALSE(future.isReady());
252 
253  // Now read from the pipe
254  std::vector<char> buf;
255  buf.resize(paddingSize);
256  auto bytesRead = readFull(readPipe.fd(), buf.data(), buf.size());
257  EXPECT_EQ(bytesRead, paddingSize);
258 
259  // Make sure flush completes successfully now
260  std::move(future).get(10ms);
261 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
ssize_t readFull(int fd, void *buf, size_t count)
Definition: FileUtil.cpp:126
void setTry(Try< T > &&t)
Definition: Promise-inl.h:122
Future< T > getFuture()
Definition: Promise-inl.h:97
void checkUnixError(ssize_t ret, Args &&...args)
Definition: Exception.h:101
std::enable_if< !std::is_same< invoke_result_t< F >, void >::value, Try< invoke_result_t< F > > >::type makeTryWith(F &&f)
Definition: Try-inl.h:223
const char * string
Definition: Conv.cpp:212
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
void pipe(CPUExecutor cpu, IOExecutor io)
TEST ( AsyncFileWriter  ,
discard   
)

Definition at line 583 of file AsyncFileWriterTest.cpp.

References ReadStats::check(), folly::checkUnixError(), ReadStats::clearSleepDuration(), folly::DBG2, folly::DBG4, folly::gen::move, folly::LogWriter::NEVER_DISCARD, pipe(), readThread(), folly::pushmi::detail::t, uint32_t, writeThread(), XLOG, and XLOGF.

583  {
584  std::array<int, 2> fds;
585  auto pipeResult = pipe(fds.data());
586  folly::checkUnixError(pipeResult, "pipe failed");
587  folly::File readPipe{fds[0], true};
588  folly::File writePipe{fds[1], true};
589 
590  ReadStats readStats;
591  std::thread reader(readThread, std::move(readPipe), &readStats);
592  {
593  AsyncFileWriter writer{std::move(writePipe)};
594 
595  std::vector<std::thread> writeThreads;
596  size_t numThreads = FLAGS_async_discard_num_normal_writers +
597  FLAGS_async_discard_num_nodiscard_writers;
598 
599  for (size_t n = 0; n < numThreads; ++n) {
600  uint32_t flags = 0;
601  if (n >= static_cast<size_t>(FLAGS_async_discard_num_normal_writers)) {
602  flags = LogWriter::NEVER_DISCARD;
603  }
604  XLOGF(DBG4, "writer {:4d} flags {:#02x}", n, flags);
605 
606  writeThreads.emplace_back(writeThread, &writer, n, flags, &readStats);
607  }
608 
609  for (auto& t : writeThreads) {
610  t.join();
611  }
612  XLOG(DBG2, "writers done");
613  }
614  // Clear the read sleep duration so the reader will finish quickly now
615  readStats.clearSleepDuration();
616  reader.join();
617  readStats.check();
618 }
flags
Definition: http_parser.h:127
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void writeThread(AsyncFileWriter *writer, size_t id, uint32_t flags, ReadStats *readStats)
void checkUnixError(ssize_t ret, Args &&...args)
Definition: Exception.h:101
#define XLOGF(level, fmt, arg1,...)
Definition: xlog.h:77
#define XLOG(level,...)
Definition: xlog.h:57
void readThread(folly::File &&file, ReadStats *stats)
void pipe(CPUExecutor cpu, IOExecutor io)
TEST ( AsyncFileWriter  ,
fork   
)

Test that AsyncFileWriter operates correctly after a fork() in both the parent and child processes.

Definition at line 624 of file AsyncFileWriterTest.cpp.

References ASSERT_EQ, ASSERT_TRUE, folly::checkUnixError(), testing::ContainsRegex(), folly::data(), folly::DBG1, EXPECT_THAT, folly::File::fd(), folly::readFile(), SKIP, stop(), string, folly::pushmi::detail::t, and XLOG.

624  {
625 #if FOLLY_HAVE_PTHREAD_ATFORK
626  TemporaryFile tmpFile{"logging_test"};
627 
628  // The number of messages to send before the fork and from each process
629  constexpr size_t numMessages = 10;
630  constexpr size_t numBgThreads = 2;
631 
632  // This can be increased to add some delay in the parent and child messages
633  // so that they are likely to be interleaved in the log rather than grouped
634  // together. This doesn't really affect the test behavior or correctness
635  // otherwise, though.
636  constexpr milliseconds sleepDuration(0);
637 
638  {
639  AsyncFileWriter writer{folly::File{tmpFile.fd(), false}};
640  writer.writeMessage(folly::to<std::string>("parent pid=", getpid(), "\n"));
641 
642  // Start some background threads just to exercise the behavior
643  // when other threads are also logging to the writer when the fork occurs
644  std::vector<std::thread> bgThreads;
645  std::atomic<bool> stop{false};
646  for (size_t n = 0; n < numBgThreads; ++n) {
647  bgThreads.emplace_back([&] {
648  size_t iter = 0;
649  while (!stop) {
650  writer.writeMessage(
651  folly::to<std::string>("bgthread_", getpid(), "_", iter, "\n"));
652  ++iter;
653  }
654  });
655  }
656 
657  for (size_t n = 0; n < numMessages; ++n) {
658  writer.writeMessage(folly::to<std::string>("prefork", n, "\n"));
659  }
660 
661  auto pid = fork();
662  folly::checkUnixError(pid, "failed to fork");
663  if (pid == 0) {
664  writer.writeMessage(folly::to<std::string>("child pid=", getpid(), "\n"));
665  for (size_t n = 0; n < numMessages; ++n) {
666  writer.writeMessage(folly::to<std::string>("child", n, "\n"));
667  std::this_thread::sleep_for(sleepDuration);
668  }
669 
670  // Use _exit() rather than exit() in the child, purely to prevent
671  // ASAN from complaining that we leak memory for the background threads.
672  // (These threads don't actually exist in the child, so it is difficult
673  // to clean up their allocated state entirely.)
674  //
675  // Explicitly flush the writer since exiting with _exit() won't do this
676  // automatically.
677  writer.flush();
678  _exit(0);
679  }
680 
681  for (size_t n = 0; n < numMessages; ++n) {
682  writer.writeMessage(folly::to<std::string>("parent", n, "\n"));
683  std::this_thread::sleep_for(sleepDuration);
684  }
685 
686  // Stop the background threads.
687  stop = true;
688  for (auto& t : bgThreads) {
689  t.join();
690  }
691 
692  int status;
693  auto waited = waitpid(pid, &status, 0);
694  folly::checkUnixError(waited, "failed to wait on child");
695  ASSERT_EQ(waited, pid);
696  }
697 
698  // Read back the logged messages
699  tmpFile.close();
701  auto ret = folly::readFile(tmpFile.path().string().c_str(), data);
702  ASSERT_TRUE(ret) << "failed to read log file";
703 
704  XLOG(DBG1) << "log contents:\n" << data;
705 
706  // The log file should contain all of the messages we wrote, from both the
707  // parent and child processes.
708  for (size_t n = 0; n < numMessages; ++n) {
709  EXPECT_THAT(
710  data, ContainsRegex(folly::to<std::string>("prefork", n, "\n")));
711  EXPECT_THAT(data, ContainsRegex(folly::to<std::string>("parent", n, "\n")));
712  EXPECT_THAT(data, ContainsRegex(folly::to<std::string>("child", n, "\n")));
713  }
714 #else
715  SKIP() << "pthread_atfork() is not supported on this platform";
716 #endif // FOLLY_HAVE_PTHREAD_ATFORK
717 }
bool readFile(int fd, Container &out, size_t num_bytes=std::numeric_limits< size_t >::max())
Definition: FileUtil.h:125
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
PolymorphicMatcher< internal::MatchesRegexMatcher > ContainsRegex(const internal::RE *regex)
#define SKIP()
Definition: TestUtils.h:55
static void stop()
int fd() const
Definition: File.h:85
void checkUnixError(ssize_t ret, Args &&...args)
Definition: Exception.h:101
#define EXPECT_THAT(value, matcher)
const char * string
Definition: Conv.cpp:212
#define XLOG(level,...)
Definition: xlog.h:57
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
TEST ( AsyncFileWriter  ,
crazyForks   
)

Have several threads concurrently performing fork() calls while several other threads continuously create and destroy AsyncFileWriter objects.

This exercises the synchronization around registration of the AtFork handlers and the creation/destruction of the AsyncFileWriter I/O thread.

Definition at line 726 of file AsyncFileWriterTest.cpp.

References folly::checkUnixError(), folly::DBG3, EXPECT_EQ, folly::File::fd(), folly::getOSThreadID(), i, mutex, folly::setThreadName(), SKIP, stop(), folly::pushmi::detail::t, and XLOG.

726  {
727 #if FOLLY_HAVE_PTHREAD_ATFORK
728  constexpr size_t numAsyncWriterThreads = 10;
729  constexpr size_t numForkThreads = 5;
730  constexpr size_t numForkIterations = 20;
731  std::atomic<bool> stop{false};
732 
733  // Spawn several threads that continuously create and destroy
734  // AsyncFileWriter objects.
735  std::vector<std::thread> asyncWriterThreads;
736  for (size_t n = 0; n < numAsyncWriterThreads; ++n) {
737  asyncWriterThreads.emplace_back([n, &stop] {
738  folly::setThreadName(folly::to<std::string>("async_", n));
739 
740  TemporaryFile tmpFile{"logging_test"};
741  while (!stop) {
742  // Create an AsyncFileWriter, write a message to it, then destroy it.
743  AsyncFileWriter writer{folly::File{tmpFile.fd(), false}};
744  writer.writeMessage(folly::to<std::string>(
745  "async thread ", folly::getOSThreadID(), "\n"));
746  }
747  });
748  }
749 
750  // Spawn several threads that repeatedly fork.
751  std::vector<std::thread> forkThreads;
752  std::mutex forkStartMutex;
753  std::condition_variable forkStartCV;
754  bool forkStart = false;
755  for (size_t n = 0; n < numForkThreads; ++n) {
756  forkThreads.emplace_back([n, &forkStartMutex, &forkStartCV, &forkStart] {
757  folly::setThreadName(folly::to<std::string>("fork_", n));
758 
759  // Wait until forkStart is set just to have a better chance of all the
760  // fork threads running simultaneously.
761  {
762  std::unique_lock<std::mutex> l(forkStartMutex);
763  forkStartCV.wait(l, [&forkStart] { return forkStart; });
764  }
765 
766  for (size_t i = 0; i < numForkIterations; ++i) {
767  XLOG(DBG3) << "fork " << n << ":" << i;
768  auto pid = fork();
769  folly::checkUnixError(pid, "forkFailed");
770  if (pid == 0) {
771  XLOG(DBG3) << "child " << getpid();
772  _exit(0);
773  }
774 
775  // parent
776  int status;
777  auto waited = waitpid(pid, &status, 0);
778  folly::checkUnixError(waited, "failed to wait on child");
779  EXPECT_EQ(waited, pid);
780  }
781  });
782  }
783 
784  // Kick off the fork threads
785  {
786  std::unique_lock<std::mutex> l(forkStartMutex);
787  forkStart = true;
788  }
789  forkStartCV.notify_all();
790 
791  // Wait for the fork threads to finish
792  for (auto& t : forkThreads) {
793  t.join();
794  }
795 
796  // Stop and wait for the AsyncFileWriter threads
797  stop = true;
798  for (auto& t : asyncWriterThreads) {
799  t.join();
800  }
801 #else
802  SKIP() << "pthread_atfork() is not supported on this platform";
803 #endif // FOLLY_HAVE_PTHREAD_ATFORK
804 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define SKIP()
Definition: TestUtils.h:55
uint64_t getOSThreadID()
Definition: ThreadId.h:80
static void stop()
int fd() const
Definition: File.h:85
void checkUnixError(ssize_t ret, Args &&...args)
Definition: Exception.h:101
bool setThreadName(std::thread::id tid, StringPiece name)
Definition: ThreadName.cpp:109
std::mutex mutex
#define XLOG(level,...)
Definition: xlog.h:57
void writeThread ( AsyncFileWriter writer,
size_t  id,
uint32_t  flags,
ReadStats readStats 
)

writeThread() writes a series of messages to the AsyncFileWriter

Definition at line 551 of file AsyncFileWriterTest.cpp.

References kMsgSuffix, ReadStats::shouldWriterStop(), folly::AsyncFileWriter::writeMessage(), and ReadStats::writerFinished().

Referenced by TEST().

555  {
556  size_t msgID = 0;
557  while (true) {
558  ++msgID;
559  writer->writeMessage(
560  folly::to<std::string>(
561  "thread ", id, " message ", msgID, kMsgSuffix, '\n'),
562  flags);
563 
564  // Break out once the reader has seen enough discards
565  if (((msgID & 0xff) == 0) && readStats->shouldWriterStop()) {
566  readStats->writerFinished(id, msgID, flags);
567  break;
568  }
569  }
570 }
void writeMessage(folly::StringPiece buffer, uint32_t flags=0) override
flags
Definition: http_parser.h:127
static constexpr StringPiece kMsgSuffix
void writerFinished(size_t threadID, size_t messagesWritten, uint32_t flags)
bool shouldWriterStop() const

Variable Documentation

constexpr StringPiece kMsgSuffix
static
Initial value:
{
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"}

Definition at line 265 of file AsyncFileWriterTest.cpp.

Referenced by ReadStats::parseMessage(), and writeThread().