void rwsched_dispatch_set_target_queue(rwsched_tasklet_ptr_t sched_tasklet, rwsched_dispatch_object_t object, rwsched_dispatch_queue_t queue) { #else void rwsched_dispatch_set_target_queue(rwsched_tasklet_ptr_t sched_tasklet, void *obj, rwsched_dispatch_queue_t queue) { rwsched_dispatch_object_t object = (rwsched_dispatch_object_t) obj; #endif // Validate input paraemters RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); rwsched_instance_ptr_t instance = sched_tasklet->instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); RW_ASSERT_TYPE(queue, rwsched_dispatch_queue_t); // If libdispatch is enabled for the entire instance, then call the libdispatch routine if (instance->use_libdispatch_only) { dispatch_set_target_queue(object._object->header.libdispatch_object._do, queue->header.libdispatch_object._dq); return; } // Not yet implemented RW_CRASH(); }
rw_status_t rwmain_bootstrap(struct rwmain_gi * rwmain) { rw_status_t status; // If this instance has no parent then there is nothing in the zookeeper // yet. We need to make a node so that anything started during bootstrap // can correctly link itself as a child. if (!rwmain->parent_id) { status = update_zk(rwmain); RW_ASSERT(status == RW_STATUS_SUCCESS); } if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWPROC) status = bootstrap_rwproc(rwmain); else if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM) status = bootstrap_rwvm(rwmain); else { status = RW_STATUS_NOTFOUND; RW_CRASH(); goto done; } done: return status; }
rwsched_dispatch_queue_t rwsched_dispatch_queue_create(rwsched_tasklet_ptr_t sched_tasklet, const char *label, dispatch_queue_attr_t attr) { struct rwsched_dispatch_queue_s *queue; // Validate input paraemters RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); rwsched_instance_ptr_t instance = sched_tasklet->instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // Allocate memory for the dispatch queue queue = (rwsched_dispatch_queue_t) RW_MALLOC0_TYPE(sizeof(*queue), rwsched_dispatch_queue_t); RW_ASSERT_TYPE(queue, rwsched_dispatch_queue_t); // If libdispatch is enabled for the entire instance, then call the libdispatch routine if (instance->use_libdispatch_only) { queue->header.libdispatch_object._dq = dispatch_queue_create(label, attr); RW_ASSERT(queue->header.libdispatch_object._dq); rwsched_tasklet_ref(sched_tasklet); ck_pr_inc_32(&sched_tasklet->counters.queues); return queue; } // Not yet implemented RW_CRASH(); return NULL; }
rw_status_t process_init_phase(struct rwmain_gi * rwmain) { rw_status_t status; rwvcs_instance_ptr_t rwvcs; rwvcs = rwmain->rwvx->rwvcs; if (rwvcs->pb_rwmanifest->init_phase->settings->rwvcs->no_autostart == false) { vcs_manifest_component *m_component; char * instance_name = NULL; instance_name = to_instance_name(rwmain->component_name, rwmain->instance_id); RW_ASSERT(*instance_name); // Lookup the component to start status = rwvcs_manifest_component_lookup(rwvcs, rwmain->component_name, &m_component); rwmain_trace_info(rwmain, "rwvcs_manifest_component_lookup %s", rwmain->component_name); RW_ASSERT(status == RW_STATUS_SUCCESS); if (m_component->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM) { RWVCS_LATENCY_CHK_PRE(rwmain->rwvx->rwsched); rwmain_rwvm_init( rwmain, m_component->rwvm, rwmain->component_name, rwmain->instance_id, instance_name, rwmain->parent_id); RWVCS_LATENCY_CHK_POST(rwmain->rwvx->rwtrace, RWTRACE_CATEGORY_RWMAIN, rwmain_rwvm_init, "rwmain_rwvm_init:%s", instance_name); } else if (m_component->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWPROC) { RWVCS_LATENCY_CHK_PRE(rwmain->rwvx->rwsched); rwmain_rwproc_init( rwmain, m_component->rwproc, rwmain->component_name, rwmain->instance_id, instance_name, rwmain->parent_id); RWVCS_LATENCY_CHK_POST(rwmain->rwvx->rwtrace, RWTRACE_CATEGORY_RWMAIN, rwmain_rwproc_init, "rwmain_rwproc_init:%s", instance_name); } else { rwmain_trace_crit( rwmain, "rwmain cannot start a component which is not a vm or process (%s)", m_component->component_name); RW_CRASH(); } } return RW_STATUS_SUCCESS; }
int rwmsg_toytask_block(rwmsg_toytask_t *toy, uint64_t id, int timeout_ms) { rwsched_instance_ptr_t instance; rwmsg_toytask_t *toytask = toy; CFSocketContext cf_context = { 0, NULL, NULL, NULL, NULL }; rwsched_CFSocketRef cfsocket; struct rwmsg_toyfd_s *toyfd; // Validate input parameters RW_CF_TYPE_VALIDATE(toytask, rwtoytask_tasklet_ptr_t); // Get the rwsched instance from the toytask instance = toytask->toysched->rwsched_instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // Lookup the cfsocket corresponding to id RW_ASSERT(id < toytask->rwsched_tasklet_info->cfsocket_array->len); cfsocket = g_array_index(toytask->rwsched_tasklet_info->cfsocket_array, rwsched_CFSocketRef, id); RW_ASSERT(cfsocket->index == id); rwsched_tasklet_CFSocketGetContext(toytask->rwsched_tasklet_info, cfsocket, &cf_context); toyfd = cf_context.info; rwsched_CFRunLoopSourceRef wakeup_source; double secondsToWait = timeout_ms * .001; wakeup_source = rwsched_tasklet_CFRunLoopRunTaskletBlock(toytask->rwsched_tasklet_info, cfsocket->callback_context.cfsource, secondsToWait); // Set the return value based on which dispatch source woke up on the semaphore int revents = 0; if (wakeup_source == NULL) { revents = 0; } else if (wakeup_source == toyfd->read_context.source.source) { revents = POLLIN; } else if (wakeup_source == toyfd->write_context.source.source) { revents = POLLOUT; } else { // This should never happen as one of the sources should have signaled the semahpore to wake it up RW_CRASH(); } // Return the revents value to the caller return revents; }
static rw_component_type component_type_str_to_enum(const char * type) { if (!strcmp(type, "rwcollection")) return RWVCS_TYPES_COMPONENT_TYPE_RWCOLLECTION; else if (!strcmp(type, "rwvm")) return RWVCS_TYPES_COMPONENT_TYPE_RWVM; else if (!strcmp(type, "rwproc")) return RWVCS_TYPES_COMPONENT_TYPE_RWPROC; else if (!strcmp(type, "proc")) return RWVCS_TYPES_COMPONENT_TYPE_PROC; else if (!strcmp(type, "rwtasklet")) return RWVCS_TYPES_COMPONENT_TYPE_RWTASKLET; else { RW_CRASH(); return RWVCS_TYPES_COMPONENT_TYPE_RWCOLLECTION; } }
void rwsched_dispatch_after_f(rwsched_tasklet_ptr_t sched_tasklet, dispatch_time_t when, rwsched_dispatch_queue_t queue, void *context, dispatch_function_t handler) { // Validate input paraemters RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); rwsched_instance_ptr_t instance = sched_tasklet->instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); RW_ASSERT_TYPE(queue, rwsched_dispatch_queue_t); // If libdispatch is enabled for the entire instance, then call the libdispatch routine if (instance->use_libdispatch_only) { RW_ASSERT(queue->header.libdispatch_object._dq); if (queue == instance->main_rwqueue && sched_tasklet->blocking_mode.blocked) { //RW_CRASH(); rwsched_dispatch_what_ptr_t what = (rwsched_dispatch_what_ptr_t) RW_MALLOC0_TYPE(sizeof(*what), rwsched_dispatch_what_ptr_t); /* always leaked! */ what->type = RWSCHED_DISPATCH_ASYNC; what->closure.handler = handler; what->closure.context = context; what->queue = queue; g_array_append_val(sched_tasklet->dispatch_what_array, what); } else { rwsched_dispatch_what_ptr_t what = (rwsched_dispatch_what_ptr_t) RW_MALLOC0_TYPE(sizeof(*what), rwsched_dispatch_what_ptr_t); what->type = RWSCHED_DISPATCH_ASYNC; what->closure.handler = handler; what->closure.context = context; what->queue = queue; rwsched_tasklet_ref(sched_tasklet); what->tasklet_info = sched_tasklet; dispatch_after_f(when, queue->header.libdispatch_object._dq, (void*)what, rwsched_dispatch_intercept); } return; } // Not yet implemented RW_CRASH(); }
static void rwmsg_toysched_io_callback(rwsched_CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) { UNUSED(address); UNUSED(data); rwsched_instance_ptr_t instance; struct rwmsg_toyfd_s *toyfd; rwmsg_toytask_t *toytask; //static int index = 1; int revents = 0; // Validate input parameters toyfd = (struct rwmsg_toyfd_s *) info; RW_CF_TYPE_VALIDATE(toyfd, rwmsg_toyfd_ptr_t); toytask = toyfd->toytask; RW_CF_TYPE_VALIDATE(toytask, rwtoytask_tasklet_ptr_t); // Get the rwsched instance from the toytask instance = toytask->toysched->rwsched_instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // Determine whether this callback represents a read or write toyfd event if (type == kCFSocketReadCallBack) { revents = POLLIN; } else if (type == kCFSocketWriteCallBack) { revents = POLLOUT; } else { RW_CRASH(); } // Invoke the user specified callback RW_ASSERT(toyfd->cb); toyfd->cb(toyfd->id, toyfd->fd, revents, toyfd->ud); // Inalidate the socket so the callback is not invoked again rwsched_tasklet_CFSocketInvalidate(toytask->rwsched_tasklet_info, s); }
rwsched_dispatch_queue_t rwsched_dispatch_get_global_queue(rwsched_tasklet_ptr_t sched_tasklet, long priority) { // Validate input paraemters RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); rwsched_instance_ptr_t instance = sched_tasklet->instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); RW_ASSERT(priority >= DISPATCH_QUEUE_PRIORITY_BACKGROUND); RW_ASSERT(priority <= DISPATCH_QUEUE_PRIORITY_HIGH); int i=0; for (i=0; i<RWSCHED_DISPATCH_QUEUE_GLOBAL_CT; i++) { if (instance->global_rwqueue[i].pri == priority) { RW_ASSERT_TYPE(instance->global_rwqueue[i].rwq, rwsched_dispatch_queue_t); return instance->global_rwqueue[i].rwq; } } RW_CRASH(); return NULL; }
void rwsched_dispatch_sync_f(rwsched_tasklet_ptr_t sched_tasklet, rwsched_dispatch_queue_t queue, void *context, dispatch_function_t handler) { // Validate input paraemters RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); rwsched_instance_ptr_t instance = sched_tasklet->instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); RW_ASSERT_TYPE(queue, rwsched_dispatch_queue_t); // If libdispatch is enabled for the entire instance, then call the libdispatch routine if (instance->use_libdispatch_only) { dispatch_sync_f(queue->header.libdispatch_object._dq, context, handler); return; } // Not yet implemented RW_CRASH(); }
rw_status_t read_pacemaker_state(rwmain_pm_struct_t *pm) { char buffer[BUF_LEN]; char tmp[999]; bool file_read = false; RW_ASSERT(pm); // Read the pacemaker status sprintf(tmp, "sudo --non-interactive cat %s", PACEMAKER_CRM_MON_FULL_FNAME); FILE *fp = popen(tmp, "r"); buffer[0] = 0; while (fgets(tmp, sizeof(tmp), fp) != NULL ) { strcat(buffer, tmp); file_read = true; } fclose(fp); #define FIND_VALUE(b_ptr, pat_str, s_char, e_char) \ ({ \ char *p1, *p2; \ if (pat_str[0]!='\0') { \ p1 = strstr(b_ptr, pat_str); if (!p1) goto _done; \ p1 += strlen(pat_str); \ } else { \ p1 = b_ptr; \ } \ p1 = strchr(p1, s_char); if (!p1) goto _done; \ p1++; \ p2 = strchr(p1, e_char); if (!p2) goto _done; \ p2[0] = '\0'; \ p2++; \ b_ptr = p2; \ &(p1[0]); \ }) if (file_read) { memset(pm, '\0', sizeof(*pm)); char *buf_ptr; struct in_addr addr; buf_ptr = &(buffer[0]); char *dc_name = FIND_VALUE(buf_ptr, "Current DC", ' ', ' '); char my_hostname[999]; int r = gethostname(my_hostname, sizeof(my_hostname)); RW_ASSERT(r != -1); if (!strcmp(my_hostname, dc_name)) { pm->i_am_dc = true; } char *dc_ip = FIND_VALUE(buf_ptr, "", '(', ')'); addr.s_addr = htonl(atoi(dc_ip)); fprintf(stderr, "My Host Name: *%s* Current DC : *%s* %s\n", my_hostname, dc_name, inet_ntoa(addr)); int i = 0; while (1) { char *node_ip = FIND_VALUE(buf_ptr, "Node:", '(', ')'); addr.s_addr = htonl(atoi(node_ip)); char *state = FIND_VALUE(buf_ptr, "", '>', '<'); pm->ip_entry[i].pm_ip_addr = strdup(inet_ntoa(addr)); if (!strcmp(state,"OFFLINE")) { pm->ip_entry[i].pm_ip_state = RWMAIN_PM_IP_STATE_FAILED; } else if (!strcmp(state, "online")) { if (!strcmp(dc_ip, node_ip)) { pm->ip_entry[i].pm_ip_state = RWMAIN_PM_IP_STATE_LEADER; } else { pm->ip_entry[i].pm_ip_state = RWMAIN_PM_IP_STATE_ACTIVE; } } else { fprintf(stderr, "pacemaker: Node=%s State=%s\n", node_ip, state); RW_CRASH(); } i++; } } else { return RW_STATUS_FAILURE; } _done: return RW_STATUS_SUCCESS; }
void start_pacemaker_and_determine_role( rwvx_instance_ptr_t rwvx, vcs_manifest *pb_rwmanifest, rwmain_pm_struct_t *pm) { RW_ASSERT(rwvx); RW_ASSERT(pb_rwmanifest); RW_ASSERT(pm); if (pb_rwmanifest->bootstrap_phase->n_ip_addrs_list == 1) { pm->i_am_dc = true; return; } #define COROSYNC_CONF_WO_NODES \ "totem {\n" \ "\tversion: 2\n" \ "\tcrypto_cipher: none\n" \ "\tcrypto_hash: none\n" \ "\tinterface {\n" \ "\t\t ringnumber: 0\n" \ "\t\t bindnetaddr: %s\n" \ "\t\t mcastport: 5405\n" \ "\t\t ttl: 1\n\t}\n" \ "\ttransport: udpu\n}\n" \ "quorum {\n\tprovider: corosync_votequorum\n}\n" \ "nodelist {\n" #define COROSYNC_CONF_NODE_TEMPLATE \ "\tnode {\n\t\tring0_addr: %s\n\t}\n" //"\tnode {\n\t\tring0_addr: %s\n\t\tnodeid: %u\n\t}\n" // Form the corosync_conf to be written to /etc/corosync/corosync.conf char corosync_conf[999]; char *local_mgmt_addr = rwvcs_manifest_get_local_mgmt_addr(pb_rwmanifest->bootstrap_phase); RW_ASSERT(local_mgmt_addr); sprintf(corosync_conf, COROSYNC_CONF_WO_NODES, local_mgmt_addr); if (pb_rwmanifest->bootstrap_phase && pb_rwmanifest->bootstrap_phase->ip_addrs_list) { RW_ASSERT(pb_rwmanifest->bootstrap_phase->n_ip_addrs_list); int i; for (i=0; i<pb_rwmanifest->bootstrap_phase->n_ip_addrs_list; i++) { RW_ASSERT(pb_rwmanifest->bootstrap_phase->ip_addrs_list[i]); char corosync_conf_node[999]; sprintf(corosync_conf_node ,COROSYNC_CONF_NODE_TEMPLATE ,pb_rwmanifest->bootstrap_phase->ip_addrs_list[i]->ip_addr); //, i+1); strcat(corosync_conf, corosync_conf_node); } } strcat(corosync_conf, "}"); fprintf(stderr, "Witing to /etc/corosync/corosync.conf\n%s\n", corosync_conf); char command[999]; int r = 0; sprintf(command, "echo \"%s\" > /tmp/blah;" "sudo mv /tmp/blah /etc/corosync/corosync.conf;" "sudo chown root /etc/corosync/corosync.conf;" "sudo chgrp root /etc/corosync/corosync.conf", corosync_conf); FILE *fp = popen(command, "r"); fclose(fp); #if 0 pid_t pid; char * argv[8]; int argc = 0; pid = fork(); if (pid < 0) { RW_CRASH(); } if (pid == 0) { argv[argc++] = "/bin/sudo"; argv[argc++] = "--non-interactive"; argv[argc++] = "/usr/sbin/pcs"; argv[argc++] = "cluster"; argv[argc++] = "stop"; argv[argc++] = NULL; execv(argv[0], argv); } #else fp = popen("sudo pkill crm_mon; sudo pcs cluster stop", "r"); fclose(fp); #endif usleep(2000000); // FIXME: dirty way to stop pacemaker service when rwmain exits if ((fork()) == 0) { setsid(); signal(SIGCHLD, SIG_DFL); if ((fork()) == 0) { sprintf(command, "while [ 1 ]; do if ! (ps -A | grep -v %u | grep -q rwmain) 2> /dev/null; then sudo pcs cluster stop; exit; fi; sleep 1; done; sudo pkill crm_mon; sudo rm -f %s 2> /dev/null; rmdir /tmp/corosync/ 2> /dev/null", getpid(), PACEMAKER_CRM_MON_FULL_FNAME); fp = popen(command, "r"); fclose(fp); exit(0); } else { exit(0); } } #if 0 pid = fork(); if (pid < 0) { RW_CRASH(); } if (pid == 0) { argv[argc++] = "/bin/sudo"; argv[argc++] = "--non-interactive"; argv[argc++] = "/usr/sbin/pcs"; argv[argc++] = "cluster"; argv[argc++] = "start"; argv[argc++] = NULL; execv(argv[0], argv); } #else fp = popen("sudo pcs cluster start", "r"); fclose(fp); #endif char *pacemaker_dc_found = NULL; while (1) { usleep(2000000); FILE *fp; fp = popen("sudo pcs status xml", "r"); char buff[999]; while (fgets(buff, sizeof(buff), fp) != NULL ) { //fprintf(stderr,"%s", buff); if ((pacemaker_dc_found = strstr(buff, "current_dc present=\"true\""))) { break; } } fclose(fp); if (pacemaker_dc_found) { char my_hostname[999]; char *pacemaker_dc_name = NULL; char *pacemaker_dc_name_end = NULL; r = gethostname(my_hostname, sizeof(my_hostname)); RW_ASSERT(r != -1); pacemaker_dc_name = strstr(pacemaker_dc_found, " name=\""); RW_ASSERT(pacemaker_dc_name != NULL); pacemaker_dc_name += sizeof(" name="); pacemaker_dc_name_end = strstr(pacemaker_dc_name, "\""); RW_ASSERT(pacemaker_dc_name_end != NULL); pacemaker_dc_name_end[0] = '\0'; if (!strcmp(my_hostname, pacemaker_dc_name)) { fprintf(stderr,"I AM pacemaker DC\n"); } else { fprintf(stderr,"I'm NOT pacemaker DC - my_hostname=%s pacemaker_dc_name=%s\n", my_hostname, pacemaker_dc_name); } break; } } /*setup a inotify watcher for /tmp/crm_mon.html */ sprintf(command, "mkdir %s", PACEMAKER_CRM_MON_DIR); fp = popen(command, "r"); fclose(fp); sprintf(command, "sudo crm_mon --daemonize --as-html %s", PACEMAKER_CRM_MON_FULL_FNAME); fp = popen(command, "r"); fclose(fp); usleep(20000); setup_inotify_watcher(rwvx); read_pacemaker_state(pm); }
/* * Initialize the zookeeper with a node for this component. Used when the * component does not have a parent and therefore no one created the zookeeper * node yet. */ rw_status_t update_zk(struct rwmain_gi * rwmain) { rw_status_t status; vcs_manifest_component * mdef; rwvcs_instance_ptr_t rwvcs; char * id = NULL; rw_component_info * ci = NULL; rwvcs = rwmain->rwvx->rwvcs; RW_ASSERT(!rwmain->parent_id); id = to_instance_name(rwmain->component_name, rwmain->instance_id); // As we only hit this point when the parent_id is NULL, we are pretty much // guaranteed that the definition has to be in the static manifest. status = rwvcs_manifest_component_lookup(rwvcs, rwmain->component_name, &mdef); if (status != RW_STATUS_SUCCESS) { RW_CRASH(); goto done; } if (mdef->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM) { ci = rwvcs_rwvm_alloc( rwmain->rwvx->rwvcs, rwmain->parent_id, rwmain->component_name, rwmain->instance_id, id); if (!ci) { RW_CRASH(); status = RW_STATUS_FAILURE; goto done; } ci->vm_info->vm_ip_address = strdup(rwmain->vm_ip_address); ci->vm_info->has_pid = true; ci->vm_info->pid = getpid(); ci->has_state = true; ci->state = RW_BASE_STATE_TYPE_STARTING; if (mdef->rwvm && mdef->rwvm->has_leader) { ci->vm_info->has_leader = true; ci->vm_info->leader= mdef->rwvm->leader; } } else if (mdef->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWPROC) { ci = rwvcs_rwproc_alloc( rwvcs, rwmain->parent_id, rwmain->component_name, rwmain->instance_id, id); if (!ci) { RW_CRASH(); status = RW_STATUS_FAILURE; goto done; } ci->proc_info->has_pid = true; ci->proc_info->pid = getpid(); ci->has_state = true; ci->proc_info->has_native = true; ci->proc_info->native = false; ci->state = RW_BASE_STATE_TYPE_STARTING; } else { RW_CRASH(); status = RW_STATUS_FAILURE; goto done; } status = rwvcs_rwzk_node_update(rwmain->rwvx->rwvcs, ci); if (status != RW_STATUS_SUCCESS) { RW_CRASH(); goto done; } done: if (id) free(id); if (ci) protobuf_free(ci); return status; }
CF_EXPORT rwsched_CFRunLoopSourceRef rwsched_tasklet_CFRunLoopRunTaskletBlock(rwsched_tasklet_ptr_t sched_tasklet, rwsched_CFRunLoopSourceRef blocking_source, CFTimeInterval secondsToWait) { // Validate input paraemters RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); rwsched_instance_ptr_t instance = sched_tasklet->instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); SInt32 runloop_status; rwsched_CFRunLoopSourceRef return_source = NULL; //int i = 0; // Validate input parameters RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // Make sure this tasklet is not already blocked RW_ASSERT(!sched_tasklet->blocking_mode.blocked); // Mark the tasklet as blocked RW_ZERO_VARIABLE(&sched_tasklet->blocking_mode); sched_tasklet->blocking_mode.blocked = TRUE; sched_tasklet->blocking_mode.cfsource = blocking_source; // Run the run loop in the default mode for up to the block interval specified // The run loop will be stopped if an event is avilable for the wakeupSource runloop_status = CFRunLoopRunInMode(instance->main_cfrunloop_mode, secondsToWait, false); // If the return value is kCFRunLoopRunTimedOut then the run loop timed out // If the return value is kCFRunLoopRunStopped then an event occured on the wakeupSource // If any other return value occurs, it is considered to be an error if (runloop_status == kCFRunLoopRunTimedOut) { CFRunLoopRef rl = CFRunLoopGetCurrent(); return_source = blocking_source; if (CFRunLoopContainsSource(rl, blocking_source->cf_object, instance->main_cfrunloop_mode)) { return_source = NULL; } } else if (runloop_status == kCFRunLoopRunStopped || runloop_status == kCFRunLoopRunFinished) { return_source = blocking_source; } else { RW_CRASH(); } g_rwresource_track_handle = sched_tasklet->rwresource_track_handle; g_tasklet_info = sched_tasklet; // relocate timers back to the main-mode rwsched_cfrunloop_relocate_timers_to_main_mode(sched_tasklet); g_rwresource_track_handle = sched_tasklet->rwresource_track_handle; g_tasklet_info = sched_tasklet; // relocate sources back to the main-mode rwsched_cfrunloop_relocate_sources_to_main_mode(sched_tasklet); //runloop_status = rwsched_instance_CFRunLoopRunInMode(instance, instance->deferred_cfrunloop_mode, 0.0, false); //RW_ASSERT(runloop_status == kCFRunLoopRunFinished || runloop_status == kCFRunLoopRunTimedOut); // Mark the tasklet as unblocked RW_ZERO_VARIABLE(&sched_tasklet->blocking_mode); g_rwresource_track_handle = sched_tasklet->rwresource_track_handle; g_tasklet_info = sched_tasklet; //Deliver any events on the dispatch sources rwsched_dispatch_unblock_sources(sched_tasklet); g_rwresource_track_handle = sched_tasklet->rwresource_track_handle; g_tasklet_info = sched_tasklet; // Return the runloop source that wokeup the blocking call, which is NULL if it timed out return return_source; }
static rwtasklet_info_ptr_t get_rwmain_tasklet_info( rwvx_instance_ptr_t rwvx, const char * component_name, int instance_id, uint32_t vm_instance_id) { rwtasklet_info_ptr_t info; char * instance_name = NULL; int broker_instance_id; info = (rwtasklet_info_ptr_t)RW_MALLOC0(sizeof(struct rwtasklet_info_s)); if (!info) { RW_CRASH(); goto err; } instance_name = to_instance_name(component_name, instance_id); if (!instance_name) { RW_CRASH(); goto err; } info->rwsched_instance = rwvx->rwsched; info->rwsched_tasklet_info = rwsched_tasklet_new(rwvx->rwsched); info->rwtrace_instance = rwvx->rwtrace; info->rwvx = rwvx; info->rwvcs = rwvx->rwvcs; info->identity.rwtasklet_instance_id = instance_id; info->identity.rwtasklet_name = strdup(component_name); char *rift_var_root = rwtasklet_info_get_rift_var_root(info); RW_ASSERT(rift_var_root); rw_status_t status = rw_setenv("RIFT_VAR_ROOT", rift_var_root); RW_ASSERT(status == RW_STATUS_SUCCESS); setenv("RIFT_VAR_ROOT", rift_var_root, true); info->rwlog_instance = rwlog_init(instance_name); broker_instance_id = 0; if (rwvx->rwvcs->pb_rwmanifest->init_phase->settings->rwmsg->multi_broker && rwvx->rwvcs->pb_rwmanifest->init_phase->settings->rwmsg->multi_broker->has_enable && rwvx->rwvcs->pb_rwmanifest->init_phase->settings->rwmsg->multi_broker->enable) { broker_instance_id = vm_instance_id ? vm_instance_id : 1; } info->rwmsg_endpoint = rwmsg_endpoint_create( 1, instance_id, broker_instance_id, info->rwsched_instance, info->rwsched_tasklet_info, info->rwtrace_instance, rwvx->rwvcs->pb_rwmanifest->init_phase->settings->rwmsg); rwtasklet_info_ref(info); free(instance_name); return info; err: if (info) free(info); if (instance_name) free(instance_name); return NULL; }
struct rwmain_gi * rwmain_alloc( rwvx_instance_ptr_t rwvx, const char * component_name, uint32_t instance_id, const char * component_type, const char * parent_id, const char * vm_ip_address, uint32_t vm_instance_id) { rw_status_t status; int r; rwtasklet_info_ptr_t info = NULL; rwdts_api_t * dts = NULL; struct rwmain_gi * rwmain = NULL; char * instance_name = NULL; rwmain = (struct rwmain_gi *)malloc(sizeof(struct rwmain_gi)); if (!rwmain) { RW_CRASH(); goto err; } bzero(rwmain, sizeof(struct rwmain_gi)); /* If the component name wasn't specified on the command line, pull it * from the manifest init-phase. */ if (!component_name) { char cn[1024]; status = rwvcs_variable_evaluate_str( rwvx->rwvcs, "$rw_component_name", cn, sizeof(cn)); if (status != RW_STATUS_SUCCESS) { RW_CRASH(); goto err; } rwmain->component_name = strdup(cn); } else { rwmain->component_name = strdup(component_name); } if (!rwmain->component_name) { RW_CRASH(); goto err; } /* If the instance id wasn't specified on the command line pull it from * the manifest init-phase if it is there, otherwise autoassign one. */ if (instance_id == 0) { int id; status = rwvcs_variable_evaluate_int( rwvx->rwvcs, "$instance_id", &id); if ((status == RW_STATUS_SUCCESS) && id) { rwmain->instance_id = (uint32_t)id; } else { status = rwvcs_rwzk_next_instance_id(rwvx->rwvcs, &rwmain->instance_id, NULL); if (status != RW_STATUS_SUCCESS) { RW_CRASH(); goto err; } } } else { rwmain->instance_id = instance_id; } if (component_type) { rwmain->component_type = component_type_str_to_enum(component_type); } else { char ctype[64]; status = rwvcs_variable_evaluate_str( rwvx->rwvcs, "$component_type", ctype, sizeof(ctype)); if (status != RW_STATUS_SUCCESS) { RW_CRASH(); goto err; } rwmain->component_type = component_type_str_to_enum(ctype); } if (vm_instance_id > 0) rwmain->vm_instance_id = vm_instance_id; else if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM) rwmain->vm_instance_id = rwmain->instance_id; else { int vm_instance_id; status = rwvcs_variable_evaluate_int( rwvx->rwvcs, "$vm_instance_id", &vm_instance_id); if (status == RW_STATUS_SUCCESS) { rwmain->vm_instance_id = (uint32_t)vm_instance_id; } } RW_ASSERT(rwmain->vm_instance_id); // 10 hz with tolerance 600 // TODO: Must take from YANG. These are currently defined as the defaults in rw-base.yang rwmain->rwproc_heartbeat = rwproc_heartbeat_alloc(10, 600); if (!rwmain->rwproc_heartbeat) { RW_CRASH(); goto err; } bzero(&rwmain->sys, sizeof(rwmain->sys)); if (parent_id) { rwmain->parent_id = strdup(parent_id); if (!rwmain->parent_id) { RW_CRASH(); goto err; } } else { char ctype[64]; status = rwvcs_variable_evaluate_str( rwvx->rwvcs, "$parent_id", ctype, sizeof(ctype)); if (status == RW_STATUS_SUCCESS) { rwmain->parent_id = strdup(ctype); } } if (rwvx->rwvcs->pb_rwmanifest->init_phase->settings->rwvcs->collapse_each_rwvm) { r = asprintf(&rwmain->vm_ip_address, "127.%u.%u.1", rwmain->instance_id / 256, rwmain->instance_id % 256); if (r == -1) { RW_CRASH(); goto err; } } else if (vm_ip_address) { rwmain->vm_ip_address = strdup(vm_ip_address); if (!rwmain->vm_ip_address) { RW_CRASH(); goto err; } char *variable[0]; r = asprintf(&variable[0], "vm_ip_address = '%s'", vm_ip_address); if (r == -1) { RW_CRASH(); goto err; } status = rwvcs_variable_list_evaluate( rwvx->rwvcs, 1, variable); if (status != RW_STATUS_SUCCESS) { RW_CRASH(); goto err; } free(variable[0]); } else { char buf[32]; status = rwvcs_variable_evaluate_str( rwvx->rwvcs, "$vm_ip_address", buf, sizeof(buf)); if (status != RW_STATUS_SUCCESS) { RW_CRASH(); goto err; } rwmain->vm_ip_address = strdup(buf); if (!rwmain->vm_ip_address) { RW_CRASH(); goto err; } } rwvx->rwvcs->identity.vm_ip_address = strdup(rwmain->vm_ip_address); if (!rwvx->rwvcs->identity.vm_ip_address) { RW_CRASH(); goto err; } rwvx->rwvcs->identity.rwvm_instance_id = rwmain->vm_instance_id; instance_name = to_instance_name(rwmain->component_name, rwmain->instance_id); RW_ASSERT(instance_name!=NULL); if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM) { rwvx->rwvcs->identity.rwvm_name = instance_name; } else if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWPROC) { RW_ASSERT(rwmain->parent_id); rwvx->rwvcs->identity.rwvm_name = strdup(rwmain->parent_id); } char rift_var_vm[255]; if (rwvx->rwvcs->identity.rwvm_name) { snprintf(rift_var_vm, 255, "%s%c%s", rwvx->rwvcs->pb_rwmanifest->bootstrap_phase->test_name, '-', rwvx->rwvcs->identity.rwvm_name); } else { snprintf(rift_var_vm, 255, "%s", rwvx->rwvcs->pb_rwmanifest->bootstrap_phase->test_name); } setenv("RIFT_VAR_VM", rift_var_vm, true); info = get_rwmain_tasklet_info( rwvx, rwmain->component_name, rwmain->instance_id, rwmain->vm_instance_id); if (!info) { RW_CRASH(); goto err; } if (rwvx->rwsched) { if (!rwvx->rwsched->rwlog_instance) { rwvx->rwsched->rwlog_instance = rwlog_init("RW.Sched"); } } if (!rwvx->rwlog) { rwvx->rwlog = rwlog_init("Logging"); } dts = rwdts_api_new( info, (rw_yang_pb_schema_t *)RWPB_G_SCHEMA_YPBCSD(RwVcs), rwmain_dts_handle_state_change, NULL, NULL); if (!dts) { RW_CRASH(); goto err; } RW_SKLIST_PARAMS_DECL( procs_sklist_params, struct rwmain_proc, instance_name, rw_sklist_comp_charptr, _sklist); RW_SKLIST_INIT(&(rwmain->procs), &procs_sklist_params); RW_SKLIST_PARAMS_DECL( tasklets_sklist_params, struct rwmain_tasklet, instance_name, rw_sklist_comp_charptr, _sklist); RW_SKLIST_INIT(&(rwmain->tasklets), &tasklets_sklist_params); RW_SKLIST_PARAMS_DECL( multivms_sklist_params, struct rwmain_multivm, key, rw_sklist_comp_charbuf, _sklist); RW_SKLIST_INIT(&(rwmain->multivms), &multivms_sklist_params); rwmain->dts = dts; rwmain->tasklet_info = info; rwmain->rwvx = rwvx; r = asprintf(&VCS_GET(rwmain)->vcs_instance_xpath, VCS_INSTANCE_XPATH_FMT, instance_name); if (r == -1) { RW_CRASH(); goto err; } VCS_GET(rwmain)->instance_name = instance_name; goto done; err: if (info) { rwsched_tasklet_free(info->rwsched_tasklet_info); free(info->identity.rwtasklet_name); rwmsg_endpoint_halt(info->rwmsg_endpoint); free(info); } if (dts) rwdts_api_deinit(dts); if (rwmain->component_name) free(rwmain->component_name); if (rwmain->parent_id) free(rwmain->parent_id); if (rwmain) free(rwmain); done: return rwmain; }
rw_tree_walker_status_t add_xml_child (XMLNode *parent, rw_confd_value_t *confd, XMLNode*& child) { confd_cs_node *cs_node = confd->cs_node; confd_value_t *child_src = confd->value; const char *name = confd_hash2str (confd->cs_node->tag); const char *ns = confd_hash2str (confd->cs_node->ns); YangNode *child_yn = nullptr; child = nullptr; YangNode *yn = parent->get_yang_node(); if (!yn) { return RW_TREE_WALKER_FAILURE; } child_yn = yn->search_child (name, ns); if (!child_yn) { return RW_TREE_WALKER_FAILURE; } if (!child_yn->is_leafy()) { child = parent->add_child(child_yn); if (child) { return RW_TREE_WALKER_SUCCESS; } return RW_TREE_WALKER_FAILURE; } char value[1024]; char *val_p = nullptr; switch (child_src->type) { default: case C_QNAME: case C_DATETIME: case C_DATE: case C_TIME: case C_DURATION: case C_NOEXISTS: case C_STR: case C_SYMBOL: case C_BIT32: case C_BIT64: case C_XMLBEGIN: case C_XMLEND: case C_OBJECTREF: case C_UNION: case C_PTR: case C_CDBBEGIN: case C_OID: case C_DEFAULT: case C_IDENTITYREF: case C_XMLBEGINDEL: case C_DQUAD: case C_HEXSTR: RW_CRASH(); break; case C_XMLTAG: break; case C_BUF: case C_INT8: case C_INT16: case C_INT32: case C_INT64: case C_UINT8: case C_UINT16: case C_UINT32: case C_UINT64: case C_DOUBLE: case C_BOOL: case C_ENUM_VALUE: case C_BINARY: case C_DECIMAL64: case C_IPV4: case C_IPV6: case C_IPV4PREFIX: case C_IPV4_AND_PLEN: case C_IPV6_AND_PLEN: case C_IPV6PREFIX: { struct confd_type *ct = cs_node->info.type; int len = confd_val2str (ct, child_src, value, sizeof (value)); if (len < 0) { return RW_TREE_WALKER_FAILURE; } val_p = &value[0]; } break; case C_LIST: { // ATTN: ATTN: // This code is inefficient. TAIL-F has been asked what the best method // for doing this is. Once TAILF responds, change this code. // ATTN: ATTN: // This also needs to change when protobuf representation of a leaf list // transitions to becoming a list of single elements struct confd_type *ct = confd_get_leaf_list_type (cs_node); RW_ASSERT(ct); int len = confd_val2str (ct, child_src, value, sizeof (value)); if (len < 0) { return RW_TREE_WALKER_FAILURE; } val_p = &value[0]; } break; } child = parent->add_child (child_yn, val_p); if (child) { return RW_TREE_WALKER_SUCCESS; } return RW_TREE_WALKER_FAILURE; }
rw_tree_walker_status_t add_pbcm_child (ProtobufCMessage *parent, rw_confd_value_t *confd, ProtobufCFieldInfo *child_tgt, bool find_field) { if (find_field) { memset (child_tgt, 0, sizeof (ProtobufCFieldInfo)); const char *name = confd_hash2str (confd->cs_node->tag); const char *ns = confd_hash2str (confd->cs_node->ns); child_tgt->fdesc = protobuf_c_message_descriptor_get_field_by_yang ( parent->descriptor, name, ns); } child_tgt->element = nullptr; child_tgt->len = 0; RW_ASSERT(child_tgt->fdesc); confd_cs_node *cs_node = confd->cs_node; confd_value_t *child_src = confd->value; uint32_t v_uint32 = 0; int32_t v_int32 = 0; uint64_t v_uint64 = 0; int64_t v_int64 = 0; double v_double = 0.0; protobuf_c_boolean v_bool = 0; switch (child_src->type) { default: case C_NOEXISTS: case C_STR: case C_SYMBOL: RW_CRASH(); break; case C_XMLTAG: // Empty in YANG, bool in pbcm v_bool = 1; child_tgt->element = &v_bool; break; case C_BUF: child_tgt->element = CONFD_GET_BUFPTR(child_src); child_tgt->len = CONFD_GET_BUFSIZE(child_src); break; case C_INT8: v_int32 = (int32_t)CONFD_GET_INT8 (child_src); child_tgt->element = &v_int32; break; case C_INT16: v_int32 = (int32_t)CONFD_GET_INT16 (child_src); child_tgt->element = &v_int32; break; case C_INT32: v_int32 = CONFD_GET_INT32 (child_src); child_tgt->element = &v_int32; break; case C_INT64: v_int64 = CONFD_GET_INT64 (child_src); child_tgt->element = &v_int64; break; case C_UINT8: v_uint32 = (uint32_t)CONFD_GET_UINT8 (child_src); child_tgt->element = &v_uint32; break; case C_UINT16: v_uint32 = (uint32_t)CONFD_GET_UINT16 (child_src); child_tgt->element = &v_uint32; break; case C_UINT32: v_uint32 = CONFD_GET_UINT32 (child_src); child_tgt->element = &v_uint32; break; case C_UINT64: v_uint64 = CONFD_GET_UINT64 (child_src); child_tgt->element = &v_uint64; break; case C_DOUBLE: v_double = CONFD_GET_DOUBLE (child_src); child_tgt->element = &v_double; break; case C_BOOL: v_bool = CONFD_GET_BOOL(child_src); child_tgt->element = &v_bool; break; case C_QNAME: RW_CRASH(); break; case C_DATETIME: RW_CRASH(); break; case C_DATE: RW_CRASH(); break; case C_TIME: RW_CRASH(); break; case C_DURATION: RW_CRASH(); break; case C_ENUM_VALUE: v_uint32 = (uint32_t) CONFD_GET_ENUM_VALUE (child_src); child_tgt->element = &v_uint32; break; case C_BIT32: RW_CRASH(); break; case C_BIT64: RW_CRASH(); break; case C_LIST: { // ATTN: ATTN: // This code is inefficient. TAIL-F has been asked what the best method // for doing this is. Once TAILF responds, change this code. // ATTN: ATTN: // This also needs to change when protobuf representation of a leaf list // transitions to becoming a list of single elements char value[1024]; struct confd_type *ct = confd_get_leaf_list_type (cs_node); RW_ASSERT(ct); int len = confd_val2str (ct, child_src, value, sizeof (value)); if (len < 0) { return RW_TREE_WALKER_FAILURE; } bool ok = protobuf_c_message_set_field_text_value ( nullptr, parent, child_tgt->fdesc, value, len); if (ok) { return RW_TREE_WALKER_SUCCESS; } else { return RW_TREE_WALKER_FAILURE; } } break; case C_XMLBEGIN: { // Add a message bool ok = protobuf_c_message_set_field_message ( nullptr, parent, child_tgt->fdesc, (ProtobufCMessage **) &child_tgt->element); if (ok) { return RW_TREE_WALKER_SUCCESS; } else { return RW_TREE_WALKER_FAILURE; } } break; case C_XMLEND: RW_CRASH(); break; case C_OBJECTREF: RW_CRASH(); break; case C_UNION: RW_CRASH(); break; case C_PTR: RW_CRASH(); break; case C_CDBBEGIN: RW_CRASH(); break; case C_OID: RW_CRASH(); break; case C_BINARY: child_tgt->element = CONFD_GET_BINARY_PTR(child_src); child_tgt->len = CONFD_GET_BINARY_SIZE(child_src); break; case C_DECIMAL64: case C_IPV4: case C_IPV6: case C_IPV4PREFIX: case C_IPV4_AND_PLEN: case C_IPV6_AND_PLEN: case C_IPV6PREFIX: { char value[1024]; struct confd_type *ct = cs_node->info.type; int len = confd_val2str (ct, child_src, value, sizeof (value)); if (len < 0) { return RW_TREE_WALKER_FAILURE; } bool ok = protobuf_c_message_set_field_text_value ( nullptr, parent, child_tgt->fdesc, value, len); if (ok) { return RW_TREE_WALKER_SUCCESS; } else { return RW_TREE_WALKER_FAILURE; } } break; case C_DEFAULT: RW_CRASH(); break; case C_IDENTITYREF: RW_CRASH(); break; case C_XMLBEGINDEL: RW_CRASH(); break; case C_DQUAD: RW_CRASH(); break; case C_HEXSTR: RW_CRASH(); break; } bool ok = protobuf_c_message_set_field (nullptr, parent, child_tgt); if (ok) { return RW_TREE_WALKER_SUCCESS; } return RW_TREE_WALKER_FAILURE; }
static rwdts_member_rsp_code_t rwdts_appconf_xact_event(rwdts_api_t *apih, rwdts_group_t *grp, rwdts_xact_t *xact, rwdts_member_event_t xact_event, /* PRECOMMIT/COMMIT/ABORT/... */ void *ctx, void *scratch_in) { rwdts_appconf_xact_t *appx = (rwdts_appconf_xact_t *)scratch_in; RW_ASSERT_TYPE(appx, rwdts_appconf_xact_t); rwdts_appconf_t *ac = appx->ac; int k; switch (xact_event) { default: break; case RWDTS_MEMBER_EVENT_ABORT: appx->abort++; RW_ASSERT(appx->abort == 1); RW_ASSERT(appx->commit == 0); appx->errs_ct = 0; /* Apply with xact=NULL to revert*/ if (ac->cb.xact_init_dtor) { ac->cb.config_apply_gi(apih, ac, NULL, RWDTS_APPCONF_ACTION_INSTALL, ac->cb.ctx, NULL); } else { ac->cb.config_apply(apih, ac, NULL, RWDTS_APPCONF_ACTION_INSTALL, ac->cb.ctx, NULL); } if (appx->errs_ct) { // Whoops, now we're doomed RWDTS_API_LOG_XACT_EVENT(apih, xact, RwDtsApiLog_notif_AppconfInstallFailed, "Appconf INSTALL failure", appx->errs_ct, rwdts_get_app_addr_res(apih, ac->cb.config_apply), apih->client_path); int i; for (i=0; i<appx->errs_ct; i++) { RWDTS_API_LOG_XACT_EVENT(apih, xact, RwDtsApiLog_notif_AppconfInstallErrors, i, appx->errs[i].rs, appx->errs[i].str); } RW_CRASH(); } break; case RWDTS_MEMBER_EVENT_PRECOMMIT: appx->precommit++; RW_ASSERT(appx->precommit == 1); RW_ASSERT(appx->commit == 0); RW_ASSERT(appx->abort == 0); /* Validate */ if (ac->cb.config_validate) { if (ac->cb.xact_init_dtor) { ac->cb.config_validate_gi(apih, ac, (rwdts_xact_t*)xact, ac->cb.ctx, appx->scratch); } else { ac->cb.config_validate(apih, ac, (rwdts_xact_t*)xact, ac->cb.ctx, appx->scratch); } } if (appx->errs_ct) { /* How to actually get xact->appconf->err[] table up to uagent etc? */ return RWDTS_ACTION_NOT_OK; } /* Reconcile */ if (ac->cb.xact_init_dtor) { ac->cb.config_apply_gi(apih, ac, (rwdts_xact_t*)xact, RWDTS_APPCONF_ACTION_RECONCILE, ac->cb.ctx, appx->scratch); } else { ac->cb.config_apply(apih, ac, (rwdts_xact_t*)xact, RWDTS_APPCONF_ACTION_RECONCILE, ac->cb.ctx, appx->scratch); } if (!appx->errs_ct) { return RWDTS_ACTION_OK; } /* How to actually get xact->appconf->err[] table up to uagent etc? */ for (k = 0; k < appx->errs_ct;free(appx->errs[k].str),k++); free(appx->errs); appx->errs = NULL; appx->errs_ct = 0; return RWDTS_ACTION_NOT_OK; /* will trigger PRECOMMIT -> ABORT */ break; case RWDTS_MEMBER_EVENT_COMMIT: appx->commit++; RW_ASSERT(appx->commit == 1); RW_ASSERT(appx->precommit == 1); RW_ASSERT(appx->abort == 0); break; } return RWDTS_ACTION_OK; }