gdp / apps / log-mirror.c @ master
History | View | Annotate | Download (3.79 KB)
1 |
/* vim: set ai sw=4 sts=4 ts=4 : */
|
---|---|
2 |
|
3 |
/*
|
4 |
** LOG-MIRROR --- mirror a log
|
5 |
**
|
6 |
** Cheap and dirty replication.
|
7 |
**
|
8 |
** ----- BEGIN LICENSE BLOCK -----
|
9 |
** Applications for the Global Data Plane
|
10 |
** From the Ubiquitous Swarm Lab, 490 Cory Hall, U.C. Berkeley.
|
11 |
**
|
12 |
** Copyright (c) 2015-2019, Regents of the University of California.
|
13 |
** All rights reserved.
|
14 |
**
|
15 |
** Permission is hereby granted, without written agreement and without
|
16 |
** license or royalty fees, to use, copy, modify, and distribute this
|
17 |
** software and its documentation for any purpose, provided that the above
|
18 |
** copyright notice and the following two paragraphs appear in all copies
|
19 |
** of this software.
|
20 |
**
|
21 |
** IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
22 |
** SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
|
23 |
** PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
|
24 |
** EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
25 |
**
|
26 |
** REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
27 |
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
28 |
** FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
|
29 |
** IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
|
30 |
** OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
|
31 |
** OR MODIFICATIONS.
|
32 |
** ----- END LICENSE BLOCK -----
|
33 |
*/
|
34 |
|
35 |
#include <gdp/gdp.h> |
36 |
|
37 |
#include <ep/ep_app.h> |
38 |
#include <ep/ep_dbg.h> |
39 |
|
40 |
#include <sysexits.h> |
41 |
|
42 |
void
|
43 |
usage(void)
|
44 |
{ |
45 |
fprintf(stderr, |
46 |
"Usage: %s [-D dbg_spec] [-G router_addr] source_log target_log\n"
|
47 |
" -D set debugging flags\n"
|
48 |
" -G IP host to contact for gdp_router\n",
|
49 |
ep_app_getprogname()); |
50 |
exit(EX_USAGE); |
51 |
} |
52 |
|
53 |
|
54 |
int
|
55 |
main(int argc, char **argv) |
56 |
{ |
57 |
int opt;
|
58 |
bool show_usage = false; |
59 |
EP_STAT estat; |
60 |
gdp_gin_t *igin, *ogin; |
61 |
char *gdpd_addr = NULL; |
62 |
const char *lname, *lmode; |
63 |
gdp_recno_t nextrecno; |
64 |
gdp_name_t gdpiname; |
65 |
gdp_event_t *gev; |
66 |
|
67 |
while ((opt = getopt(argc, argv, "D:G:")) > 0) |
68 |
{ |
69 |
switch (opt)
|
70 |
{ |
71 |
case 'D': |
72 |
ep_dbg_set(optarg); |
73 |
break;
|
74 |
|
75 |
case 'G': |
76 |
gdpd_addr = optarg; |
77 |
break;
|
78 |
|
79 |
default:
|
80 |
show_usage = true;
|
81 |
break;
|
82 |
} |
83 |
} |
84 |
argc -= optind; |
85 |
argv += optind; |
86 |
|
87 |
if (show_usage || argc != 2) |
88 |
usage(); |
89 |
|
90 |
// initialize GDP library
|
91 |
estat = gdp_init(gdpd_addr); |
92 |
if (!EP_STAT_ISOK(estat))
|
93 |
{ |
94 |
ep_app_error("GDP Initialization failed");
|
95 |
goto fail0;
|
96 |
} |
97 |
|
98 |
// allow thread to settle to avoid interspersed debug output
|
99 |
ep_time_nanosleep(INT64_C(100000000));
|
100 |
|
101 |
// open target GCL (must already exist)
|
102 |
lname = argv[1];
|
103 |
lmode = "append";
|
104 |
gdp_parse_name(argv[1], gdpiname);
|
105 |
estat = gdp_gin_open(gdpiname, GDP_MODE_AO, NULL, &ogin);
|
106 |
EP_STAT_CHECK(estat, goto fail1);
|
107 |
nextrecno = gdp_gin_getnrecs(ogin) + 1;
|
108 |
|
109 |
// open a source GCL with the provided name
|
110 |
lname = argv[0];
|
111 |
lmode = "read";
|
112 |
gdp_parse_name(argv[0], gdpiname);
|
113 |
estat = gdp_gin_open(gdpiname, GDP_MODE_RO, NULL, &igin);
|
114 |
EP_STAT_CHECK(estat, goto fail1);
|
115 |
|
116 |
// subscribe to input starting from the first recno target does not have
|
117 |
estat = gdp_gin_subscribe_by_recno(igin, nextrecno, 0, NULL, NULL, NULL); |
118 |
EP_STAT_CHECK(estat, goto fail2);
|
119 |
|
120 |
// copy forever
|
121 |
while ((gev = gdp_event_next(igin, NULL)) != NULL) |
122 |
{ |
123 |
switch (gdp_event_gettype(gev))
|
124 |
{ |
125 |
case GDP_EVENT_DATA:
|
126 |
// copy the record to the new log
|
127 |
estat = gdp_gin_append(ogin, gdp_event_getdatum(gev), NULL);
|
128 |
EP_STAT_CHECK(estat, goto fail3);
|
129 |
break;
|
130 |
|
131 |
case GDP_EVENT_DONE:
|
132 |
case GDP_EVENT_SHUTDOWN:
|
133 |
ep_app_error("unexpected end of subscription");
|
134 |
estat = EP_STAT_END_OF_FILE; |
135 |
goto fail2;
|
136 |
|
137 |
default:
|
138 |
// ignore
|
139 |
break;
|
140 |
} |
141 |
} |
142 |
|
143 |
fail3:
|
144 |
ep_app_error("append failed");
|
145 |
|
146 |
fail2:
|
147 |
// close GCLs / release resources
|
148 |
//XXX someday
|
149 |
|
150 |
if (false) |
151 |
{ |
152 |
fail1:
|
153 |
ep_app_error("could not open %s for %s", lname, lmode);
|
154 |
} |
155 |
|
156 |
fail0:
|
157 |
ep_app_message(estat, "exiting with status");
|
158 |
return EP_STAT_ISOK(estat) ? EX_OK : EX_UNAVAILABLE;
|
159 |
} |