4
4
#include <unistd.h>
5
5
#include <assert.h>
6
6
#include <time.h>
7
+ #include <signal.h>
8
+ #include <errno.h>
9
+ #include <sys/wait.h>
7
10
8
11
#include "clog.h"
9
12
#include "parser.h"
@@ -54,7 +57,7 @@ static void free_client_data(client_data_t *cd) {
54
57
static int next_client_id = 0 ;
55
58
static void onconnect (void * stream , void * * clientdata ) {
56
59
* clientdata = create_client_data (next_client_id ++ );
57
- shout ("[%d] connected\n" , CLIENT_ID (* clientdata ));
60
+ debug ("[%d] connected\n" , CLIENT_ID (* clientdata ));
58
61
}
59
62
60
63
static void notify_listeners (Transaction * t , int status ) {
@@ -88,7 +91,7 @@ static void notify_listeners(Transaction *t, int status) {
88
91
}
89
92
90
93
static void ondisconnect (void * stream , void * clientdata ) {
91
- shout ("[%d] disconnected\n" , CLIENT_ID (clientdata ));
94
+ debug ("[%d] disconnected\n" , CLIENT_ID (clientdata ));
92
95
93
96
if (CLIENT_XID (clientdata ) != INVALID_XID ) {
94
97
int i ;
@@ -126,7 +129,7 @@ static void ondisconnect(void *stream, void *clientdata) {
126
129
}
127
130
128
131
#ifdef DEBUG
129
- static void shout_cmd (void * clientdata , cmd_t * cmd ) {
132
+ static void debug_cmd (void * clientdata , cmd_t * cmd ) {
130
133
char * cmdname ;
131
134
switch (cmd -> cmd ) {
132
135
case CMD_RESERVE : cmdname = "RESERVE" ; break ;
@@ -137,15 +140,15 @@ static void shout_cmd(void *clientdata, cmd_t *cmd) {
137
140
case CMD_STATUS : cmdname = "STATUS" ; break ;
138
141
default : cmdname = "unknown" ;
139
142
}
140
- shout ("[%d] %s" , CLIENT_ID (clientdata ), cmdname );
143
+ debug ("[%d] %s" , CLIENT_ID (clientdata ), cmdname );
141
144
int i ;
142
145
for (i = 0 ; i < cmd -> argc ; i ++ ) {
143
- shout (" %llu" , cmd -> argv [i ]);
146
+ debug (" %llu" , cmd -> argv [i ]);
144
147
}
145
- shout ("\n" );
148
+ debug ("\n" );
146
149
}
147
150
#else
148
- #define shout_cmd (...)
151
+ #define debug_cmd (...)
149
152
#endif
150
153
151
154
#define CHECK (COND , CDATA , MSG ) \
@@ -197,14 +200,14 @@ static char *onreserve(void *stream, void *clientdata, cmd_t *cmd) {
197
200
int minsize = cmd -> argv [1 ];
198
201
xid_t maxxid = minxid + minsize - 1 ;
199
202
200
- shout (
203
+ debug (
201
204
"[%d] RESERVE: asked for range %llu-%llu\n" ,
202
205
CLIENT_ID (clientdata ),
203
206
minxid , maxxid
204
207
);
205
208
206
209
if ((prev_gxid >= minxid ) || (maxxid >= next_gxid )) {
207
- shout (
210
+ debug (
208
211
"[%d] RESERVE: local range %llu-%llu is not between global range %llu-%llu\n" ,
209
212
CLIENT_ID (clientdata ),
210
213
minxid , maxxid ,
@@ -215,7 +218,7 @@ static char *onreserve(void *stream, void *clientdata, cmd_t *cmd) {
215
218
maxxid = max (maxxid , minxid + minsize - 1 );
216
219
next_gxid = maxxid + 1 ;
217
220
}
218
- shout (
221
+ debug (
219
222
"[%d] RESERVE: allocating range %llu-%llu\n" ,
220
223
CLIENT_ID (clientdata ),
221
224
minxid , maxxid
@@ -514,7 +517,7 @@ static char *onnoise(void *stream, void *clientdata, cmd_t *cmd) {
514
517
// }
515
518
516
519
static char * oncmd (void * stream , void * clientdata , cmd_t * cmd ) {
517
- shout_cmd (clientdata , cmd );
520
+ debug_cmd (clientdata , cmd );
518
521
519
522
char * result = NULL ;
520
523
switch (cmd -> cmd ) {
@@ -547,12 +550,6 @@ static char *ondata(void *stream, void *clientdata, size_t len, char *data) {
547
550
parser_t parser = CLIENT_PARSER (clientdata );
548
551
char * response = NULL ;
549
552
550
- // shout(
551
- // "[%d] got some data[%lu] %s\n",
552
- // CLIENT_ID(clientdata),
553
- // len, data
554
- // );
555
-
556
553
// The idea is to feed each character through
557
554
// the parser, which will return a cmd from
558
555
// time to time.
@@ -585,16 +582,102 @@ static char *ondata(void *stream, void *clientdata, size_t len, char *data) {
585
582
}
586
583
587
584
static void usage (char * prog ) {
588
- printf ("Usage: %s [-d DATADIR] [-a HOST] [-p PORT]\n" , prog );
585
+ printf (
586
+ "Usage: %s [-d DATADIR] [-k] [-a HOST] [-p PORT] [-l LOGFILE]\n"
587
+ " dtmd will try to kill the other one running at\n"
588
+ " the same DATADIR.\n"
589
+ " -l : Run as a daemon and write output to LOGFILE.\n"
590
+ " -k : Just kill the other dtm and exit.\n" ,
591
+ prog
592
+ );
593
+ }
594
+
595
+ // Reads a pid from the file at 'pidpath'.
596
+ // Returns the pid, or 0 in case of error.
597
+ int read_pid (char * pidpath ) {
598
+ FILE * f = fopen (pidpath , "r" );
599
+ if (f == NULL ) {
600
+ debug ("failed to open pidfile for reading: %s\n" , strerror (errno ));
601
+ return 0 ;
602
+ }
603
+
604
+ int pid = 0 ;
605
+ if (fscanf (f , "%d" , & pid ) != 1 ) {
606
+ shout ("failed to read pid from pidfile\n" );
607
+ pid = 0 ;
608
+ }
609
+
610
+ if (fclose (f )) {
611
+ shout ("failed to close pidfile O_o: %s\n" , strerror (errno ));
612
+ }
613
+ return pid ;
614
+ }
615
+
616
+ // Returns the pid, or 0 in case of error.
617
+ int write_pid (char * pidpath , int pid ) {
618
+ FILE * f = fopen (pidpath , "w" );
619
+ if (f == NULL ) {
620
+ shout ("failed to open pidfile for writing: %s\n" , strerror (errno ));
621
+ return 0 ;
622
+ }
623
+
624
+ if (fprintf (f , "%d\n" , pid ) < 0 ) {
625
+ shout ("failed to write pid to pidfile\n" );
626
+ pid = 0 ;
627
+ }
628
+
629
+ if (fclose (f )) {
630
+ shout ("failed to close pidfile O_o: %s\n" , strerror (errno ));
631
+ }
632
+ return pid ;
633
+ }
634
+
635
+ // If there is a pidfile in 'datadir',
636
+ // sends TERM signal to the corresponding pid.
637
+ void kill_the_elder (char * datadir ) {
638
+ char * pidpath = join_path (datadir , "dtmd.pid" );
639
+ int pid = read_pid (pidpath );
640
+ free (pidpath );
641
+
642
+ if (pid > 1 ) {
643
+ if (kill (pid , SIGTERM )) {
644
+ switch (errno ) {
645
+ case EPERM :
646
+ shout ("was not allowed to kill pid=%d\n" , pid );
647
+ break ;
648
+ case ESRCH :
649
+ shout ("pid=%d not found for killing\n" , pid );
650
+ break ;
651
+ }
652
+ }
653
+ debug ("SIGTERM sent to pid=%d\n" pid );
654
+ debug ("waiting for pid=%d to die\n" pid );
655
+ waitpid (pid , NULL , 0 );
656
+ debug ("pid=%d died\n" pid );
657
+ } else {
658
+ debug ("no elder to kill\n" pid );
659
+ }
660
+ }
661
+
662
+ char * pidpath ;
663
+ void die (int signum ) {
664
+ shout ("terminated\n" );
665
+ if (unlink (pidpath ) == -1 ) {
666
+ shout ("could not remove pidfile: %s\n" , strerror (errno ));
667
+ }
668
+ exit (signum );
589
669
}
590
670
591
671
int main (int argc , char * * argv ) {
592
672
char * datadir = DEFAULT_DATADIR ;
593
673
char * listenhost = DEFAULT_LISTENHOST ;
674
+ char * logfilename = NULL ;
675
+ bool daemonize = false;
676
+ bool assassin = false;
594
677
int listenport = DEFAULT_LISTENPORT ;
595
678
596
679
int opt ;
597
- while ((opt = getopt (argc , argv , "hd:a:p:" )) != -1 ) {
680
+ while ((opt = getopt (argc , argv , "hd:a:p:l:k " )) != -1 ) {
598
681
switch (opt ) {
599
682
case 'd' :
600
683
datadir = optarg ;
@@ -605,21 +688,51 @@ int main(int argc, char **argv) {
605
688
case 'p' :
606
689
listenport = atoi (optarg );
607
690
break ;
691
+ case 'l' :
692
+ logfilename = optarg ;
693
+ daemonize = true;
694
+ break ;
608
695
case 'h' :
609
696
usage (argv [0 ]);
610
697
return EXIT_SUCCESS ;
698
+ case 'k' :
699
+ assassin = true;
700
+ break ;
611
701
default :
612
702
usage (argv [0 ]);
613
703
return EXIT_FAILURE ;
614
704
}
615
705
}
616
706
707
+ kill_the_elder (datadir );
708
+ if (assassin ) {
709
+ return EXIT_SUCCESS ;
710
+ }
711
+
712
+ if (logfilename ) {
713
+ freopen (logfilename , "a" , stdout );
714
+ freopen (logfilename , "a" , stderr );
715
+ }
716
+
617
717
clg = clog_open (datadir );
618
718
if (!clg ) {
619
719
shout ("could not open clog at '%s'\n" , datadir );
620
720
return EXIT_FAILURE ;
621
721
}
622
722
723
+ if (daemonize ) {
724
+ if (daemon (true, true) == -1 ) {
725
+ shout ("could not daemonize: %s\n" , strerror (errno ));
726
+ return EXIT_FAILURE ;
727
+ }
728
+ }
729
+
730
+ pidpath = join_path (datadir , "dtmd.pid" );
731
+ signal (SIGTERM , die );
732
+ signal (SIGINT , die );
733
+
734
+ write_pid (pidpath , getpid ());
735
+
623
736
prev_gxid = MIN_XID ;
624
737
next_gxid = MIN_XID ;
625
738
transactions_count = 0 ;
@@ -630,5 +743,6 @@ int main(int argc, char **argv) {
630
743
);
631
744
632
745
clog_close (clg );
746
+
633
747
return retcode ;
634
748
}
0 commit comments