📄 repl_meta_data.c
字号:
/* fix meta data count */ nmd.ctr.ctr1.count = ni; /* * sort meta data array, and move the rdn attribute entry to the end */ replmd_replPropertyMetaDataCtr1_sort(&nmd.ctr.ctr1, &rdn_attr->attributeID_id); /* generated NDR encoded values */ ndr_err = ndr_push_struct_blob(&guid_value, msg, NULL, &guid, (ndr_push_flags_fn_t)ndr_push_GUID); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ldb_oom(module->ldb); return LDB_ERR_OPERATIONS_ERROR; } ndr_err = ndr_push_struct_blob(&nmd_value, msg, lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")), &nmd, (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(down_req); ldb_oom(module->ldb); return LDB_ERR_OPERATIONS_ERROR; } /* * add the autogenerated values */ ret = ldb_msg_add_value(msg, "objectGUID", &guid_value, NULL); if (ret != LDB_SUCCESS) { talloc_free(down_req); ldb_oom(module->ldb); return LDB_ERR_OPERATIONS_ERROR; } ret = ldb_msg_add_string(msg, "whenChanged", time_str); if (ret != LDB_SUCCESS) { talloc_free(down_req); ldb_oom(module->ldb); return LDB_ERR_OPERATIONS_ERROR; } ret = samdb_msg_add_uint64(module->ldb, msg, msg, "uSNCreated", seq_num); if (ret != LDB_SUCCESS) { talloc_free(down_req); ldb_oom(module->ldb); return LDB_ERR_OPERATIONS_ERROR; } ret = samdb_msg_add_uint64(module->ldb, msg, msg, "uSNChanged", seq_num); if (ret != LDB_SUCCESS) { talloc_free(down_req); ldb_oom(module->ldb); return LDB_ERR_OPERATIONS_ERROR; } ret = ldb_msg_add_value(msg, "replPropertyMetaData", &nmd_value, NULL); if (ret != LDB_SUCCESS) { talloc_free(down_req); ldb_oom(module->ldb); return LDB_ERR_OPERATIONS_ERROR; } /* * sort the attributes by attid before storing the object */ replmd_ldb_message_sort(msg, schema); ldb_set_timeout_from_prev_req(module->ldb, req, down_req); /* go on with the call chain */ ret = ldb_next_request(module, down_req); /* do not free down_req as the call results may be linked to it, * it will be freed when the upper level request get freed */ if (ret == LDB_SUCCESS) { req->handle = down_req->handle; } return ret;}static int replmd_add(struct ldb_module *module, struct ldb_request *req){ return replmd_prepare_originating(module, req, req->op.add.message->dn, "replmd_add", replmd_add_originating);}static int replmd_modify_originating(struct ldb_module *module, struct ldb_request *req, const struct dsdb_schema *schema){ struct ldb_request *down_req; struct ldb_message *msg; int ret; time_t t = time(NULL); uint64_t seq_num; ldb_debug(module->ldb, LDB_DEBUG_TRACE, "replmd_modify_originating\n"); down_req = talloc(req, struct ldb_request); if (down_req == NULL) { return LDB_ERR_OPERATIONS_ERROR; } *down_req = *req; /* we have to copy the message as the caller might have it as a const */ down_req->op.mod.message = msg = ldb_msg_copy_shallow(down_req, req->op.mod.message); if (msg == NULL) { talloc_free(down_req); return LDB_ERR_OPERATIONS_ERROR; } /* TODO: * - get the whole old object * - if the old object doesn't exist report an error * - give an error when a readonly attribute should * be modified * - merge the changed into the old object * if the caller set values to the same value * ignore the attribute, return success when no * attribute was changed * - calculate the new replPropertyMetaData attribute */ if (add_time_element(msg, "whenChanged", t) != 0) { talloc_free(down_req); return LDB_ERR_OPERATIONS_ERROR; } /* Get a sequence number from the backend */ ret = ldb_sequence_number(module->ldb, LDB_SEQ_NEXT, &seq_num); if (ret == LDB_SUCCESS) { if (add_uint64_element(msg, "uSNChanged", seq_num) != 0) { talloc_free(down_req); return LDB_ERR_OPERATIONS_ERROR; } } /* TODO: * - sort the attributes by attid with replmd_ldb_message_sort() * - replace the old object with the newly constructed one */ ldb_set_timeout_from_prev_req(module->ldb, req, down_req); /* go on with the call chain */ ret = ldb_next_request(module, down_req); /* do not free down_req as the call results may be linked to it, * it will be freed when the upper level request get freed */ if (ret == LDB_SUCCESS) { req->handle = down_req->handle; } return ret;}static int replmd_modify(struct ldb_module *module, struct ldb_request *req){ return replmd_prepare_originating(module, req, req->op.mod.message->dn, "replmd_modify", replmd_modify_originating);}static int replmd_replicated_request_reply_helper(struct replmd_replicated_request *ar, int ret){ struct ldb_reply *ares = NULL; ar->handle->status = ret; ar->handle->state = LDB_ASYNC_DONE; if (!ar->orig_req->callback) { return LDB_SUCCESS; } /* we're done and need to report the success to the caller */ ares = talloc_zero(ar, struct ldb_reply); if (!ares) { ar->handle->status = LDB_ERR_OPERATIONS_ERROR; ar->handle->state = LDB_ASYNC_DONE; return LDB_ERR_OPERATIONS_ERROR; } ares->type = LDB_REPLY_EXTENDED; ares->response = NULL; return ar->orig_req->callback(ar->module->ldb, ar->orig_req->context, ares);}static int replmd_replicated_request_done(struct replmd_replicated_request *ar){ return replmd_replicated_request_reply_helper(ar, LDB_SUCCESS);}static int replmd_replicated_request_error(struct replmd_replicated_request *ar, int ret){ return replmd_replicated_request_reply_helper(ar, ret);}static int replmd_replicated_request_werror(struct replmd_replicated_request *ar, WERROR status){ int ret = LDB_ERR_OTHER; /* TODO: do some error mapping */ return replmd_replicated_request_reply_helper(ar, ret);}static int replmd_replicated_apply_next(struct replmd_replicated_request *ar);static int replmd_replicated_apply_add_callback(struct ldb_context *ldb, void *private_data, struct ldb_reply *ares){#ifdef REPLMD_FULL_ASYNC /* TODO: activate this code when ldb support full async code */ struct replmd_replicated_request *ar = talloc_get_type(private_data, struct replmd_replicated_request); ar->sub.change_ret = ldb_wait(ar->sub.search_req->handle, LDB_WAIT_ALL); if (ar->sub.change_ret != LDB_SUCCESS) { return replmd_replicated_request_error(ar, ar->sub.change_ret); } talloc_free(ar->sub.mem_ctx); ZERO_STRUCT(ar->sub); ar->index_current++; return replmd_replicated_apply_next(ar);#else return LDB_SUCCESS;#endif}static int replmd_replicated_apply_add(struct replmd_replicated_request *ar){ enum ndr_err_code ndr_err; struct ldb_message *msg; struct replPropertyMetaDataBlob *md; struct ldb_val md_value; uint32_t i; uint64_t seq_num; int ret; /* * TODO: check if the parent object exist */ /* * TODO: handle the conflict case where an object with the * same name exist */ msg = ar->objs->objects[ar->index_current].msg; md = ar->objs->objects[ar->index_current].meta_data; ret = ldb_sequence_number(ar->module->ldb, LDB_SEQ_NEXT, &seq_num); if (ret != LDB_SUCCESS) { return replmd_replicated_request_error(ar, ret); } ret = ldb_msg_add_value(msg, "objectGUID", &ar->objs->objects[ar->index_current].guid_value, NULL); if (ret != LDB_SUCCESS) { return replmd_replicated_request_error(ar, ret); } ret = ldb_msg_add_string(msg, "whenChanged", ar->objs->objects[ar->index_current].when_changed); if (ret != LDB_SUCCESS) { return replmd_replicated_request_error(ar, ret); } ret = samdb_msg_add_uint64(ar->module->ldb, msg, msg, "uSNCreated", seq_num); if (ret != LDB_SUCCESS) { return replmd_replicated_request_error(ar, ret); } ret = samdb_msg_add_uint64(ar->module->ldb, msg, msg, "uSNChanged", seq_num); if (ret != LDB_SUCCESS) { return replmd_replicated_request_error(ar, ret); } /* * the meta data array is already sorted by the caller */ for (i=0; i < md->ctr.ctr1.count; i++) { md->ctr.ctr1.array[i].local_usn = seq_num; } ndr_err = ndr_push_struct_blob(&md_value, msg, lp_iconv_convenience(ldb_get_opaque(ar->module->ldb, "loadparm")), md, (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status)); } ret = ldb_msg_add_value(msg, "replPropertyMetaData", &md_value, NULL); if (ret != LDB_SUCCESS) { return replmd_replicated_request_error(ar, ret); } replmd_ldb_message_sort(msg, ar->schema); ret = ldb_build_add_req(&ar->sub.change_req, ar->module->ldb, ar->sub.mem_ctx, msg, NULL, ar, replmd_replicated_apply_add_callback); if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);#ifdef REPLMD_FULL_ASYNC /* TODO: activate this code when ldb support full async code */ return ldb_next_request(ar->module, ar->sub.change_req);#else ret = ldb_next_request(ar->module, ar->sub.change_req); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ar->module->ldb, "Failed to add replicated object %s: %s", ldb_dn_get_linearized(ar->sub.change_req->op.add.message->dn), ldb_errstring(ar->module->ldb)); return replmd_replicated_request_error(ar, ret); } ar->sub.change_ret = ldb_wait(ar->sub.change_req->handle, LDB_WAIT_ALL); if (ar->sub.change_ret != LDB_SUCCESS) { ldb_asprintf_errstring(ar->module->ldb, "Failed while waiting on add replicated object %s: %s", ldb_dn_get_linearized(ar->sub.change_req->op.add.message->dn), ldb_errstring(ar->module->ldb)); return replmd_replicated_request_error(ar, ar->sub.change_ret); } talloc_free(ar->sub.mem_ctx); ZERO_STRUCT(ar->sub); ar->index_current++; return LDB_SUCCESS;#endif}static int replmd_replPropertyMetaData1_conflict_compare(struct replPropertyMetaData1 *m1, struct replPropertyMetaData1 *m2){ int ret; if (m1->version != m2->version) { return m1->version - m2->version; } if (m1->originating_change_time != m2->originating_change_time) { return m1->originating_change_time - m2->originating_change_time; } ret = GUID_compare(&m1->originating_invocation_id, &m2->originating_invocation_id); if (ret != 0) { return ret; } return m1->originating_usn - m2->originating_usn;}static int replmd_replicated_apply_merge_callback(struct ldb_context *ldb, void *private_data, struct ldb_reply *ares){#ifdef REPLMD_FULL_ASYNC /* TODO: activate this code when ldb support full async code */ struct replmd_replicated_request *ar = talloc_get_type(private_data, struct replmd_replicated_request); ret = ldb_next_request(ar->module, ar->sub.change_req); if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret); ar->sub.change_ret = ldb_wait(ar->sub.search_req->handle, LDB_WAIT_ALL); if (ar->sub.change_ret != LDB_SUCCESS) { return replmd_replicated_request_error(ar, ar->sub.change_ret); } talloc_free(ar->sub.mem_ctx); ZERO_STRUCT(ar->sub); ar->index_current++; return LDB_SUCCESS;#else return LDB_SUCCESS;#endif}static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar){ enum ndr_err_code ndr_err; struct ldb_message *msg; struct replPropertyMetaDataBlob *rmd; struct replPropertyMetaDataBlob omd; const struct ldb_val *omd_value; struct replPropertyMetaDataBlob nmd; struct ldb_val nmd_value; uint32_t i,j,ni=0; uint32_t removed_attrs = 0; uint64_t seq_num; int ret; msg = ar->objs->objects[ar->index_current].msg;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -