| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* id.c - keep track of the next id to be given out */
- #include "back-ldbm.h"
- ID
- next_id(backend *be)
- {
- ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
- ID id;
- /*Lock*/
- PR_Lock( inst->inst_nextid_mutex );
- /*Test if nextid hasn't been initialized. */
- if (inst->inst_nextid < 1) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm backend instance: nextid not initialized... exiting.\n", 0,0,0);
- exit(1);
- }
- /*Increment the in-memory nextid*/
- inst->inst_nextid++;
- id = inst->inst_nextid - 1;
-
- /*unlock*/
- PR_Unlock( inst->inst_nextid_mutex );
- /* if ID is above the threshold, the database may need rebuilding soon */
- if (id >= ID_WARNING_THRESHOLD) {
- if ( id >= MAXID ) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm backend instance: FATAL ERROR: backend '%s' has no"
- "IDs left. DATABASE MUST BE REBUILT.\n", be->be_name, 0,
- 0);
- id = MAXID;
- } else {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm backend instance: WARNING: backend '%s' may run out "
- "of IDs. Please, rebuild database.\n", be->be_name, 0, 0);
- }
- }
- return( id );
- }
- void
- next_id_return( backend *be, ID id )
- {
- ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
- /*Lock*/
- PR_Lock( inst->inst_nextid_mutex );
- /*Test if nextid hasn't been initialized. */
- if (inst->inst_nextid < 1) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm backend instance: nextid not initialized... exiting\n", 0,0,0);
- exit(1);
- }
- if ( id != inst->inst_nextid - 1 ) {
- PR_Unlock( inst->inst_nextid_mutex );
- return;
- }
- /*decrement the in-memory version*/
- inst->inst_nextid--;
- /*unlock this bad boy*/
- PR_Unlock( inst->inst_nextid_mutex );
- }
- ID
- next_id_get( backend *be )
- {
- ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
- ID id;
-
- /*lock*/
- PR_Lock( inst->inst_nextid_mutex );
- /*Test if nextid hasn't been initialized.*/
- if (inst->inst_nextid < 1) {
- LDAPDebug( LDAP_DEBUG_ANY,
- "ldbm backend instance: nextid not initialized... exiting\n", 0,0,0);
- exit(1);
- }
-
- id = inst->inst_nextid;
- PR_Unlock( inst->inst_nextid_mutex );
-
- return( id );
- }
- /*
- * Function: get_ids_from_disk
- *
- * Returns: squat
- *
- * Description: Opend the id2entry file and obtains the largest
- * ID in use, and sets li->li_nextid. If no IDs
- * could be read from id2entry, li->li_nextid
- * is set to 1.
- */
- void
- get_ids_from_disk(backend *be)
- {
- ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
- DB *id2entrydb; /*the id2entry database*/
- int return_value = -1;
- /*For the nextid, we go directly to the id2entry database,
- and grab the max ID*/
-
- /*Get a copy of the id2entry database*/
- if ( (return_value = dblayer_get_id2entry( be, &id2entrydb )) != 0 ) {
- id2entrydb = NULL;
- }
- /* lock the nextid mutex*/
- PR_Lock( inst->inst_nextid_mutex );
- /*
- * If there is no id2entry database, then we can assume that there
- * are no entries, and that nextid should be 1
- */
- if (id2entrydb == NULL) {
- inst->inst_nextid = 1;
- /* unlock */
- PR_Unlock( inst->inst_nextid_mutex );
- return;
- } else {
-
- /*Get the last key*/
- DBC *dbc = NULL;
- DBT key = {0}; /*For the nextid*/
- DBT Value = {0};
- Value.flags = DB_DBT_MALLOC;
- key.flags = DB_DBT_MALLOC;
- return_value = id2entrydb->cursor(id2entrydb,NULL,&dbc,0);
- if (0 == return_value) {
- return_value = dbc->c_get(dbc,&key,&Value,DB_LAST);
- if ( (0 == return_value) && (NULL != key.dptr) ) {
- inst->inst_nextid = id_stored_to_internal(key.dptr) + 1;
- } else {
- inst->inst_nextid = 1; /* error case: set 1 */
- }
- slapi_ch_free(&(key.data));
- slapi_ch_free(&(Value.data));
- dbc->c_close(dbc);
- } else {
- inst->inst_nextid = 1; /* when there is no id2entry, start from id 1 */
- }
- }
-
- /*close the cache*/
- dblayer_release_id2entry( be, id2entrydb );
- /* unlock */
- PR_Unlock( inst->inst_nextid_mutex );
- return;
- }
- /* routines to turn an internal machine-representation ID into the one we store (big-endian) */
- void id_internal_to_stored(ID i,char *b)
- {
- if ( sizeof(ID) > 4 ) {
- memset (b+4, 0, sizeof(ID)-4);
- }
- b[0] = (char)(i >> 24);
- b[1] = (char)(i >> 16);
- b[2] = (char)(i >> 8);
- b[3] = (char)i;
- }
- ID id_stored_to_internal(char* b)
- {
- ID i;
- i = (ID)b[3] & 0x000000ff;
- i |= (((ID)b[2]) << 8) & 0x0000ff00;
- i |= (((ID)b[1]) << 16) & 0x00ff0000;
- i |= ((ID)b[0]) << 24;
- return i;
- }
|