/*
This file is part of Bolixo.
Bolixo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bolixo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bolixo. If not, see .
*/
/*
Command line tool to control documentd
*/
#include
#include
#include
#include
#include
#include
#include
#include "bolixo.m"
using namespace std;
#include "bolixo.h"
#include "proto/bod_client.protodef"
#include "proto/documentd_control.protoch"
#define bod_control_status_NOTNEED
#define bod_control_quit_NOTNEED
#define bod_control_debug_NOTNEED
#define bod_control_debugfile_NOTNEED
#define bod_control_helptest_NOTNEED
#define bod_control_publishemail_NOTNEED
#define bod_control_help_connect_NOTNEED
#define bod_control_nodelogin_NOTNEED
#define bod_control_nodelogout_NOTNEED
#define bod_control_instrument_NOTNEED
#define bod_control_keepmsgs_NOTNEED
#define bod_control_erase_session_NOTNEED
#define bod_control_set_admin_session_NOTNEED
#define bod_control_slowplaystep_NOTNEED
#include "proto/bod_control.protoch"
int main (int argc, char *argv[])
{
glocal int ret = -1;
glocal const char *control = "/var/lib/lxc/documentd/rootfs/var/run/blackhole/documentd.sock";
glocal const char *bod_control = "/var/lib/lxc/bod/rootfs/var/run/blackhole/bod-2.sock";
glocal unsigned idle_time = 60*60; // One hour
glocal bool force = false;
glocal.ret = (argc,argv,"bolixo");
setproginfo ("documentd-control",VERSION
,MSG_U(I_DOCUMENTD_CONTROL
,"Command line tool to control documentd\n"
"\n"
"\tchessmaxskill 1-5\n"
"\tdebug 0/1\n"
"\tdebugfile filename\n"
"\tdeleteoldgames\n"
"\tendgame gameid revision\n"
"\tendgames\n"
"\tinstrument 0|1\n"
"\tlistgames\n"
"\tplaystep gameid command=value ...\n"
"\tprotocolstats 0|1\n"
"\tquit\n"
"\tresetgame gameid\n"
"\tsetflag flag value\n"
"\tstatus\n"
"\tstartgame gameid\n"
));
setarg ('p',"control","Unix socket to reach documentd",glocal.control,false);
setarg (' ',"bod-control","Unix socket to reach bod",glocal.bod_control,false);
setarg (' ',"idle-time","Idle time for a game (deleted after that)",glocal.idle_time,false);
setarg (' ',"force","Force endgame (for endgame and deleteoldgames)",glocal.force,false);
glocal int ret = -1;
glocal CONNECT_INFO con;
glocal CONNECT_INFO con_bod;
glocal.con.port = glocal.control;
glocal.con_bod.port = glocal.bod_control;
if (strcmp(argv[0],"status")==0 && argc==1){
(glocal.con);
if (!internal_error) glocal.ret = 0;
for (auto x:lines) printf ("%s\n",x);
}else if (strcmp(argv[0],"listgames")==0 && argc==1){
(glocal.con);
if (!internal_error) glocal.ret = 0;
for (auto x:stats){
printf ("gameid=%s modified=%u modified_by=%s last_activity=%u revision=%u\n"
,x.gameid,x.modified,x.modified_by,x.last_activity,x.revision);
}
}else if (strcmp(argv[0],"deleteoldgames")==0 && argc==1){
for (unsigned i=0; i<2; i++){
(glocal.con);
if (!internal_error) glocal.ret = 0;
time_t old_now = time(nullptr) - glocal.idle_time;
for (auto x:stats){
glocal bool delete_ok = true;
glocal const char *gameid = x.gameid;
if (x.modified != 0 && x.modified < old_now){
// It was modified some time ago, must be saved using bod
(glocal.con_bod,x.gameid);
if (!success){
tlmp_error (MSG_U(E_FAILSAVEGAME,"Can't save document/game %s: %s\n")
,glocal.gameid,msg);
glocal.delete_ok = false;
}
}
if (glocal.force || (glocal.delete_ok && x.last_activity < old_now)){
// This game/document has not been accessed for some time
// We delete the game. The revision obtained by listgame
// must match when the deletion is executed in documentd.
// If it does not match, it means the game was modified
// while we were saving. So endgame fails.
// But failure is not a problem. The game continue to
// exist in documentd.
glocal const char *gameid = x.gameid;
(glocal.con,x.gameid,x.revision,glocal.force);
if (!success) tlmp_error ("deleteoldgames: can't delete %s: %s\n",glocal.gameid,msg);
}
}
}
}else if (strcmp(argv[0],"quit")==0 && argc==1){
(glocal.con);
if (!internal_error) glocal.ret = 0;
}else if (strcmp(argv[0],"debug")==0 && argc==2){
(glocal.con,atoi(argv[1]));
}else if (strcmp(argv[0],"debugfile")==0 && argc==2){
(glocal.con,argv[1]);
}else if (strcmp(argv[0],"load")==0 && argc == 2){
(glocal.con,argv[1]);
printf ("success=%d msg=%s\n",success,msg);
}else if (strcmp(argv[0],"save")==0 && argc == 2){
(glocal.con,argv[1]);
printf ("success=%d msg=%s\n",success,msg);
}else if (strcmp(argv[0],"startgame")==0 && argc == 3){
(glocal.con,argv[1],argv[2]);
printf ("success=%d msg=%s\n",success,msg);
}else if (strcmp(argv[0],"endgame")==0 && argc == 3){
(glocal.con,argv[1],atoi(argv[2]),glocal.force);
printf ("success=%d msg=%s\n",success,msg);
}else if (strcmp(argv[0],"endgames")==0 && argc == 1){
(glocal.con);
}else if (strcmp(argv[0],"resetgame")==0 && argc == 2){
(glocal.con,argv[1]);
printf ("success=%d msg=%s\n",success,msg);
}else if (strcmp(argv[0],"playstep")==0 && argc > 2){
vector args;
for (int i=2; i(glocal.con,argv[1],args);
if (!success){
printf ("success=%d unknown=%d msg=%s\n",success,unknown,msg);
}else{
for (auto &r:res){
if (strcmp(r.var,"content")==0){
printf ("Content:\n%s\n",r.val);
}else{
printf ("var=%s val=%s\n",r.var,r.val);
}
}
}
}else if (strcmp(argv[0],"instrument")==0 && argc==2){
(glocal.con,atoi(argv[1]));
}else if (strcmp(argv[0],"protocolstats")==0 && argc==2){
(glocal.con,atoi(argv[1]));
}else if (strcmp(argv[0],"chessmaxskill")==0 && argc==2){
(glocal.con,atoi(argv[1]));
}else if (strcmp(argv[0],"setflag")==0 && argc==3){
(glocal.con,argv[1],argv[2]);
}else{
tlmp_error ("Invalid command: %s\n",argv[0]);
usage();
}
return glocal.ret;
return glocal.ret;
}