void evaluate_hand(int Decks[2][5][2], int Hands[2], const char *hNames[]) { int i; for( i = 0; i < 2; i++) { if ((check_flush(Decks, i)) && (check_straight(Decks, i))) { Hands[i] = 9; continue; } else if (check_four(Decks, i)) { Hands[i] = 8; continue; } else if (check_full(Decks, i)) { Hands[i] = 7; continue; } else if (check_flush(Decks, i)) { Hands[i] = 6; continue; } else if (check_straight(Decks, i)) { Hands[i] = 5; continue; } else if (check_three(Decks, i)) { Hands[i] = 4; continue; } else if (check_two_pair(Decks, i)) { Hands[i] = 3; continue; } else if (check_pair(Decks, i)) { Hands[i] = 2; continue; } else Hands[i] = 1; } if (Hands[0] > Hands[1]) printf("HAND 1 WINNER with %s\n ", hNames[Hands[0]-1]); else if (Hands[1] > Hands[0]) printf("HAND 2 WINNER with %s\n", hNames[Hands[1]-1]); else if (getMax(Decks, 0) > getMax(Decks, 1)) printf("HAND 1 WINNER with %s\n ", hNames[Hands[0]-1]); else if (getMax(Decks, 1) > getMax(Decks, 0)) printf("HAND 2 WINNER with %s\n", hNames[Hands[1]-1]); else printf("Split\n"); }
int main() { int arr[50], i, n; scanf("%d", &n); for (i = 0; i < n; ++i) scanf("%d", &arr[i]); int x; scanf("%d", &x); check_pair(arr, n, x); return 0; }
int strategy(const int hd[], const int fd[], int cg, int tk, const int ud[], int us) { int myhd[HNUM]; int hdnum[13] = {0}; // 数位 int hdsuite[4] = {0}; // マーク arr_copy(myhd, hd, HNUM); check_myhd(myhd, hdnum, hdsuite); if ( check_pair(myhd, hdnum) ) { return -1; } else { return 1; } //if ( tk < 2 ) { return -1; } //if ( poker_point(myhd) > P2 ) { return -1; } //return 0; }
static int perform_test(const char *title, pj_stun_config *stun_cfg, unsigned server_flag, struct test_cfg *caller_cfg, struct test_cfg *callee_cfg) { pjlib_state pjlib_state; struct test_sess *sess; int rc; PJ_LOG(3,("", INDENT "%s", title)); capture_pjlib_state(stun_cfg, &pjlib_state); rc = create_sess(stun_cfg, server_flag, caller_cfg, callee_cfg, &sess); if (rc != 0) return rc; #define ALL_READY (sess->caller.result.init_status!=PJ_EPENDING && \ sess->callee.result.init_status!=PJ_EPENDING) /* Wait until both ICE transports are initialized */ WAIT_UNTIL(30, ALL_READY, rc); if (!ALL_READY) { PJ_LOG(3,("", INDENT "err: init timed-out")); destroy_sess(sess, 500); return -100; } if (sess->caller.result.init_status != sess->caller.cfg.expected.init_status) { app_perror(INDENT "err: caller init", sess->caller.result.init_status); destroy_sess(sess, 500); return -102; } if (sess->callee.result.init_status != sess->callee.cfg.expected.init_status) { app_perror(INDENT "err: callee init", sess->callee.result.init_status); destroy_sess(sess, 500); return -104; } /* Failure condition */ if (sess->caller.result.init_status != PJ_SUCCESS || sess->callee.result.init_status != PJ_SUCCESS) { rc = 0; goto on_return; } /* Init ICE on caller */ rc = pj_ice_strans_init_ice(sess->caller.ice, sess->caller.cfg.role, &sess->caller.ufrag, &sess->caller.pass); if (rc != PJ_SUCCESS) { app_perror(INDENT "err: caller pj_ice_strans_init_ice()", rc); destroy_sess(sess, 500); return -100; } /* Init ICE on callee */ rc = pj_ice_strans_init_ice(sess->callee.ice, sess->callee.cfg.role, &sess->callee.ufrag, &sess->callee.pass); if (rc != PJ_SUCCESS) { app_perror(INDENT "err: callee pj_ice_strans_init_ice()", rc); destroy_sess(sess, 500); return -110; } /* Start ICE on callee */ rc = start_ice(&sess->callee, &sess->caller); if (rc != PJ_SUCCESS) { destroy_sess(sess, 500); return -120; } /* Wait for callee's answer_delay */ poll_events(stun_cfg, sess->callee.cfg.answer_delay, PJ_FALSE); /* Start ICE on caller */ rc = start_ice(&sess->caller, &sess->callee); if (rc != PJ_SUCCESS) { destroy_sess(sess, 500); return -130; } /* Wait until negotiation is complete on both endpoints */ #define ALL_DONE (sess->caller.result.nego_status!=PJ_EPENDING && \ sess->callee.result.nego_status!=PJ_EPENDING) WAIT_UNTIL(30, ALL_DONE, rc); if (!ALL_DONE) { PJ_LOG(3,("", INDENT "err: negotiation timed-out")); destroy_sess(sess, 500); return -140; } if (sess->caller.result.nego_status != sess->caller.cfg.expected.nego_status) { app_perror(INDENT "err: caller negotiation failed", sess->caller.result.nego_status); destroy_sess(sess, 500); return -150; } if (sess->callee.result.nego_status != sess->callee.cfg.expected.nego_status) { app_perror(INDENT "err: callee negotiation failed", sess->callee.result.nego_status); destroy_sess(sess, 500); return -160; } /* Verify that both agents have agreed on the same pair */ rc = check_pair(&sess->caller, &sess->callee, -170); if (rc != 0) { destroy_sess(sess, 500); return rc; } rc = check_pair(&sess->callee, &sess->caller, -180); if (rc != 0) { destroy_sess(sess, 500); return rc; } /* Looks like everything is okay */ /* Destroy ICE stream transports first to let it de-allocate * TURN relay (otherwise there'll be timer/memory leak, unless * we wait for long time in the last poll_events() below). */ if (sess->caller.ice) { pj_ice_strans_destroy(sess->caller.ice); sess->caller.ice = NULL; } if (sess->callee.ice) { pj_ice_strans_destroy(sess->callee.ice); sess->callee.ice = NULL; } on_return: /* Wait.. */ poll_events(stun_cfg, 500, PJ_FALSE); /* Now destroy everything */ destroy_sess(sess, 500); /* Flush events */ poll_events(stun_cfg, 100, PJ_FALSE); rc = check_pjlib_state(stun_cfg, &pjlib_state); if (rc != 0) { return rc; } return 0; }
int main(int argc, char *argv[]) { double u[NN], v[NN], p[NN], fat[NN], Vc[NN], w[NN][N2], a[NX+1][NY+1][NZ+1], B[NX+1][NY+1][NZ+1], u_ave[NN]; double xx[NN], yy[NN], zz[NN], r[NN]; double ageb[NN], agek[NN]; int state[NN], div_times[NN], touch[NN]; int lj[NN][N2]; int indx[NN]; // lj[i][0...indx-1] int ljd[NN][N2]; int ljd_indx[NN]; // ljd[i][0...ljd_indx-1] /* debug */ int pair[NN], pair2[NN], pair_indx = 0; double L[NN]; int other_cell[NN]; int tb[NN]; int ncell_var, num; int i, j, k; int KEY_INPUT_DATA; char celldata_name[100]; char str[100], str_chem[100]; FILE *finput, *fdebug; void checkstate(int [], int ); void checkparam(); int nmx = (int)(COMPRESS_FACTOR * LX/(2.0*R_memb)); int nmy = (int)(COMPRESS_FACTOR * LY/(2.0*R_memb)); printf("mkdir %s\n", OUTPUTDIR ); sprintf(str, "mkdir -p %s", OUTPUTDIR); system(str); checkparam(); if (fabs(dx-dh)>EPS || fabs(dy-dh)>EPS || fabs(dz-dh)>EPS) { printf("error: dx=%f dy=%f dz=%f.\n", dx, dy, dz); printf("grid size must be dh=%f.\n", dh); exit(1); } if (argc <= 1) { printf("input file name required\n"); exit(1); } strcpy(celldata_name, argv[1]); if((finput = fopen(celldata_name, "r")) == NULL) { printf("input file error2\n"); exit(1); } if ((num = count_line(finput)) != NN) { printf(" error: input data file not consistent.\n"); printf("input file lines = %d: NN = %d\n", num, NN); exit(5); } fclose(finput); if((finput = fopen(celldata_name, "r")) == NULL) { printf("input file error2\n"); exit(1); } initialize_state(state, ageb, agek, fat, Vc); /* input vales, initialize gj, return first blank cell's index*/ initialize_vars(finput, xx, yy, zz, lj, state, r, ageb, agek, div_times, fat, Vc, touch, L, other_cell, tb, &ncell_var, &NDER, &NMEMB); printf("variables initialized: NDER=%d NMEMB=%d ncell=%d NN=%d\n", NDER, NMEMB, ncell_var, NN); if (nmx != NMX || nmy != NMY) { printf("error: number of membrane particles inconsistent with parameter file\n"); exit(1); } checkstate(state, ncell_var); connect_lj(lj, state, ncell_var, xx, yy, zz, r, indx); printf("lj connection initialized\n"); check_pair(ncell_var, xx, yy, zz, pair, pair2, &pair_indx, L, other_cell); fclose(finput); initial_u(u, v, p, a, B, w); // initialization KEY_INPUT_DATA = atoi(argv[2]); if (KEY_INPUT_DATA != 1 && KEY_INPUT_DATA != 0) { printf("error: 2nd argument must be 0 or 1\n"); exit(3); } if (KEY_INPUT_DATA) { printf("chemical data read from recycled_data\n"); sprintf(str_chem, "recycled_data"); input_uvp(str_chem, u, v, p, a, B, w, ncell_var); } if (SYSTEM == WHOLE) { printf("computing the whole epidermis.\n"); // SYSTEM = WHOLE; } else if (SYSTEM == BASAL) { printf("computing only the basal layer and the dermis.\n"); // SYSTEM = BASAL; } else { printf("parameter SYSTEM must be 'WHOLE' or 'BASAL'\n"); exit(1); } if (KEY_FORCED_SC) printf("forced cornification enabled\n"); else printf("forced cornification disabled\n"); if (KEY_INPUT_DATA && KEY_FORCED_SC) { printf("error: forced cornification must be disabled\n"); exit(1); } else if (!KEY_INPUT_DATA && !KEY_FORCED_SC) { printf("WARNING: sc formation would take longer without forced cornification.\n"); } if (KEY_DERMAL_CHANGE) printf("computing dermal change\n"); else printf("fixed dermal shape\n"); printf("divmax=%d, accel_div=%f MALIGNANT=%d\n", div_max, accel_div, MALIGNANT); printf("K_TOTAL=%f, K_DESMOSOME_RATIO=%f\n", K_TOTAL, K_DESMOSOME_RATIO); evolution(u, v, p, w, a, B, xx, yy, zz, r, ageb, agek, state, div_times, fat, Vc, touch, lj, indx, &ncell_var, u_ave, pair, pair2, &pair_indx, L, other_cell, ljd, ljd_indx, tb); printf("finished\n"); return 0; }
/* * Common attr_filter checks */ static rlm_rcode_t CC_HINT(nonnull(1,2)) attr_filter_common(void *instance, REQUEST *request, RADIUS_PACKET *packet) { rlm_attr_filter_t *inst = instance; VALUE_PAIR *vp; vp_cursor_t input, check, out; VALUE_PAIR *input_item, *check_item, *output; PAIR_LIST *pl; int found = 0; int pass, fail = 0; char const *keyname = NULL; char buffer[256]; if (!packet) return RLM_MODULE_NOOP; if (!inst->key) { VALUE_PAIR *namepair; namepair = pairfind(request->packet->vps, PW_REALM, 0, TAG_ANY); if (!namepair) { return (RLM_MODULE_NOOP); } keyname = namepair->vp_strvalue; } else { int len; len = radius_xlat(buffer, sizeof(buffer), request, inst->key, NULL, NULL); if (len < 0) { return RLM_MODULE_FAIL; } if (len == 0) { return RLM_MODULE_NOOP; } keyname = buffer; } /* * Head of the output list */ output = NULL; fr_cursor_init(&out, &output); /* * Find the attr_filter profile entry for the entry. */ for (pl = inst->attrs; pl; pl = pl->next) { int fall_through = 0; int relax_filter = inst->relaxed; /* * If the current entry is NOT a default, * AND the realm does NOT match the current entry, * then skip to the next entry. */ if ((strcmp(pl->name, "DEFAULT") != 0) && (strcmp(keyname, pl->name) != 0)) { continue; } RDEBUG2("Matched entry %s at line %d", pl->name, pl->lineno); found = 1; for (check_item = fr_cursor_init(&check, &pl->check); check_item; check_item = fr_cursor_next(&check)) { if (!check_item->da->vendor && (check_item->da->attr == PW_FALL_THROUGH) && (check_item->vp_integer == 1)) { fall_through = 1; continue; } else if (!check_item->da->vendor && check_item->da->attr == PW_RELAX_FILTER) { relax_filter = check_item->vp_integer; continue; } /* * If it is a SET operator, add the attribute to * the output list without checking it. */ if (check_item->op == T_OP_SET ) { vp = paircopyvp(packet, check_item); if (!vp) { goto error; } radius_xlat_do(request, vp); fr_cursor_insert(&out, vp); } } /* * Iterate through the input items, comparing * each item to every rule, then moving it to the * output list only if it matches all rules * for that attribute. IE, Idle-Timeout is moved * only if it matches all rules that describe an * Idle-Timeout. */ for (input_item = fr_cursor_init(&input, &packet->vps); input_item; input_item = fr_cursor_next(&input)) { pass = fail = 0; /* reset the pass,fail vars for each reply item */ /* * Reset the check_item pointer to beginning of the list */ for (check_item = fr_cursor_first(&check); check_item; check_item = fr_cursor_next(&check)) { /* * Vendor-Specific is special, and matches any VSA if the * comparison is always true. */ if ((check_item->da->attr == PW_VENDOR_SPECIFIC) && (input_item->da->vendor != 0) && (check_item->op == T_OP_CMP_TRUE)) { pass++; continue; } if (input_item->da == check_item->da) { check_pair(request, check_item, input_item, &pass, &fail); } } RDEBUG3("Attribute \"%s\" allowed by %i rules, disallowed by %i rules", input_item->da->name, pass, fail); /* * Only move attribute if it passed all rules, or if the config says we * should copy unmatched attributes ('relaxed' mode). */ if (fail == 0 && (pass > 0 || relax_filter)) { if (!pass) { RDEBUG3("Attribute \"%s\" allowed by relaxed mode", input_item->da->name); } vp = paircopyvp(packet, input_item); if (!vp) { goto error; } fr_cursor_insert(&out, vp); } } /* If we shouldn't fall through, break */ if (!fall_through) { break; } } /* * No entry matched. We didn't do anything. */ if (!found) { rad_assert(!output); return RLM_MODULE_NOOP; } /* * Replace the existing request list with our filtered one */ pairfree(&packet->vps); packet->vps = output; if (request->packet->code == PW_CODE_AUTHENTICATION_REQUEST) { request->username = pairfind(request->packet->vps, PW_STRIPPED_USER_NAME, 0, TAG_ANY); if (!request->username) { request->username = pairfind(request->packet->vps, PW_USER_NAME, 0, TAG_ANY); } request->password = pairfind(request->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY); } return RLM_MODULE_UPDATED; error: pairfree(&output); return RLM_MODULE_FAIL; }
/* Its goal is to add all children to the current node, move the current node * pointer and recursively call itself. */ int build_branch(const short wordnum, struct strie_pair *main_node) { int j; short cur_word_num, checking_word_num; struct strie_pair *cur_node = main_node; struct strie_pair *tmp_node = NULL; struct strie_pair *schild = NULL; struct strie_pair *latest_child = NULL; short *cur_available_first_children = NULL; while (main_node) { cur_available_first_children = (short *)calloc(wordnum, sizeof(short)); memcpy(cur_available_first_children, \ main_node->available_first_children, \ sizeof(short) * wordnum); // cur_node - the node, which participants we are trying to scan // main_node - the node _to_ which we are trying to add these participants cur_node = main_node; while (cur_node) { for (cur_word_num = 0; cur_word_num < 2; cur_word_num++) { // The global index of the word to check checking_word_num = cur_node->crossed_word[cur_word_num]; // We shouldn't allow to search previous words for pairs if (checking_word_num < cur_node->procreator) break; if (!(tmp_node = words[checking_word_num].firstchild)) break; for (j = 0; j < cur_available_first_children[checking_word_num]; j++) tmp_node = tmp_node->brother; while (tmp_node) { cur_available_first_children[checking_word_num]++; if (NULL != (schild = check_pair(main_node, tmp_node))) { // Add new child to main_node schild->parent = main_node; schild->available_first_children = (short *)calloc(wordnum, sizeof(short)); memcpy(schild->available_first_children, \ cur_available_first_children, \ sizeof(short) * wordnum); // Add child to the parent either as the first // child or add the brother to the latest child if (NULL == main_node->firstchild || NULL == latest_child) { main_node->firstchild = schild; } else { latest_child->brother = schild; } latest_child = schild; // Check whether it's better than current best_branch if (best_branch->depth < schild->depth) best_branch = schild; } tmp_node = tmp_node->brother; } } cur_node = cur_node->parent; } if (cur_available_first_children) free(cur_available_first_children); // Go down or to the brother or to the first !NULL parent's brother if (main_node->firstchild) { main_node = main_node->firstchild; } else if (main_node->brother) { main_node = main_node->brother; } else if (main_node->parent) { // Find first parent's brother != NULL tmp_node = main_node->parent; while (tmp_node && !tmp_node->brother) tmp_node = tmp_node->parent; if (tmp_node) { main_node = tmp_node->brother; } else { // We've processed all tree for one crossword word return 0; } } else { // We've processed all tree for one crossword word return 0; } } // This code is reached only when all pairs for the word have been // processed return 0; }
// handle a workunit which has new results // int handle_wu( DB_VALIDATOR_ITEM_SET& validator, std::vector<VALIDATOR_ITEM>& items ) { int canonical_result_index = -1; bool update_result, retry; TRANSITION_TIME transition_time = NO_CHANGE; int retval = 0, x; DB_ID_TYPE canonicalid = 0; double credit = 0; unsigned int i; WORKUNIT& wu = items[0].wu; g_wup = &wu; if (wu.canonical_resultid) { log_messages.printf(MSG_NORMAL, "[WU#%lu %s] Already has canonical result %lu\n", wu.id, wu.name, wu.canonical_resultid ); ++log_messages; // Here if WU already has a canonical result. // Get unchecked results and see if they match the canonical result // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if (result.id == wu.canonical_resultid) { canonical_result_index = i; } } if (canonical_result_index == -1) { log_messages.printf(MSG_CRITICAL, "[WU#%lu %s] Can't find canonical result %lu\n", wu.id, wu.name, wu.canonical_resultid ); return 0; } RESULT& canonical_result = items[canonical_result_index].res; // scan this WU's results, and check the unchecked ones // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if (result.server_state != RESULT_SERVER_STATE_OVER) continue; if (result.outcome != RESULT_OUTCOME_SUCCESS) continue; switch (result.validate_state) { case VALIDATE_STATE_INIT: case VALIDATE_STATE_INCONCLUSIVE: break; default: continue; } log_messages.printf(MSG_NORMAL, "[WU#%lu] handle_wu(): testing result %lu\n", wu.id, result.id ); check_pair(result, canonical_result, retry); if (retry) { // this usually means an NFS mount has failed; // arrange to try again later. // transition_time = DELAYED; goto leave; } update_result = false; if (result.outcome == RESULT_OUTCOME_VALIDATE_ERROR) { update_result = true; } // this might be last result, so let transitioner // trigger file delete etc. if needed // transition_time = IMMEDIATE; DB_HOST host; retval = host.lookup_id(result.hostid); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%lu] lookup of host %lu failed: %s\n", result.id, result.hostid, boincerror(retval) ); continue; } HOST host_initial = host; bool update_hav = false; DB_HOST_APP_VERSION hav; retval = hav_lookup(hav, result.hostid, generalized_app_version_id(result.app_version_id, result.appid) ); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%lu %s] hav_lookup returned %d\n", result.id, result.name, retval ); hav.host_id = 0; } DB_HOST_APP_VERSION hav_orig = hav; vector<DB_HOST_APP_VERSION> havv; havv.push_back(hav); vector<RESULT> rv; switch (result.validate_state) { case VALIDATE_STATE_VALID: update_result = true; update_hav = true; log_messages.printf(MSG_NORMAL, "[RESULT#%lu %s] pair_check() matched: setting result to valid\n", result.id, result.name ); retval = is_valid(host, result, wu, havv[0]); if (retval) { log_messages.printf(MSG_NORMAL, "[RESULT#%lu %s] is_valid() error: %s\n", result.id, result.name, boincerror(retval) ); } // do credit computation, but grant credit of canonical result // rv.push_back(result); assign_credit_set( wu, rv, app, app_versions, havv, max_granted_credit, credit ); if (!no_credit) { result.granted_credit = canonical_result.granted_credit; grant_credit(host, result.sent_time, result.granted_credit); if (config.credit_by_app) { grant_credit_by_app(result, result.granted_credit); } } break; case VALIDATE_STATE_INVALID: update_result = true; update_hav = true; log_messages.printf(MSG_NORMAL, "[RESULT#%lu %s] pair_check() didn't match: setting result to invalid\n", result.id, result.name ); is_invalid(havv[0]); } if (hav.host_id && update_hav) { if (dry_run) { log_messages.printf(MSG_NORMAL, "DB not updated (dry run)\n"); } else { log_messages.printf(MSG_NORMAL, "[HOST#%lu AV#%lu] [outlier=%d] Updating HAV in DB. pfc.n=%f->%f\n", havv[0].host_id, havv[0].app_version_id, result.runtime_outlier, hav_orig.pfc.n, havv[0].pfc.n ); retval=havv[0].update_validator(hav_orig); if (retval) { log_messages.printf(MSG_CRITICAL, "[HOST#%lu AV%lu] hav.update_validator() failed: %s\n", hav.host_id, hav.app_version_id, boincerror(retval) ); } } } host.update_diff_validator(host_initial); if (update_result) { log_messages.printf(MSG_NORMAL, "[RESULT#%lu %s] granted_credit %f\n", result.id, result.name, result.granted_credit ); if (dry_run) { log_messages.printf(MSG_NORMAL, "DB not updated (dry run)\n"); } else { retval = validator.update_result(result); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%lu %s] Can't update result: %s\n", result.id, result.name, boincerror(retval) ); } } } } } else { // Here if WU doesn't have a canonical result yet. // Try to get one vector<RESULT> viable_results; vector<DB_HOST_APP_VERSION> host_app_versions, host_app_versions_orig; log_messages.printf(MSG_NORMAL, "[WU#%lu %s] handle_wu(): No canonical result yet\n", wu.id, wu.name ); ++log_messages; // make a vector of the "viable" (i.e. possibly canonical) results, // and a parallel vector of host_app_versions // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if (result.server_state != RESULT_SERVER_STATE_OVER) continue; if (result.outcome != RESULT_OUTCOME_SUCCESS) continue; if (result.validate_state == VALIDATE_STATE_INVALID) continue; viable_results.push_back(result); DB_HOST_APP_VERSION hav; retval = hav_lookup(hav, result.hostid, generalized_app_version_id(result.app_version_id, result.appid) ); if (retval) { hav.host_id=0; // flag that it's missing } host_app_versions.push_back(hav); host_app_versions_orig.push_back(hav); } log_messages.printf(MSG_DEBUG, "[WU#%lu %s] Found %d viable results\n", wu.id, wu.name, (int)viable_results.size() ); if (viable_results.size() >= (unsigned int)wu.min_quorum) { log_messages.printf(MSG_DEBUG, "[WU#%lu %s] Enough for quorum, checking set.\n", wu.id, wu.name ); double dummy; retval = check_set(viable_results, wu, canonicalid, dummy, retry); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%lu %s] check_set() error: %s\n", wu.id, wu.name, boincerror(retval) ); return retval; } if (retry) transition_time = DELAYED; // if we found a canonical instance, decide on credit // if (canonicalid) { // always do the credit calculation, to update statistics, // even if we're granting credit a different way // retval = assign_credit_set( wu, viable_results, app, app_versions, host_app_versions, max_granted_credit, credit ); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%lu %s] assign_credit_set(): %s\n", wu.id, wu.name, boincerror(retval) ); transition_time = DELAYED; goto leave; } if (credit_from_wu) { retval = get_credit_from_wu(wu, viable_results, credit); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%lu %s] get_credit_from_wu(): credit not specified in WU\n", wu.id, wu.name ); credit = 0; } } else if (credit_from_runtime) { credit = 0; for (i=0; i<viable_results.size(); i++) { RESULT& result = viable_results[i]; if (result.id == canonicalid) { DB_HOST host; retval = host.lookup_id(result.hostid); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%lu %s] host %lu lookup failed\n", wu.id, wu.name, result.hostid ); break; } double runtime = result.elapsed_time; if (runtime <=0 || runtime > max_runtime) { runtime = max_runtime; } credit = result.flops_estimate * runtime * COBBLESTONE_SCALE; log_messages.printf(MSG_NORMAL, "[WU#%lu][RESULT#%lu] credit_from_runtime %.2f = %.0fs * %.2fGFLOPS\n", wu.id, result.id, credit, runtime, result.flops_estimate/1e9 ); break; } } } else if (no_credit) { credit = 0; } if (max_granted_credit && credit>max_granted_credit) { credit = max_granted_credit; } } // scan the viable results. // update as needed, // and count the # of results that are still viable // (some may now have outcome VALIDATE_ERROR, // or validate_state INVALID) // int n_viable_results = 0; for (i=0; i<viable_results.size(); i++) { RESULT& result = viable_results[i]; DB_HOST_APP_VERSION& hav = host_app_versions[i]; DB_HOST_APP_VERSION& hav_orig = host_app_versions_orig[i]; update_result = false; bool update_host = false; if (result.outcome != RESULT_OUTCOME_SUCCESS || result.validate_state == VALIDATE_STATE_INVALID ) { transition_time = IMMEDIATE; update_result = true; } else { n_viable_results++; } DB_HOST host; HOST host_initial; switch (result.validate_state) { case VALIDATE_STATE_VALID: case VALIDATE_STATE_INVALID: retval = host.lookup_id(result.hostid); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%lu] lookup of host %lu: %s\n", result.id, result.hostid, boincerror(retval) ); continue; } host_initial = host; } switch (result.validate_state) { case VALIDATE_STATE_VALID: update_result = true; update_host = true; retval = is_valid(host, result, wu, host_app_versions[i]); if (retval) { log_messages.printf(MSG_DEBUG, "[RESULT#%lu %s] is_valid() failed: %s\n", result.id, result.name, boincerror(retval) ); } if (!no_credit) { result.granted_credit = credit; grant_credit(host, result.sent_time, credit); log_messages.printf(MSG_NORMAL, "[RESULT#%lu %s] Valid; granted %f credit [HOST#%lu]\n", result.id, result.name, result.granted_credit, result.hostid ); if (config.credit_by_app) { grant_credit_by_app(result, credit); } } break; case VALIDATE_STATE_INVALID: update_result = true; update_host = true; log_messages.printf(MSG_NORMAL, "[RESULT#%lu %s] Invalid [HOST#%lu]\n", result.id, result.name, result.hostid ); is_invalid(host_app_versions[i]); break; case VALIDATE_STATE_INIT: log_messages.printf(MSG_NORMAL, "[RESULT#%lu %s] Inconclusive [HOST#%lu]\n", result.id, result.name, result.hostid ); result.validate_state = VALIDATE_STATE_INCONCLUSIVE; update_result = true; break; } if (dry_run) { log_messages.printf(MSG_NORMAL, "DB not updated (dry run)\n"); } else { if (hav.host_id) { log_messages.printf(MSG_NORMAL, "[HOST#%lu AV#%lu] [outlier=%d] Updating HAV in DB. pfc.n=%f->%f\n", hav.host_id, hav.app_version_id, result.runtime_outlier, hav_orig.pfc.n, hav.pfc.n ); retval = hav.update_validator(hav_orig); if (retval) { log_messages.printf(MSG_CRITICAL, "[HOST#%lu AV%lu] hav.update_validator() failed: %s\n", hav.host_id, hav.app_version_id, boincerror(retval) ); } } if (update_host) { retval = host.update_diff_validator(host_initial); if (retval) { log_messages.printf(MSG_CRITICAL, "[HOST#%lu] host.update_diff_validator() failed: %s\n", host.id, boincerror(retval) ); } } if (update_result) { retval = validator.update_result(result); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%lu %s] result.update() failed: %s\n", result.id, result.name, boincerror(retval) ); } } } } if (canonicalid) { // if we found a canonical result, // trigger the assimilator, but do NOT trigger // the transitioner - doing so creates a race condition // transition_time = NEVER; log_messages.printf(MSG_DEBUG, "[WU#%lu %s] Found a canonical result: id=%lu\n", wu.id, wu.name, canonicalid ); wu.canonical_resultid = canonicalid; wu.canonical_credit = credit; wu.assimilate_state = ASSIMILATE_READY; // don't need to send any more results // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if (result.server_state != RESULT_SERVER_STATE_UNSENT) { continue; } result.server_state = RESULT_SERVER_STATE_OVER; result.outcome = RESULT_OUTCOME_DIDNT_NEED; if (dry_run) { log_messages.printf(MSG_NORMAL, "DB not updated (dry run)\n"); } else { retval = validator.update_result(result); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%lu %s] result.update() failed: %s\n", result.id, result.name, boincerror(retval) ); } } } } else { // here if no consensus. // check if #viable results is too large // if (n_viable_results > wu.max_success_results) { wu.error_mask |= WU_ERROR_TOO_MANY_SUCCESS_RESULTS; transition_time = IMMEDIATE; } // if #viable results >= target_nresults, // we need more results, so bump target_nresults // NOTE: n_viable_results should never be > target_nresults, // but accommodate that if it should happen // if (n_viable_results >= wu.target_nresults) { wu.target_nresults = n_viable_results+1; transition_time = IMMEDIATE; } } } } leave: --log_messages; switch (transition_time) { case IMMEDIATE: wu.transition_time = time(0); break; case DELAYED: x = time(0) + 6*3600; if (x < wu.transition_time) wu.transition_time = x; break; case NEVER: wu.transition_time = INT_MAX; break; case NO_CHANGE: break; } wu.need_validate = 0; if (dry_run) { log_messages.printf(MSG_NORMAL, "DB not updated (dry run)\n"); } else { retval = validator.update_workunit(wu); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%lu %s] update_workunit() failed: %s\n", wu.id, wu.name, boincerror(retval) ); return retval; } } return 0; }
// handle a workunit which has new results // int handle_wu( DB_VALIDATOR_ITEM_SET& validator, std::vector<VALIDATOR_ITEM>& items ) { int canonical_result_index = -1; bool update_result, retry; TRANSITION_TIME transition_time = NO_CHANGE; int retval = 0, canonicalid = 0, x; double credit = 0; unsigned int i; WORKUNIT& wu = items[0].wu; g_wup = &wu; if (wu.canonical_resultid) { log_messages.printf(MSG_NORMAL, "[WU#%d %s] Already has canonical result %d\n", wu.id, wu.name, wu.canonical_resultid ); ++log_messages; // Here if WU already has a canonical result. // Get unchecked results and see if they match the canonical result // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if (result.id == wu.canonical_resultid) { canonical_result_index = i; } } if (canonical_result_index == -1) { log_messages.printf(MSG_CRITICAL, "[WU#%d %s] Can't find canonical result %d\n", wu.id, wu.name, wu.canonical_resultid ); return 0; } RESULT& canonical_result = items[canonical_result_index].res; // scan this WU's results, and check the unchecked ones // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if (result.server_state != RESULT_SERVER_STATE_OVER) continue; if (result.outcome != RESULT_OUTCOME_SUCCESS) continue; switch (result.validate_state) { case VALIDATE_STATE_INIT: case VALIDATE_STATE_INCONCLUSIVE: break; default: continue; } log_messages.printf(MSG_NORMAL, "[WU#%d] handle_wu(): testing result %d\n", wu.id, result.id ); check_pair(result, canonical_result, retry); if (retry) { // this usually means an NFS mount has failed; // arrange to try again later. // transition_time = DELAYED; goto leave; } update_result = false; if (result.outcome == RESULT_OUTCOME_VALIDATE_ERROR) { update_result = true; } // this might be last result, so let transitioner // trigger file delete etc. if needed // transition_time = IMMEDIATE; DB_HOST host; retval = host.lookup_id(result.hostid); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%d] lookup of host %d failed: %s\n", result.id, result.hostid, boincerror(retval) ); continue; } HOST host_initial = host; bool update_hav = false; DB_HOST_APP_VERSION hav; retval = hav_lookup(hav, result.hostid, generalized_app_version_id(result.app_version_id, result.appid) ); if (retval) { hav.host_id = 0; } DB_HOST_APP_VERSION hav_orig = hav; vector<DB_HOST_APP_VERSION> havv; havv.push_back(hav); vector<RESULT> rv; switch (result.validate_state) { case VALIDATE_STATE_VALID: update_result = true; update_hav = true; log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] pair_check() matched: setting result to valid\n", result.id, result.name ); retval = is_valid(host, result, wu, havv[0]); if (retval) { log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] is_valid() error: %s\n", result.id, result.name, boincerror(retval) ); } // do credit computation, but grant credit of canonical result // rv.push_back(result); assign_credit_set( wu, rv, app, app_versions, havv, max_granted_credit, credit ); result.granted_credit = canonical_result.granted_credit; grant_credit(host, result.sent_time, result.granted_credit); break; case VALIDATE_STATE_INVALID: update_result = true; update_hav = true; log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] pair_check() didn't match: setting result to invalid\n", result.id, result.name ); is_invalid(havv[0]); } if (hav.host_id && update_hav) { havv[0].update_validator(hav_orig); } host.update_diff_validator(host_initial); if (update_result) { log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] granted_credit %f\n", result.id, result.name, result.granted_credit ); retval = validator.update_result(result); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%d %s] Can't update result: %s\n", result.id, result.name, boincerror(retval) ); } } } } else { vector<RESULT> results; vector<DB_HOST_APP_VERSION> host_app_versions, host_app_versions_orig; int nsuccess_results; // Here if WU doesn't have a canonical result yet. // Try to get one log_messages.printf(MSG_NORMAL, "[WU#%d %s] handle_wu(): No canonical result yet\n", wu.id, wu.name ); ++log_messages; // make a vector of the successful results, // and a parallel vector of host_app_versions // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if ((result.server_state == RESULT_SERVER_STATE_OVER) && (result.outcome == RESULT_OUTCOME_SUCCESS) ) { results.push_back(result); DB_HOST_APP_VERSION hav; retval = hav_lookup(hav, result.hostid, generalized_app_version_id(result.app_version_id, result.appid) ); if (retval) { hav.host_id=0; // flag that it's missing } host_app_versions.push_back(hav); host_app_versions_orig.push_back(hav); } } log_messages.printf(MSG_DEBUG, "[WU#%d %s] Found %d successful results\n", wu.id, wu.name, (int)results.size() ); if (results.size() >= (unsigned int)wu.min_quorum) { log_messages.printf(MSG_DEBUG, "[WU#%d %s] Enough for quorum, checking set.\n", wu.id, wu.name ); double dummy; retval = check_set(results, wu, canonicalid, dummy, retry); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%d %s] check_set() error: %s, exiting\n", wu.id, wu.name, boincerror(retval) ); return retval; } if (retry) transition_time = DELAYED; if (credit_from_wu) { retval = get_credit_from_wu(wu, results, credit); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%d %s] get_credit_from_wu(): credit not specified in WU\n", wu.id, wu.name ); credit = 0; } } else { if (canonicalid) { retval = assign_credit_set( wu, results, app, app_versions, host_app_versions, max_granted_credit, credit ); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%d %s] assign_credit_set(): %s\n", wu.id, wu.name, boincerror(retval) ); transition_time = DELAYED; goto leave; } } } if (max_granted_credit && credit>max_granted_credit) { credit = max_granted_credit; } // scan results. // update as needed, and count the # of results // that are still outcome=SUCCESS // (some may have changed to VALIDATE_ERROR) // nsuccess_results = 0; for (i=0; i<results.size(); i++) { RESULT& result = results[i]; DB_HOST_APP_VERSION& hav = host_app_versions[i]; DB_HOST_APP_VERSION& hav_orig = host_app_versions_orig[i]; update_result = false; bool update_host = false; if (result.outcome == RESULT_OUTCOME_VALIDATE_ERROR) { transition_time = IMMEDIATE; update_result = true; } else { nsuccess_results++; } DB_HOST host; HOST host_initial; switch (result.validate_state) { case VALIDATE_STATE_VALID: case VALIDATE_STATE_INVALID: retval = host.lookup_id(result.hostid); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%d] lookup of host %d: %s\n", result.id, result.hostid, boincerror(retval) ); continue; } host_initial = host; } switch (result.validate_state) { case VALIDATE_STATE_VALID: update_result = true; update_host = true; retval = is_valid(host, result, wu, host_app_versions[i]); if (retval) { log_messages.printf(MSG_DEBUG, "[RESULT#%d %s] is_valid() failed: %s\n", result.id, result.name, boincerror(retval) ); } result.granted_credit = credit; grant_credit(host, result.sent_time, credit); log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] Valid; granted %f credit [HOST#%d]\n", result.id, result.name, result.granted_credit, result.hostid ); break; case VALIDATE_STATE_INVALID: update_result = true; update_host = true; log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] Invalid [HOST#%d]\n", result.id, result.name, result.hostid ); is_invalid(host_app_versions[i]); break; case VALIDATE_STATE_INIT: log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] Inconclusive [HOST#%d]\n", result.id, result.name, result.hostid ); result.validate_state = VALIDATE_STATE_INCONCLUSIVE; update_result = true; break; } if (hav.host_id) { retval = hav.update_validator(hav_orig); } if (update_host) { retval = host.update_diff_validator(host_initial); } if (update_result) { retval = validator.update_result(result); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%d %s] result.update() failed: %s\n", result.id, result.name, boincerror(retval) ); } } } if (canonicalid) { // if we found a canonical result, // trigger the assimilator, but do NOT trigger // the transitioner - doing so creates a race condition // transition_time = NEVER; log_messages.printf(MSG_DEBUG, "[WU#%d %s] Found a canonical result: id=%d\n", wu.id, wu.name, canonicalid ); wu.canonical_resultid = canonicalid; wu.canonical_credit = credit; wu.assimilate_state = ASSIMILATE_READY; // don't need to send any more results // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if (result.server_state != RESULT_SERVER_STATE_UNSENT) { continue; } result.server_state = RESULT_SERVER_STATE_OVER; result.outcome = RESULT_OUTCOME_DIDNT_NEED; retval = validator.update_result(result); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%d %s] result.update() failed: %s\n", result.id, result.name, boincerror(retval) ); } } } else { // here if no consensus. // check if #success results is too large // if (nsuccess_results > wu.max_success_results) { wu.error_mask |= WU_ERROR_TOO_MANY_SUCCESS_RESULTS; transition_time = IMMEDIATE; } // if #success results >= target_nresults, // we need more results, so bump target_nresults // NOTE: nsuccess_results should never be > target_nresults, // but accommodate that if it should happen // if (nsuccess_results >= wu.target_nresults) { wu.target_nresults = nsuccess_results+1; transition_time = IMMEDIATE; } } } } leave: --log_messages; switch (transition_time) { case IMMEDIATE: wu.transition_time = time(0); break; case DELAYED: x = time(0) + 6*3600; if (x < wu.transition_time) wu.transition_time = x; break; case NEVER: wu.transition_time = INT_MAX; break; case NO_CHANGE: break; } wu.need_validate = 0; retval = validator.update_workunit(wu); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%d %s] update_workunit() failed: %s; exiting\n", wu.id, wu.name, boincerror(retval) ); return retval; } return 0; }
static int perform_test2(const char *title, pj_stun_config *stun_cfg, unsigned server_flag, struct test_cfg *caller_cfg, struct test_cfg *callee_cfg, struct sess_param *test_param) { pjlib_state pjlib_state; struct test_sess *sess; unsigned i; int rc; PJ_LOG(3,(THIS_FILE, INDENT "%s", title)); capture_pjlib_state(stun_cfg, &pjlib_state); rc = create_sess(stun_cfg, server_flag, caller_cfg, callee_cfg, test_param, &sess); if (rc != 0) return rc; #define ALL_READY (sess->caller.result.init_status!=PJ_EPENDING && \ sess->callee.result.init_status!=PJ_EPENDING) /* Wait until both ICE transports are initialized */ WAIT_UNTIL(30000, ALL_READY, rc); if (!ALL_READY) { PJ_LOG(3,(THIS_FILE, INDENT "err: init timed-out")); destroy_sess(sess, 500); return -100; } if (sess->caller.result.init_status != sess->caller.cfg.expected.init_status) { app_perror(INDENT "err: caller init", sess->caller.result.init_status); destroy_sess(sess, 500); return -102; } if (sess->callee.result.init_status != sess->callee.cfg.expected.init_status) { app_perror(INDENT "err: callee init", sess->callee.result.init_status); destroy_sess(sess, 500); return -104; } /* Failure condition */ if (sess->caller.result.init_status != PJ_SUCCESS || sess->callee.result.init_status != PJ_SUCCESS) { rc = 0; goto on_return; } /* Init ICE on caller */ rc = pj_ice_strans_init_ice(sess->caller.ice, sess->caller.cfg.role, &sess->caller.ufrag, &sess->caller.pass); if (rc != PJ_SUCCESS) { app_perror(INDENT "err: caller pj_ice_strans_init_ice()", rc); destroy_sess(sess, 500); return -100; } /* Init ICE on callee */ rc = pj_ice_strans_init_ice(sess->callee.ice, sess->callee.cfg.role, &sess->callee.ufrag, &sess->callee.pass); if (rc != PJ_SUCCESS) { app_perror(INDENT "err: callee pj_ice_strans_init_ice()", rc); destroy_sess(sess, 500); return -110; } /* Start ICE on callee */ rc = start_ice(&sess->callee, &sess->caller); if (rc != PJ_SUCCESS) { destroy_sess(sess, 500); return -120; } /* Wait for callee's answer_delay */ poll_events(stun_cfg, sess->callee.cfg.answer_delay, PJ_FALSE); /* Start ICE on caller */ rc = start_ice(&sess->caller, &sess->callee); if (rc != PJ_SUCCESS) { destroy_sess(sess, 500); return -130; } for (i=0; i<sess->param->worker_cnt; ++i) { pj_status_t status; status = pj_thread_create(sess->pool, "worker_thread", worker_thread_proc, sess, 0, 0, &sess->worker_threads[i]); if (status != PJ_SUCCESS) { PJ_LOG(3,(THIS_FILE, INDENT "err: create thread")); destroy_sess(sess, 500); return -135; } } if (sess->param->destroy_after_create) goto on_destroy; if (sess->param->destroy_after_one_done) { while (sess->caller.result.init_status==PJ_EPENDING && sess->callee.result.init_status==PJ_EPENDING) { if (sess->param->worker_cnt) pj_thread_sleep(0); else poll_events(stun_cfg, 0, PJ_FALSE); } goto on_destroy; } WAIT_UNTIL(30000, ALL_DONE, rc); if (!ALL_DONE) { PJ_LOG(3,(THIS_FILE, INDENT "err: negotiation timed-out")); destroy_sess(sess, 500); return -140; } if (sess->caller.result.nego_status != sess->caller.cfg.expected.nego_status) { app_perror(INDENT "err: caller negotiation failed", sess->caller.result.nego_status); destroy_sess(sess, 500); return -150; } if (sess->callee.result.nego_status != sess->callee.cfg.expected.nego_status) { app_perror(INDENT "err: callee negotiation failed", sess->callee.result.nego_status); destroy_sess(sess, 500); return -160; } /* Verify that both agents have agreed on the same pair */ rc = check_pair(&sess->caller, &sess->callee, -170); if (rc != 0) { destroy_sess(sess, 500); return rc; } rc = check_pair(&sess->callee, &sess->caller, -180); if (rc != 0) { destroy_sess(sess, 500); return rc; } /* Looks like everything is okay */ on_destroy: /* Destroy ICE stream transports first to let it de-allocate * TURN relay (otherwise there'll be timer/memory leak, unless * we wait for long time in the last poll_events() below). */ if (sess->caller.ice) { pj_ice_strans_destroy(sess->caller.ice); sess->caller.ice = NULL; } if (sess->callee.ice) { pj_ice_strans_destroy(sess->callee.ice); sess->callee.ice = NULL; } on_return: /* Wait.. */ poll_events(stun_cfg, 200, PJ_FALSE); /* Now destroy everything */ destroy_sess(sess, 500); /* Flush events */ poll_events(stun_cfg, 100, PJ_FALSE); rc = check_pjlib_state(stun_cfg, &pjlib_state); if (rc != 0) { return rc; } return rc; }
// Return zero iff we resolved the WU // int handle_wu( DB_VALIDATOR_ITEM_SET& validator, std::vector<VALIDATOR_ITEM>& items ) { int canonical_result_index = -1; bool update_result, retry; TRANSITION_TIME transition_time = NO_CHANGE; int retval = 0, canonicalid = 0, x; double credit = 0; unsigned int i; WORKUNIT& wu = items[0].wu; g_wup = &wu; if (wu.canonical_resultid) { log_messages.printf(MSG_NORMAL, "[WU#%d %s] Already has canonical result %d\n", wu.id, wu.name, wu.canonical_resultid ); ++log_messages; // Here if WU already has a canonical result. // Get unchecked results and see if they match the canonical result // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if (result.id == wu.canonical_resultid) { canonical_result_index = i; } } if (canonical_result_index == -1) { log_messages.printf(MSG_CRITICAL, "[WU#%d %s] Can't find canonical result %d\n", wu.id, wu.name, wu.canonical_resultid ); return 0; } RESULT& canonical_result = items[canonical_result_index].res; // scan this WU's results, and check the unchecked ones // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if (result.server_state != RESULT_SERVER_STATE_OVER) continue; if (result.outcome != RESULT_OUTCOME_SUCCESS) continue; switch (result.validate_state) { case VALIDATE_STATE_INIT: case VALIDATE_STATE_INCONCLUSIVE: break; default: continue; } log_messages.printf(MSG_NORMAL, "[WU#%d] handle_wu(): testing result %d\n", wu.id, result.id ); check_pair(result, canonical_result, retry); if (retry) transition_time = DELAYED; update_result = false; if (result.outcome == RESULT_OUTCOME_VALIDATE_ERROR) { update_result = true; } // this might be last result, so let validator // trigger file delete etc. if needed // transition_time = IMMEDIATE; switch (result.validate_state) { case VALIDATE_STATE_VALID: update_result = true; if (result.granted_credit == 0) { result.granted_credit = grant_claimed_credit ? result.claimed_credit : wu.canonical_credit; if (max_granted_credit && result.granted_credit > max_granted_credit) { result.granted_credit = max_granted_credit; } } log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] pair_check() matched: setting result to valid; credit %f\n", result.id, result.name, result.granted_credit ); retval = is_valid(result, wu); if (retval) { log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] Can't grant credit: %d\n", result.id, result.name, retval ); } break; case VALIDATE_STATE_INVALID: update_result = true; log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] pair_check() didn't match: setting result to invalid\n", result.id, result.name ); is_invalid(wu, result); } if (update_result) { log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] granted_credit %f\n", result.id, result.name, result.granted_credit ); retval = validator.update_result(result); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%d %s] Can't update result: %d\n", result.id, result.name, retval ); } } } } else { vector<RESULT> results; int nsuccess_results; // Here if WU doesn't have a canonical result yet. // Try to get one log_messages.printf(MSG_NORMAL, "[WU#%d %s] handle_wu(): No canonical result yet\n", wu.id, wu.name ); ++log_messages; // make a vector of only successful results // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if ((result.server_state == RESULT_SERVER_STATE_OVER) && (result.outcome == RESULT_OUTCOME_SUCCESS) ) { results.push_back(result); } } log_messages.printf(MSG_DEBUG, "[WU#%d %s] Found %d successful results\n", wu.id, wu.name, (int)results.size() ); if (results.size() >= (unsigned int)wu.min_quorum) { log_messages.printf(MSG_DEBUG, "[WU#%d %s] Enough for quorum, checking set.\n", wu.id, wu.name ); retval = check_set(results, wu, canonicalid, credit, retry); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%d %s] check_set returned %d, exiting\n", wu.id, wu.name, retval ); return retval; } if (retry) transition_time = DELAYED; if (credit_from_wu) { retval = get_credit_from_wu(wu, results, credit); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%d %s] get_credit_from_wu returned %d\n", wu.id, wu.name, retval ); return retval; } } if (max_granted_credit && credit>max_granted_credit) { credit = max_granted_credit; } // scan results. // update as needed, and count the # of results // that are still outcome=SUCCESS // (some may have changed to VALIDATE_ERROR) // nsuccess_results = 0; for (i=0; i<results.size(); i++) { update_result = false; RESULT& result = results[i]; if (result.outcome == RESULT_OUTCOME_VALIDATE_ERROR) { transition_time = IMMEDIATE; update_result = true; } else { nsuccess_results++; } switch (result.validate_state) { case VALIDATE_STATE_VALID: // grant credit for valid results // update_result = true; if (result.granted_credit == 0) { result.granted_credit = grant_claimed_credit ? result.claimed_credit : credit; if (max_granted_credit && result.granted_credit > max_granted_credit) { result.granted_credit = max_granted_credit; } } retval = is_valid(result, wu); if (retval) { log_messages.printf(MSG_DEBUG, "[RESULT#%d %s] is_valid() failed: %d\n", result.id, result.name, retval ); } log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] Valid; granted %f credit [HOST#%d]\n", result.id, result.name, result.granted_credit, result.hostid ); break; case VALIDATE_STATE_INVALID: log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] Invalid [HOST#%d]\n", result.id, result.name, result.hostid ); is_invalid(wu, result); update_result = true; break; case VALIDATE_STATE_INIT: log_messages.printf(MSG_NORMAL, "[RESULT#%d %s] Inconclusive [HOST#%d]\n", result.id, result.name, result.hostid ); result.validate_state = VALIDATE_STATE_INCONCLUSIVE; update_result = true; break; } if (update_result) { retval = validator.update_result(result); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%d %s] result.update() failed: %d\n", result.id, result.name, retval ); } } } if (canonicalid) { // if we found a canonical result, // trigger the assimilator, but do NOT trigger // the transitioner - doing so creates a race condition // transition_time = NEVER; log_messages.printf(MSG_DEBUG, "[WU#%d %s] Found a canonical result: id=%d\n", wu.id, wu.name, canonicalid ); wu.canonical_resultid = canonicalid; wu.canonical_credit = credit; wu.assimilate_state = ASSIMILATE_READY; // If found a canonical result, don't send any unsent results // for (i=0; i<items.size(); i++) { RESULT& result = items[i].res; if (result.server_state != RESULT_SERVER_STATE_UNSENT) { continue; } result.server_state = RESULT_SERVER_STATE_OVER; result.outcome = RESULT_OUTCOME_DIDNT_NEED; retval = validator.update_result(result); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%d %s] result.update() failed: %d\n", result.id, result.name, retval ); } } } else { // here if no consensus. // check if #success results is too large // if (nsuccess_results > wu.max_success_results) { wu.error_mask |= WU_ERROR_TOO_MANY_SUCCESS_RESULTS; transition_time = IMMEDIATE; } // if #success results == than target_nresults, // we need more results, so bump target_nresults // NOTE: nsuccess_results should never be > target_nresults, // but accommodate that if it should happen // if (nsuccess_results >= wu.target_nresults) { wu.target_nresults = nsuccess_results+1; transition_time = IMMEDIATE; } } } } --log_messages; switch (transition_time) { case IMMEDIATE: wu.transition_time = time(0); break; case DELAYED: x = time(0) + 6*3600; if (x < wu.transition_time) wu.transition_time = x; break; case NEVER: wu.transition_time = INT_MAX; break; case NO_CHANGE: break; } wu.need_validate = 0; retval = validator.update_workunit(wu); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%d %s] update_workunit() failed: %d; exiting\n", wu.id, wu.name, retval ); return retval; } return 0; }