Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
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;
}