/* is it safe to commit the grant? * if we didn't hear from all sites on the initial grant, we may * need to delay the commit * * TODO: investigate possibility to devise from history whether a * missing site could be holding a ticket or not */ static int ticket_dangerous(struct ticket_config *tk) { int tdiff; /* we may be invoked often, don't spam the log unnecessarily */ static int no_log_delay_msg; if (!is_time_set(&tk->delay_commit)) return 0; if (is_past(&tk->delay_commit) || all_sites_replied(tk)) { if (tk->leader == local) { tk_log_info("%s, committing to CIB", is_past(&tk->delay_commit) ? "ticket delay expired" : "all sites replied"); } time_reset(&tk->delay_commit); no_log_delay_msg = 0; return 0; } tdiff = time_left(&tk->delay_commit); tk_log_debug("delay ticket commit for another " intfmt(tdiff)); if (!no_log_delay_msg) { tk_log_info("delaying ticket commit to CIB for " intfmt(tdiff)); tk_log_info("(or all sites are reached)"); no_log_delay_msg = 1; } return 1; }
void elections_end(struct ticket_config *tk) { struct booth_site *new_leader; if (is_past(&tk->election_end)) { /* This is previous election timed out */ tk_log_info("elections finished"); } tk->in_election = 0; new_leader = majority_votes(tk); if (new_leader == local) { won_elections(tk); tk_log_info("granted successfully here"); } else if (new_leader) { tk_log_info("ticket granted at %s", site_string(new_leader)); } else { tk_log_info("nobody won elections, new elections"); tk->outcome = RLT_MORE; foreach_tkt_req(tk, notify_client); if (!new_election(tk, NULL, is_tie(tk) ? 2 : 0, OR_AGAIN)) { ticket_activate_timeout(tk); } } }
static void log_reacquire_reason(struct ticket_config *tk) { int valid; const char *where_granted = "\0"; char buff[64]; valid = is_time_set(&tk->term_expires) && !is_past(&tk->term_expires); if (tk->leader == local) { where_granted = "granted here"; } else { snprintf(buff, sizeof(buff), "granted to %s", site_string(tk->leader)); where_granted = buff; } if (!valid) { tk_log_warn("%s, but not valid " "anymore (will try to reacquire)", where_granted); } if (tk->is_granted && tk->leader != local) { if (tk->leader && tk->leader != no_leader) { tk_log_error("granted here, but also %s, " "that's really too bad (will try to reacquire)", where_granted); } else { tk_log_warn("granted here, but we're " "not recorded as the grantee (will try to reacquire)"); } } }
int disown_if_expired(struct ticket_config *tk) { if (is_past(&tk->term_expires) || !tk->leader) { disown_ticket(tk); return 1; } return 0; }
int new_election(struct ticket_config *tk, struct booth_site *preference, int update_term, cmd_reason_t reason) { struct booth_site *new_leader; if (local->type != SITE) return 0; if ((is_reason(OR_TKT_LOST, tk) || is_reason(OR_STEPDOWN, tk)) && check_attr_prereq(tk, GRANT_AUTO)) { tk_log_info("attribute prerequisite not met, " "not starting elections"); return 0; } /* elections were already started, but not yet finished/timed out */ if (is_time_set(&tk->election_end) && !is_past(&tk->election_end)) return 1; if (ANYDEBUG) { int tdiff; if (is_time_set(&tk->election_end)) { tdiff = -time_left(&tk->election_end); tk_log_debug("starting elections, previous finished since " intfmt(tdiff)); } else { tk_log_debug("starting elections"); } tk_log_debug("elections caused by %s %s", state_to_string(reason), reason == OR_AGAIN ? state_to_string(tk->election_reason) : "" ); } /* §5.2 */ /* If there was _no_ answer, don't keep incrementing the term number * indefinitely. If there was no peer, there'll probably be no one * listening now either. However, we don't know if we were * invoked due to a timeout (caller does). */ /* increment the term only if either the current term was * valid or if there was a tie (in that case update_term > 1) */ if ((update_term > 1) || (update_term && tk->last_valid_tk && tk->last_valid_tk->current_term >= tk->current_term)) { /* save the previous term, we may need to send out the * MY_INDEX message */ if (tk->state != ST_CANDIDATE) { save_committed_tkt(tk); } tk->current_term++; } set_future_time(&tk->election_end, tk->timeout); tk->in_election = 1; tk_log_info("starting new election (term=%d)", tk->current_term); clear_election(tk); if(preference) new_leader = preference; else new_leader = (local->type == SITE) ? local : NULL; record_vote(tk, local, new_leader); tk->voted_for = new_leader; set_state(tk, ST_CANDIDATE); /* some callers may want just to repeat on timeout */ if (reason == OR_AGAIN) { reason = tk->election_reason; } else { tk->election_reason = reason; } ticket_broadcast(tk, OP_REQ_VOTE, OP_VOTE_FOR, RLT_SUCCESS, reason); add_random_delay(tk); return 0; }
void CEngSemStructure::ImpersonalVerb(int iEngNode) { // не применяется, если граф не собран if( !IsConnected() ) return; // if( m_Nodes[iEngNode].m_MainWordNo==-1 ) return; int iRusNode = m_Nodes[iEngNode].RusNode; if( iRusNode == -1 ) return; const CSemNode& rusNode = RusStr.GetNode(iRusNode); // CEngSemNode& engNode = m_Nodes[iEngNode]; CEngSemWord& engWord = engNode.m_Words[engNode.m_MainWordNo]; if( !engWord.HasPOS(eVERB) && !engWord.HasPOS(eMOD) ) return; if( engNode.HasRelOperator("_мягк_пригласит_наклонение") || engNode.HasRelOperator("_пригласит_наклонение") ) return; if( engNode.m_Words[0].m_Lemma=="have" ) return; if( engNode.m_Words[0].m_Lemma=="keep" ) return; vector<long> inRels; GetIncomingRelations(iEngNode, inRels, false); for( int k=0; k<inRels.size(); k++ ) { if( m_Nodes[m_Relations[inRels[k]].m_SourceNodeNo].m_Words[0].m_Lemma=="keep" ) return; } if (!HasSubjAsFirstValency(engNode)) return; // модальный глагол bool bModCX = ( engNode.GetType()!=NoneRoss && GetRossHolder(engNode.GetType())->HasFieldValue("SF","MODL",engNode.GetUnitNo()) ); // (3|прш) + мн bool bCase1 = (engWord.HasOneGrammem(eThirdPerson) || is_past(engWord.GetTense())) && engWord.HasOneGrammem(ePlural); // (3|(ср&прш)) + ед bool bCase2 = ( engWord.HasOneGrammem(eThirdPerson) || (is_past(engWord.GetTense()) && !engWord.HasOneGrammem(eMasculinum) && !engWord.HasOneGrammem(eFeminum)) ) && engWord.HasOneGrammem(eSingular); if( !bCase1 && !bCase2 ) return; // если есть subj if ( GetSubj(iEngNode) != -1 ) return; // для помет pass(ADR) ищем адресата vector<long> outRels; GetOutcomingRelations(iEngNode,outRels); int iAdrRel = -1; if( HasALG(m_Nodes[iEngNode].GetType(),m_Nodes[iEngNode].GetUnitNo(),"pass(ADR)") ) { for( int i=0; i<outRels.size(); i++ ) { int iSrc = m_Nodes[m_Relations[outRels[i]].m_SourceNodeNo].m_ClauseNo; int iTrg = m_Nodes[m_Relations[outRels[i]].m_TargetNodeNo].m_ClauseNo; if( iSrc != iTrg ) continue; if( m_Relations[outRels[i]].m_Valency.m_RelationStr=="ADR" ) { iAdrRel = outRels[i]; break; } } } // ищем объект, который не subj int iObjRel = -1; for(int i=0; i<outRels.size(); i++ ) { int iSrc = m_Nodes[m_Relations[outRels[i]].m_SourceNodeNo].m_ClauseNo; int iTrg = m_Nodes[m_Relations[outRels[i]].m_TargetNodeNo].m_ClauseNo; if( iSrc != iTrg ) continue; if( IsObjPattern(m_Relations[outRels[i]]) ) { iObjRel = outRels[i]; break; } } // будующий subj int iSubRel = iAdrRel; if( iSubRel==-1 ) iSubRel = iObjRel; // если есть кого - переведем его в subj, проставим Passive и число if( iSubRel != -1 ) { m_Relations[iSubRel].m_SynReal.m_Cortege = engNode.m_Patterns[0].m_GramCorteges[0]; m_Relations[iSubRel].m_Valency = engNode.m_Vals[0]; m_Relations[iSubRel].m_Position = "<"; m_Relations[iSubRel].m_PosType = FromAlgorithmPosType; CEngSemNode& impNode = m_Nodes[m_Relations[iSubRel].m_SourceNodeNo]; CEngSemNode& objNode = m_Nodes[m_Relations[iSubRel].m_TargetNodeNo]; int iImpMainWord = impNode.m_MainWordNo; assert( iImpMainWord != -1 ); impNode.m_Words[iImpMainWord].m_bMorphologicalPassiveForm = true; int iRusObj = objNode.RusNode; if( iRusObj != -1 ) TransferNumberGrammems(RusStr.GetNode(iRusObj),impNode.m_Words[iImpMainWord]); // тот же пассив надо проставить всем "и" узлам без Subj for( int i=0; i<outRels.size(); i++ ) { int iSrc = m_Nodes[m_Relations[outRels[i]].m_SourceNodeNo].m_ClauseNo; int iTrg = m_Nodes[m_Relations[outRels[i]].m_TargetNodeNo].m_ClauseNo; if( iSrc == iTrg ) continue; if( m_Relations[outRels[i]].m_Valency.m_RelationStr != "AND" ) continue; int iNode = m_Relations[outRels[i]].m_TargetNodeNo; if( !m_Nodes[iNode].HasPOS(eVERB) ) continue; vector<long> outRels2; GetOutcomingRelations(iNode,outRels2); bool bHasSub = false; for( int j=0; j<outRels2.size(); j++ ) { if( IsSubj(m_Relations[outRels2[j]]) ) bHasSub = true; } if( bHasSub ) continue; if( m_Nodes[iNode].m_MainWordNo == -1 ) continue; m_Nodes[iNode].m_Words[m_Nodes[iNode].m_MainWordNo].m_bMorphologicalPassiveForm = true; if( iRusObj != -1 ) TransferNumberGrammems(RusStr.GetNode(iRusObj),m_Nodes[iNode].m_Words[m_Nodes[iNode].m_MainWordNo]); } return; } for( int k=0; k<inRels.size(); k++ ) { int iSrc = m_Nodes[m_Relations[inRels[k]].m_SourceNodeNo].m_ClauseNo; int iTrg = m_Nodes[m_Relations[inRels[k]].m_TargetNodeNo].m_ClauseNo; if( iSrc == iTrg ) continue; if( m_Relations[inRels[k]].m_Valency.m_RelationStr == "AND" ) return; // часть глагольной MUA } // нет объекта CEngSemNode newNode; if( bCase1 ) { CreateSimpleEnglNode("they",newNode,0,true); newNode.m_Words[0].AddFormGrammem (ePlural); } else if( !bModCX ) { CreateSimpleEnglNode("it",newNode,0,true); newNode.m_Words[0].AddFormGrammem(eSingular); } else { CreateSimpleEnglNode("one",newNode,0,true); newNode.m_Words[0].AddFormGrammem(eSingular); } newNode.m_ClauseNo = m_Nodes[iEngNode].m_ClauseNo; long wNo = m_Nodes[iEngNode].GetMinWordNo(); FreeWordNo(wNo); newNode.m_Words[0].m_WordNo = wNo; m_Nodes.push_back(newNode); CEngSemRelation newRel(CValency("ImpersonalVerb",A_C),iEngNode,m_Nodes.size()-1,""); newRel.m_bInterpreted = false; if (!engNode.m_Patterns.empty() && !engNode.m_Patterns[0].m_GramCorteges.empty()) newRel.m_SynReal.m_Cortege = engNode.m_Patterns[0].m_GramCorteges[0]; if (!engNode.m_Vals.empty()) newRel.m_Valency = engNode.m_Vals[0]; newRel.m_Position = "<"; newRel.m_PosType = FromAlgorithmPosType; m_Relations.push_back(newRel); }
int list_ticket(char **pdata, unsigned int *len) { struct ticket_config *tk; char timeout_str[64]; char pending_str[64]; char *data, *cp; int i, alloc; time_t ts; *pdata = NULL; *len = 0; alloc = booth_conf->ticket_count * (BOOTH_NAME_LEN * 2 + 128); data = malloc(alloc); if (!data) return -ENOMEM; cp = data; foreach_ticket(i, tk) { if (is_time_set(&tk->term_expires)) { ts = wall_ts(&tk->term_expires); strftime(timeout_str, sizeof(timeout_str), "%F %T", localtime(&ts)); } else strcpy(timeout_str, "INF"); if (tk->leader == local && is_time_set(&tk->delay_commit) && !is_past(&tk->delay_commit)) { ts = wall_ts(&tk->delay_commit); strcpy(pending_str, " (commit pending until "); strftime(pending_str + strlen(" (commit pending until "), sizeof(pending_str) - strlen(" (commit pending until ") - 1, "%F %T", localtime(&ts)); strcat(pending_str, ")"); } else *pending_str = '\0'; cp += snprintf(cp, alloc - (cp - data), "ticket: %s, leader: %s", tk->name, ticket_leader_string(tk)); if (is_owned(tk)) { cp += snprintf(cp, alloc - (cp - data), ", expires: %s%s\n", timeout_str, pending_str); } else { cp += snprintf(cp, alloc - (cp - data), "\n"); } if (alloc - (cp - data) <= 0) { free(data); return -ENOMEM; } } *pdata = data; *len = cp - data; return 0; }