1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
|
/** 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;
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, NULL);
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);
}
|