aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2017-09-01 15:27:56 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2017-09-01 15:27:56 +0200
commit07b6ff826546e931c0ebf03e30a872ba24e963fc (patch)
tree5ef8de3ceba68683c3bdeaaf316a70245d114bbd
parentf4f2d5e29ee02d7785ef0150398df7c164feee44 (diff)
downloadble-toys-07b6ff826546e931c0ebf03e30a872ba24e963fc.tar.gz
ble-toys-07b6ff826546e931c0ebf03e30a872ba24e963fc.tar.bz2
ble-toys-07b6ff826546e931c0ebf03e30a872ba24e963fc.tar.xz
ble-toys-07b6ff826546e931c0ebf03e30a872ba24e963fc.zip
sample-tee.cpp: tool for writing and rotating log files, similar to unix's tee command.
sample-add-timestamp.cpp: Actually using the resolution flag.
-rw-r--r--apps/CMakeLists.txt1
-rw-r--r--apps/sample-add-timestamp.cpp29
-rw-r--r--apps/sample-tee.cpp111
3 files changed, 128 insertions, 13 deletions
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index 98c9915..8f8feb3 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -103,6 +103,7 @@ add_app(NAME ble-scan)
add_app(NAME sample-add-timestamp)
add_app(NAME sample-convert)
add_app(NAME sample-select)
+add_app(NAME sample-tee)
add_app(NAME sm-db-insert)
add_app(NAME sm-db-select)
add_app(NAME sm-get-value)
diff --git a/apps/sample-add-timestamp.cpp b/apps/sample-add-timestamp.cpp
index ec3c43a..5493524 100644
--- a/apps/sample-add-timestamp.cpp
+++ b/apps/sample-add-timestamp.cpp
@@ -13,9 +13,10 @@ namespace po = boost::program_options;
class TimestampAddingSampleOutputStream : public SampleConsumer {
public:
- TimestampAddingSampleOutputStream(shared_ptr<SampleConsumer> output, KeyDictionary &dict, string timestamp_name)
- : output_(output), timestamp_key(dict.indexOf(timestamp_name)) {
- if (input_time_resolution_ == time_resolution::MILLISECONDS) {
+ TimestampAddingSampleOutputStream(shared_ptr<SampleConsumer> output, KeyDictionary &dict,
+ time_resolution resolution, string timestamp_name) :
+ output_(output), resolution_(resolution), timestamp_key(dict.indexOf(timestamp_name)) {
+ if (resolution_ == time_resolution::MILLISECONDS) {
factor = 1000;
} else {
factor = 1;
@@ -34,7 +35,7 @@ public:
private:
const SampleKey *timestamp_key;
- const time_resolution input_time_resolution_ = time_resolution::MILLISECONDS;
+ const time_resolution resolution_;
int factor;
shared_ptr<SampleConsumer> output_;
};
@@ -60,22 +61,24 @@ public:
const int buffer_size = 1024;
int main(app_execution &execution) override {
- auto stdin = shared_ptr<istream>(&cin, noop_deleter);
- auto stdout = shared_ptr<ostream>(&cout, noop_deleter);
- KeyDictionary dict;
+ auto out = shared_ptr<ostream>(&cout, noop_deleter);
+ KeyDictionary dict;
sample_output_stream_options options = {};
- auto writer = open_sample_writer(stdout, dict, output_format, options);
- auto p = make_shared<TimestampAddingSampleOutputStream>(std::move(writer), dict, timestamp_name);
+ auto writer = open_sample_writer(out, dict, output_format, options);
+ auto p = make_shared<TimestampAddingSampleOutputStream>(std::move(writer), dict, resolution, timestamp_name);
auto parser = open_sample_stream_parser(p, dict);
int recordCount = 0;
- while (!stdin->eof()) {
+ auto in = shared_ptr<istream>(&cin, noop_deleter);
+// in->rdbuf(nullptr);
+
+ while (!in->eof()) {
char buffer[buffer_size];
- stdin->read(buffer, buffer_size);
- auto gcount = static_cast<size_t>(stdin->gcount());
+ in->read(buffer, buffer_size);
+ auto gcount = static_cast<size_t>(in->gcount());
recordCount++;
@@ -83,7 +86,7 @@ public:
parser->process(b);
}
- stdout->flush();
+ out->flush();
return EXIT_SUCCESS;
};
diff --git a/apps/sample-tee.cpp b/apps/sample-tee.cpp
new file mode 100644
index 0000000..50c0c9b
--- /dev/null
+++ b/apps/sample-tee.cpp
@@ -0,0 +1,111 @@
+#include "apps.h"
+#include "trygvis/sensor/io.h"
+#include <boost/tokenizer.hpp>
+#include <fstream>
+
+namespace trygvis {
+namespace apps {
+
+using namespace std;
+using namespace trygvis::sensor;
+using namespace trygvis::sensor::io;
+using boost::tokenizer;
+namespace po = boost::program_options;
+
+class sample_tee final : public app, public SampleConsumer {
+private:
+ using clock = std::chrono::steady_clock;
+ using timestamp = std::chrono::time_point<clock>;
+
+ sample_format_type output_format = sample_format_type::KEY_VALUE;
+ sample_format_type file_output_format = sample_format_type::KEY_VALUE;
+ string file_name;
+ sample_output_stream_options options = {};
+ KeyDictionary dict;
+
+ shared_ptr<ostream> out;
+ unique_ptr<SampleConsumer> out_writer;
+ ofstream file;
+ timestamp next_flush;
+
+public:
+ sample_tee() : app("sample-to-file") {}
+
+ ~sample_tee() override = default;
+
+ void add_options(po::options_description_easy_init &options) override
+ {
+ options("output-format", po::value<sample_format_type>(&output_format)->default_value(output_format));
+ options("file-output-format",
+ po::value<sample_format_type>(&file_output_format)->default_value(file_output_format));
+ options("file", po::value<string>(&file_name));
+ }
+
+ int main(app_execution &execution) override
+ {
+ if (file_name.size() == 0) {
+ cerr << "Missing required argument --file" << endl;
+ return EXIT_FAILURE;
+ }
+
+ cerr << "Writing samples to " << file_name << endl;
+
+ const int buffer_size = 1024;
+ char buffer[buffer_size];
+
+ out = shared_ptr<ostream>(&cout, noop_deleter);
+ out_writer = std::move(open_sample_writer(out, dict, output_format, options));
+
+ next_flush = clock::now();
+
+ auto parser = open_sample_stream_parser(shared_ptr<SampleConsumer>(this, noop_deleter), dict);
+ auto in = shared_ptr<istream>(&cin, noop_deleter);
+ in->rdbuf(nullptr);
+ while (!in->eof()) {
+ in->read(buffer, buffer_size);
+ auto gcount = static_cast<size_t>(in->gcount());
+
+ out->write(buffer, gcount);
+
+ mutable_buffers_1 b = boost::asio::buffer(buffer, gcount);
+ parser->process(b);
+ }
+
+ file.flush();
+ file.close();
+
+ return EXIT_SUCCESS;
+ };
+
+protected:
+
+ void onSample(const SampleRecord &sample) override
+ {
+ out_writer->onSample(sample);
+
+ file.open(file_name, ios_base::out | ios_base::app);
+ if (file.good()) {
+ shared_ptr<ostream> output(&file, noop_deleter);
+ auto file_writer = std::move(open_sample_writer(output, dict, file_output_format, options));
+ file_writer->onSample(sample);
+ }
+
+ auto now = clock::now();
+
+ if(now >= next_flush) {
+ file.flush();
+ next_flush = now + chrono::seconds(3);
+
+ cerr << "flush" << endl;
+ }
+ }
+};
+}
+}
+
+int main(int argc, const char *argv[])
+{
+ using namespace trygvis::apps;
+
+ return real_main(new sample_tee(), argc, argv);
+}