v1.3 : added auto file reloading

+ Files now auto reload when changes are detected
+ Added --no-reload option to disable auto reloading
* Internal cleanups
This commit is contained in:
zawz 2019-09-26 11:42:11 +02:00
parent 8486fa3984
commit 1c8c3ac9d2
5 changed files with 147 additions and 58 deletions

View file

@ -8,8 +8,6 @@
#include "command.hpp"
#include <ztd/filedat.hpp>
void sh(std::string const& string);
class Device
{
public:
@ -34,7 +32,6 @@ public:
std::vector<ConnectCommand> connectCommands;
std::vector<DisconnectCommand> disconnectCommands;
std::thread thread;
pid_t thread_pid;
private:
static void loop(Device* dev);
@ -42,4 +39,6 @@ private:
extern std::vector<Device*> device_list;
void clean_devices();
#endif //DEVICE_HPP

View file

@ -5,10 +5,16 @@
#define LIST_COMMAND "aseqdump -l | tail -n +2 | cut -c10-42 | tr -s ' '"
#define LIST_EXTENDED_COMMAND "aseqdump -l | tail -n +2 | cut -c-42"
#include <string>
extern int announce_thread_pid;
void kill_all();
void device_check();
void announce_loop();
void filetime_loop(std::string filepath);
#endif //SYSTEM_HPP

View file

@ -5,6 +5,7 @@
#include <string.h>
#include <signal.h>
#include <iostream>
#include <ztd/shell.hpp>
#include "log.hpp"
@ -40,11 +41,6 @@ static bool _isNum(char a)
return (a>='0' && a<='9');
}
void sh(std::string const& string)
{
system(string.c_str());
}
Device::Device()
{
busy=false;
@ -63,8 +59,7 @@ bool Device::start_loop()
if(this->busy)
return false;
this->busy = true;
this->thread = std::thread(Device::loop, this);
this->thread.detach();
std::thread(Device::loop, this).detach();
return true;
}
@ -295,7 +290,7 @@ void Device::run_signal(char* buff)
{
std::string command="code=" + strval + ";";
command += dequote(it.shell);
std::thread(sh, command).detach();
std::thread(ztd::sh, command, true).detach();
}
}
else
@ -372,7 +367,7 @@ void Device::run_signal(char* buff)
+ ";channel=" + std::to_string(channel)
+ ";velocity=" + std::to_string(value) + ";";
command += dequote(it.shell);
std::thread(sh, command).detach();
std::thread(ztd::sh, command, true).detach();
}
}
}
@ -399,7 +394,7 @@ void Device::run_signal(char* buff)
else
command += std::to_string((long int) result);
command += ";" + dequote(it.shell);
std::thread(sh, command).detach();
std::thread(ztd::sh, command, true).detach();
}
}
}
@ -425,7 +420,7 @@ void Device::run_signal(char* buff)
else
command += std::to_string((long int) result);
command += ";" + dequote(it.shell);
std::thread(sh, command).detach();
std::thread(ztd::sh, command, true).detach();
}
}
} // if type
@ -447,7 +442,7 @@ void Device::loop(Device* dev)
for( auto it : dev->connectCommands )
{
std::thread(sh, dequote(it.shell)).detach();
std::thread(ztd::sh, dequote(it.shell), true).detach();
}
while (getline(&buff, &buff_size, stream) > 0)
@ -457,7 +452,7 @@ void Device::loop(Device* dev)
for( auto it : dev->disconnectCommands )
{
std::thread(sh, dequote(it.shell)).detach();
std::thread(ztd::sh, dequote(it.shell), true).detach();
}
log("Device '" + dev->name + "' disconnected\n");
@ -466,3 +461,12 @@ void Device::loop(Device* dev)
dev->thread_pid=-1;
free(buff);
}
void clean_devices()
{
for(auto it : device_list)
{
delete it;
}
device_list.clear();
}

View file

