int schedule_retry(jsonrpc_request_t* req) { if(!req) { ERR("Trying to schedule retry for a null request.\n"); return -1; } if(req->retry == 0) { return -1; } req->ntries++; if(req->retry > 0 && req->ntries > req->retry) { WARN("Number of retries exceeded. Failing request.\n"); return -1; } /* next retry in milliseconds */ unsigned int time = req->ntries * req->ntries * req->timeout; if(time > RETRY_MAX_TIME) { time = RETRY_MAX_TIME; } jsonrpc_request_t* new_req = create_request(req->cmd); new_req->ntries = req->ntries; free_request(req); const struct timeval tv = ms_to_tv(time); new_req->retry_ev = evtimer_new(global_ev_base, retry_cb, (void*)new_req); if(evtimer_add(new_req->retry_ev, &tv)<0) { ERR("event_add failed while setting request retry timer (%s).", strerror(errno)); goto error; } return 0; error: ERR("schedule_retry failed.\n"); return -1; }
static void ipv6ns_unreachable(void *arg) { struct ra *rap = arg; struct timeval tv; /* We could add an unreachable flag and persist the information, * but that is more effort than it's probably worth. */ syslog(LOG_WARNING, "%s: %s is unreachable, expiring it", rap->iface->name, rap->sfrom); rap->expired = 1; ipv6_buildroutes(); script_runreason(rap->iface, "ROUTERADVERT"); /* XXX not RA */ /* We should still test if it's reachable or not so * incase it comes back to life and it's preferable. */ if (rap->reachable) { ms_to_tv(&tv, rap->reachable); } else { tv.tv_sec = REACHABLE_TIME; tv.tv_usec = 0; } eloop_timeout_add_tv(&tv, ipv6ns_proberouter, rap); }
int jsonrpc_send(str conn, jsonrpc_request_t* req, bool notify_only) { char* json = (char*)json_dumps(req->payload, JSON_COMPACT); char* ns; size_t bytes; bytes = netstring_encode_new(&ns, json, (size_t)strlen(json)); bool sent = false; jsonrpc_server_group_t* c_grp = NULL; if(global_server_group != NULL) c_grp = *global_server_group; jsonrpc_server_group_t* p_grp = NULL; jsonrpc_server_group_t* w_grp = NULL; jsonrpc_server_t* s = NULL; server_list_t* tried_servers = NULL; DEBUG("SENDING DATA\n"); for(; c_grp != NULL; c_grp = c_grp->next) { if(strncmp(conn.s, c_grp->conn.s, c_grp->conn.len) != 0) continue; for(p_grp = c_grp->sub_group; p_grp != NULL; p_grp = p_grp->next) { w_grp = p_grp->sub_group; while(!sent) { loadbalance_by_weight(&s, w_grp, tried_servers); if (s == NULL || s->status != JSONRPC_SERVER_CONNECTED) { break; } if(bufferevent_write(s->bev, ns, bytes) == 0) { sent = true; if(!notify_only) { s->req_count++; if (s->hwm > 0 && s->req_count >= s->hwm) { WARN("%.*s:%d in connection group %.*s has exceeded its high water mark (%d)\n", STR(s->addr), s->port, STR(s->conn), s->hwm); } } req->server = s; break; } else { addto_server_list(s, &tried_servers); } } if (sent) { break; } WARN("Failed to send to priority group, %d\n", p_grp->priority); if(p_grp->next != NULL) { INFO("Proceeding to next priority group, %d\n", p_grp->next->priority); } } if (sent) { break; } } if(!sent) { WARN("Failed to send to connection group, \"%.*s\"\n", STR(conn)); if(schedule_retry(req)<0) { fail_request(JRPC_ERR_RETRY, req, "Failed to schedule retry"); } } free_server_list(tried_servers); if(ns) pkg_free(ns); if(json) free(json); if (sent && notify_only == false) { const struct timeval tv = ms_to_tv(req->timeout); req->timeout_ev = evtimer_new(global_ev_base, timeout_cb, (void*)req); if(event_add(req->timeout_ev, &tv)<0) { ERR("event_add failed while setting request timer (%s).", strerror(errno)); return -1; } } return sent; }