This one is on top of the don't reset errors diff. This diff includes a minor bump. Don't know if we're still to close after unlock.
If certain components (session, agentcaps, region, index, object) are in a closed state while they are expected to be open, there is no way to retry them without destroying the entire structure and rebuilding it from scratch. This diff adds agentx_retry, which walks the tree and retries all in state AX_CSTATE_CLOSE. This function could be triggered by the admin, e.g. on a daemon reload. OK? If so, now? martijn@ diff --git a/Symbols.list b/Symbols.list index 6eda2be..a5c8bf7 100644 --- a/Symbols.list +++ b/Symbols.list @@ -4,6 +4,7 @@ agentx_log_info agentx_log_debug agentx agentx_connect +agentx_retry agentx_read agentx_write agentx_wantwrite diff --git a/agentx.3 b/agentx.3 index d45a3ae..81322c6 100644 --- a/agentx.3 +++ b/agentx.3 @@ -24,6 +24,7 @@ .Nm agentx_log_debug , .Nm agentx , .Nm agentx_connect , +.Nm agentx_retry , .Nm agentx_read , .Nm agentx_write , .Nm agentx_wantwrite , @@ -95,6 +96,8 @@ .Ft void .Fn agentx_connect "struct agentx *sa" "int fd" .Ft void +.Fn agentx_retry "struct agentx *sa" +.Ft void .Fn agentx_read "struct agentx *sa" .Ft void .Fn agentx_write "struct agentx *sa" @@ -367,6 +370,12 @@ is ready for a write, the function .Fn agentx_write should be called. .Pp +If any of the session, agentcaps, region, index, or objects failed to enable +correctly +.Pq as can be seen by the admin through the logs +they can be retried through +.Fn agentx_retry. +.Pp .Fa sa can be freed via .Fn agentx_free . diff --git a/agentx.c b/agentx.c index 8df1032..5f4f382 100644 --- a/agentx.c +++ b/agentx.c @@ -133,6 +133,7 @@ void (*agentx_wantwrite)(struct agentx *, int) = agentx_wantwritenow; static void agentx_reset(struct agentx *); static void agentx_free_finalize(struct agentx *); +static int agentx_session_retry(struct agentx_session *); static int agentx_session_start(struct agentx_session *); static int agentx_session_finalize(struct ax_pdu *, void *); static int agentx_session_close(struct agentx_session *, @@ -140,6 +141,7 @@ static int agentx_session_close(struct agentx_session *, static int agentx_session_close_finalize(struct ax_pdu *, void *); static void agentx_session_free_finalize(struct agentx_session *); static void agentx_session_reset(struct agentx_session *); +static int agentx_context_retry(struct agentx_context *); static void agentx_context_start(struct agentx_context *); static void agentx_context_free_finalize(struct agentx_context *); static void agentx_context_reset(struct agentx_context *); @@ -149,6 +151,7 @@ static int agentx_agentcaps_close(struct agentx_agentcaps *); static int agentx_agentcaps_close_finalize(struct ax_pdu *, void *); static void agentx_agentcaps_free_finalize(struct agentx_agentcaps *); static void agentx_agentcaps_reset(struct agentx_agentcaps *); +static int agentx_region_retry(struct agentx_region *); static int agentx_region_start(struct agentx_region *); static int agentx_region_finalize(struct ax_pdu *, void *); static int agentx_region_close(struct agentx_region *); @@ -229,6 +232,25 @@ agentx_connect(struct agentx *ax, int fd) agentx_finalize(ax, fd); } +void +agentx_retry(struct agentx *ax) +{ + struct agentx_session *axs; + + if (ax->ax_fd == -1) + return; + + TAILQ_FOREACH(axs, &(ax->ax_sessions), axs_ax_sessions) { + if (axs->axs_cstate == AX_CSTATE_OPEN) { + if (agentx_session_retry(axs) == -1) + return; + } else if (axs->axs_cstate == AX_CSTATE_CLOSE) { + if (agentx_session_start(axs) == -1) + return; + } + } +} + static void agentx_start(struct agentx *ax) { @@ -401,6 +423,26 @@ agentx_session(struct agentx *ax, uint32_t oid[], return axs; } +static int +agentx_session_retry(struct agentx_session *axs) +{ + struct agentx_context *axc; + +#ifdef AX_DEBUG + if (axs->axs_cstate != AX_CSTATE_OPEN) + agentx_log_axs_fatalx(axs, "%s: unexpected retry", __func__); +#endif + + TAILQ_FOREACH(axc, &(axs->axs_contexts), axc_axs_contexts) { + if (axc->axc_cstate == AX_CSTATE_OPEN) { + if (agentx_context_retry(axc) == -1) + return -1; + } else if (axc->axc_cstate == AX_CSTATE_CLOSE) + agentx_context_start(axc); + } + return 0; +} + static int agentx_session_start(struct agentx_session *axs) { @@ -628,6 +670,36 @@ agentx_context(struct agentx_session *axs, const char *name) return axc; } +static int +agentx_context_retry(struct agentx_context *axc) +{ + struct agentx_agentcaps *axa; + struct agentx_region *axr; + +#ifdef AX_DEBUG + if (axc->axc_cstate != AX_CSTATE_OPEN) + agentx_log_axc_fatalx(axc, "%s: unexpected retry", __func__); +#endif + + TAILQ_FOREACH(axa, &(axc->axc_agentcaps), axa_axc_agentcaps) { + if (axa->axa_cstate == AX_CSTATE_CLOSE) { + if (agentx_agentcaps_start(axa) == -1) + return -1; + } + } + TAILQ_FOREACH(axr, &(axc->axc_regions), axr_axc_regions) { + if (axr->axr_cstate == AX_CSTATE_OPEN) { + if (agentx_region_retry(axr) == -1) + return -1; + } else if (axr->axr_cstate == AX_CSTATE_CLOSE) { + if (agentx_region_start(axr) == -1) + return -1; + } + } + return 0; +} + + static void agentx_context_start(struct agentx_context *axc) { @@ -1076,6 +1148,33 @@ agentx_region(struct agentx_context *axc, uint32_t oid[], return axr; } +static int +agentx_region_retry(struct agentx_region *axr) +{ + struct agentx_index *axi; + struct agentx_object *axo; + +#ifdef AX_DEBUG + if (axr->axr_cstate != AX_CSTATE_OPEN) + agentx_log_axc_fatalx(axr->axr_axc, + "%s: unexpected retry", __func__); +#endif + + TAILQ_FOREACH(axi, &(axr->axr_indices), axi_axr_indices) { + if (axi->axi_cstate == AX_CSTATE_CLOSE) { + if (agentx_index_start(axi) == -1) + return -1; + } + } + TAILQ_FOREACH(axo, &(axr->axr_objects), axo_axr_objects) { + if (axo->axo_cstate == AX_CSTATE_CLOSE) { + if (agentx_object_start(axo) == -1) + return -1; + } + } + return 0; +} + static int agentx_region_start(struct agentx_region *axr) { diff --git a/agentx.h b/agentx.h index 8f338d4..ac73c31 100644 --- a/agentx.h +++ b/agentx.h @@ -55,6 +55,7 @@ extern void (*agentx_log_debug)(const char *, ...) struct agentx *agentx(void (*)(struct agentx *, void *, int), void *); void agentx_connect(struct agentx *, int); +void agentx_retry(struct agentx *); void agentx_read(struct agentx *); void agentx_write(struct agentx *); extern void (*agentx_wantwrite)(struct agentx *, int); diff --git a/shlib_version b/shlib_version index 1edea46..893819d 100644 --- a/shlib_version +++ b/shlib_version @@ -1,2 +1,2 @@ major=1 -minor=0 +minor=1