int main(void) { Dict *dict; Octstr *foo, *bar; unsigned long i; gwlib_init(); foo = octstr_imm("foo"); bar = octstr_imm("bar"); debug("",0,"Dict simple test."); dict = dict_create(10, NULL); dict_put(dict, foo, bar); info(0, "foo gives %s", octstr_get_cstr(dict_get(dict, foo))); if (dict_key_count(dict) == 1) info(0, "there is but one foo."); else error(0, "key count is %ld, should be 1.", dict_key_count(dict)); dict_destroy(dict); debug("",0,"Dict extended/huge test."); dict = dict_create(HUGE_SIZE, (void (*)(void *))octstr_destroy); for (i = 1; i <= HUGE_SIZE; i++) { unsigned long val; Octstr *okey, *oval; uuid_t id; char key[UUID_STR_LEN + 1]; uuid_generate(id); uuid_unparse(id, key); val = gw_rand(); okey = octstr_create(key); oval = octstr_format("%ld", val); dict_put(dict, okey, oval); } gwthread_sleep(5); /* give hash table some time */ if (dict_key_count(dict) == HUGE_SIZE) info(0, "ok, got %d entries in the dictionary.", HUGE_SIZE); else error(0, "key count is %ld, should be %d.", dict_key_count(dict), HUGE_SIZE); dict_destroy(dict); gwlib_shutdown(); return 0; }
static void set_zero(Octstr *ostr) { octstr_set_char(ostr, (1 + (int) (octstr_len(ostr) *gw_rand()/ (RAND_MAX+1.0))), '\0'); }
static Boxc *route_msg(List *route_info, Msg *msg) { AddrPar *ap; Boxc *conn, *best; int i, b, len; ap = gwlist_search(route_info, msg, cmp_route); if (ap == NULL) { debug("bb.boxc", 0, "Did not find previous routing info for WDP, " "generating new"); route: if (gwlist_len(wapbox_list) == 0) return NULL; gwlist_lock(wapbox_list); /* take random wapbox from list, and then check all wapboxes * and select the one with lowest load level - if tied, the first * one */ len = gwlist_len(wapbox_list); b = gw_rand() % len; best = gwlist_get(wapbox_list, b); for(i = 0; i < gwlist_len(wapbox_list); i++) { conn = gwlist_get(wapbox_list, (i+b) % len); if (conn != NULL && best != NULL) if (conn->load < best->load) best = conn; } if (best == NULL) { warning(0, "wapbox_list empty!"); gwlist_unlock(wapbox_list); return NULL; } conn = best; conn->load++; /* simulate new client until we get new values */ ap = gw_malloc(sizeof(AddrPar)); ap->address = octstr_duplicate(msg->wdp_datagram.source_address); ap->port = msg->wdp_datagram.source_port; ap->wapboxid = conn->id; gwlist_produce(route_info, ap); gwlist_unlock(wapbox_list); } else conn = gwlist_search(wapbox_list, ap, cmp_boxc); if (conn == NULL) { /* routing failed; wapbox has disappeared! * ..remove routing info and re-route */ debug("bb.boxc", 0, "Old wapbox has disappeared, re-routing"); gwlist_delete_equal(route_info, ap); ap_destroy(ap); goto route; } return conn; }
/* * Route the incoming message to one of the following input queues: * a specific smsbox conn * a random smsbox conn if no shortcut routing and msg->sms.boxc_id match * * BEWARE: All logic inside here should be fast, hence speed processing * optimized, because every single MO message passes this function and we * have to ensure that no unncessary overhead is done. */ int route_incoming_to_boxc(Msg *msg) { Boxc *bc = NULL, *best = NULL; Octstr *s, *r, *rs; long len, b, i; int full_found = 0; s = r = NULL; gw_assert(msg_type(msg) == sms); /* msg_dump(msg, 0); */ /* * We have a specific route to pass this msg to smsbox-id * Lookup the connection in the dictionary. */ gw_rwlock_rdlock(smsbox_list_rwlock); if (gwlist_len(smsbox_list) == 0) { gw_rwlock_unlock(smsbox_list_rwlock); warning(0, "smsbox_list empty!"); if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) { gwlist_produce(incoming_sms, msg); return 0; } else return -1; } if (octstr_len(msg->sms.boxc_id) > 0) { bc = dict_get(smsbox_by_id, msg->sms.boxc_id); if (bc == NULL) { /* * something is wrong, this was the smsbox connection we used * for sending, so it seems this smsbox is gone */ warning(0,"Could not route message to smsbox id <%s>, smsbox is gone!", octstr_get_cstr(msg->sms.boxc_id)); } } else { /* * Check if we have a "smsbox-route" for this msg. * Where the shortcode route has a higher priority then the smsc-id rule. * Highest priority has the combined <shortcode>:<smsc-id> route. */ Octstr *os = octstr_format("%s:%s", octstr_get_cstr(msg->sms.receiver), octstr_get_cstr(msg->sms.smsc_id)); s = (msg->sms.smsc_id ? dict_get(smsbox_by_smsc, msg->sms.smsc_id) : NULL); r = (msg->sms.receiver ? dict_get(smsbox_by_receiver, msg->sms.receiver) : NULL); rs = (os ? dict_get(smsbox_by_smsc_receiver, os) : NULL); octstr_destroy(os); bc = rs ? dict_get(smsbox_by_id, rs) : (r ? dict_get(smsbox_by_id, r) : (s ? dict_get(smsbox_by_id, s) : NULL)); } /* check if we found our routing */ if (bc != NULL) { if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(bc->incoming)) { gwlist_produce(bc->incoming, msg); gw_rwlock_unlock(smsbox_list_rwlock); return 1; /* we are done */ } else { gw_rwlock_unlock(smsbox_list_rwlock); return -1; } } else if (s != NULL || r != NULL || octstr_len(msg->sms.boxc_id) > 0) { gw_rwlock_unlock(smsbox_list_rwlock); /* * we have routing defined, but no smsbox connected at the moment. * put msg into global incoming queue and wait until smsbox with * such boxc_id connected. */ if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) { gwlist_produce(incoming_sms, msg); return 0; } else return -1; } /* * ok, none of the routing things applied previously, so route it to * a random smsbox. */ /* take random smsbox from list, and then check all smsboxes * and select the one with lowest load level - if tied, the first * one */ len = gwlist_len(smsbox_list); b = gw_rand() % len; for(i = 0; i < gwlist_len(smsbox_list); i++) { bc = gwlist_get(smsbox_list, (i+b) % len); if (bc->boxc_id != NULL || bc->routable == 0) bc = NULL; if (bc != NULL && max_incoming_sms_qlength > 0 && gwlist_len(bc->incoming) > max_incoming_sms_qlength) { full_found = 1; bc = NULL; } if ((bc != NULL && best != NULL && bc->load < best->load) || (bc != NULL && best == NULL)) { best = bc; } } if (best != NULL) { best->load++; gwlist_produce(best->incoming, msg); } gw_rwlock_unlock(smsbox_list_rwlock); if (best == NULL && full_found == 0) { warning(0, "smsbox_list empty!"); if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) { gwlist_produce(incoming_sms, msg); return 0; } else return -1; } else if (best == NULL && full_found == 1) return -1; return 1; }
void gw_em_listener(void *arg) { fd_set in_pipes; int i,j; int *job_id; int greater, rc, rcm; char c; char info[GW_EM_MAX_INFO]; char s_job_id[GW_EM_MAX_JOB_ID]; char result[GW_EM_MAX_RESULT]; char action[GW_EM_MAX_ACTION]; char str[GW_EM_MAX_STRING]; int fd; gw_job_t *job; time_t now; char contact_file[PATH_MAX]; FILE *file; gw_em_mad_t *em_mad; char *ptmp; int *fds; int num_fds; gw_em_mad_t **em_mads; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); fds = (int *) malloc(sizeof(int)*gw_conf.number_of_users*GW_MAX_MADS); em_mads = (gw_em_mad_t **) malloc(sizeof(gw_em_mad_t *) * gw_conf.number_of_users * GW_MAX_MADS); while (1) { greater = gw_user_pool_set_em_pipes(&in_pipes, fds, &num_fds, em_mads, gw_em.um_em_pipe_r); rc = select( greater+1, &in_pipes, NULL, NULL, NULL); if ( rc <= 0 ) continue; for (i=0; i<num_fds; i++) { fd = fds[i]; if ( FD_ISSET(fd, &in_pipes) ) { if ( fd == gw_em.um_em_pipe_r ) { rc = read(fd, (void *) &c, sizeof(char)); #ifdef GWEMDEBUG gw_log_print("EM",'D',"Updating MAD pipes (action is %c)\n",c); #endif continue; } #ifdef GWEMDEBUG gw_log_print("EM",'D',"Reading from MAD pipe %i.\n",i); #endif j = 0; do { rc = read(fd, (void *) &c, sizeof(char)); str[j++] = c; } while ((rc > 0) && (c != '\n') && (j < (GW_EM_MAX_STRING-1))); str[j] = '\0'; if (rc <= 0) { gw_log_print("EM",'W',"Error reading MAD (%s) message\n", em_mads[i]->name); rcm = gw_em_mad_reload(em_mads[i]); if ( rcm == 0 ) { gw_log_print("EM",'I',"MAD (%s) successfully reloaded\n", em_mads[i]->name); gw_job_pool_em_recover(em_mads[i], &(gw_em.am)); } else { gw_log_print("EM",'E',"Error reloading MAD (%s)\n", em_mads[i]->name); em_mads[i]->mad_em_pipe = -1; } continue; } sscanf(str,"%" GW2STR(GW_EM_MAX_ACTION) "s %" GW2STR(GW_EM_MAX_JOB_ID) "s %" GW2STR(GW_EM_MAX_RESULT) "s %" GW2STR(GW_EM_MAX_INFO) "[^\n]", action, s_job_id, result, info); #ifdef GWEMDEBUG gw_log_print("EM",'D',"MAD message received:\"%s %s %s %s\".\n", action, s_job_id, result, info); #endif if (s_job_id[0] == '-') continue; job_id = (int *) malloc (sizeof(int)); *job_id = atoi(s_job_id); job = gw_job_pool_get(*job_id, GW_TRUE); if (job == NULL) { gw_log_print("EM",'W',"MAD message for job %s, but it does not exist: \"%s %s %s %s\".\n", s_job_id,action, s_job_id, result, info); free(job_id); continue; } if (job->job_state != GW_JOB_STATE_PRE_WRAPPER && job->job_state != GW_JOB_STATE_WRAPPER && job->job_state != GW_JOB_STATE_MIGR_CANCEL && job->job_state != GW_JOB_STATE_STOP_CANCEL && job->job_state != GW_JOB_STATE_KILL_CANCEL) { gw_log_print("EM",'W',"MAD message for job %i but not in an execution state.\n", *job_id); free(job_id); pthread_mutex_unlock(&(job->mutex)); continue; } else if ( job->em_state == GW_EM_STATE_HARD_KILL ) { gw_log_print("EM",'W',"MAD message for job %i but it is being killed (hard).\n", *job_id); free(job_id); pthread_mutex_unlock(&(job->mutex)); continue; } if (strcmp(action, "SUBMIT") == 0) { if (strcmp(result, "FAILURE") == 0) { gw_job_print(job, "EM",'E',"Job submission failed: %s\n", info); gw_log_print("EM",'E',"Submission of job %d failed: %s.\n", job->id, info); gw_am_trigger(&(gw_em.am), "GW_EM_STATE_FAILED", (void *) job_id); } else /* Save persistent job contact */ { snprintf(contact_file, PATH_MAX-1, GW_VAR_DIR "/%i/job.contact", job->id); file = fopen(contact_file, "w"); if ( file != NULL ) { fprintf(file, "%s\n", info); fclose(file); } gw_am_trigger(&(gw_em.am), "GW_EM_STATE_PENDING", (void *) job_id); } } else if (strcmp(action, "CANCEL") == 0) { if (strcmp(result, "SUCCESS") == 0) { gw_job_print(job, "EM",'I',"Job cancel succeeded.\n"); gw_log_print("EM",'I',"Cancel of job %i succeeded.\n", *job_id); } else { gw_job_print(job, "EM",'E',"Job cancel failed (%s).\n",info); gw_log_print("EM",'E',"Cancel of job %d failed: %s.\n",job->id, info); } } else if (strcmp(action, "POLL") == 0) { if (strcmp(result, "SUCCESS") == 0) { now = time(NULL); job->next_poll_time = now + gw_conf.poll_interval/2 + gw_rand(gw_conf.poll_interval); gw_job_print(job, "EM",'E',"Job poll OK (%s), will poll again in %d seconds.\n", info, job->next_poll_time - now); if (strcmp(info, "PENDING") == 0) gw_am_trigger(&(gw_em.am), "GW_EM_STATE_PENDING", (void *) job_id); else if (strcmp(info, "SUSPENDED") == 0) gw_am_trigger(&(gw_em.am), "GW_EM_STATE_SUSPENDED", (void *) job_id); else if (strcmp(info, "ACTIVE") == 0) gw_am_trigger(&(gw_em.am),"GW_EM_STATE_ACTIVE", (void *) job_id); else if (strstr(info, "DONE") != NULL) { ptmp = strstr(info,"DONE:"); if ((ptmp != NULL) && (strlen(ptmp+5) > 0))/*No-wrapper mode*/ job->exit_code=atoi(ptmp+5); gw_am_trigger(&(gw_em.am), "GW_EM_STATE_DONE", (void *) job_id); } else if (strcmp(info, "FAILED") == 0) gw_am_trigger(&(gw_em.am), "GW_EM_STATE_FAILED", (void *) job_id); } else { job->history->failed_polls++; em_mad = job->history->em_mad; if ( job->history->failed_polls == 3 ) { gw_job_print(job, "EM",'E',"Job poll failed (%s), assuming the job is done.\n",info); gw_am_trigger(&(gw_em.am), "GW_EM_STATE_DONE", (void *) job_id); } else { now = time(NULL); job->next_poll_time = now + gw_conf.poll_interval*job->history->failed_polls + gw_rand(gw_conf.poll_interval*job->history->failed_polls); gw_job_print(job, "EM",'E',"Job poll failed (%s), will poll again in %d seconds.\n", info, job->next_poll_time - now); free(job_id); } } } else if (strcmp(action, "RECOVER") == 0) { if (strcmp(result, "SUCCESS") == 0) { if (strcmp(info, "PENDING") == 0) gw_am_trigger(&(gw_em.am), "GW_EM_STATE_PENDING", (void *) job_id); else if (strcmp(info, "SUSPENDED") == 0) gw_am_trigger(&(gw_em.am), "GW_EM_STATE_SUSPENDED", (void *) job_id); else if (strcmp(info, "ACTIVE") == 0) gw_am_trigger(&(gw_em.am),"GW_EM_STATE_ACTIVE", (void *) job_id); else if (strstr(info, "DONE") != NULL) { ptmp = strstr(info,"DONE:"); if ((ptmp != NULL) && (strlen(ptmp+5) > 0))/*No-wrapper mode*/ job->exit_code = atoi(ptmp+5); gw_am_trigger(&(gw_em.am), "GW_EM_STATE_DONE", (void *) job_id); } else if (strcmp(info, "FAILED") == 0) { /* Do not retry */ job->history->tries= job->template.number_of_retries; gw_am_trigger(&(gw_em.am), "GW_EM_STATE_FAILED", (void *) job_id); } } else { gw_job_print(job,"EM",'E',"Job recover failed (%s), assuming the job is done.\n", info); gw_log_print("EM",'E',"Recover of job %i failed.\n", *job_id); gw_am_trigger(&(gw_em.am), "GW_EM_STATE_DONE", (void *) job_id); } }
void gw_em_submit(void *_job_id) { int job_id; gw_job_t *job; char *rsl=NULL; char *contact; gw_job_state_t state; char rsl_filename[2048]; FILE *fd; time_t now; /* ----------------------------------------------------------- */ /* 0.- Get job pointer, check if it exits and lock mutex */ /* ----------------------------------------------------------- */ if ( _job_id != NULL ) { job_id = *( (int *) _job_id ); job = gw_job_pool_get(job_id, GW_TRUE); if ( job == NULL ) { gw_log_print("EM",'E',"Job %s no longer exists (PENDING).\n", job_id); return; } } else return; if (job->history == NULL) { gw_log_print("EM",'E',"History of job %s doesn't exists\n", job_id); free(_job_id); pthread_mutex_unlock(&(job->mutex)); return; } state = job->job_state; /* ----------------------------------------------------------- */ /* 1.- Get execution MAD for this host */ /* ----------------------------------------------------------- */ job->em_state = GW_EM_STATE_INIT; job->history->counter = -1; if ( job->job_state == GW_JOB_STATE_PRE_WRAPPER ) { contact = job->history->em_fork_rc; rsl = (char *) job->history->em_mad->pre_wrapper_rsl((void *) job); } else { contact = job->history->em_rc; rsl = (char *) job->history->em_mad->wrapper_rsl((void *) job); } if ( rsl == NULL ) { job->em_state = GW_EM_STATE_FAILED; gw_log_print("EM",'E',"Job %i failed, could not generate RSL.\n", job_id); gw_am_trigger(gw_em.dm_am, "GW_DM_WRAPPER_FAILED", _job_id); pthread_mutex_unlock(&(job->mutex)); return; } sprintf(rsl_filename, "%s/job.rsl.%i", job->directory,job->restarted); fd = fopen(rsl_filename,"w"); if (fd != NULL ) { gw_job_print(job,"EM",'I',"Submitting wrapper to %s, RSL used is in %s.\n",contact,rsl_filename); fprintf(fd,"%s",rsl); fclose(fd); } else { job->em_state = GW_EM_STATE_FAILED; gw_log_print("EM",'E',"Job %i failed, could not open RSL file.\n", job_id); gw_job_print(job,"EM",'E',"Job failed, could not open RSL file %s.\n",rsl_filename); gw_am_trigger(gw_em.dm_am, "GW_DM_WRAPPER_FAILED", _job_id); pthread_mutex_unlock(&(job->mutex)); return; } /* -------------------------------------------------------------------- */ now = time(NULL); job->next_poll_time = now + gw_conf.poll_interval/2 + gw_rand(gw_conf.poll_interval); /* randomize polls */ gw_job_print(job,"EM",'I',"Job will be polled in %d seconds.\n", job->next_poll_time-now); job->last_checkpoint_time = 0; job->history->stats[LAST_SUSPENSION_TIME] = now; job->history->stats[SUSPENSION_TIME] = 0; job->history->stats[ACTIVE_TIME] = 0; job->history->tries++; /* -------------------------------------------------------------------- */ pthread_mutex_unlock(&(job->mutex)); gw_em_mad_submit(job->history->em_mad, job_id, contact, rsl_filename); /* -------------------------------------------------------------------- */ free(_job_id); free(rsl); }