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:
parent
8486fa3984
commit
1c8c3ac9d2
5 changed files with 147 additions and 58 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
132
src/main.cpp
132
src/main.cpp
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue