nextid.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. /* id.c - keep track of the next id to be given out */
  42. #include "back-ldbm.h"
  43. ID
  44. next_id(backend *be)
  45. {
  46. ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
  47. ID id;
  48. /*Lock*/
  49. PR_Lock( inst->inst_nextid_mutex );
  50. /*Test if nextid hasn't been initialized. */
  51. if (inst->inst_nextid < 1) {
  52. LDAPDebug( LDAP_DEBUG_ANY,
  53. "ldbm backend instance: nextid not initialized... exiting.\n", 0,0,0);
  54. exit(1);
  55. }
  56. /*Increment the in-memory nextid*/
  57. inst->inst_nextid++;
  58. id = inst->inst_nextid - 1;
  59. /*unlock*/
  60. PR_Unlock( inst->inst_nextid_mutex );
  61. /* if ID is above the threshold, the database may need rebuilding soon */
  62. if (id >= ID_WARNING_THRESHOLD) {
  63. if ( id >= MAXID ) {
  64. LDAPDebug( LDAP_DEBUG_ANY,
  65. "ldbm backend instance: FATAL ERROR: backend '%s' has no"
  66. "IDs left. DATABASE MUST BE REBUILT.\n", be->be_name, 0,
  67. 0);
  68. id = MAXID;
  69. } else {
  70. LDAPDebug( LDAP_DEBUG_ANY,
  71. "ldbm backend instance: WARNING: backend '%s' may run out "
  72. "of IDs. Please, rebuild database.\n", be->be_name, 0, 0);
  73. }
  74. }
  75. return( id );
  76. }
  77. void
  78. next_id_return( backend *be, ID id )
  79. {
  80. ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
  81. /*Lock*/
  82. PR_Lock( inst->inst_nextid_mutex );
  83. /*Test if nextid hasn't been initialized. */
  84. if (inst->inst_nextid < 1) {
  85. LDAPDebug( LDAP_DEBUG_ANY,
  86. "ldbm backend instance: nextid not initialized... exiting\n", 0,0,0);
  87. exit(1);
  88. }
  89. if ( id != inst->inst_nextid - 1 ) {
  90. PR_Unlock( inst->inst_nextid_mutex );
  91. return;
  92. }
  93. /*decrement the in-memory version*/
  94. inst->inst_nextid--;
  95. /*unlock this bad boy*/
  96. PR_Unlock( inst->inst_nextid_mutex );
  97. }
  98. ID
  99. next_id_get( backend *be )
  100. {
  101. ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
  102. ID id;
  103. /*lock*/
  104. PR_Lock( inst->inst_nextid_mutex );
  105. /*Test if nextid hasn't been initialized.*/
  106. if (inst->inst_nextid < 1) {
  107. LDAPDebug( LDAP_DEBUG_ANY,
  108. "ldbm backend instance: nextid not initialized... exiting\n", 0,0,0);
  109. exit(1);
  110. }
  111. id = inst->inst_nextid;
  112. PR_Unlock( inst->inst_nextid_mutex );
  113. return( id );
  114. }
  115. /*
  116. * Function: get_ids_from_disk
  117. *
  118. * Returns: squat
  119. *
  120. * Description: Opend the id2entry file and obtains the largest
  121. * ID in use, and sets li->li_nextid. If no IDs
  122. * could be read from id2entry, li->li_nextid
  123. * is set to 1.
  124. */
  125. void
  126. get_ids_from_disk(backend *be)
  127. {
  128. ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
  129. DB *id2entrydb; /*the id2entry database*/
  130. int return_value = -1;
  131. /*For the nextid, we go directly to the id2entry database,
  132. and grab the max ID*/
  133. /*Get a copy of the id2entry database*/
  134. if ( (return_value = dblayer_get_id2entry( be, &id2entrydb )) != 0 ) {
  135. id2entrydb = NULL;
  136. }
  137. /* lock the nextid mutex*/
  138. PR_Lock( inst->inst_nextid_mutex );
  139. /*
  140. * If there is no id2entry database, then we can assume that there
  141. * are no entries, and that nextid should be 1
  142. */
  143. if (id2entrydb == NULL) {
  144. inst->inst_nextid = 1;
  145. /* unlock */
  146. PR_Unlock( inst->inst_nextid_mutex );
  147. return;
  148. } else {
  149. /*Get the last key*/
  150. DBC *dbc = NULL;
  151. DBT key = {0}; /*For the nextid*/
  152. DBT Value = {0};
  153. Value.flags = DB_DBT_MALLOC;
  154. key.flags = DB_DBT_MALLOC;
  155. return_value = id2entrydb->cursor(id2entrydb,NULL,&dbc,0);
  156. if (0 == return_value) {
  157. return_value = dbc->c_get(dbc,&key,&Value,DB_LAST);
  158. if ( (0 == return_value) && (NULL != key.dptr) ) {
  159. inst->inst_nextid = id_stored_to_internal(key.dptr) + 1;
  160. } else {
  161. inst->inst_nextid = 1; /* error case: set 1 */
  162. }
  163. slapi_ch_free(&(key.data));
  164. slapi_ch_free(&(Value.data));
  165. dbc->c_close(dbc);
  166. } else {
  167. inst->inst_nextid = 1; /* when there is no id2entry, start from id 1 */
  168. }
  169. }
  170. /*close the cache*/
  171. dblayer_release_id2entry( be, id2entrydb );
  172. /* unlock */
  173. PR_Unlock( inst->inst_nextid_mutex );
  174. return;
  175. }
  176. /* routines to turn an internal machine-representation ID into the one we store (big-endian) */
  177. void id_internal_to_stored(ID i,char *b)
  178. {
  179. if ( sizeof(ID) > 4 ) {
  180. memset (b+4, 0, sizeof(ID)-4);
  181. }
  182. b[0] = (char)(i >> 24);
  183. b[1] = (char)(i >> 16);
  184. b[2] = (char)(i >> 8);
  185. b[3] = (char)i;
  186. }
  187. ID id_stored_to_internal(char* b)
  188. {
  189. ID i;
  190. i = (ID)b[3] & 0x000000ff;
  191. i |= (((ID)b[2]) << 8) & 0x0000ff00;
  192. i |= (((ID)b[1]) << 16) & 0x00ff0000;
  193. i |= ((ID)b[0]) << 24;
  194. return i;
  195. }