2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved.
20 * Process globals (we could put these in the machtab I suppose).
24 unsigned short myport;
26 const char *progname = "ex_rep_base";
28 static void event_callback __P((DB_ENV *, u_int32_t, void *));
36 SETUP_DATA setup_info;
42 thread_t all_thr, ckp_thr, conn_thr, lga_thr;
43 void *astatus, *cstatus;
47 struct sigaction sigact;
52 memset(&setup_info, 0, sizeof(SETUP_DATA));
53 setup_info.progname = progname;
54 master_eid = DB_EID_INVALID;
55 memset(&my_app_data, 0, sizeof(APP_DATA));
60 if ((ret = create_env(progname, &dbenv)) != 0)
62 dbenv->app_private = &my_app_data;
63 (void)dbenv->set_event_notify(dbenv, event_callback);
65 /* Parse command line and perform common replication setup. */
66 if ((ret = common_rep_setup(dbenv, argc, argv, &setup_info)) != 0)
69 if (setup_info.role == MASTER)
70 master_eid = SELF_EID;
72 myaddr = strdup(setup_info.self.host);
73 myport = setup_info.self.port;
76 /* Initialize the Windows sockets DLL. */
77 if ((ret = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) {
79 "Unable to initialize Windows sockets: %d\n", ret);
84 * Turn off SIGPIPE so that we don't kill processes when they
85 * happen to lose a connection at the wrong time.
87 memset(&sigact, 0, sizeof(sigact));
88 sigact.sa_handler = SIG_IGN;
89 if ((ret = sigaction(SIGPIPE, &sigact, NULL)) != 0) {
91 "Unable to turn off SIGPIPE: %s\n", strerror(ret));
97 * We are hardcoding priorities here that all clients have the
98 * same priority except for a designated master who gets a higher
102 machtab_init(&machtab, setup_info.nsites)) != 0)
104 my_app_data.comm_infrastructure = machtab;
106 if ((ret = env_init(dbenv, setup_info.home)) != 0)
110 * Now sets up comm infrastructure. There are two phases. First,
111 * we open our port for listening for incoming connections. Then
112 * we attempt to connect to every host we know about.
115 (void)dbenv->rep_set_transport(dbenv, SELF_EID, quote_send);
118 ca.home = setup_info.home;
119 ca.progname = progname;
120 ca.machtab = machtab;
121 ca.port = setup_info.self.port;
122 if ((ret = thread_create(&conn_thr, NULL, connect_thread, &ca)) != 0) {
123 dbenv->errx(dbenv, "can't create connect thread");
128 aa.progname = progname;
129 aa.home = setup_info.home;
130 aa.machtab = machtab;
131 aa.sites = setup_info.site_list;
132 aa.nsites = setup_info.remotesites;
133 if ((ret = thread_create(&all_thr, NULL, connect_all, &aa)) != 0) {
134 dbenv->errx(dbenv, "can't create connect-all thread");
138 /* Start checkpoint and log archive threads. */
140 supa.shared = &my_app_data.shared_data;
141 if ((ret = start_support_threads(dbenv, &supa, &ckp_thr, &lga_thr))
146 * We have now got the entire communication infrastructure set up.
147 * It's time to declare ourselves to be a client or master.
149 if (setup_info.role == MASTER) {
150 if ((ret = dbenv->rep_start(dbenv, NULL, DB_REP_MASTER)) != 0) {
151 dbenv->err(dbenv, ret, "dbenv->rep_start failed");
155 memset(&local, 0, sizeof(local));
157 local.size = (u_int32_t)strlen(myaddr) + 1;
159 dbenv->rep_start(dbenv, &local, DB_REP_CLIENT)) != 0) {
160 dbenv->err(dbenv, ret, "dbenv->rep_start failed");
163 /* Sleep to give ourselves time to find a master. */
167 if ((ret = doloop(dbenv, &my_app_data.shared_data)) != 0) {
168 dbenv->err(dbenv, ret, "Main loop failed");
172 /* Finish checkpoint and log archive threads. */
173 if ((ret = finish_support_threads(&ckp_thr, &lga_thr)) != 0)
176 /* Wait on the connection threads. */
177 if (thread_join(all_thr, &astatus) || thread_join(conn_thr, &cstatus)) {
181 if ((uintptr_t)astatus != EXIT_SUCCESS ||
182 (uintptr_t)cstatus != EXIT_SUCCESS) {
188 * We have used the DB_TXN_NOSYNC environment flag for improved
189 * performance without the usual sacrifice of transactional durability,
190 * as discussed in the "Transactional guarantees" page of the Reference
191 * Guide: if one replication site crashes, we can expect the data to
192 * exist at another site. However, in case we shut down all sites
193 * gracefully, we push out the end of the log here so that the most
194 * recent transactions don't mysteriously disappear.
196 if ((ret = dbenv->log_flush(dbenv, NULL)) != 0)
197 dbenv->err(dbenv, ret, "log_flush");
199 err: if (machtab != NULL)
202 (void)dbenv->close(dbenv, 0);
204 /* Shut down the Windows sockets DLL. */
211 event_callback(dbenv, which, info)
216 APP_DATA *app = dbenv->app_private;
217 SHARED_DATA *shared = &app->shared_data;
220 case DB_EVENT_REP_CLIENT:
221 shared->is_master = 0;
222 shared->in_client_sync = 1;
225 case DB_EVENT_REP_ELECTED:
227 master_eid = SELF_EID;
230 case DB_EVENT_REP_MASTER:
231 shared->is_master = 1;
232 shared->in_client_sync = 0;
235 case DB_EVENT_REP_NEWMASTER:
236 master_eid = *(int*)info;
237 shared->in_client_sync = 1;
240 case DB_EVENT_REP_STARTUPDONE:
241 shared->in_client_sync = 0;
245 dbenv->errx(dbenv, "ignoring event %d", which);