| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- /** BEGIN COPYRIGHT BLOCK
- * Copyright (C) 2013 Red Hat, Inc.
- * All rights reserved.
- *
- * License: GPL (version 3 or any later version).
- * See LICENSE for details.
- * END COPYRIGHT BLOCK **/
- #include "sync.h"
- static Slapi_PluginDesc pdesc = {PLUGIN_NAME, VENDOR, DS_PACKAGE_VERSION, "Context Synchronization (RFC4533) plugin"};
- static int sync_start(Slapi_PBlock *pb);
- static int sync_close(Slapi_PBlock *pb);
- static int sync_preop_init(Slapi_PBlock *pb);
- static int sync_postop_init(Slapi_PBlock *pb);
- static int sync_be_postop_init(Slapi_PBlock *pb);
- static int sync_betxn_preop_init(Slapi_PBlock *pb);
- static int sync_persist_register_operation_extension(void);
- static PRUintn thread_primary_op;
- /*
- * Destructor for the per-thread primary operation list HEAD node.
- * Called by NSPR when a thread exits, to free the HEAD node
- * and any remaining linked list entries.
- */
- static void
- sync_thread_primary_op_destructor(void *priv)
- {
- OPERATION_PL_CTX_T *head = (OPERATION_PL_CTX_T *)priv;
- if (head) {
- OPERATION_PL_CTX_T *curr_op = head->next;
- while (curr_op) {
- OPERATION_PL_CTX_T *next = curr_op->next;
- slapi_entry_free(curr_op->entry);
- slapi_entry_free(curr_op->eprev);
- slapi_ch_free((void **)&curr_op);
- curr_op = next;
- }
- slapi_ch_free((void **)&head);
- }
- }
- int
- sync_init(Slapi_PBlock *pb)
- {
- char *plugin_identity = NULL;
- int rc = 0;
- slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM,
- "--> sync_init\n");
- /**
- * Store the plugin identity for later use.
- * Used for internal operations
- */
- slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_identity);
- PR_ASSERT(plugin_identity);
- if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
- (void *)sync_start) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
- (void *)sync_close) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *)&pdesc) != 0 ||
- sync_persist_register_operation_extension()) {
- slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
- "sync_init - Failed to register plugin\n");
- rc = 1;
- }
- if (rc == 0) {
- char *plugin_type = "preoperation";
- /* the config change checking post op */
- if (slapi_register_plugin(
- plugin_type,
- 1, /* Enabled */
- "sync_init", /* this function desc */
- sync_preop_init, /* init func for post op */
- SYNC_PREOP_DESC, /* plugin desc */
- NULL,
- plugin_identity)) {
- slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
- "sync_init - Failed to register preop plugin\n");
- rc = 1;
- }
- }
- if (rc == 0) {
- char *plugin_type = "postoperation";
- /* the config change checking post op */
- if (slapi_register_plugin(plugin_type,
- 1, /* Enabled */
- "sync_init", /* this function desc */
- sync_postop_init, /* init func for post op */
- SYNC_POSTOP_DESC, /* plugin desc */
- NULL,
- plugin_identity)) {
- slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
- "sync_init - Failed to register postop plugin\n");
- rc = 1;
- }
- }
- if (rc == 0) {
- char *plugin_type = "betxnpreoperation";
- /* the config change checking post op */
- if (slapi_register_plugin(plugin_type,
- 1, /* Enabled */
- "sync_init", /* this function desc */
- sync_betxn_preop_init, /* init func for post op */
- SYNC_BETXN_PREOP_DESC, /* plugin desc */
- NULL,
- plugin_identity)) {
- slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
- "sync_init - Failed to register be_txn_pre_op plugin\n");
- rc = 1;
- }
- }
- if (rc == 0) {
- char *plugin_type = "bepostoperation";
- /* the config change checking post op */
- if (slapi_register_plugin(plugin_type,
- 1, /* Enabled */
- "sync_init", /* this function desc */
- sync_be_postop_init, /* init func for be_post op */
- SYNC_BE_POSTOP_DESC, /* plugin desc */
- NULL,
- plugin_identity)) {
- slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
- "sync_init - Failed to register be_txn_pre_op plugin\n");
- rc = 1;
- }
- }
- return (rc);
- }
- static int
- sync_preop_init(Slapi_PBlock *pb)
- {
- int rc;
- rc = slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_SEARCH_FN, (void *)sync_srch_refresh_pre_search);
- rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ENTRY_FN, (void *)sync_srch_refresh_pre_entry);
- rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_RESULT_FN, (void *)sync_srch_refresh_pre_result);
- rc |= sync_register_operation_extension();
- return (rc);
- }
- static int
- sync_postop_init(Slapi_PBlock *pb)
- {
- int rc;
- rc = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_SEARCH_FN, (void *)sync_srch_refresh_post_search);
- return (rc);
- }
- static int
- sync_be_postop_init(Slapi_PBlock *pb)
- {
- int rc;
- rc = slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_ADD_FN, (void *)sync_add_persist_post_op);
- rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_DELETE_FN, (void *)sync_del_persist_post_op);
- rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODIFY_FN, (void *)sync_mod_persist_post_op);
- rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODRDN_FN, (void *)sync_modrdn_persist_post_op);
- return (rc);
- }
- static int
- sync_betxn_preop_init(Slapi_PBlock *pb)
- {
- int rc;
- rc = slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN, (void *)sync_update_persist_betxn_pre_op);
- rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN, (void *)sync_update_persist_betxn_pre_op);
- rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN, (void *)sync_update_persist_betxn_pre_op);
- rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN, (void *)sync_update_persist_betxn_pre_op);
- return (rc);
- }
- /*
- sync_start
- --------------
- Register the Content Synchronization Control.
- Initialize locks and queues for the persitent phase.
- */
- static int
- sync_start(Slapi_PBlock *pb)
- {
- int argc;
- char **argv;
- Slapi_Entry *e = NULL;
- PRBool allow_openldap_compat = PR_FALSE;
- slapi_register_supported_control(LDAP_CONTROL_SYNC,
- SLAPI_OPERATION_SEARCH);
- slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM,
- "--> sync_start\n");
- if (slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e) != 0) {
- slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, " sync_start, no config found, that's okay 👍\n");
- }
- if (e) {
- /* Do we allow openldap sync? */
- Slapi_Attr *chattr = NULL;
- if (slapi_entry_attr_find(e, SYNC_ALLOW_OPENLDAP_COMPAT, &chattr) == 0) {
- Slapi_Value *sval = NULL;
- slapi_attr_first_value(chattr, &sval);
- const struct berval *value = slapi_value_get_berval(sval);
- if (NULL != value && NULL != value->bv_val && '\0' != value->bv_val[0]) {
- if (strcasecmp(value->bv_val, "on") == 0) {
- allow_openldap_compat = PR_TRUE;
- }
- }
- }
- }
- sync_register_allow_openldap_compat(allow_openldap_compat);
- if (slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc) != 0 ||
- slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv) != 0) {
- slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
- "sync_start - Unable to get arguments\n");
- return (-1);
- }
- /* It registers a per thread 'thread_primary_op' variable that is
- * a list of pending operations. For simple operation, this list
- * only contains one operation. For nested, the list contains the operations
- * in the order that they were applied
- */
- PR_NewThreadPrivateIndex(&thread_primary_op, sync_thread_primary_op_destructor);
- sync_persist_initialize(argc, argv);
- return (0);
- }
- /*
- sync_close
- --------------
- Free locks and queues allocated.
- */
- static int
- sync_close(Slapi_PBlock *pb __attribute__((unused)))
- {
- sync_persist_terminate_all();
- sync_unregister_operation_entension();
- return (0);
- }
- /* Return the head of the operations list
- * the head is the primary operation.
- * The list is private to that thread and contains
- * all nested operations applied by the thread.
- */
- OPERATION_PL_CTX_T *
- get_thread_primary_op(void)
- {
- OPERATION_PL_CTX_T *head = NULL;
- head = (OPERATION_PL_CTX_T *)PR_GetThreadPrivate(thread_primary_op);
- if (head == NULL) {
- /* if it was not initialized set it to zero */
- head = (OPERATION_PL_CTX_T *) slapi_ch_calloc(1, sizeof(OPERATION_PL_CTX_T));
- head->flags = OPERATION_PL_HEAD;
- PR_SetThreadPrivate(thread_primary_op, head);
- }
- return head->next;
- }
- /* It is set with a non NULL op when this is a primary operation
- * else it set to NULL when the all pending list has be flushed.
- * The list is flushed when no more operations (in that list) are
- * pending (OPERATION_PL_PENDING).
- */
- void
- set_thread_primary_op(OPERATION_PL_CTX_T *op)
- {
- OPERATION_PL_CTX_T *head;
- head = (OPERATION_PL_CTX_T *) PR_GetThreadPrivate(thread_primary_op);
- if (head == NULL) {
- /* if it was not initialized set it to zero */
- head = (OPERATION_PL_CTX_T *) slapi_ch_calloc(1, sizeof(OPERATION_PL_CTX_T));
- head->flags = OPERATION_PL_HEAD;
- PR_SetThreadPrivate(thread_primary_op, (void *) head);
- }
- head->next = op;
- }
- /* The following definitions are used for the operation pending list
- * (used by sync_repl). To retrieve a specific operation in the pending
- * list, the operation extension contains the index of the operation in
- * the pending list
- */
- static int sync_persist_extension_type; /* initialized in sync_persist_register_operation_extension */
- static int sync_persist_extension_handle; /* initialized in sync_persist_register_operation_extension */
- op_ext_ident_t *
- sync_persist_get_operation_extension(Slapi_PBlock *pb)
- {
- Slapi_Operation *op;
- op_ext_ident_t *ident;
- slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- ident = slapi_get_object_extension(sync_persist_extension_type, op,
- sync_persist_extension_handle);
- slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "sync_persist_get_operation_extension operation (op=0x%lx) -> %d\n",
- (ulong) op, ident ? ident->idx_pl : -1);
- return (op_ext_ident_t *) ident;
- }
- void
- sync_persist_set_operation_extension(Slapi_PBlock *pb, op_ext_ident_t *op_ident)
- {
- Slapi_Operation *op;
- slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "sync_persist_set_operation_extension operation (op=0x%lx) -> %d\n",
- (ulong) op, op_ident ? op_ident->idx_pl : -1);
- slapi_set_object_extension(sync_persist_extension_type, op,
- sync_persist_extension_handle, (void *)op_ident);
- }
- /* operation extension constructor */
- static void *
- sync_persist_operation_extension_constructor(void *object __attribute__((unused)), void *parent __attribute__((unused)))
- {
- /* we only set the extension value explicitly in sync_update_persist_betxn_pre_op */
- return NULL; /* we don't set anything in the ctor */
- }
- /* consumer operation extension destructor */
- static void
- sync_persist_operation_extension_destructor(void *ext, void *object __attribute__((unused)), void *parent __attribute__((unused)))
- {
- op_ext_ident_t *op_ident = (op_ext_ident_t *)ext;
- slapi_ch_free((void **)&op_ident);
- }
- static int
- sync_persist_register_operation_extension(void)
- {
- return slapi_register_object_extension(SYNC_PLUGIN_SUBSYSTEM,
- SLAPI_EXT_OPERATION,
- sync_persist_operation_extension_constructor,
- sync_persist_operation_extension_destructor,
- &sync_persist_extension_type,
- &sync_persist_extension_handle);
- }
|