From 8d6b499fa0356c420d60d13e0a83b8dddf39378c Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzeleny@redhat.com>
Date: Fri, 29 Apr 2011 09:45:10 -0400
Subject: [PATCH] Fixed lastUSN checking improvements

This patch fixes some issues with setting lastUSN attribute and it adds
check against the highest user/group USN after enumeration to keep
better track of the real highest USN. Optimal solution here would be to
schedule a check of rootDSE entry right after the enumeration finishes,
but for the moment this is good enough.
---
 src/providers/ldap/ldap_id.c      |    9 ++++++---
 src/providers/ldap/ldap_id_enum.c |   15 +++++++++++++++
 src/providers/ldap/sdap_id_op.c   |    4 ++--
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index de6183335bb47eb7508b8e4f18ea055caec7822d..a3c9c0cd451cb7290cefcd5f18d6c17c2e71319e 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -726,9 +726,12 @@ static void sdap_check_online_done(struct tevent_req *req)
     } else {
         dp_err = DP_ERR_OK;
 
-        if (strcmp(srv_opts->server_id, ctx->srv_opts->server_id) == 0 &&
-            srv_opts->supports_usn &&
-            ctx->srv_opts->last_usn > srv_opts->last_usn) {
+        if (!ctx->srv_opts) {
+            srv_opts->max_user_value = 0;
+            srv_opts->max_group_value = 0;
+        } else if (strcmp(srv_opts->server_id, ctx->srv_opts->server_id) == 0
+                   && srv_opts->supports_usn
+                   && ctx->srv_opts->last_usn > srv_opts->last_usn) {
             ctx->srv_opts->max_user_value = 0;
             ctx->srv_opts->max_group_value = 0;
             ctx->srv_opts->last_usn = srv_opts->last_usn;
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c
index d7dd33e43fb8c1498d09641451dda8c2f79faac1..68d113bf96a6db226c8a9541f5dbbd543ef043ae 100644
--- a/src/providers/ldap/ldap_id_enum.c
+++ b/src/providers/ldap/ldap_id_enum.c
@@ -511,6 +511,8 @@ static void enum_users_op_done(struct tevent_req *subreq)
     struct enum_users_state *state = tevent_req_data(req,
                                                      struct enum_users_state);
     char *usn_value;
+    char *endptr = NULL;
+    unsigned usn_number;
     int ret;
 
     ret = sdap_get_users_recv(subreq, state, &usn_value);
@@ -523,6 +525,12 @@ static void enum_users_op_done(struct tevent_req *subreq)
     if (usn_value) {
         talloc_zfree(state->ctx->srv_opts->max_user_value);
         state->ctx->srv_opts->max_user_value = talloc_steal(state->ctx, usn_value);
+
+        usn_number = strtoul(usn_value, &endptr, 10);
+        if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value))
+            && (usn_number > state->ctx->srv_opts->last_usn)) {
+            state->ctx->srv_opts->last_usn = usn_number;
+        }
     }
 
     DEBUG(4, ("Users higher USN value: [%s]\n",
@@ -629,6 +637,8 @@ static void enum_groups_op_done(struct tevent_req *subreq)
     struct enum_groups_state *state = tevent_req_data(req,
                                                  struct enum_groups_state);
     char *usn_value;
+    char *endptr = NULL;
+    unsigned usn_number;
     int ret;
 
     ret = sdap_get_groups_recv(subreq, state, &usn_value);
@@ -642,6 +652,11 @@ static void enum_groups_op_done(struct tevent_req *subreq)
         talloc_zfree(state->ctx->srv_opts->max_group_value);
         state->ctx->srv_opts->max_group_value =
                                         talloc_steal(state->ctx, usn_value);
+        usn_number = strtoul(usn_value, &endptr, 10);
+        if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value))
+            && (usn_number > state->ctx->srv_opts->last_usn)) {
+            state->ctx->srv_opts->last_usn = usn_number;
+        }
     }
 
     DEBUG(4, ("Groups higher USN value: [%s]\n",
diff --git a/src/providers/ldap/sdap_id_op.c b/src/providers/ldap/sdap_id_op.c
index 1f692a158e9f043ff905ad1a613cfa4a0eb95171..11a379cc96a77615bd62b1fe58daa2413f38087a 100644
--- a/src/providers/ldap/sdap_id_op.c
+++ b/src/providers/ldap/sdap_id_op.c
@@ -537,9 +537,9 @@ static void sdap_id_op_connect_done(struct tevent_req *subreq)
                 current_srv_opts->last_usn > srv_opts->last_usn) {
                 DEBUG(5, ("Server was probably re-initialized\n"));
 
-                current_srv_opts->max_user_value= 0;
+                current_srv_opts->max_user_value = 0;
                 current_srv_opts->max_group_value = 0;
-                current_srv_opts->last_usn = 0;
+                current_srv_opts->last_usn = srv_opts->last_usn;
             }
         }
         ret = sdap_id_conn_data_set_expire_timer(conn_data);
-- 
1.7.4.1

