updaterefs: Do not open transaction even when unnecessary
authorGarming Sam <garming@catalyst.net.nz>
Wed, 29 Mar 2017 02:21:04 +0000 (15:21 +1300)
committerGarming Sam <garming@samba.org>
Thu, 13 Apr 2017 09:25:06 +0000 (11:25 +0200)
This can be called during GetNCChanges (a generally read-only call), it
is not wise to be blocking the database for no reason.

Signed-off-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Garming Sam <garming@samba.org>
Autobuild-Date(master): Thu Apr 13 11:25:06 CEST 2017 on sn-devel-144

source4/rpc_server/drsuapi/updaterefs.c

index 457f393fd9d751ae58b0caa764c902e4beea3e16..9cf3556f49729ebd6cba945776d2ed5887d8ef2b 100644 (file)
@@ -35,6 +35,43 @@ struct repsTo {
        struct repsFromToBlob *r;
 };
 
+static WERROR uref_check_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
+                             struct ldb_dn *dn, struct GUID *dest_guid,
+                             uint32_t options)
+{
+       struct repsTo reps;
+       WERROR werr;
+       unsigned int i;
+       bool found = false;
+
+       werr = dsdb_loadreps(sam_ctx, mem_ctx, dn, "repsTo", &reps.r, &reps.count);
+       if (!W_ERROR_IS_OK(werr)) {
+               return werr;
+       }
+
+       for (i=0; i<reps.count; i++) {
+               if (GUID_equal(dest_guid,
+                              &reps.r[i].ctr.ctr1.source_dsa_obj_guid)) {
+                       found = true;
+                       break;
+               }
+       }
+
+       if (options & DRSUAPI_DRS_ADD_REF) {
+               if (found && !(options & DRSUAPI_DRS_DEL_REF)) {
+                       return WERR_DS_DRA_REF_ALREADY_EXISTS;
+               }
+       }
+
+       if (options & DRSUAPI_DRS_DEL_REF) {
+               if (!found && !(options & DRSUAPI_DRS_ADD_REF)) {
+                       return WERR_DS_DRA_REF_NOT_FOUND;
+               }
+       }
+
+       return WERR_OK;
+}
+
 /*
   add a replication destination for a given partition GUID
  */
@@ -197,6 +234,22 @@ WERROR drsuapi_UpdateRefs(struct imessaging_context *msg_ctx,
                return WERR_DS_DRA_BAD_NC;
        }
 
+       /*
+        * First check without a transaction open.
+        *
+        * This means that in the usual case, it will never open it and never
+        * bother to refresh the dreplsrv.
+        */
+       werr = uref_check_dest(sam_ctx, mem_ctx, dn, &req->dest_dsa_guid,
+                              req->options);
+       if (W_ERROR_EQUAL(werr, WERR_DS_DRA_REF_ALREADY_EXISTS) ||
+           W_ERROR_EQUAL(werr, WERR_DS_DRA_REF_NOT_FOUND)) {
+               if (req->options & DRSUAPI_DRS_GETCHG_CHECK) {
+                       return WERR_OK;
+               }
+               return werr;
+       }
+
        if (ldb_transaction_start(sam_ctx) != LDB_SUCCESS) {
                DEBUG(0,(__location__ ": Failed to start transaction on samdb: %s\n",
                         ldb_errstring(sam_ctx)));