ldbm_add.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /* add.c - ldap ldbm back-end add routine */
  42. #include "back-ldbm.h"
  43. extern char *numsubordinates;
  44. extern char *hassubordinates;
  45. static void delete_update_entry_dn_operational_attributes(struct backentry *ep);
  46. /* in order to find the parent, we must have either the parent dn or uniqueid
  47. This function will return true if either are set, or false otherwise */
  48. static int
  49. have_parent_address(const Slapi_DN *parentsdn, const char *parentuniqueid)
  50. {
  51. if (parentuniqueid && parentuniqueid[0]) {
  52. return 1; /* have parent uniqueid */
  53. }
  54. if (parentsdn && !slapi_sdn_isempty(parentsdn)) {
  55. return 1; /* have parent dn */
  56. }
  57. return 0; /* have no address */
  58. }
  59. int
  60. ldbm_back_add( Slapi_PBlock *pb )
  61. {
  62. backend *be;
  63. struct ldbminfo *li;
  64. ldbm_instance *inst;
  65. char *dn = NULL;
  66. Slapi_Entry *e;
  67. struct backentry *tombstoneentry = NULL;
  68. struct backentry *addingentry = NULL;
  69. struct backentry *parententry = NULL;
  70. ID pid;
  71. int isroot;
  72. char *errbuf= NULL;
  73. back_txn txn;
  74. back_txnid parent_txn;
  75. int retval = -1;
  76. char *msg;
  77. int managedsait;
  78. int ldap_result_code = LDAP_SUCCESS;
  79. char *ldap_result_message= NULL;
  80. char *ldap_result_matcheddn= NULL;
  81. int retry_count = 0;
  82. int disk_full = 0;
  83. modify_context parent_modify_c = {0};
  84. int parent_found = 0;
  85. int rc;
  86. int addingentry_id_assigned= 0;
  87. int addingentry_in_cache= 0;
  88. int tombstone_in_cache= 0;
  89. Slapi_DN sdn;
  90. Slapi_DN parentsdn;
  91. Slapi_Operation *operation;
  92. int dblock_acquired= 0;
  93. int is_replicated_operation= 0;
  94. int is_resurect_operation= 0;
  95. int is_tombstone_operation= 0;
  96. int is_fixup_operation= 0;
  97. int is_ruv = 0; /* True if the current entry is RUV */
  98. CSN *opcsn = NULL;
  99. entry_address addr;
  100. slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
  101. slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e );
  102. slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
  103. slapi_pblock_get( pb, SLAPI_MANAGEDSAIT, &managedsait );
  104. slapi_pblock_get( pb, SLAPI_PARENT_TXN, (void**)&parent_txn );
  105. slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
  106. slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, &is_replicated_operation );
  107. slapi_pblock_get( pb, SLAPI_BACKEND, &be);
  108. is_resurect_operation= operation_is_flag_set(operation,OP_FLAG_RESURECT_ENTRY);
  109. is_tombstone_operation= operation_is_flag_set(operation,OP_FLAG_TOMBSTONE_ENTRY);
  110. is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
  111. is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
  112. inst = (ldbm_instance *) be->be_instance_info;
  113. slapi_sdn_init(&sdn);
  114. slapi_sdn_init(&parentsdn);
  115. /* Get rid of ldbm backend attributes that you are not allowed to specify yourself */
  116. slapi_entry_delete_values( e, hassubordinates, NULL );
  117. slapi_entry_delete_values( e, numsubordinates, NULL );
  118. dblayer_txn_init(li,&txn);
  119. /* The dblock serializes writes to the database,
  120. * which reduces deadlocking in the db code,
  121. * which means that we run faster.
  122. *
  123. * But, this lock is re-enterant for the fixup
  124. * operations that the URP code in the Replication
  125. * plugin generates.
  126. */
  127. if(SERIALLOCK(li) && !is_fixup_operation)
  128. {
  129. dblayer_lock_backend(be);
  130. dblock_acquired= 1;
  131. }
  132. rc= 0;
  133. /*
  134. * We are about to pass the last abandon test, so from now on we are
  135. * committed to finish this operation. Set status to "will complete"
  136. * before we make our last abandon check to avoid race conditions in
  137. * the code that processes abandon operations.
  138. */
  139. if (operation) {
  140. operation->o_status = SLAPI_OP_STATUS_WILL_COMPLETE;
  141. }
  142. if ( slapi_op_abandoned( pb ) ) {
  143. ldap_result_code = -1; /* needs to distinguish from "success" */
  144. goto error_return;
  145. }
  146. if (!is_tombstone_operation && !is_resurect_operation)
  147. {
  148. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
  149. }
  150. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_UNIQUEID_ENTRY);
  151. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
  152. while(rc!=0)
  153. {
  154. /* JCM - copying entries can be expensive... should optimize */
  155. /*
  156. * Some present state information is passed through the PBlock to the
  157. * backend pre-op plugin. To ensure a consistent snapshot of this state
  158. * we wrap the reading of the entry with the dblock.
  159. */
  160. if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_UNIQUEID_ENTRY))
  161. {
  162. /* Check if an entry with the intended uniqueid already exists. */
  163. done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_UNIQUEID_ENTRY); /* Could be through this multiple times */
  164. addr.dn = NULL;
  165. addr.uniqueid = (char*)slapi_entry_get_uniqueid(e); /* jcm - cast away const */
  166. ldap_result_code= get_copy_of_entry(pb, &addr, &txn, SLAPI_ADD_EXISTING_UNIQUEID_ENTRY, !is_replicated_operation);
  167. }
  168. if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY))
  169. {
  170. slapi_pblock_get( pb, SLAPI_ADD_TARGET, &dn );
  171. slapi_sdn_set_dn_byref(&sdn, dn);
  172. slapi_sdn_get_backend_parent(&sdn,&parentsdn,pb->pb_backend);
  173. /* Check if an entry with the intended DN already exists. */
  174. done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_DN_ENTRY); /* Could be through this multiple times */
  175. addr.dn = dn;
  176. addr.uniqueid = NULL;
  177. ldap_result_code= get_copy_of_entry(pb, &addr, &txn, SLAPI_ADD_EXISTING_DN_ENTRY, !is_replicated_operation);
  178. }
  179. /* if we can find the parent by dn or uniqueid, and the operation has requested the parent
  180. then get it */
  181. if(have_parent_address(&parentsdn, operation->o_params.p.p_add.parentuniqueid) &&
  182. slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY))
  183. {
  184. done_with_pblock_entry(pb,SLAPI_ADD_PARENT_ENTRY); /* Could be through this multiple times */
  185. addr.dn = (char*)slapi_sdn_get_dn (&parentsdn); /* get_copy_of_entry assumes the DN is not normalized */
  186. addr.uniqueid = operation->o_params.p.p_add.parentuniqueid;
  187. ldap_result_code= get_copy_of_entry(pb, &addr, &txn, SLAPI_ADD_PARENT_ENTRY, !is_replicated_operation);
  188. /* need to set parentsdn or parentuniqueid if either is not set? */
  189. }
  190. /* Call the Backend Pre Add plugins */
  191. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  192. rc= plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN);
  193. if(rc==-1)
  194. {
  195. /*
  196. * Plugin indicated some kind of failure,
  197. * or that this Operation became a No-Op.
  198. */
  199. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  200. goto error_return;
  201. }
  202. /*
  203. * (rc!=-1 && rc!= 0) means that the plugin changed things, so we go around
  204. * the loop once again to get the new present state.
  205. */
  206. /* JCMREPL - Warning: A Plugin could cause an infinite loop by always returning a result code that requires some action. */
  207. }
  208. /*
  209. * Originally (in the U-M LDAP 3.3 code), there was a comment near this
  210. * code about a race condition. The race was that a 2nd entry could be
  211. * added between the time when we check for an already existing entry
  212. * and the cache_add_entry_lock() call below. A race condition no
  213. * longer exists, because now we keep the parent entry locked for
  214. * the duration of the old race condition's window of opportunity.
  215. */
  216. /*
  217. * Fetch the parent entry and acquire the cache lock.
  218. */
  219. if(have_parent_address(&parentsdn, operation->o_params.p.p_add.parentuniqueid))
  220. {
  221. addr.dn = (char*)slapi_sdn_get_dn (&parentsdn);
  222. addr.uniqueid = operation->o_params.p.p_add.parentuniqueid;
  223. parententry = find_entry2modify_only(pb,be,&addr,&txn);
  224. if (parententry && parententry->ep_entry) {
  225. if (!operation->o_params.p.p_add.parentuniqueid){
  226. /* Set the parentuniqueid now */
  227. operation->o_params.p.p_add.parentuniqueid = slapi_ch_strdup(slapi_entry_get_uniqueid(parententry->ep_entry));
  228. }
  229. if (slapi_sdn_isempty(&parentsdn)) {
  230. /* Set the parentsdn now */
  231. slapi_sdn_set_dn_byval(&parentsdn, slapi_entry_get_dn_const(parententry->ep_entry));
  232. }
  233. }
  234. modify_init(&parent_modify_c,parententry);
  235. }
  236. /* Check if the entry we have been asked to add already exists */
  237. {
  238. Slapi_Entry *entry;
  239. slapi_pblock_get( pb, SLAPI_ADD_EXISTING_DN_ENTRY, &entry);
  240. if ( entry != NULL )
  241. {
  242. /* The entry already exists */
  243. ldap_result_code= LDAP_ALREADY_EXISTS;
  244. goto error_return;
  245. }
  246. else
  247. {
  248. /*
  249. * did not find the entry - this is good, since we're
  250. * trying to add it, but we have to check whether the
  251. * entry we did match has a referral we should return
  252. * instead. we do this only if managedsait is not on.
  253. */
  254. if ( !managedsait && !is_tombstone_operation )
  255. {
  256. int err= 0;
  257. Slapi_DN ancestordn= {0};
  258. struct backentry *ancestorentry;
  259. ancestorentry= dn2ancestor(pb->pb_backend,&sdn,&ancestordn,&txn,&err);
  260. slapi_sdn_done(&ancestordn);
  261. if ( ancestorentry != NULL )
  262. {
  263. int sentreferral= check_entry_for_referral(pb, ancestorentry->ep_entry, backentry_get_ndn(ancestorentry), "ldbm_back_add");
  264. cache_return( &inst->inst_cache, &ancestorentry );
  265. if(sentreferral)
  266. {
  267. ldap_result_code= -1; /* The result was sent by check_entry_for_referral */
  268. goto error_return;
  269. }
  270. }
  271. }
  272. }
  273. }
  274. if ((operation_is_flag_set(operation,OP_FLAG_ACTION_SCHEMA_CHECK)) && slapi_entry_schema_check(pb, e) != 0)
  275. {
  276. LDAPDebug(LDAP_DEBUG_TRACE, "entry failed schema check\n", 0, 0, 0);
  277. ldap_result_code = LDAP_OBJECT_CLASS_VIOLATION;
  278. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
  279. goto error_return;
  280. }
  281. /* Check attribute syntax */
  282. if (slapi_entry_syntax_check(pb, e, 0) != 0)
  283. {
  284. LDAPDebug(LDAP_DEBUG_TRACE, "entry failed syntax check\n", 0, 0, 0);
  285. ldap_result_code = LDAP_INVALID_SYNTAX;
  286. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
  287. goto error_return;
  288. }
  289. opcsn = operation_get_csn (operation);
  290. if(is_resurect_operation)
  291. {
  292. char *reason = NULL;
  293. /*
  294. * When we resurect a tombstone we must use its UniqueID
  295. * to find the tombstone entry and lock it down in the cache.
  296. */
  297. addr.dn = NULL;
  298. addr.uniqueid = (char *)slapi_entry_get_uniqueid(e); /* jcm - cast away const */
  299. tombstoneentry = find_entry2modify( pb, be, &addr, NULL );
  300. if ( tombstoneentry==NULL )
  301. {
  302. ldap_result_code= -1;
  303. goto error_return; /* error result sent by find_entry2modify() */
  304. }
  305. tombstone_in_cache = 1;
  306. addingentry = backentry_dup( tombstoneentry );
  307. if ( addingentry==NULL )
  308. {
  309. ldap_result_code= LDAP_OPERATIONS_ERROR;
  310. goto error_return;
  311. }
  312. /*
  313. * To resurect a tombstone we must fix its DN and remove the
  314. * parent UniqueID that we stashed in there.
  315. *
  316. * The entry comes back to life as a Glue entry, so we add the
  317. * magic objectclass.
  318. */
  319. slapi_pblock_get( pb, SLAPI_ADD_TARGET, &dn );
  320. slapi_sdn_set_dn_byref(&sdn, dn);
  321. slapi_entry_set_dn(addingentry->ep_entry, slapi_ch_strdup(dn)); /* The DN is passed into the entry. */
  322. /* LPREPL: the DN is normalized...Somehow who should get a not normalized one */
  323. addingentry->ep_id = slapi_entry_attr_get_ulong(addingentry->ep_entry,"entryid");
  324. slapi_entry_attr_delete(addingentry->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID);
  325. slapi_entry_delete_string(addingentry->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE);
  326. /* Now also remove the nscpEntryDN */
  327. if (slapi_entry_attr_delete(addingentry->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN) != 0){
  328. LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Couldn't remove %s\n", dn, SLAPI_ATTR_NSCP_ENTRYDN, 0);
  329. }
  330. /* And copy the reason from e */
  331. reason = slapi_entry_attr_get_charptr(e, "nsds5ReplConflict");
  332. if (reason) {
  333. if (!slapi_entry_attr_hasvalue(addingentry->ep_entry, "nsds5ReplConflict", reason)) {
  334. slapi_entry_add_string(addingentry->ep_entry, "nsds5ReplConflict", reason);
  335. LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Added Conflict reason %s\n", dn, reason, 0);
  336. }
  337. slapi_ch_free((void **)&reason);
  338. }
  339. /* Clear the Tombstone Flag in the entry */
  340. slapi_entry_clear_flag(addingentry->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
  341. /* make sure the objectclass
  342. - does not contain any duplicate values
  343. - has CSNs for the new values we added
  344. */
  345. {
  346. Slapi_Attr *sa = NULL;
  347. Slapi_Value sv;
  348. const struct berval *svbv = NULL;
  349. /* add the extensibleobject objectclass with csn if not present */
  350. slapi_entry_attr_find(addingentry->ep_entry, SLAPI_ATTR_OBJECTCLASS, &sa);
  351. slapi_value_init_string(&sv, "extensibleobject");
  352. svbv = slapi_value_get_berval(&sv);
  353. if (slapi_attr_value_find(sa, svbv)) { /* not found, so add it */
  354. if (opcsn) {
  355. value_update_csn(&sv, CSN_TYPE_VALUE_UPDATED, opcsn);
  356. }
  357. slapi_attr_add_value(sa, &sv);
  358. }
  359. value_done(&sv);
  360. /* add the glue objectclass with csn if not present */
  361. slapi_value_init_string(&sv, "glue");
  362. svbv = slapi_value_get_berval(&sv);
  363. if (slapi_attr_value_find(sa, svbv)) { /* not found, so add it */
  364. if (opcsn) {
  365. value_update_csn(&sv, CSN_TYPE_VALUE_UPDATED, opcsn);
  366. }
  367. slapi_attr_add_value(sa, &sv);
  368. }
  369. value_done(&sv);
  370. }
  371. }
  372. else
  373. {
  374. /*
  375. * Try to add the entry to the cache, assign it a new entryid
  376. * and mark it locked. This should only fail if the entry
  377. * already exists.
  378. */
  379. /*
  380. * next_id will add this id to the list of ids that are pending
  381. * id2entry indexing.
  382. */
  383. addingentry = backentry_init( e );
  384. if ( ( addingentry->ep_id = next_id( be ) ) >= MAXID ) {
  385. LDAPDebug( LDAP_DEBUG_ANY,
  386. "add: maximum ID reached, cannot add entry to "
  387. "backend '%s'", be->be_name, 0, 0 );
  388. ldap_result_code = LDAP_OPERATIONS_ERROR;
  389. goto error_return;
  390. }
  391. addingentry_id_assigned= 1;
  392. if (!is_fixup_operation)
  393. {
  394. if ( opcsn == NULL && operation->o_csngen_handler )
  395. {
  396. /*
  397. * Current op is a user request. Opcsn will be assigned
  398. * if the dn is in an updatable replica.
  399. */
  400. opcsn = entry_assign_operation_csn ( pb, e, parententry ? parententry->ep_entry : NULL );
  401. }
  402. if ( opcsn != NULL )
  403. {
  404. entry_set_csn (e, opcsn);
  405. entry_add_dncsn (e, opcsn);
  406. entry_add_rdn_csn (e, opcsn);
  407. entry_set_maxcsn (e, opcsn);
  408. }
  409. }
  410. if (is_tombstone_operation)
  411. {
  412. /* Directly add the entry as a tombstone */
  413. /*
  414. * 1) If the entry has an existing DN, change it to be
  415. * "nsuniqueid=<uniqueid>, <old dn>"
  416. * 2) Add the objectclass value "tombstone" and arrange for only
  417. * that value to be indexed.
  418. * 3) If the parent entry was found, set the nsparentuniqueid
  419. * attribute to be the unique id of that parent.
  420. */
  421. char *untombstoned_dn = slapi_entry_get_dn(e);
  422. if (NULL == untombstoned_dn)
  423. {
  424. untombstoned_dn = "";
  425. }
  426. slapi_entry_set_dn(addingentry->ep_entry, compute_entry_tombstone_dn(untombstoned_dn, addr.uniqueid));
  427. /* Work around pb with slapi_entry_add_string (defect 522327) doesn't check duplicate values */
  428. if (!slapi_entry_attr_hasvalue(addingentry->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE)) {
  429. slapi_entry_add_string(addingentry->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE);
  430. slapi_entry_set_flag(addingentry->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
  431. }
  432. if (NULL != operation->o_params.p.p_add.parentuniqueid)
  433. {
  434. slapi_entry_add_string(addingentry->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID, operation->o_params.p.p_add.parentuniqueid);
  435. }
  436. }
  437. }
  438. /*
  439. * Get the parent dn and see if the corresponding entry exists.
  440. * If the parent does not exist, only allow the "root" user to
  441. * add the entry.
  442. */
  443. if ( !slapi_sdn_isempty(&parentsdn) )
  444. {
  445. /* This is getting the parent */
  446. if (NULL == parententry)
  447. {
  448. /* Here means that we didn't find the parent */
  449. int err = 0;
  450. Slapi_DN ancestordn= {0};
  451. struct backentry *ancestorentry;
  452. LDAPDebug( LDAP_DEBUG_TRACE,
  453. "parent does not exist, pdn = %s\n",
  454. slapi_sdn_get_dn(&parentsdn), 0, 0 );
  455. ancestorentry = dn2ancestor(be, &parentsdn, &ancestordn, &txn, &err );
  456. cache_return( &inst->inst_cache, &ancestorentry );
  457. ldap_result_code= LDAP_NO_SUCH_OBJECT;
  458. ldap_result_matcheddn= slapi_ch_strdup((char *)slapi_sdn_get_dn(&ancestordn)); /* jcm - cast away const. */
  459. slapi_sdn_done(&ancestordn);
  460. goto error_return;
  461. }
  462. ldap_result_code = plugin_call_acl_plugin (pb, e, NULL, NULL, SLAPI_ACL_ADD,
  463. ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
  464. if ( ldap_result_code != LDAP_SUCCESS )
  465. {
  466. LDAPDebug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 );
  467. ldap_result_message= errbuf;
  468. goto error_return;
  469. }
  470. pid = parententry->ep_id;
  471. }
  472. else
  473. { /* no parent */
  474. if ( !isroot && !is_replicated_operation)
  475. {
  476. LDAPDebug( LDAP_DEBUG_TRACE, "no parent & not root\n",
  477. 0, 0, 0 );
  478. ldap_result_code= LDAP_INSUFFICIENT_ACCESS;
  479. goto error_return;
  480. }
  481. parententry = NULL;
  482. pid = 0;
  483. }
  484. if(is_resurect_operation)
  485. {
  486. /*
  487. * add the entrydn operational attributes
  488. */
  489. add_update_entrydn_operational_attributes(addingentry);
  490. }
  491. else if (is_tombstone_operation)
  492. {
  493. /* Remove the entrydn operational attributes */
  494. delete_update_entry_dn_operational_attributes(addingentry);
  495. }
  496. else
  497. {
  498. /*
  499. * add the parentid, entryid and entrydn operational attributes
  500. */
  501. add_update_entry_operational_attributes(addingentry, pid);
  502. }
  503. /* Tentatively add the entry to the cache. We do this after adding any
  504. * operational attributes to ensure that the cache is sized correctly. */
  505. if ( cache_add_tentative( &inst->inst_cache, addingentry, NULL )!= 0 )
  506. {
  507. LDAPDebug( LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected\n", 0, 0, 0 );
  508. ldap_result_code= LDAP_ALREADY_EXISTS;
  509. goto error_return;
  510. }
  511. addingentry_in_cache= 1;
  512. /*
  513. * Before we add the entry, find out if the syntax of the aci
  514. * aci attribute values are correct or not. We don't want to
  515. * the entry if the syntax is incorrect.
  516. */
  517. if ( plugin_call_acl_verify_syntax (pb, addingentry->ep_entry, &errbuf) != 0 ) {
  518. LDAPDebug( LDAP_DEBUG_TRACE, "ACL syntax error\n", 0,0,0);
  519. ldap_result_code= LDAP_INVALID_SYNTAX;
  520. ldap_result_message= errbuf;
  521. goto error_return;
  522. }
  523. /* Having decided that we're really going to do the operation, let's modify
  524. the in-memory state of the parent to reflect the new child (update
  525. subordinate count specifically */
  526. if (NULL != parententry)
  527. {
  528. retval = parent_update_on_childchange(&parent_modify_c,1,NULL); /* 1==add */\
  529. /* The modify context now contains info needed later */
  530. if (0 != retval) {
  531. ldap_result_code= LDAP_OPERATIONS_ERROR;
  532. goto error_return;
  533. }
  534. parent_found = 1;
  535. parententry = NULL;
  536. }
  537. /*
  538. * So, we believe that no code up till here actually added anything
  539. * to persistent store. From now on, we're transacted
  540. */
  541. for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++) {
  542. if (retry_count > 0) {
  543. dblayer_txn_abort(li,&txn);
  544. /* We're re-trying */
  545. LDAPDebug( LDAP_DEBUG_TRACE, "Add Retrying Transaction\n", 0, 0, 0 );
  546. #ifndef LDBM_NO_BACKOFF_DELAY
  547. {
  548. PRIntervalTime interval;
  549. interval = PR_MillisecondsToInterval(slapi_rand() % 100);
  550. DS_Sleep(interval);
  551. }
  552. #endif
  553. }
  554. retval = dblayer_txn_begin(li,parent_txn,&txn);
  555. if (0 != retval) {
  556. if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
  557. disk_full = 1;
  558. ldap_result_code= LDAP_OPERATIONS_ERROR;
  559. goto diskfull_return;
  560. }
  561. ldap_result_code= LDAP_OPERATIONS_ERROR;
  562. goto error_return;
  563. }
  564. retval = id2entry_add( be, addingentry, &txn );
  565. if (DB_LOCK_DEADLOCK == retval)
  566. {
  567. LDAPDebug( LDAP_DEBUG_ARGS, "add 1 DEADLOCK\n", 0, 0, 0 );
  568. /* Retry txn */
  569. continue;
  570. }
  571. if (retval != 0) {
  572. LDAPDebug( LDAP_DEBUG_TRACE, "id2entry_add failed, err=%d %s\n",
  573. retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  574. if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
  575. disk_full = 1;
  576. ldap_result_code= LDAP_OPERATIONS_ERROR;
  577. goto diskfull_return;
  578. }
  579. ldap_result_code= LDAP_OPERATIONS_ERROR;
  580. goto error_return;
  581. }
  582. if(is_resurect_operation)
  583. {
  584. retval = index_addordel_string(be,SLAPI_ATTR_OBJECTCLASS,SLAPI_ATTR_VALUE_TOMBSTONE,addingentry->ep_id,BE_INDEX_DEL,&txn);
  585. if (DB_LOCK_DEADLOCK == retval) {
  586. LDAPDebug( LDAP_DEBUG_ARGS, "add 2 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
  587. /* Retry txn */
  588. continue;
  589. }
  590. if (0 != retval) {
  591. LDAPDebug( LDAP_DEBUG_TRACE, "add 1 BAD, err=%d %s\n",
  592. retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  593. if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
  594. disk_full = 1;
  595. ldap_result_code= LDAP_OPERATIONS_ERROR;
  596. goto diskfull_return;
  597. }
  598. ldap_result_code= LDAP_OPERATIONS_ERROR;
  599. goto error_return;
  600. }
  601. retval = index_addordel_string(be,SLAPI_ATTR_UNIQUEID,slapi_entry_get_uniqueid(addingentry->ep_entry),addingentry->ep_id,BE_INDEX_DEL,&txn);
  602. if (DB_LOCK_DEADLOCK == retval) {
  603. LDAPDebug( LDAP_DEBUG_ARGS, "add 3 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
  604. /* Retry txn */
  605. continue;
  606. }
  607. if (0 != retval) {
  608. LDAPDebug( LDAP_DEBUG_TRACE, "add 2 BAD, err=%d %s\n",
  609. retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  610. if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
  611. disk_full = 1;
  612. ldap_result_code= LDAP_OPERATIONS_ERROR;
  613. goto diskfull_return;
  614. }
  615. ldap_result_code= LDAP_OPERATIONS_ERROR;
  616. goto error_return;
  617. }
  618. retval = index_addordel_string(be,SLAPI_ATTR_NSCP_ENTRYDN,slapi_sdn_get_ndn(&sdn),addingentry->ep_id,BE_INDEX_DEL,&txn);
  619. if (DB_LOCK_DEADLOCK == retval) {
  620. LDAPDebug( LDAP_DEBUG_ARGS, "add 4 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
  621. /* Retry txn */
  622. continue;
  623. }
  624. if (0 != retval) {
  625. LDAPDebug( LDAP_DEBUG_TRACE, "add 3 BAD, err=%d %s\n",
  626. retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  627. if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
  628. disk_full = 1;
  629. ldap_result_code= LDAP_OPERATIONS_ERROR;
  630. goto diskfull_return;
  631. }
  632. ldap_result_code= LDAP_OPERATIONS_ERROR;
  633. goto error_return;
  634. }
  635. }
  636. if (is_tombstone_operation)
  637. {
  638. retval = index_addordel_entry( be, addingentry, BE_INDEX_ADD | BE_INDEX_TOMBSTONE, &txn );
  639. }
  640. else
  641. {
  642. retval = index_addordel_entry( be, addingentry, BE_INDEX_ADD, &txn );
  643. }
  644. if (DB_LOCK_DEADLOCK == retval)
  645. {
  646. LDAPDebug( LDAP_DEBUG_ARGS, "add 5 DEADLOCK\n", 0, 0, 0 );
  647. /* retry txn */
  648. continue;
  649. }
  650. if (retval != 0) {
  651. LDAPDebug( LDAP_DEBUG_ANY, "add: attempt to index %lu failed\n",
  652. (u_long)addingentry->ep_id, 0, 0 );
  653. if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
  654. disk_full = 1;
  655. ldap_result_code= LDAP_OPERATIONS_ERROR;
  656. goto diskfull_return;
  657. }
  658. ldap_result_code= LDAP_OPERATIONS_ERROR;
  659. goto error_return;
  660. }
  661. if (parent_found) {
  662. /* Push out the db modifications from the parent entry */
  663. retval = modify_update_all(be,pb,&parent_modify_c,&txn);
  664. if (DB_LOCK_DEADLOCK == retval)
  665. {
  666. LDAPDebug( LDAP_DEBUG_ARGS, "add 4 DEADLOCK\n", 0, 0, 0 );
  667. /* Retry txn */
  668. continue;
  669. }
  670. if (0 != retval) {
  671. LDAPDebug( LDAP_DEBUG_TRACE, "add 1 BAD, err=%d %s\n",
  672. retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  673. if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
  674. disk_full = 1;
  675. ldap_result_code= LDAP_OPERATIONS_ERROR;
  676. goto diskfull_return;
  677. }
  678. ldap_result_code= LDAP_OPERATIONS_ERROR;
  679. goto error_return;
  680. }
  681. }
  682. /*
  683. * Update the Virtual List View indexes
  684. */
  685. if (!is_ruv)
  686. {
  687. retval= vlv_update_all_indexes(&txn, be, pb, NULL, addingentry);
  688. if (DB_LOCK_DEADLOCK == retval) {
  689. LDAPDebug( LDAP_DEBUG_ARGS,
  690. "add DEADLOCK vlv_update_index\n", 0, 0, 0 );
  691. /* Retry txn */
  692. continue;
  693. }
  694. if (0 != retval) {
  695. LDAPDebug( LDAP_DEBUG_TRACE,
  696. "vlv_update_index failed, err=%d %s\n",
  697. retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  698. if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
  699. disk_full = 1;
  700. ldap_result_code= LDAP_OPERATIONS_ERROR;
  701. goto diskfull_return;
  702. }
  703. ldap_result_code= LDAP_OPERATIONS_ERROR;
  704. goto error_return;
  705. }
  706. }
  707. if (retval == 0) {
  708. break;
  709. }
  710. }
  711. if (retry_count == RETRY_TIMES) {
  712. /* Failed */
  713. LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in add\n", 0, 0, 0 );
  714. ldap_result_code= LDAP_OPERATIONS_ERROR;
  715. goto error_return;
  716. }
  717. /*
  718. * At this point, everything's cool, and the only thing which
  719. * can go wrong is a transaction commit failure.
  720. */
  721. slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, NULL );
  722. slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, slapi_entry_dup( addingentry->ep_entry ));
  723. if(is_resurect_operation)
  724. {
  725. /*
  726. * We can now switch the tombstone entry with the real entry.
  727. */
  728. if (cache_replace( &inst->inst_cache, tombstoneentry, addingentry ) != 0 )
  729. {
  730. /* This happens if the dn of addingentry already exists */
  731. ldap_result_code= LDAP_ALREADY_EXISTS;
  732. cache_unlock_entry( &inst->inst_cache, tombstoneentry );
  733. goto error_return;
  734. }
  735. /*
  736. * The tombstone was locked down in the cache... we can
  737. * get rid of the entry in the cache now.
  738. */
  739. cache_unlock_entry( &inst->inst_cache, tombstoneentry );
  740. cache_return( &inst->inst_cache, &tombstoneentry );
  741. tombstone_in_cache = 0; /* deleted */
  742. }
  743. if (parent_found)
  744. {
  745. /* switch the parent entry copy into play */
  746. modify_switch_entries( &parent_modify_c,be);
  747. }
  748. retval = dblayer_txn_commit(li,&txn);
  749. if (0 != retval)
  750. {
  751. if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
  752. disk_full = 1;
  753. ldap_result_code= LDAP_OPERATIONS_ERROR;
  754. goto diskfull_return;
  755. }
  756. ldap_result_code= LDAP_OPERATIONS_ERROR;
  757. goto error_return;
  758. }
  759. rc= 0;
  760. goto common_return;
  761. error_return:
  762. if ( addingentry_id_assigned )
  763. {
  764. next_id_return( be, addingentry->ep_id );
  765. }
  766. if ( NULL != addingentry )
  767. {
  768. if ( addingentry_in_cache )
  769. {
  770. cache_remove(&inst->inst_cache, addingentry);
  771. }
  772. backentry_clear_entry(addingentry); /* e is released in the frontend */
  773. backentry_free( &addingentry ); /* release the backend wrapper, here */
  774. }
  775. if(tombstone_in_cache)
  776. {
  777. cache_return(&inst->inst_cache, &tombstoneentry);
  778. }
  779. if (rc == DB_RUNRECOVERY) {
  780. dblayer_remember_disk_filled(li);
  781. ldbm_nasty("Add",80,rc);
  782. disk_full = 1;
  783. }
  784. /* It is specifically OK to make this call even when no transaction was in progress */
  785. dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */
  786. diskfull_return:
  787. if (disk_full)
  788. rc= return_on_disk_full(li);
  789. else
  790. rc= SLAPI_FAIL_GENERAL;
  791. common_return:
  792. if (addingentry_in_cache)
  793. {
  794. cache_return( &inst->inst_cache, &addingentry );
  795. }
  796. /* bepost op needs to know this result */
  797. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  798. /* JCMREPL - The bepostop is called even if the operation fails. */
  799. plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_ADD_FN);
  800. modify_term(&parent_modify_c,be);
  801. done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_DN_ENTRY);
  802. done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_UNIQUEID_ENTRY);
  803. done_with_pblock_entry(pb,SLAPI_ADD_PARENT_ENTRY);
  804. if(dblock_acquired)
  805. {
  806. dblayer_unlock_backend(be);
  807. }
  808. if(ldap_result_code!=-1)
  809. {
  810. slapi_send_ldap_result( pb, ldap_result_code, ldap_result_matcheddn, ldap_result_message, 0, NULL );
  811. }
  812. slapi_sdn_done(&sdn);
  813. slapi_sdn_done(&parentsdn);
  814. slapi_ch_free( (void**)&ldap_result_matcheddn );
  815. slapi_ch_free( (void**)&errbuf );
  816. return rc;
  817. }
  818. /*
  819. * add the parentid, entryid and entrydn, operational attributes.
  820. *
  821. * Note: This is called from the ldif2ldbm code.
  822. */
  823. void
  824. add_update_entry_operational_attributes(struct backentry *ep, ID pid)
  825. {
  826. struct berval bv;
  827. struct berval *bvp[2];
  828. char buf[40]; /* Enough for an EntryID */
  829. bvp[0] = &bv;
  830. bvp[1] = NULL;
  831. /* parentid */
  832. /* If the pid is 0, then the entry does not have a parent. It
  833. * may be the case that the entry is a suffix. In any case,
  834. * the parentid attribute should only be added if the entry
  835. * has a parent. */
  836. if (pid != 0) {
  837. sprintf( buf, "%lu", (u_long)pid );
  838. bv.bv_val = buf;
  839. bv.bv_len = strlen( buf );
  840. entry_replace_values( ep->ep_entry, "parentid", bvp );
  841. }
  842. /* entryid */
  843. sprintf( buf, "%lu", (u_long)ep->ep_id );
  844. bv.bv_val = buf;
  845. bv.bv_len = strlen( buf );
  846. entry_replace_values( ep->ep_entry, "entryid", bvp );
  847. /* entrydn */
  848. add_update_entrydn_operational_attributes(ep);
  849. }
  850. /*
  851. * add the entrydn operational attribute.
  852. */
  853. void
  854. add_update_entrydn_operational_attributes(struct backentry *ep)
  855. {
  856. struct berval bv;
  857. struct berval *bvp[2];
  858. /* entrydn */
  859. bvp[0] = &bv;
  860. bvp[1] = NULL;
  861. bv.bv_val = (void*)backentry_get_ndn(ep);
  862. bv.bv_len = strlen( bv.bv_val );
  863. entry_replace_values_with_flags( ep->ep_entry, "entrydn", bvp, SLAPI_ATTR_FLAG_NORMALIZED );
  864. }
  865. /*
  866. * delete the entrydn operational attributes
  867. */
  868. static void
  869. delete_update_entry_dn_operational_attributes(struct backentry *ep)
  870. {
  871. slapi_entry_attr_delete( ep->ep_entry, "entrydn");
  872. }