X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Freconnect.c;h=2ae65c6809958b630eac1a9d082fcd135fef6df8;hb=557092898d7ac9d7451d565720c56fba811494e8;hp=fadeeb89b20a834522093786698cc45ef5d6a65c;hpb=3ed497fc10033c9857140270d60ef6aa2d7c0c08;p=openvswitch diff --git a/lib/reconnect.c b/lib/reconnect.c index fadeeb89..2ae65c68 100644 --- a/lib/reconnect.c +++ b/lib/reconnect.c @@ -57,6 +57,7 @@ struct reconnect { int backoff; long long int last_received; long long int last_connected; + unsigned int max_tries; /* These values are simply for statistics reporting, not otherwise used * directly by anything internal. */ @@ -69,6 +70,7 @@ struct reconnect { static void reconnect_transition__(struct reconnect *, long long int now, enum state state); static long long int reconnect_deadline__(const struct reconnect *); +static bool reconnect_may_retry(struct reconnect *); static const char * reconnect_state_name__(enum state state) @@ -99,6 +101,7 @@ reconnect_create(long long int now) fsm->backoff = 0; fsm->last_received = now; fsm->last_connected = now; + fsm->max_tries = UINT_MAX; fsm->creation_time = now; return fsm; @@ -160,6 +163,26 @@ reconnect_get_probe_interval(const struct reconnect *fsm) return fsm->probe_interval; } +/* Limits the maximum number of times that 'fsm' will ask the client to try to + * reconnect to 'max_tries'. UINT_MAX (the default) means an unlimited number + * of tries. + * + * After the number of tries has expired, the 'fsm' will disable itself + * instead of backing off and retrying. */ +void +reconnect_set_max_tries(struct reconnect *fsm, unsigned int max_tries) +{ + fsm->max_tries = max_tries; +} + +/* Returns the current remaining number of connection attempts, UINT_MAX if + * the number is unlimited. */ +unsigned int +reconnect_get_max_tries(struct reconnect *fsm) +{ + return fsm->max_tries; +} + /* Configures the backoff parameters for 'fsm'. 'min_backoff' is the minimum * number of milliseconds, and 'max_backoff' is the maximum, between connection * attempts. @@ -213,7 +236,7 @@ reconnect_is_enabled(const struct reconnect *fsm) void reconnect_enable(struct reconnect *fsm, long long int now) { - if (fsm->state == S_VOID) { + if (fsm->state == S_VOID && reconnect_may_retry(fsm)) { reconnect_transition__(fsm, now, S_BACKOFF); fsm->backoff = 0; } @@ -250,7 +273,7 @@ reconnect_force_reconnect(struct reconnect *fsm, long long int now) void reconnect_disconnected(struct reconnect *fsm, long long int now, int error) { - if (fsm->state != S_BACKOFF) { + if (!(fsm->state & (S_BACKOFF | S_VOID))) { /* Report what happened. */ if (fsm->state & (S_ACTIVE | S_IDLE)) { if (error > 0) { @@ -285,7 +308,9 @@ reconnect_disconnected(struct reconnect *fsm, long long int now, int error) VLOG_INFO("%s: waiting %.3g seconds before reconnect\n", fsm->name, fsm->backoff / 1000.0); } - reconnect_transition__(fsm, now, S_BACKOFF); + + reconnect_transition__(fsm, now, + reconnect_may_retry(fsm) ? S_BACKOFF : S_VOID); } } @@ -521,3 +546,13 @@ reconnect_get_stats(const struct reconnect *fsm, long long int now, stats->state = reconnect_state_name__(fsm->state); stats->state_elapsed = now - fsm->state_entered; } + +static bool +reconnect_may_retry(struct reconnect *fsm) +{ + bool may_retry = fsm->max_tries > 0; + if (may_retry && fsm->max_tries != UINT_MAX) { + fsm->max_tries--; + } + return may_retry; +}