Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: add -1/--singleshot option #450

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions include/Channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class Channel {
Channel(const std::list<Option> &pOptions, const std::string api, const std::string pUuid,
ReadingIdentifier::Ptr pIdentifier);
virtual ~Channel();
bool running();

// Doesn't touch the object, could also be static, but static breaks google mock.
void start(Ptr this_shared) {
Expand All @@ -70,8 +71,6 @@ class Channel {
pthread_cancel(_thread);
}

bool running() const { return _thread_running; }

const char *name() const { return _name.c_str(); }
std::list<Option> &options() { return _options; }

Expand Down
4 changes: 4 additions & 0 deletions include/Config_Options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class Config_Options {
bool channel_index() const { return _channel_index; }
bool local() const { return _local; }
bool foreground() const { return _foreground; }
bool singleshot() const { return _singleshot; }

bool doRegistration() const { return _doRegistration; }

Expand All @@ -95,6 +96,8 @@ class Config_Options {

void foreground(const bool v) { _foreground = v; }

void singleshot(const bool v) { _singleshot = v; }

void doRegistration(const bool v) { _doRegistration = v; }

void haveTimeMachine(const bool v) { _time_machine = v; }
Expand All @@ -117,6 +120,7 @@ class Config_Options {
int _channel_index : 1; // give a index of all available channels via local interface
int _local : 1; // enable local interface
int _foreground : 1; // don't daemonize
int _singleshot : 1; // only get a single reading from each meter, then exit
int _doRegistration : 1; // FIXME
int _time_machine : 1; // accept readings from before smart-metering existed
};
Expand Down
2 changes: 1 addition & 1 deletion include/MeterMap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class MeterMap {
inline iterator end() { return _channels.end(); }
inline size_t size() { return _channels.size(); }

bool running() const { return _thread_running; }
bool running();

private:
Meter::Ptr _meter;
Expand Down
15 changes: 15 additions & 0 deletions src/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ Channel::Channel(const std::list<Option> &pOptions, const std::string apiProtoco
pthread_cond_init(&condition, NULL); // initialize thread syncronization helpers
}

bool Channel::running() {
if (!_thread_running)
return _thread_running;
int ret = pthread_tryjoin_np(_thread, NULL);
if (ret == EBUSY) {
// thread still running
_thread_running = true;
} else if (ret != 0) {
print(log_alert, "error from pthread_tryjoin_np()", name());
} else {
_thread_running = false;
}
return _thread_running;
}

/**
* Free all allocated memory recursively
*/
Expand Down
4 changes: 2 additions & 2 deletions src/Config_Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ static const char *option_type_str[] = {"null", "boolean", "double", "int",
Config_Options::Config_Options()
: _config("/etc/vzlogger.conf"), _log(""), _pds(0), _port(8080), _verbosity(0),
_comet_timeout(30), _buffer_length(-1), _retry_pause(15), _local(false), _foreground(false),
_time_machine(false) {
_singleshot(false), _time_machine(false) {
_logfd = NULL;
}

Config_Options::Config_Options(const std::string filename)
: _config(filename), _log(""), _pds(0), _port(8080), _verbosity(0), _comet_timeout(30),
_buffer_length(-1), _retry_pause(15), _local(false), _foreground(false),
_buffer_length(-1), _retry_pause(15), _local(false), _foreground(false), _singleshot(false),
_time_machine(false) {
_logfd = NULL;
}
Expand Down
21 changes: 21 additions & 0 deletions src/MeterMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,27 @@ void MeterMap::start() {
}
}

bool MeterMap::running() {
int ret;
if (!_thread_running)
return _thread_running;
for (iterator it = _channels.begin(); it != _channels.end(); it++) {
if ((*it)->running())
return _thread_running;
}
ret = pthread_tryjoin_np(_thread, NULL);
if (ret == EBUSY) {
// thread still running
return _thread_running;
} else if (ret != 0) {
print(log_alert, "error from pthread_tryjoin_np()", _meter->name());
} else {
// tread has exited
}
_thread_running = false;
return false;
}

void MeterMap::cancel() { // is called from MapContainer::quit which is called from sigint handler
// handler ::quit
print(log_finest, "MeterMap::cancel entered...", _meter->name());
Expand Down
23 changes: 15 additions & 8 deletions src/protocols/MeterS0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@

#include "Options.hpp"
#include "protocols/MeterS0.hpp"
#include <Config_Options.hpp>
#include <VZException.hpp>

extern Config_Options options;

MeterS0::MeterS0(std::list<Option> options, HWIF *hwif, HWIF *hwif_dir)
: Protocol("s0"), _hwif(hwif), _hwif_dir(hwif_dir), _counter_thread_stop(false),
_send_zero(false), _debounce_delay_ms(0), _nonblocking_delay_ns(1e5), _first_impulse(true) {
Expand Down Expand Up @@ -417,10 +420,12 @@ ssize_t MeterS0::read(std::vector<Reading> &rds, size_t n) {
rds[ret].value(value);
++ret;
}
rds[ret].identifier(new StringIdentifier("Impulse"));
rds[ret].time(req);
rds[ret].value(t_imp);
++ret;
if (!options.singleshot()) {
rds[ret].identifier(new StringIdentifier("Impulse"));
rds[ret].time(req);
rds[ret].value(t_imp);
++ret;
}
}

if (_send_zero || t_imp_neg > 0) {
Expand All @@ -431,10 +436,12 @@ ssize_t MeterS0::read(std::vector<Reading> &rds, size_t n) {
rds[ret].value(value);
++ret;
}
rds[ret].identifier(new StringIdentifier("Impulse_neg"));
rds[ret].time(req);
rds[ret].value(t_imp_neg);
++ret;
if (!options.singleshot()) {
rds[ret].identifier(new StringIdentifier("Impulse_neg"));
rds[ret].time(req);
rds[ret].value(t_imp_neg);
++ret;
}
}
if (_first_impulse && ret > 0)
_first_impulse = false;
Expand Down
11 changes: 11 additions & 0 deletions src/threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,14 @@ void *reading_thread(void *arg) {
//(*ch)->size(), (*ch)->dump().c_str());
}
}

if (options.singleshot())
break;

if (mtr->interval() > 0) {
print(log_info, "Next reading in %i seconds", mtr->name(), mtr->interval());
sleep(mtr->interval());
}
} while (true);
} catch (std::exception &e) {
std::stringstream oss;
Expand Down Expand Up @@ -257,6 +265,9 @@ void *logging_thread(void *arg) { // is started by Channel::start and stopped vi
try {
ch->wait();
api->send();

if (options.singleshot())
break;
} catch (std::exception &e) {
print(log_alert, "Logging thread failed due to: %s", ch->name(), e.what());
}
Expand Down
8 changes: 7 additions & 1 deletion src/vzlogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const struct option long_options[] = {
{"config", required_argument, 0, 'c'},
{"log", required_argument, 0, 'o'},
{"foreground", no_argument, 0, 'f'},
{"singleshot", no_argument, 0, '1'},
#ifdef LOCAL_SUPPORT
{"httpd", no_argument, 0, 'l'},
{"httpd-port", required_argument, 0, 'p'},
Expand All @@ -95,6 +96,7 @@ const char *long_options_descs[] = {
"configuration file",
"log file",
"run in foreground, do not daemonize",
"get only one reading for each meter, then exit",
#ifdef LOCAL_SUPPORT
"activate local interface (tiny HTTPd which serves live readings)",
"TCP port for HTTPd",
Expand Down Expand Up @@ -331,7 +333,7 @@ void signalHandlerReOpenLog(int) { mainLoopReopenLogfile = true; }
*/
int config_parse_cli(int argc, char *argv[], Config_Options *options) {
while (1) {
int c = getopt_long(argc, argv, "c:o:p:lhrVfv:", long_options, NULL);
int c = getopt_long(argc, argv, "c:o:p:lhrVf1v:", long_options, NULL);

/* detect the end of the options. */
if (c == -1)
Expand All @@ -356,6 +358,10 @@ int config_parse_cli(int argc, char *argv[], Config_Options *options) {
options->foreground(1);
break;

case '1':
options->singleshot(1);
break;

case 'c': /* config file */
options->config(optarg);
break;
Expand Down
1 change: 1 addition & 0 deletions tests/mocks/Channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Channel {
MOCK_METHOD1(start, void(Channel::Ptr));
MOCK_METHOD0(join, void());
MOCK_METHOD0(cancel, void());
MOCK_METHOD0(running, bool());
MOCK_METHOD0(name, const char *());
MOCK_METHOD0(options, std::list<Option> &());
MOCK_METHOD0(apiProtocol, const std::string());
Expand Down
2 changes: 2 additions & 0 deletions tests/mocks/mock_MeterS0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ using ::testing::Test;
#include "Meter.hpp"
#include "protocols/MeterS0.hpp"

int options; // FIXME

namespace mock_MeterS0 {

class mock_S0hwif : public MeterS0::HWIF {
Expand Down