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

Reply via email to