aboutsummaryrefslogtreecommitdiffstats
path: root/vespalog/src/test/threads/testthreads.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vespalog/src/test/threads/testthreads.cpp')
-rw-r--r--vespalog/src/test/threads/testthreads.cpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/vespalog/src/test/threads/testthreads.cpp b/vespalog/src/test/threads/testthreads.cpp
new file mode 100644
index 00000000000..6e5f72da524
--- /dev/null
+++ b/vespalog/src/test/threads/testthreads.cpp
@@ -0,0 +1,139 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+#include <iostream>
+#include <string>
+
+using std::string;
+
+
+LOG_SETUP(".threadtest");
+
+class FileThread : public FastOS_Runnable
+{
+ bool _done;
+ string _file;
+public:
+ FileThread(string file) : _done(false), _file(file) {}
+ virtual void Run(FastOS_ThreadInterface *thread, void *arg);
+ void stop() {_done = true; }
+};
+
+class LoggerThread : public FastOS_Runnable
+{
+ bool _done;
+public:
+ bool _useLogBuffer;
+ LoggerThread() : _done(false), _useLogBuffer(false) {}
+ virtual void Run(FastOS_ThreadInterface *thread, void *arg);
+ void stop() {_done = true; }
+};
+
+
+
+
+void
+FileThread::Run(FastOS_ThreadInterface *, void *)
+{
+ unlink(_file.c_str());
+ while (!_done) {
+ int fd = open(_file.c_str(), O_RDWR | O_CREAT | O_APPEND, 0644);
+ if (fd == -1) {
+ fprintf(stderr, "open failed: %s\n", strerror(errno));
+ exit(1);
+ }
+ FastOS_Thread::Sleep(5);
+ struct stat buf;
+ fstat(fd, &buf);
+ if (buf.st_size != 0) {
+ fprintf(stderr, "%s isn't empty anymore\n", _file.c_str());
+ exit(1);
+ }
+ if (close(fd) != 0) {
+ fprintf(stderr, "close of %d failed: %s\n", fd, strerror(errno));
+ exit(1);
+ }
+ }
+}
+
+
+void
+LoggerThread::Run(FastOS_ThreadInterface *, void *)
+{
+ int counter = 0;
+ while (!_done) {
+ if (_useLogBuffer) {
+ LOGBM(info, "bla bla bla %u", ++counter);
+ } else {
+ LOG(info, "bla bla bla");
+ }
+ }
+}
+
+
+class ThreadTester : public FastOS_Application
+{
+public:
+ int Main();
+};
+
+int
+ThreadTester::Main()
+{
+ std::cerr << "Testing that logging is threadsafe. 30 sec test.\n";
+ FastOS_ThreadPool pool(128 * 1024);
+
+ const int numWriters = 30;
+ const int numLoggers = 10;
+
+ auto writers = std::array<std::unique_ptr<FileThread>, numWriters>();
+ auto loggers = std::array<std::unique_ptr<LoggerThread>, numLoggers>();
+
+ for (int i = 0; i < numWriters; i++) {
+ char filename[100];
+ sprintf(filename, "empty.%d", i);
+ writers[i] = std::make_unique<FileThread>(filename);
+ pool.NewThread(writers[i].get());
+ }
+ for (int i = 0; i < numLoggers; i++) {
+ loggers[i] = std::make_unique<LoggerThread>();
+ pool.NewThread(loggers[i].get());
+ }
+
+ FastOS_Time start;
+ start.SetNow();
+ // Reduced runtime to half as the test now repeats itself to test with
+ // buffering. (To avoid test taking a minute)
+ while (start.MilliSecsToNow() < 15 * 1000) {
+ unlink(_argv[1]);
+ FastOS_Thread::Sleep(1);
+ }
+ // Then set to use logbuffer and continue
+ for (int i = 0; i < numLoggers; i++) {
+ loggers[i]->_useLogBuffer = true;
+ }
+ start.SetNow();
+ while (start.MilliSecsToNow() < 15 * 1000) {
+ unlink(_argv[1]);
+ FastOS_Thread::Sleep(1);
+ }
+
+ for (int i = 0; i < numLoggers; i++) {
+ loggers[i]->stop();
+ }
+ for (int i = 0; i < numWriters; i++) {
+ writers[i]->stop();
+ }
+
+ pool.Close();
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ ThreadTester app;
+ return app.Entry(argc, argv);
+}
+
+