@ -14,7 +14,7 @@
#include <ztd/options.hpp>
#include <ztd/shell.hpp>
#define VERSION_STRING "v1.2"
#define VERSION_STRING "v1.3"
ztd::option_set options;
@ -59,8 +59,7 @@ void cleanup()
void stop(int ret)
{
if(announce_thread_pid>0)
kill(announce_thread_pid, SIGINT);
kill_all();
exit(ret);
}
@ -69,12 +68,59 @@ void inthandler(int dummy)
stop(0);
}
void load_filedat(ztd::filedat& file, bool from_stdin, std::string const& path)
{
if(from_stdin)
{
log("Loading map from stdin\n");
file.import_stdin();
}
else
{
file.setFilePath(path);
log("Loading map file '" + path + "'\n");
if(options.find("zfd")->activated)
{
file.import_file();
}
else if(options.find("mim")->activated)
{
file.data() = mimtochk(file_strimport(path));
}
else
{
std::string filestr=file_strimport(path);
if(is_mim(filestr))
{
file.data() = mimtochk(filestr);
}
else
{
file.import_file();
}
}
}
}
void load_commands(ztd::chunkdat const& data)
{
clean_devices();
for(int i=0 ; i<data.listSize() ; i++)
{
Device *newDevice = new Device;
newDevice->import_chunk(data[i]);
device_list.push_back(newDevice);
log("Loaded "+std::to_string(newDevice->nb_command)+" commands for device '"+newDevice->name+"'\n");
}
}
int main(int argc, char* argv[])
{
signal(SIGINT, inthandler);
signal(SIGCHLD, SIG_IGN); //not expecting returns from child processes
bool piped=false;
bool autoreload=true;
if (!isatty(fileno(stdin)))
piped = true;
@ -98,6 +144,7 @@ int main(int argc, char* argv[])
options.add(ztd::option('z',"zfd", false, "Read file in zfd format"));
options.add(ztd::option('o',"output", true, "Output the resulting zfd map to file. - for stdout", "file"));
options.add(ztd::option("aligner", true, "String to use for aligning output map format. Default \\t", "string"));
options.add(ztd::option("no-reload", false, "Disable auto reloading when file changes are detected"));
options.add(ztd::option("\rIf no file format is specified, the program will try to guess the format"));
// options.add(ztd::option('i',"interactive", false, "Start in interactive mode"));
@ -146,12 +193,12 @@ int main(int argc, char* argv[])
}
if( options.find('L')->activated )
{
sh("aseqdump -l");
ztd::sh("aseqdump -l", true);
stop(0);
}
if( options.find('l')->activated )
{
sh(LIST_COMMAND);
ztd::sh(LIST_COMMAND, true);
stop(0);
}
@ -168,6 +215,10 @@ int main(int argc, char* argv[])
}
//behavioral options
if( options.find("no-reload")->activated )
{
autoreload=false;
}
if( options.find("no-log")->activated )
{
log_on=false;
@ -181,6 +232,7 @@ int main(int argc, char* argv[])
//no argument: display help
ztd::filedat file;
bool no_arg=false;
std::string filepath;
if (arg.size() <= 0 || arg[0] == "")
{
no_arg=true;
@ -192,42 +244,16 @@ int main(int argc, char* argv[])
}
else
{
file.setFilePath(arg[0]);
filepath=arg[0];
}
//main processing
try
{
if(no_arg)
{
log("Loading map from stdin\n");
file.import_stdin();
}
else
{
log("Loading map file '" + arg[0] + "'\n");
if(options.find("zfd")->activated)
{
file.import_file();
}
else if(options.find("mim")->activated)
{
file.data() = mimtochk(file_strimport(arg[0]));
}
else
{
std::string filestr=file_strimport(arg[0]);
if(is_mim(filestr))
{
file.data() = mimtochk(filestr);
}
else
{
file.import_file();
}
}
}
//load
load_filedat(file, no_arg, filepath);
//output
if(options.find('o')->activated)
{
if(options.find('o')->argument == "-") {
@ -240,17 +266,39 @@ int main(int argc, char* argv[])
return 0;
}
//create commands
for(int i=0 ; i<file.data().listSize() ; i++)
{
Device *newDevice = new Device;
newDevice->import_chunk(file[i]);
device_list.push_back(newDevice);
log("Loaded "+std::to_string(newDevice->nb_command)+" commands for device '"+newDevice->name+"'\n");
}
load_commands(file.data());
autoreload = autoreload && !no_arg;
//main loop
log("Starting scan for devices\n");
if(autoreload)
std::thread(filetime_loop, filepath).detach();
announce_loop();
ztd::chunkdat bak_data = file.data();
while(autoreload)
{
log("Reloading file\n");
try
{
load_filedat(file, false, filepath);
load_commands(file.data());
bak_data = file.data();
}
catch (ztd::format_error& e)
{
ztd::printFormatException(e);
log("Reloading old config\n");
load_commands(bak_data);
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << std::endl;
log("Reloading old config\n");
load_commands(bak_data);
}
announce_loop();
}
}
catch (ztd::format_error& e)
{

View file

@ -3,6 +3,10 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
#include <string>
#include <vector>
@ -13,6 +17,17 @@
int announce_thread_pid = 0;
void kill_all()
{
if(announce_thread_pid>0)
kill(announce_thread_pid, SIGINT);
for(auto it : device_list)
{
if(it->thread_pid>0)
kill(it->thread_pid, SIGINT);
}
}
void device_check()
{
char* buff = NULL;
@ -86,3 +101,20 @@ void announce_loop()
if(buff != NULL)
free(buff);
}
void filetime_loop(std::string filepath)
{
struct stat attrib;
stat(filepath.c_str(), &attrib);
time_t last_time=attrib.st_ctime;
while(true)
{
stat(filepath.c_str(), &attrib);
if(attrib.st_ctime > last_time)
{
kill_all();
last_time = attrib.st_ctime;
}
sleep(1);
}
}