static cs_error_t sam_confdb_update_key (enum sam_confdb_key_t key, const char *value) { cs_error_t err; const char *svalue; uint64_t hc_period, last_hc; const char *ssvalue[] = { [SAM_RECOVERY_POLICY_QUIT] = "quit", [SAM_RECOVERY_POLICY_RESTART] = "restart" }; switch (key) { case SAM_CONFDB_KEY_RECOVERY: svalue = ssvalue[SAM_RP_MASK (sam_internal_data.recovery_policy)]; if ((err = confdb_key_create_typed (sam_internal_data.confdb_handle, sam_internal_data.confdb_pid_handle, "recovery", svalue, strlen ((const char *)svalue), CONFDB_VALUETYPE_STRING)) != CS_OK) { goto exit_error; } break; case SAM_CONFDB_KEY_HC_PERIOD: hc_period = sam_internal_data.time_interval; if ((err = confdb_key_create_typed (sam_internal_data.confdb_handle, sam_internal_data.confdb_pid_handle, "poll_period", &hc_period, sizeof (hc_period), CONFDB_VALUETYPE_UINT64)) != CS_OK) { goto exit_error; } break; case SAM_CONFDB_KEY_LAST_HC: last_hc = cs_timestamp_get(); if ((err = confdb_key_create_typed (sam_internal_data.confdb_handle, sam_internal_data.confdb_pid_handle, "last_updated", &last_hc, sizeof (last_hc), CONFDB_VALUETYPE_UINT64)) != CS_OK) { goto exit_error; } break; case SAM_CONFDB_KEY_STATE: svalue = value; if ((err = confdb_key_create_typed (sam_internal_data.confdb_handle, sam_internal_data.confdb_pid_handle, "state", svalue, strlen ((const char *)svalue), CONFDB_VALUETYPE_STRING)) != CS_OK) { goto exit_error; } break; } return (CS_OK); exit_error: return (err); }
int join(commandline_t *comline, char *main_envp[]) { int i, err; int envptr = 0; int argvptr = 0; char scratch[1024]; char config_modules[1024]; cman_handle_t h = NULL; int status; hdb_handle_t object_handle; confdb_handle_t confdb_handle; int res; pid_t corosync_pid; int p[2]; confdb_callbacks_t callbacks = { .confdb_key_change_notify_fn = NULL, .confdb_object_create_change_notify_fn = NULL, .confdb_object_delete_change_notify_fn = NULL }; /* * If we can talk to cman then we're already joined (or joining); */ h = cman_admin_init(NULL); if (h) die("Node is already active"); /* Set up environment variables for override */ if (comline->multicast_addr) { snprintf(scratch, sizeof(scratch), "CMAN_MCAST_ADDR=%s", comline->multicast_addr); envp[envptr++] = strdup(scratch); } if (comline->votes_opt) { snprintf(scratch, sizeof(scratch), "CMAN_VOTES=%d", comline->votes); envp[envptr++] = strdup(scratch); } if (comline->expected_votes_opt) { snprintf(scratch, sizeof(scratch), "CMAN_EXPECTEDVOTES=%d", comline->expected_votes); envp[envptr++] = strdup(scratch); } if (comline->port) { snprintf(scratch, sizeof(scratch), "CMAN_IP_PORT=%d", comline->port); envp[envptr++] = strdup(scratch); } if (comline->nodeid) { snprintf(scratch, sizeof(scratch), "CMAN_NODEID=%d", comline->nodeid); envp[envptr++] = strdup(scratch); } if (comline->clustername_opt) { snprintf(scratch, sizeof(scratch), "CMAN_CLUSTER_NAME=%s", comline->clustername); envp[envptr++] = strdup(scratch); } if (comline->nodenames[0]) { snprintf(scratch, sizeof(scratch), "CMAN_NODENAME=%s", comline->nodenames[0]); envp[envptr++] = strdup(scratch); } if (comline->key_filename) { snprintf(scratch, sizeof(scratch), "CMAN_KEYFILE=%s", comline->key_filename); envp[envptr++] = strdup(scratch); } if (comline->two_node) { snprintf(scratch, sizeof(scratch), "CMAN_2NODE=true"); envp[envptr++] = strdup(scratch); } if (comline->verbose ^ DEBUG_STARTUP_ONLY) { snprintf(scratch, sizeof(scratch), "CMAN_DEBUG=%d", comline->verbose); envp[envptr++] = strdup(scratch); } if (comline->nostderr_debug) { snprintf(scratch, sizeof(scratch), "CMAN_NOSTDERR_DEBUG=true"); envp[envptr++] = strdup(scratch); } if (comline->noconfig_opt) { envp[envptr++] = strdup("CMAN_NOCONFIG=true"); snprintf(config_modules, sizeof(config_modules), "cmanpreconfig"); } else { snprintf(config_modules, sizeof(config_modules), "%s:cmanpreconfig", comline->config_lcrso); } if (comline->noopenais_opt) { envp[envptr++] = strdup("CMAN_NOOPENAIS=true"); } snprintf(scratch, sizeof(scratch), "COROSYNC_DEFAULT_CONFIG_IFACE=%s", config_modules); envp[envptr++] = strdup(scratch); /* Copy any COROSYNC_* env variables to the new daemon */ i=0; while (i < MAX_ARGS && main_envp[i]) { if (strncmp(main_envp[i], "COROSYNC_", 9) == 0) envp[envptr++] = main_envp[i]; i++; } /* Create a pipe to monitor cman startup progress */ if (pipe(p) < 0) die("unable to create pipe: %s", strerror(errno)); fcntl(p[1], F_SETFD, 0); /* Don't close on exec */ snprintf(scratch, sizeof(scratch), "CMAN_PIPE=%d", p[1]); envp[envptr++] = strdup(scratch); envp[envptr++] = NULL; /* Always run corosync -f because we have already forked twice anyway, and we want to return any exit code that might happen */ /* also strdup strings because it's otherwise virtually impossible to fix * build warnings due to the way argv C implementation is done */ argv[0] = strdup("corosync"); argv[++argvptr] = strdup("-f"); if (comline->nosetpri_opt) argv[++argvptr] = strdup("-p"); argv[++argvptr] = NULL; /* Fork/exec cman */ switch ( (corosync_pid = fork()) ) { case -1: die("fork of corosync daemon failed: %s", strerror(errno)); case 0: /* child */ close(p[0]); if (comline->verbose & DEBUG_STARTUP_ONLY) { fprintf(stderr, "Starting %s", COROSYNCBIN); for (i=0; i< argvptr; i++) { fprintf(stderr, " %s", argv[i]); } fprintf(stderr, "\n"); for (i=0; i<envptr-1; i++) { fprintf(stderr, "%s\n", envp[i]); } } be_daemon(); sprintf(scratch, "FORKED: %d\n", getpid()); err = write(p[1], scratch, strlen(scratch)); execve(COROSYNCBIN, argv, envp); /* exec failed - tell the parent process */ sprintf(scratch, "execve of " COROSYNCBIN " failed: %s", strerror(errno)); err = write(p[1], scratch, strlen(scratch)); exit(1); break; default: /* parent */ break; } /* Give the daemon a chance to start up, and monitor the pipe FD for messages */ i = 0; close(p[1]); /* Wait for the process to start or die */ sleep(1); do { fd_set fds; struct timeval tv={1, 0}; char message[1024]; char *messageptr = message; FD_ZERO(&fds); FD_SET(p[0], &fds); status = select(p[0]+1, &fds, NULL, NULL, &tv); /* Did we get a cman-reported error? */ if (status == 1) { int len; if ((len = read(p[0], message, sizeof(message)) > 0)) { /* Forked OK - get the real corosync pid */ if (sscanf(messageptr, "FORKED: %d", &corosync_pid) == 1) { if (comline->verbose & DEBUG_STARTUP_ONLY) fprintf(stderr, "forked process ID is %d\n", corosync_pid); status = 0; /* There might be a SUCCESS or error message in the pipe too. */ messageptr = strchr(messageptr, '\n'); if (messageptr && strlen(messageptr) > 1) messageptr++; else continue; } /* Success! get the new PID of double-forked corosync */ if (sscanf(messageptr, "SUCCESS: %d", &corosync_pid) == 1) { if (comline->verbose & DEBUG_STARTUP_ONLY) fprintf(stderr, "corosync running, process ID is %d\n", corosync_pid); status = 0; break; } else if (messageptr) { fprintf(stderr, "%s\n", messageptr); status = 1; break; } } else if (len < 0 && errno == EINTR) { continue; } else { /* Error or EOF - check the child status */ status = check_corosync_status(corosync_pid); if (status == 0) break; } } } while (status == 0); close(p[0]); /* If corosync has started, try to connect to cman ... if it's still there */ if (status == 0) { do { if (status == 0) { if (kill(corosync_pid, 0) < 0) { status = check_corosync_status(corosync_pid); die("corosync died during startup\n"); } h = cman_admin_init(NULL); if (!h && comline->verbose & DEBUG_STARTUP_ONLY) { fprintf(stderr, "waiting for cman to start\n"); status = check_corosync_status(corosync_pid); } } sleep (1); } while (!h && ++i < 100); } if (!h) die("corosync daemon didn't start"); if ((comline->verbose & DEBUG_STARTUP_ONLY) && !cman_is_active(h)) fprintf(stderr, "corosync started, but not joined the cluster yet.\n"); cman_finish(h); /* Copy all COROSYNC_* environment variables into objdb so they can be used to validate new configurations later */ res = confdb_initialize (&confdb_handle, &callbacks); if (res != CS_OK) goto join_exit; res = confdb_object_create(confdb_handle, OBJECT_PARENT_HANDLE, "cman_private", strlen("cman_private"), &object_handle); if (res == CS_OK) { int envnum = 0; const char *envvar = main_envp[envnum]; const char *equal; char envname[PATH_MAX]; while (envvar) { if (strncmp("COROSYNC_", envvar, 9) == 0) { equal = strchr(envvar, '='); if (equal) { strncpy(envname, envvar, PATH_MAX); if (equal-envvar < PATH_MAX) { envname[equal-envvar] = '\0'; res = confdb_key_create_typed(confdb_handle, object_handle, envname, equal+1, strlen(equal+1),CONFDB_VALUETYPE_STRING); } } } envvar = main_envp[++envnum]; } } res = confdb_key_create_typed(confdb_handle, object_handle, "COROSYNC_DEFAULT_CONFIG_IFACE", config_modules, strlen(config_modules), CONFDB_VALUETYPE_STRING); confdb_finalize (confdb_handle); join_exit: return 0; }
static void create_object_key(confdb_handle_t handle, char *name_pt) { char * obj_name_pt; char * new_obj_name_pt; char * save_pt; hdb_handle_t obj_handle; hdb_handle_t parent_object_handle = OBJECT_PARENT_HANDLE; char tmp_name[OBJ_NAME_SIZE]; cs_error_t res; char parent_name[OBJ_NAME_SIZE]; char key_name[OBJ_NAME_SIZE]; char key_value[OBJ_NAME_SIZE]; get_parent_name(name_pt, parent_name); get_key(name_pt, key_name, key_value); strncpy (tmp_name, parent_name, sizeof (tmp_name)); tmp_name[sizeof (tmp_name) - 1] = '\0'; obj_name_pt = strtok_r(tmp_name, SEPERATOR_STR, &save_pt); /* * Create parent object tree */ while (obj_name_pt != NULL) { res = confdb_object_find_start(handle, parent_object_handle); if (res != CS_OK) { fprintf (stderr, "Could not start object_find %d\n", res); exit (EXIT_FAILURE); } new_obj_name_pt = strtok_r (NULL, SEPERATOR_STR, &save_pt); res = confdb_object_find(handle, parent_object_handle, obj_name_pt, strlen (obj_name_pt), &obj_handle); if (res != CS_OK || new_obj_name_pt == NULL) { if (validate_name(obj_name_pt) != CS_OK) { fprintf(stderr, "Incorrect object name \"%s\", \"=\" not allowed.\n", obj_name_pt); exit(EXIT_FAILURE); } if (debug) printf ("%s:%d: %s\n", __func__,__LINE__, obj_name_pt); res = confdb_object_create (handle, parent_object_handle, obj_name_pt, strlen (obj_name_pt), &obj_handle); if (res != CS_OK) { fprintf(stderr, "Failed to create object \"%s\". Error %d.\n", obj_name_pt, res); } } parent_object_handle = obj_handle; obj_name_pt = new_obj_name_pt; } /* * Create key */ res = confdb_key_create_typed (handle, obj_handle, key_name, key_value, strlen(key_value), CONFDB_VALUETYPE_STRING); if (res != CS_OK) { fprintf(stderr, "Failed to create the key %s=%s. Error %d\n", key_name, key_value, res); } }
static void write_key(confdb_handle_t handle, char * path_pt) { hdb_handle_t obj_handle; char parent_name[OBJ_NAME_SIZE]; char key_name[OBJ_NAME_SIZE]; char key_value[OBJ_NAME_SIZE]; char old_key_value[OBJ_NAME_SIZE]; size_t old_key_value_len; cs_error_t res; confdb_value_types_t type; /* find the parent object */ get_parent_name(path_pt, parent_name); get_key(path_pt, key_name, key_value); if (debug == 1) printf ("%d: key:\"%s\", value:\"%s\"\n", __LINE__, key_name, key_value); if (validate_name(key_name) != CS_OK) { fprintf(stderr, "Incorrect key name, can not have \"=\" or \"%c\"\n", SEPERATOR); exit(EXIT_FAILURE); } res = find_object (handle, parent_name, FIND_OBJECT_ONLY, &obj_handle); if (res != CS_OK) { fprintf(stderr, "Can't find parent object of \"%s\"\n", path_pt); exit(EXIT_FAILURE); } /* get the current key */ res = confdb_key_get_typed (handle, obj_handle, key_name, old_key_value, &old_key_value_len, &type); if (res == CS_OK) { /* replace the current value */ res = confdb_key_replace (handle, obj_handle, key_name, strlen(key_name), old_key_value, old_key_value_len, key_value, strlen(key_value)); if (res != CS_OK) fprintf(stderr, "Failed to replace the key %s=%s. Error %d\n", key_name, key_value, res); } else { /* not there, create a new key */ res = confdb_key_create_typed (handle, obj_handle, key_name, key_value, strlen(key_value), CONFDB_VALUETYPE_STRING); if (res != CS_OK) fprintf(stderr, "Failed to create the key %s=%s. Error %d\n", key_name, key_value, res); } }
int main(int argc, char *argv[]) { #ifdef USE_CONFDB confdb_handle_t handle; confdb_callbacks_t callbacks; hdb_handle_t object_handle; #endif #ifdef USE_CMAP cmap_handle_t handle; cmap_track_handle_t track_handle; int retries; cs_error_t result; #endif uint32_t u32; int status; int i; cs_error_t res; char str_val[255]; int ch; char *ep; change_uint32 = 0; change_str_len = 0; no_childs = 16; burst_count = 64; while ((ch = getopt(argc, argv, "hus:c:n:")) != -1) { switch (ch) { case 'u': change_uint32 = 1; break; case 's': change_str_len = strtol(optarg, &ep, 10); if (change_str_len <= 0 || *ep != '\0') { warnx("illegal number, -s argument -- %s", optarg); usage(); } break; case 'c': no_childs = strtol(optarg, &ep, 10); if (no_childs <= 0 || *ep != '\0') { warnx("illegal number, -c argument -- %s", optarg); usage(); } break; case 'n': burst_count = strtol(optarg, &ep, 10); if (burst_count <= 0 || *ep != '\0') { warnx("illegal number, -n argument -- %s", optarg); usage(); } break; case 'h': case '?': default: usage(); /* NOTREACHED */ } } signal(SIGPIPE, SIG_IGN); setlinebuf(stdout); #ifdef USE_CONFDB memset(&callbacks, 0, sizeof(callbacks)); assert(confdb_initialize(&handle, &callbacks) == CS_OK); assert(confdb_object_create(handle, OBJECT_PARENT_HANDLE, "testconfdb", strlen("testconfdb"), &object_handle) == CS_OK); assert(confdb_finalize(handle) == CS_OK); #endif my_id = create_childs(); u32 = my_id; #ifdef USE_CONFDB snprintf(my_key_uint, sizeof(my_key_uint), "testkeyu32id%u", my_id); snprintf(my_key_str, sizeof(my_key_str), "testkeystrid%u", my_id); #endif #ifdef USE_CMAP snprintf(my_key_uint, sizeof(my_key_uint), "testconfdb.testkeyu32id%u", my_id); snprintf(my_key_str, sizeof(my_key_str), "testconfdb.testkeystrid%u", my_id); #endif for (i = 0; i < change_str_len; i++) { str_val[i] = ((my_id + i) % ('Z' - 'A' + 1)) + 'A'; } str_val[i] = '\0'; if (my_id > 0) { #ifdef USE_CONFDB memset(&callbacks, 0, sizeof(callbacks)); callbacks.confdb_key_change_notify_fn = confdb_key_change_notify; assert(confdb_initialize(&handle, &callbacks) == CS_OK); #endif #ifdef USE_CMAP retries = 0; cs_repeat(retries, 30, result = cmap_initialize(&handle)); assert(result == CS_OK); #endif if (change_uint32) { #ifdef USE_CONFDB assert(confdb_key_create_typed(handle, object_handle, my_key_uint, &u32, sizeof(u32), CONFDB_VALUETYPE_UINT32) == CS_OK); #endif #ifdef USE_CMAP assert(cmap_set_uint32(handle, my_key_uint, u32) == CS_OK); #endif } if (change_str_len > 0) { #ifdef USE_CONFDB assert(confdb_key_create_typed(handle, object_handle, my_key_str, str_val, strlen(str_val), CONFDB_VALUETYPE_STRING) == CS_OK); #endif #ifdef USE_CMAP assert(cmap_set_string(handle, my_key_str, str_val) == CS_OK); #endif } } else { /* * "Wait" for other processes to initialize */ poll(NULL, 0, 1000); printf("Confdb-track-and-change initialization finished\n"); } if (my_id > 0) { signal(SIGINT, sigint_handler_child); #ifdef USE_CONFDB assert(confdb_track_changes(handle, object_handle, OBJECT_KEY_REPLACED) == CS_OK); #endif #ifdef USE_CMAP assert(cmap_track_add(handle, "testconfdb.", CMAP_TRACK_MODIFY | CMAP_TRACK_PREFIX, cmap_notify, NULL, &track_handle) == CS_OK); #endif if (change_uint32) { #ifdef USE_CONFDB assert(confdb_key_increment(handle, object_handle, my_key_uint, strlen(my_key_uint), &u32) == CS_OK); #endif #ifdef USE_CMAP assert(cmap_inc(handle, my_key_uint) == CS_OK); #endif expected_msgs_uint = 1; } if (change_str_len > 0) { inc_str(str_val, change_str_len); #ifdef USE_CONFDB assert(confdb_key_replace(handle, object_handle, my_key_str, strlen(my_key_str), NULL, 0, str_val, strlen(str_val)) == CS_OK); #endif #ifdef USE_CMAP assert(cmap_set_string(handle, my_key_str, str_val) == CS_OK); #endif expected_msgs_str = 1; } /* * Give other processes a little time to initialize */ poll(NULL, 0, 250); do { #ifdef USE_CONFDB res = confdb_dispatch(handle, CS_DISPATCH_BLOCKING); #endif #ifdef USE_CMAP res = cmap_dispatch(handle, CS_DISPATCH_BLOCKING); #endif } while (res == CS_OK || res == CS_ERR_TRY_AGAIN); } else { signal(SIGINT, sigint_handler_parent); for (i = 0; i < no_childs; i++) { wait(&status); } #ifdef USE_CONFDB confdb_object_destroy(handle, object_handle); #endif printf("Confdb-track-and-change finalization finished\n"); } return (0); }