ARB
arb_sync.cxx
Go to the documentation of this file.
1 // ========================================================= //
2 // //
3 // File : arb_sync.cxx //
4 // Purpose : synchronize processes via arb database //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in Sep 25 //
7 // http://www.arb-home.de/ //
8 // //
9 // ========================================================= //
10 
11 #include <algorithm>
12 
13 #include <arbdbt.h>
14 #include <arb_sleep.h>
15 
16 static void report_error(GB_ERROR err) {
17  fprintf(stderr, "Error running arb_sync: %s\n", err);
18 }
19 
21  if (error) {
22  report_error(error);
23  return EXIT_FAILURE;
24  }
25  return EXIT_SUCCESS;
26 }
27 
28 static int arb_sync_write(const char *ID, const char *value) {
29  GB_shell shell;
30  GBDATA *gb_main = GB_open(":", "r");
32 
33  if (gb_main) {
34  GB_transaction ta(gb_main);
35  error = GB_write_sync_value(gb_main, ID, value);
36  ta.close(error);
37 
38  GB_close(gb_main);
39  }
40  else {
41  error = GB_await_error();
42  }
43 
44  return exitcodeFrom(error);
45 }
46 static int arb_sync_wait(const char *ID, const char *wantedValue) {
47  GB_shell shell;
48  GBDATA *gb_main = GB_open(":", "r");
50 
51  if (gb_main) {
52  bool value_reached = false;
53  const long MIN_DELAY = 250;
54  const long MAX_DELAY = 3500;
55  long loop = 0;
56 
57  while (!value_reached) {
58  const char *currentValue = NULp;
59  {
60  GB_transaction ta(gb_main);
61  currentValue = GB_read_sync_value(gb_main, ID);
62  if (!currentValue) {
63  error = GB_await_error();
64  fprintf(stderr, "Error running arb_sync: failed to GB_read_sync_value: %s (will retry)\n", error);
65  }
66  }
67 
68  long delay_ms = 0; // ms to sleep
69  if (currentValue) {
70  if (strcmp(currentValue, wantedValue) == 0) {
71  fprintf(stderr, "Sync '%s' reached wanted value '%s'\n", ID, currentValue);
72  delay_ms = 0;
73  value_reached = true;
74  }
75  else {
76  fprintf(stderr, "Sync '%s' has value '%s' (waiting for '%s')\n", ID, currentValue, wantedValue);
77  delay_ms = std::min(MAX_DELAY, loop * 77 + MIN_DELAY);
78  }
79  }
80  else {
81  delay_ms = 1554;
82  }
83 
84  ARB_sleep(delay_ms, MS);
85  loop++;
86  }
87 
88  GB_close(gb_main);
89  }
90  else {
91  error = GB_await_error();
92  }
93 
94  return exitcodeFrom(error);
95 }
96 
97 static int show_usage(const char *error) {
98  const char *usage =
99  "Usage: arb_sync <modeflag> <ID> <value>\n"
100  "Purpose: Use the running arb database to synchronise processes.\n"
101  "<ID>::= a unique identifier for synchronisation\n"
102  "<value>::= used value\n"
103  "<modeflag>::=\n"
104  " --write store specified value for ID\n"
105  " --wait wait until ID reaches specified value\n"
106  ;
107  fputs(usage, stderr);
108 
109  if (error) {
110  fprintf(stderr, "Error in arb_sync: %s\n", error);
111  return EXIT_FAILURE;
112  }
113 
114  return EXIT_SUCCESS;
115 }
116 
117 static bool requests_help(const char *arg) {
118  return
119  strcmp(arg, "--help") == 0 ||
120  strcmp(arg, "-h") == 0;
121 }
122 
123 int ARB_main(int argc, char *argv[]) {
124  int exitcode = EXIT_SUCCESS;
125 
126  const char *mode = NULp;
127  const char *ID = NULp;
128  const char *value = NULp;
129 
130  while (argc>1) {
131  const char *arg = argv[1];
132 
133  if (!mode) mode = arg;
134  else if (!ID) ID = arg;
135  else if (!value) value = arg;
136  else exitcode = show_usage(GBS_global_string("too many arguments (%s)", arg));
137 
138  argc--;argv++;
139  }
140 
141  if (!mode) exitcode = show_usage("missing argument <modeflag>");
142  else if (requests_help(mode)) exitcode = show_usage(NULp);
143  else if (!ID) exitcode = show_usage("missing argument <ID>");
144  else if (!value) exitcode = show_usage("missing argument <value>");
145  else {
146  if (strcmp(mode, "--write") == 0) exitcode = arb_sync_write(ID, value);
147  else if (strcmp(mode, "--wait") == 0) exitcode = arb_sync_wait(ID, value);
148  else exitcode = show_usage(GBS_global_string("Unknown <modeflag> '%s'", mode));
149  }
150 
151  return exitcode;
152 }
153 
154 
const char * GB_ERROR
Definition: arb_core.h:25
GBDATA * GB_open(const char *path, const char *opent)
Definition: ad_load.cxx:1363
static int exitcodeFrom(GB_ERROR error)
Definition: arb_sync.cxx:20
int ARB_main(int argc, char *argv[])
Definition: arb_sync.cxx:123
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
#define EXIT_SUCCESS
Definition: arb_a2ps.c:154
static int arb_sync_wait(const char *ID, const char *wantedValue)
Definition: arb_sync.cxx:46
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
static int show_usage(const char *error)
Definition: arb_sync.cxx:97
static void error(const char *msg)
Definition: mkptypes.cxx:96
GB_CSTR GB_read_sync_value(GBDATA *gb_main, const char *id)
Definition: adsocket.cxx:951
int32_t ID
GB_ERROR GB_write_sync_value(GBDATA *gb_main, const char *id, const char *value)
Definition: adsocket.cxx:939
void ARB_sleep(int amount, TimeUnit tu)
Definition: arb_sleep.h:32
#define EXIT_FAILURE
Definition: arb_a2ps.c:157
static void report_error(GB_ERROR err)
Definition: arb_sync.cxx:16
fputs(TRACE_PREFIX, stderr)
GB_ERROR close(GB_ERROR error)
Definition: arbdbpp.cxx:35
Definition: arb_sleep.h:30
#define NULp
Definition: cxxforward.h:116
static bool requests_help(const char *arg)
Definition: arb_sync.cxx:117
GB_transaction ta(gb_var)
GBDATA * gb_main
Definition: adname.cxx:32
void usage()
Definition: readseq.c:328
#define min(a, b)
Definition: f2c.h:153
static int arb_sync_write(const char *ID, const char *value)
Definition: arb_sync.cxx:28
void GB_close(GBDATA *gbd)
Definition: arbdb.cxx:655