source: trunk/TOOLS/arb_sync.cxx

Last change on this file was 19549, checked in by westram, 5 weeks ago
  • reintegrates 'sync' into 'trunk'
    • fixes #869
      • introduces synchronisation of external commands via DB
      • macros now wait for these external commands to finish ⇒ macro can continue with results
  • adds: log:branches/sync@19535:19548
File size: 4.7 KB
Line 
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
16static void report_error(GB_ERROR err) {
17    fprintf(stderr, "Error running arb_sync: %s\n", err);
18}
19
20static int exitcodeFrom(GB_ERROR error) {
21    if (error) {
22        report_error(error);
23        return EXIT_FAILURE;
24    }
25    return EXIT_SUCCESS;
26}
27
28static int arb_sync_write(const char *ID, const char *value) {
29    GB_shell  shell;
30    GBDATA   *gb_main = GB_open(":", "r");
31    GB_ERROR  error   = NULp;
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}
46static int arb_sync_wait(const char *ID, const char *wantedValue) {
47    GB_shell  shell;
48    GBDATA   *gb_main = GB_open(":", "r");
49    GB_ERROR  error   = NULp;
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
97static 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
117static bool requests_help(const char *arg) {
118    return
119        strcmp(arg, "--help") == 0 ||
120        strcmp(arg, "-h") == 0;
121}
122
123int 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
Note: See TracBrowser for help on using the repository browser.