[Fedora-directory-commits] ldapserver/ldap/servers/slapd attrsyntax.c, 1.6, 1.7 backend.c, 1.6, 1.7 backend_manager.c, 1.9, 1.10 dse.c, 1.8, 1.9 entry.c, 1.14, 1.15 mapping_tree.c, 1.12, 1.13 pblock.c, 1.12, 1.13 proto-slap.h, 1.32, 1.33 schema.c, 1.11, 1.12 schemaparse.c, 1.5, 1.6 slap.h, 1.32, 1.33 slapi-plugin.h, 1.21, 1.22 slapi-private.h, 1.21, 1.22

Noriko Hosoi (nhosoi) fedora-directory-commits at redhat.com
Wed Jun 4 22:22:58 UTC 2008


Author: nhosoi

Update of /cvs/dirsec/ldapserver/ldap/servers/slapd
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv32401/ldap/servers/slapd

Modified Files:
	attrsyntax.c backend.c backend_manager.c dse.c entry.c 
	mapping_tree.c pblock.c proto-slap.h schema.c schemaparse.c 
	slap.h slapi-plugin.h slapi-private.h 
Log Message:
Resolves: #436837
Summary: Dynamically reload schema via task interface
Description: implemented task based schema file reloading
(see also http://directory.fedoraproject.org/wiki/Dynamically_Reload_Schema)



Index: attrsyntax.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/attrsyntax.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- attrsyntax.c	4 Oct 2007 16:27:47 -0000	1.6
+++ attrsyntax.c	4 Jun 2008 22:22:55 -0000	1.7
@@ -452,6 +452,7 @@
 
     if((asi=attr_syntax_get_by_name_locking_optional(s, PR_TRUE, PR_FALSE)) != NULL ) {
 		r = slapi_ch_strdup(asi->asi_name);
+		attr_syntax_return( asi );
 	}
 	if ( NULL == asi ) {
 		r = attr_syntax_normalize_no_lookup( s );
@@ -501,6 +502,7 @@
 	}
 	if ( NULL != asi ) {
 		plugin = asi->asi_plugin;
+		attr_syntax_return( asi );
 	}
 	return( plugin );
 }
@@ -890,6 +892,19 @@
 	}
 }
 
+static int
+attr_syntax_force_to_delete(struct asyntaxinfo *asip, void *arg)
+{
+	struct attr_syntax_enum_flaginfo	*fi;
+
+	PR_ASSERT( asip != NULL );
+	fi = (struct attr_syntax_enum_flaginfo *)arg;
+	PR_ASSERT( fi != NULL );
+
+	attr_syntax_delete_no_lock( asip, PR_FALSE );
+	return ATTR_SYNTAX_ENUM_REMOVE;
+}
+
 
 /*
  * Clear 'flag' within all attribute definitions.
@@ -921,6 +936,19 @@
 				(void *)&fi, PR_TRUE );
 }
 
+/*
+ * Delete all attribute definitions 
+ */
+void
+attr_syntax_delete_all()
+{
+	struct attr_syntax_enum_flaginfo fi;
+
+	memset( &fi, 0, sizeof(fi));
+	attr_syntax_enumerate_attrs( attr_syntax_force_to_delete,
+				(void *)&fi, PR_TRUE );
+}
+
 static int
 attr_syntax_init(void)
 {


Index: backend.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/backend.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- backend.c	10 Nov 2006 23:45:40 -0000	1.6
+++ backend.c	4 Jun 2008 22:22:55 -0000	1.7
@@ -48,52 +48,52 @@
 be_init( Slapi_Backend *be, const char *type, const char *name, int isprivate, int logchanges, int sizelimit, int timelimit )
 {
     char text[128];
-	slapdFrontendConfig_t *fecfg;
-	be->be_suffix = NULL;
+    slapdFrontendConfig_t *fecfg;
+    be->be_suffix = NULL;
     be->be_suffixlock= PR_NewLock();
     be->be_suffixcount= 0;
-	/* e.g. dn: cn=config,cn=NetscapeRoot,cn=ldbm database,cn=plugins,cn=config */
-	PR_snprintf(text, sizeof(text),"cn=%s,cn=%s,cn=plugins,cn=config", name, type);
+    /* e.g. dn: cn=config,cn=NetscapeRoot,cn=ldbm database,cn=plugins,cn=config */
+    PR_snprintf(text, sizeof(text),"cn=%s,cn=%s,cn=plugins,cn=config", name, type);
     be->be_basedn= slapi_ch_strdup(slapi_dn_normalize(text));
-	PR_snprintf(text, sizeof(text), "cn=config,cn=%s,cn=%s,cn=plugins,cn=config", name, type);
-	be->be_configdn= slapi_ch_strdup(slapi_dn_normalize(text));
-	PR_snprintf(text, sizeof(text), "cn=monitor,cn=%s,cn=%s,cn=plugins,cn=config", name, type);
-	be->be_monitordn= slapi_ch_strdup(slapi_dn_normalize(text));
-	be->be_sizelimit = sizelimit;
-	be->be_timelimit = timelimit;
-	/* maximum group nesting level before giving up */
-	be->be_maxnestlevel = SLAPD_DEFAULT_GROUPNESTLEVEL;
-	be->be_noacl= 0;
+    PR_snprintf(text, sizeof(text), "cn=config,cn=%s,cn=%s,cn=plugins,cn=config", name, type);
+    be->be_configdn= slapi_ch_strdup(slapi_dn_normalize(text));
+    PR_snprintf(text, sizeof(text), "cn=monitor,cn=%s,cn=%s,cn=plugins,cn=config", name, type);
+    be->be_monitordn= slapi_ch_strdup(slapi_dn_normalize(text));
+    be->be_sizelimit = sizelimit;
+    be->be_timelimit = timelimit;
+    /* maximum group nesting level before giving up */
+    be->be_maxnestlevel = SLAPD_DEFAULT_GROUPNESTLEVEL;
+    be->be_noacl= 0;
         be->be_flags=0;
-	if (( fecfg = getFrontendConfig()) != NULL )
-	{
-	    if ( fecfg->backendconfig != NULL && fecfg->backendconfig[ 0 ] != NULL )
-	    {
-    		be->be_backendconfig = slapi_ch_strdup( fecfg->backendconfig[0] );
-	    }
-		else
-		{
-			be->be_backendconfig= NULL;
-		}
-	    be->be_readonly = fecfg->readonly;
-	}
-	else
-	{
-		be->be_readonly= 0;
-		be->be_backendconfig= NULL;
-	}
-	be->be_lastmod = LDAP_UNDEFINED;
-	be->be_type = slapi_ch_strdup(type);
-	be->be_include = NULL;
-	be->be_private = isprivate;
+    if (( fecfg = getFrontendConfig()) != NULL )
+    {
+        if ( fecfg->backendconfig != NULL && fecfg->backendconfig[ 0 ] != NULL )
+        {
+            be->be_backendconfig = slapi_ch_strdup( fecfg->backendconfig[0] );
+        }
+        else
+        {
+            be->be_backendconfig= NULL;
+        }
+        be->be_readonly = fecfg->readonly;
+    }
+    else
+    {
+        be->be_readonly= 0;
+        be->be_backendconfig= NULL;
+    }
+    be->be_lastmod = LDAP_UNDEFINED;
+    be->be_type = slapi_ch_strdup(type);
+    be->be_include = NULL;
+    be->be_private = isprivate;
     be->be_logchanges = logchanges;
-	be->be_database = NULL;
-	be->be_writeconfig = NULL;
+    be->be_database = NULL;
+    be->be_writeconfig = NULL;
     be->be_delete_on_exit = 0;
-	be->be_state = BE_STATE_STOPPED;
-	be->be_state_lock = PR_NewLock();
-	be->be_name = slapi_ch_strdup(name);
-	be->be_mapped = 0;
+    be->be_state = BE_STATE_STOPPED;
+    be->be_state_lock = PR_NewLock();
+    be->be_name = slapi_ch_strdup(name);
+    be->be_mapped = 0;
 }
 
 void 
@@ -115,12 +115,17 @@
     /* JCM char **be_include; ??? */
     slapi_ch_free((void **)&be->be_name);
     PR_DestroyLock(be->be_state_lock);
+    if (be->be_lock != NULL)
+    {
+        PR_DestroyRWLock(be->be_lock);
+        be->be_lock = NULL;
+    }
 }
 
 void
 slapi_be_delete_onexit (Slapi_Backend *be)
 {
-	be->be_delete_on_exit = 1;
+    be->be_delete_on_exit = 1;
 }
 
 void
@@ -161,6 +166,12 @@
 	return r;
 }
 
+int
+be_isdeleted( const Slapi_Backend *be )
+{
+	return BE_STATE_DELETED == be->be_state;
+}
+
 void 
 be_addsuffix(Slapi_Backend *be,const Slapi_DN *suffix)
 {


Index: backend_manager.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/backend_manager.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- backend_manager.c	9 Apr 2007 23:02:41 -0000	1.9
+++ backend_manager.c	4 Jun 2008 22:22:55 -0000	1.10
@@ -149,6 +149,15 @@
     return be;
 }
 
+/*
+ * Rule: before coming to this point, slapi_be_Wlock(be) must be acquired.
+ */
+void
+be_replace_dse_internal(Slapi_Backend *be, struct dse *pdse)
+{
+    be->be_database->plg_private= (void*)pdse;
+}
+
 Slapi_Backend* 
 slapi_get_first_backend (char **cookie)
 {
@@ -341,8 +350,7 @@
             slapi_pblock_set( &pb, SLAPI_BACKEND, backends[i] );
 
             (*backends[i]->be_cleanup)( &pb );
-            be_done(backends[i]);
-            slapi_ch_free((void **)&backends[i]);
+            slapi_be_free(&backends[i]);
         }
     }
     slapi_ch_free((void**)&backends);


Index: dse.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/dse.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- dse.c	18 Oct 2007 00:08:34 -0000	1.8
+++ dse.c	4 Jun 2008 22:22:55 -0000	1.9
@@ -210,7 +210,7 @@
     Slapi_Entry *e= NULL;
     struct dse_node *n;
 
-	if (use_lock == DSE_USE_LOCK)
+	if (use_lock == DSE_USE_LOCK && pdse->dse_rwlock)
 		PR_RWLock_Rlock(pdse->dse_rwlock);
 
     n = dse_find_node( pdse, dn );
@@ -219,7 +219,7 @@
         e = slapi_entry_dup(n->entry);
     }
 
-	if (use_lock == DSE_USE_LOCK)
+	if (use_lock == DSE_USE_LOCK && pdse->dse_rwlock)
 		PR_RWLock_Unlock(pdse->dse_rwlock);
 
     return e;
@@ -444,6 +444,31 @@
  * Get rid of a dse structure.
  */
 int
+dse_destroy(struct dse *pdse)
+{
+    int nentries = 0;
+    if (pdse->dse_rwlock)
+        PR_RWLock_Wlock(pdse->dse_rwlock);
+    slapi_ch_free((void **)&(pdse->dse_filename));
+    slapi_ch_free((void **)&(pdse->dse_tmpfile));
+    slapi_ch_free((void **)&(pdse->dse_fileback));
+    slapi_ch_free((void **)&(pdse->dse_filestartOK));
+    dse_callback_deletelist(&pdse->dse_callback);
+    charray_free(pdse->dse_filelist);
+    nentries = avl_free(pdse->dse_tree, dse_internal_delete_entry);
+    if (pdse->dse_rwlock) {
+        PR_RWLock_Unlock(pdse->dse_rwlock);
+        PR_DestroyRWLock(pdse->dse_rwlock);
+    }
+    slapi_ch_free((void **)&pdse);
+    LDAPDebug( SLAPI_DSE_TRACELEVEL, "Removed [%d] entries from the dse tree.\n",
+                 nentries,0,0 );
+}
+
+/*
+ * Get rid of a dse structure.
+ */
+int
 dse_deletedse(Slapi_PBlock *pb)
 {
     struct dse *pdse = NULL;
@@ -452,22 +477,10 @@
 
     if (pdse)
     {
-		int nentries = 0;
-		PR_RWLock_Wlock(pdse->dse_rwlock);
-        slapi_ch_free((void **)&(pdse->dse_filename));
-        slapi_ch_free((void **)&(pdse->dse_tmpfile));
-        slapi_ch_free((void **)&(pdse->dse_fileback));
-        slapi_ch_free((void **)&(pdse->dse_filestartOK));
-        dse_callback_deletelist(&pdse->dse_callback);
-        nentries = avl_free(pdse->dse_tree, dse_internal_delete_entry);
-		PR_RWLock_Unlock(pdse->dse_rwlock);
-        PR_DestroyRWLock(pdse->dse_rwlock);
-        slapi_ch_free((void **)&pdse);
-	LDAPDebug( SLAPI_DSE_TRACELEVEL, "Removed [%d] entries from the dse tree.\n",
-						 nentries,0,0 );
+        dse_destroy(pdse);
     }
 
-	/* data is freed, so make sure no one tries to use it */
+    /* data is freed, so make sure no one tries to use it */
     slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, NULL);
 
     return 0;
@@ -633,9 +646,9 @@
 
 static int
 dse_read_one_file(struct dse *pdse, const char *filename, Slapi_PBlock *pb,
-		int primary_file )
+        int primary_file )
 {
-    Slapi_Entry	*e= NULL;
+    Slapi_Entry    *e= NULL;
     char *entrystr= NULL;
     char *buf = NULL;
     char *lastp = NULL;
@@ -643,44 +656,47 @@
     PRInt32 nr = 0;
     PRFileInfo prfinfo;
     PRFileDesc *prfd = 0;
+    int schema_flags = 0;
+
+    slapi_pblock_get(pb, SLAPI_SCHEMA_FLAGS, &schema_flags);
 
     if ( (NULL != pdse) && (NULL != filename) )
     {
         if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS )
         {
-			/* the "real" file does not exist; see if there is a tmpfile */
-			if ( pdse->dse_tmpfile &&
-				 PR_GetFileInfo( pdse->dse_tmpfile, &prfinfo ) == PR_SUCCESS ) {
-				rc = PR_Rename(pdse->dse_tmpfile, filename);
-				if (rc == PR_SUCCESS) {
-					slapi_log_error(SLAPI_LOG_FATAL, "dse",
-									"The configuration file %s was restored from backup %s\n",
-									filename, pdse->dse_tmpfile);
-					rc = 1;
-				} else {
-					slapi_log_error(SLAPI_LOG_FATAL, "dse",
-									"The configuration file %s was not restored from backup %s, error %d\n",
-									filename, pdse->dse_tmpfile, rc);
-					rc = 0;
-				}
-			} else {
-				rc = 0; /* fail */
-			}
+            /* the "real" file does not exist; see if there is a tmpfile */
+            if ( pdse->dse_tmpfile &&
+                 PR_GetFileInfo( pdse->dse_tmpfile, &prfinfo ) == PR_SUCCESS ) {
+                rc = PR_Rename(pdse->dse_tmpfile, filename);
+                if (rc == PR_SUCCESS) {
+                    slapi_log_error(SLAPI_LOG_FATAL, "dse",
+                                    "The configuration file %s was restored from backup %s\n",
+                                    filename, pdse->dse_tmpfile);
+                    rc = 1;
+                } else {
+                    slapi_log_error(SLAPI_LOG_FATAL, "dse",
+                                    "The configuration file %s was not restored from backup %s, error %d\n",
+                                    filename, pdse->dse_tmpfile, rc);
+                    rc = 0;
+                }
+            } else {
+                rc = 0; /* fail */
+            }
         }
         if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS )
         {
-			slapi_log_error(SLAPI_LOG_FATAL, "dse",
-							"The configuration file %s could not be accessed, error %d\n",
-							filename, rc);
+            slapi_log_error(SLAPI_LOG_FATAL, "dse",
+                            "The configuration file %s could not be accessed, error %d\n",
+                            filename, rc);
             rc = 0; /* Fail */
         }
         else if (( prfd = PR_Open( filename, PR_RDONLY, SLAPD_DEFAULT_FILE_MODE )) == NULL )
         {
-			slapi_log_error(SLAPI_LOG_FATAL, "dse",
-							"The configuration file %s could not be read. "
-							SLAPI_COMPONENT_NAME_NSPR " %d (%s)\n",
-							filename,
-							PR_GetError(), slapd_pr_strerror(PR_GetError()));
+            slapi_log_error(SLAPI_LOG_FATAL, "dse",
+                            "The configuration file %s could not be read. "
+                            SLAPI_COMPONENT_NAME_NSPR " %d (%s)\n",
+                            filename,
+                            PR_GetError(), slapd_pr_strerror(PR_GetError()));
             rc = 0; /* Fail */
         }
         else
@@ -690,9 +706,9 @@
             buf = slapi_ch_malloc( prfinfo.size + 1 );
             if (( nr = slapi_read_buffer( prfd, buf, prfinfo.size )) < 0 )
             {
-				slapi_log_error(SLAPI_LOG_FATAL, "dse",
-								"Could only read %d of %d bytes from config file %s\n",
-								nr, prfinfo.size, filename);
+                slapi_log_error(SLAPI_LOG_FATAL, "dse",
+                                "Could only read %d of %d bytes from config file %s\n",
+                                nr, prfinfo.size, filename);
                 rc = 0; /* Fail */
                 done= 1;
             }
@@ -702,16 +718,18 @@
 
             if(!done)
             {
-				int dont_check_dups = 0;
-				int str2entry_flags = SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES |
-							SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF ;
-
-				PR_ASSERT(pb);
-				slapi_pblock_get(pb, SLAPI_DSE_DONT_CHECK_DUPS, &dont_check_dups);
-				if ( !dont_check_dups ) {
-					str2entry_flags |= SLAPI_STR2ENTRY_REMOVEDUPVALS;
-				}
-					
+                int dont_check_dups = 0;
+                int str2entry_flags = SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES |
+                            SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF ;
+                if (schema_flags & DSE_SCHEMA_LOCKED)
+                    str2entry_flags |= SLAPI_STR2ENTRY_NO_SCHEMA_LOCK;
+
+                PR_ASSERT(pb);
+                slapi_pblock_get(pb, SLAPI_DSE_DONT_CHECK_DUPS, &dont_check_dups);
+                if ( !dont_check_dups ) {
+                    str2entry_flags |= SLAPI_STR2ENTRY_REMOVEDUPVALS;
+                }
+                    
                 /* Convert LDIF to entry structures */
                 rc= 1; /* assume we will succeed */
                 while (( entrystr = dse_read_next_entry( buf, &lastp )) != NULL )
@@ -722,47 +740,47 @@
                         int returncode = 0;
                         char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= {0};
 
-						LDAPDebug(SLAPI_DSE_TRACELEVEL, "dse_read_one_file"
-								" processing entry \"%s\" in file %s%s\n",
-								slapi_entry_get_dn_const(e), filename,
-								primary_file ? " (primary file)" : "" );
+                        LDAPDebug(SLAPI_DSE_TRACELEVEL, "dse_read_one_file"
+                                " processing entry \"%s\" in file %s%s\n",
+                                slapi_entry_get_dn_const(e), filename,
+                                primary_file ? " (primary file)" : "" );
 
-						/* remove the numsubordinates attr, which may be bogus */
-						slapi_entry_attr_delete(e, subordinatecount);
+                        /* remove the numsubordinates attr, which may be bogus */
+                        slapi_entry_attr_delete(e, subordinatecount);
 
-						/* set the "primary file" flag if appropriate */
-						slapi_pblock_set( pb, SLAPI_DSE_IS_PRIMARY_FILE, &primary_file );
+                        /* set the "primary file" flag if appropriate */
+                        slapi_pblock_set( pb, SLAPI_DSE_IS_PRIMARY_FILE, &primary_file );
                         if(dse_call_callback(pdse, pb, DSE_OPERATION_READ,
-									DSE_FLAG_PREOP, e, NULL, &returncode,
-									returntext) == SLAPI_DSE_CALLBACK_OK)
+                                    DSE_FLAG_PREOP, e, NULL, &returncode,
+                                    returntext) == SLAPI_DSE_CALLBACK_OK)
                         {
-							/* this will free the entry if not added, so it is
-							   definitely consumed by this call */
-							dse_add_entry_pb(pdse, e, pb);
+                            /* this will free the entry if not added, so it is
+                               definitely consumed by this call */
+                            dse_add_entry_pb(pdse, e, pb);
+                        }
+                        else /* free entry if not used */
+                        {
+                            slapi_log_error(SLAPI_LOG_FATAL, "dse",
+                                            "The entry %s in file %s is invalid, error code %d (%s) - %s\n",
+                                            slapi_entry_get_dn_const(e),
+                                            filename, returncode,
+                                            ldap_err2string(returncode),
+                                            returntext);
+                            slapi_entry_free(e);
+                            rc = 0;    /* failure */
                         }
-						else /* free entry if not used */
-						{
-							slapi_log_error(SLAPI_LOG_FATAL, "dse",
-											"The entry %s in file %s is invalid, error code %d (%s) - %s\n",
-											slapi_entry_get_dn_const(e),
-											filename, returncode,
-											ldap_err2string(returncode),
-											returntext);
-							slapi_entry_free(e);
-							rc = 0;	/* failure */
-						}
                     } else {
-						slapi_log_error( SLAPI_LOG_FATAL, "dse",
-								"parsing dse entry [%s]\n", entrystr );
-						rc = 0;	/* failure */
-					}
+                        slapi_log_error( SLAPI_LOG_FATAL, "dse",
+                                "parsing dse entry [%s]\n", entrystr );
+                        rc = 0;    /* failure */
+                    }
                 }
             }
-			slapi_ch_free((void **)&buf);
+            slapi_ch_free((void **)&buf);
         }
     }
 
-	return rc;
+    return rc;
 }
 
 /*
@@ -892,7 +910,8 @@
 {
 	int		rc = 0;	/* default: no error */
 
-	PR_RWLock_Rlock(pdse->dse_rwlock);
+	if (pdse->dse_rwlock)
+		PR_RWLock_Rlock(pdse->dse_rwlock);
 
 	if ( !pdse->dse_is_updateable ) {
 		if ( !pdse->dse_readonly_error_reported ) {
@@ -908,7 +927,8 @@
         rc = 1;	/* return an error to the client */
     }
 
-	PR_RWLock_Unlock(pdse->dse_rwlock);
+	if (pdse->dse_rwlock)
+		PR_RWLock_Unlock(pdse->dse_rwlock);
 
 	if ( rc != 0 ) {
         slapi_send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
@@ -1056,7 +1076,8 @@
 	slapi_pblock_get(pb, SLAPI_DSE_MERGE_WHEN_ADDING, &merge);
 
 	/* keep write lock during both tree update and file write operations */
-	PR_RWLock_Wlock(pdse->dse_rwlock);
+	if (pdse->dse_rwlock)
+		PR_RWLock_Wlock(pdse->dse_rwlock);
 	if (merge) 
 	{
 		rc= avl_insert( &(pdse->dse_tree), n, entry_dn_cmp, dupentry_merge );
@@ -1079,7 +1100,8 @@
 	} else { /* duplicate entry ignored */
 		dse_node_delete(&n); /* This also deletes the contained entry */
 	}
-	PR_RWLock_Unlock(pdse->dse_rwlock);
+	if (pdse->dse_rwlock)
+		PR_RWLock_Unlock(pdse->dse_rwlock);
 
 	if (rc == -1) 
 	{
@@ -1254,7 +1276,7 @@
     if ( NULL != e )
     {
         struct dse_node *n= dse_node_new(e);
-		if (use_lock)
+		if (use_lock && pdse->dse_rwlock)
 			PR_RWLock_Wlock(pdse->dse_rwlock);
         rc = avl_insert( &(pdse->dse_tree), n, entry_dn_cmp, dupentry_replace );
 		if (write_file)
@@ -1265,7 +1287,7 @@
 			dse_node_delete(&n);
 			rc = 0; /* for return to caller */
 		}
-		if (use_lock)
+		if (use_lock && pdse->dse_rwlock)
 			PR_RWLock_Unlock(pdse->dse_rwlock);
     }
     return rc;
@@ -1366,7 +1388,8 @@
     slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
 
 	/* keep write lock for both tree deleting and file writing */
-	PR_RWLock_Wlock(pdse->dse_rwlock);
+	if (pdse->dse_rwlock)
+		PR_RWLock_Wlock(pdse->dse_rwlock);
     if ((deleted_node = (struct dse_node *)avl_delete(&pdse->dse_tree,
 													  n, entry_dn_cmp)))
 		dse_node_delete(&deleted_node);
@@ -1379,7 +1402,8 @@
 								 SLAPI_OPERATION_DELETE);
         dse_write_file_nolock(pdse);
     }
-	PR_RWLock_Unlock(pdse->dse_rwlock);
+	if (pdse->dse_rwlock)
+		PR_RWLock_Unlock(pdse->dse_rwlock);
 
     return 1;
 }
@@ -1555,9 +1579,11 @@
      */ 
 	if ( pb->pb_op == NULL
 			|| !operation_is_flag_set( pb->pb_op, OP_FLAG_PS_CHANGESONLY )) {
-		PR_RWLock_Rlock(pdse->dse_rwlock);
+		if (pdse->dse_rwlock)
+			PR_RWLock_Rlock(pdse->dse_rwlock);
 		dse_apply_nolock(pdse,dse_search_filter_entry,(caddr_t)&stuff);
-		PR_RWLock_Unlock(pdse->dse_rwlock);
+		if (pdse->dse_rwlock)
+			PR_RWLock_Unlock(pdse->dse_rwlock);
 	}
 
 	if (stuff.ss) /* something was found which matched our criteria */


Index: entry.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/entry.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- entry.c	18 Oct 2007 00:08:34 -0000	1.14
+++ entry.c	4 Jun 2008 22:22:55 -0000	1.15
@@ -1067,7 +1067,14 @@
 
 	if ( flags & SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES )
 	{
-		slapi_schema_expand_objectclasses( e );
+		if ( flags & SLAPI_STR2ENTRY_NO_SCHEMA_LOCK )
+		{
+			schema_expand_objectclasses_nolock( e );
+		}
+		else
+		{
+			slapi_schema_expand_objectclasses( e );
+		}
 	}
 
     if ( flags & SLAPI_STR2ENTRY_TOMBSTONE_CHECK )


Index: mapping_tree.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/mapping_tree.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- mapping_tree.c	18 Oct 2007 00:08:34 -0000	1.12
+++ mapping_tree.c	4 Jun 2008 22:22:55 -0000	1.13
@@ -1605,7 +1605,7 @@
     mapping_tree_node_add_child(mapping_tree_root, node);
     node= add_internal_mapping_tree_node("cn=monitor", be, mapping_tree_root);
     mapping_tree_node_add_child(mapping_tree_root, node);
-    be= slapi_be_select_by_instance_name( "schema-internal" );
+    be= slapi_be_select_by_instance_name( DSE_SCHEMA );
     node= add_internal_mapping_tree_node("cn=schema", be, mapping_tree_root);
     mapping_tree_node_add_child(mapping_tree_root, node);
 
@@ -2003,7 +2003,7 @@
 
         mtn_unlock();
         *be = slapi_be_select_by_instance_name(DSE_BACKEND);
-        if(*be != NULL)
+        if(*be != NULL && !be_isdeleted(*be))
         {
             ret  = LDAP_SUCCESS;
             slapi_be_Rlock(*be);    /* also done inside mtn_get_be() below */
@@ -2026,7 +2026,7 @@
      * fail if the backend is read-only, 
      * or if the whole server is readonly AND backend is public (!private)
      */
-    if ((ret == LDAP_SUCCESS) && *be &&
+    if ((ret == LDAP_SUCCESS) && *be && !be_isdeleted(*be) &&
         ((*be)->be_readonly ||
         (slapi_config_get_readonly() && !slapi_be_private(*be)))) {
         unsigned long op_type = operation_get_type(op);
@@ -2101,7 +2101,7 @@
             && (scope == LDAP_SCOPE_BASE) )  { 
         mtn_unlock();
         be = slapi_be_select_by_instance_name(DSE_BACKEND);
-        if(be != NULL)
+        if(be != NULL && !be_isdeleted(be))
         {
             be_list[0]=be;
             be_list[1] = NULL;
@@ -2128,7 +2128,7 @@
             && (scope != LDAP_SCOPE_BASE)) )
                     && (!be || strncmp(be->be_name, "default", 8)))
         {
-            if (be)
+            if (be && !be_isdeleted(be))
             {
                 /* wrong backend or referall, ignore it */
                 slapi_log_error(SLAPI_LOG_ARGS, NULL,
@@ -2139,7 +2139,7 @@
         }
         else
         {
-            if (be)
+            if (be && !be_isdeleted(be))
             {
                     be_list[be_index++]=be;
             }
@@ -2285,7 +2285,7 @@
 
     if (ret != LDAP_SUCCESS)
     {
-        if (*be)
+        if (be && !be_isdeleted(be))
         {
             slapi_be_Unlock(*be);
             *be = NULL;
@@ -2521,7 +2521,7 @@
     }
 
     if (result == LDAP_SUCCESS) {
-        if (*be) {
+        if (*be && !be_isdeleted(*be)) {
             slapi_log_error(SLAPI_LOG_ARGS, NULL,
                 "mapping tree selected backend : %s\n",
                 slapi_be_get_name(*be));
@@ -2790,7 +2790,7 @@
 int
 slapi_on_internal_backends(const Slapi_DN *sdn)
 {
-        char *backend_names[] = {"frontend-internal", "schema-internal"};
+        char *backend_names[] = {DSE_BACKEND, DSE_SCHEMA};
         int internal = 1;
         int numOfInternalBackends = 2;                           
         int count;


Index: pblock.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/pblock.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- pblock.c	18 Oct 2007 20:49:01 -0000	1.12
+++ pblock.c	4 Jun 2008 22:22:55 -0000	1.13
@@ -559,9 +559,12 @@
 	case SLAPI_PLUGIN_POSTSTART_FN:
 		(*(IFP *)value) = pblock->pb_plugin->plg_poststart;
 		break;
-        case SLAPI_PLUGIN_DB_WIRE_IMPORT_FN:
-                (*(IFP *)value) = pblock->pb_plugin->plg_wire_import;
-                break;
+	case SLAPI_PLUGIN_DB_WIRE_IMPORT_FN:
+		(*(IFP *)value) = pblock->pb_plugin->plg_wire_import;
+		break;
+	case SLAPI_PLUGIN_DB_ADD_SCHEMA_FN:
+		(*(IFP *)value) = pblock->pb_plugin->plg_add_schema;
+		break;
 	case SLAPI_PLUGIN_DB_SEQ_FN:
 		if ( pblock->pb_plugin->plg_type != SLAPI_PLUGIN_DATABASE ) {
 			return( -1 );
@@ -1583,9 +1586,9 @@
 		(*(int *)value) = pblock->pb_dse_is_primary_file;
 		break;
 		
-	/* used internally by schema code */
-	case SLAPI_SCHEMA_USER_DEFINED_ONLY:
-		(*(int *)value) = pblock->pb_schema_user_defined_only;
+	/* used internally by schema code (schema.c) */
+	case SLAPI_SCHEMA_FLAGS:
+		(*(int *)value) = pblock->pb_schema_flags;
 		break;
 
 	case SLAPI_URP_NAMING_COLLISION_DN:
@@ -1836,9 +1839,12 @@
 	case SLAPI_PLUGIN_POSTSTART_FN:
 		pblock->pb_plugin->plg_poststart = (IFP) value;
 		break;
-        case SLAPI_PLUGIN_DB_WIRE_IMPORT_FN:
-                pblock->pb_plugin->plg_wire_import = (IFP) value;
-                break;
+	case SLAPI_PLUGIN_DB_WIRE_IMPORT_FN:
+		pblock->pb_plugin->plg_wire_import = (IFP) value;
+		break;
+	case SLAPI_PLUGIN_DB_ADD_SCHEMA_FN:
+		pblock->pb_plugin->plg_add_schema = (IFP) value;
+		break;
 	case SLAPI_PLUGIN_DB_SEQ_FN:
 		if ( pblock->pb_plugin->plg_type != SLAPI_PLUGIN_DATABASE ) {
 			return( -1 );
@@ -2824,9 +2830,9 @@
 		pblock->pb_dse_is_primary_file = *((int *)value);
 		break;
 		
-	/* used internally by schema code only */
-	case SLAPI_SCHEMA_USER_DEFINED_ONLY:
-		pblock->pb_schema_user_defined_only = *((int *)value);
+	/* used internally by schema code (schema.c) */
+	case SLAPI_SCHEMA_FLAGS:
+		pblock->pb_schema_flags = *((int *)value);
 		break;
 
 	case SLAPI_URP_NAMING_COLLISION_DN:


Index: proto-slap.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/proto-slap.h,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- proto-slap.h	3 Apr 2008 21:07:55 -0000	1.32
+++ proto-slap.h	4 Jun 2008 22:22:55 -0000	1.33
@@ -117,6 +117,7 @@
  */
 void attr_syntax_return( struct asyntaxinfo *asi );
 void attr_syntax_return_locking_optional( struct asyntaxinfo *asi, PRBool use_lock );
+void attr_syntax_delete_all(void);
 
 /*
  * value.c
@@ -192,6 +193,7 @@
  * backend_manager.c
  */
 Slapi_Backend *be_new_internal(struct dse *pdse, const char *type, const char *name);
+void be_replace_dse_internal(Slapi_Backend *be, struct dse *pdse);
 int fedse_create_startOK(char *filename,  char *startokfilename, const char *configdir);
 void be_cleanupall();
 void be_flushall();
@@ -550,10 +552,12 @@
 #define DSE_OPERATION_WRITE 0x200
 
 #define DSE_BACKEND             "frontend-internal"
+#define DSE_SCHEMA              "schema-internal"
 
 struct dse *dse_new( char *filename, char *tmpfilename, char *backfilename, char *startokfilename, const char *configdir);
 struct dse *dse_new_with_filelist(char *filename, char *tmpfilename, char *backfilename, char *startokfilename, const char *configdir, char **filelist);
 int dse_deletedse(Slapi_PBlock *pb);
+int dse_destroy(struct dse *pdse);
 int dse_read_file(struct dse *pdse, Slapi_PBlock *pb);
 int dse_bind( Slapi_PBlock *pb );
 int dse_unbind( Slapi_PBlock *pb );
@@ -853,11 +857,19 @@
 /* csn is consumed. */
 void g_set_global_schema_csn(CSN *csn);
 void slapi_schema_expand_objectclasses( Slapi_Entry *e );
+/* lock to protect both objectclass and schema_dse */
+void slapi_load_schemafile_lock( void );
+void slapi_load_schemafile_unlock( void );
+/* API to validate the schema files */
+int slapi_validate_schema_files(char *schemadir);
+/* API to reload the schema files */
+int slapi_reload_schema_files(char *schemadir);
 
 /*
  * schemaparse.c
  */
 void normalize_oc( void );
+void normalize_oc_nolock( void );
 /* Note: callers of oc_update_inheritance_nolock() must hold a write lock */
 void oc_update_inheritance_nolock( struct objclass *oc );
 


Index: schema.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/schema.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- schema.c	25 Sep 2007 19:43:50 -0000	1.11
+++ schema.c	4 Jun 2008 22:22:55 -0000	1.12
@@ -111,7 +111,7 @@
 static int schema_replace_objectclasses ( Slapi_PBlock *pb, LDAPMod *mod,
 		char *errorbuf, size_t errorbufsize );
 static int read_oc_ldif ( const char *input, struct objclass **oc,
-		char *errorbuf, size_t errorbufsize, int nolock, int is_user_defined,
+		char *errorbuf, size_t errorbufsize, PRUint32 flags, int is_user_defined,
 		int schema_ds4x_compat );
 static int schema_check_name(char *name, PRBool isAttribute, char *errorbuf,
 		size_t errorbufsize );
@@ -122,8 +122,8 @@
 static int strip_oc_options ( struct objclass *poc );
 static char *stripOption (char *attr);
 static int read_at_ldif(const char *input, struct asyntaxinfo **asipp,
-		char *errorbuf, size_t errorbufsize, int nolock, int is_user_defined,
-		int schema_ds4x_compat, int is_remote);
+		char *errorbuf, size_t errorbufsize, PRUint32 flags,
+		int is_user_defined, int schema_ds4x_compat, int is_remote);
 static char **parse_qdlist(const char *s, int *n, int strip_options);
 static void free_qdlist(char **vals, int n);
 static char **parse_qdescrs(const char *s, int *n);
@@ -456,6 +456,7 @@
   int i, oc_count = 0;
   int unknown_class = 0;
   char errtext[ BUFSIZ ];
+  PRUint32 schema_flags;
 
   /* smart referrals are not allowed in Directory Lite */
   if ( config_is_slapd_lite() ) {
@@ -468,8 +469,10 @@
    * say the schema checked out ok if we're not checking schema at
    * all, or if this is a replication update.
    */
-  if (pb != NULL)
+  if (pb != NULL) {
     slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_replicated_operation);
+	slapi_pblock_get(pb, SLAPI_SCHEMA_FLAGS, &schema_flags);
+  }
   if ( schemacheck == 0 || is_replicated_operation ) {
     return( 0 );
   }
@@ -504,7 +507,8 @@
   /*
    * Need the read lock to create the oc array and while we use it.
    */
-  oc_lock_read();
+  if (!(schema_flags & DSE_SCHEMA_LOCKED))
+    oc_lock_read();
 
   oc_count = 0;
   for (i= slapi_attr_first_value(aoc,&v); i != -1;
@@ -623,7 +627,8 @@
 
  out:
   /* Done with the oc array so can release the lock */
-  oc_unlock();
+  if (!(schema_flags & DSE_SCHEMA_LOCKED))
+    oc_unlock();
   slapi_ch_free((void**)&oclist);
 
   return( ret );
@@ -686,7 +691,7 @@
 {
     struct objclass *oc;
     int i, j;
-    int	rc = 1;		/* failure */
+    int	rc = 1;    /* failure */
  
     /* always allow objectclass and entryid attributes */
     /* MFW XXX  THESE SHORTCUTS SHOULD NOT BE NECESSARY BUT THEY MASK 
@@ -704,43 +709,43 @@
 
       /* does it require the type? */
       for ( j = 0; oc->oc_required && oc->oc_required[j] != NULL; j++ ) {
-	if ( slapi_attr_type_cmp( oc->oc_required[j],
-				  type, SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
-	  rc = 0;
-	  break;
-	}
+        if ( slapi_attr_type_cmp( oc->oc_required[j],
+                                  type, SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
+          rc = 0;
+          break;
+        }
       }
-	  
+          
       if ( 0 != rc ) {
-	/* does it allow the type? */
-	for ( j = 0; oc->oc_allowed && oc->oc_allowed[j] != NULL; j++ ) {
-	  if ( slapi_attr_type_cmp( oc->oc_allowed[j],
-				    type, SLAPI_TYPE_CMP_SUBTYPE ) == 0 || 
-	       strcmp( oc->oc_allowed[j],"*" ) == 0 ) {
-	    rc = 0;
-	    break;
-	  }
-	}
-	/* maybe the next oc allows it */
+        /* does it allow the type? */
+        for ( j = 0; oc->oc_allowed && oc->oc_allowed[j] != NULL; j++ ) {
+          if ( slapi_attr_type_cmp( oc->oc_allowed[j],
+                                    type, SLAPI_TYPE_CMP_SUBTYPE ) == 0 || 
+               strcmp( oc->oc_allowed[j],"*" ) == 0 ) {
+            rc = 0;
+            break;
+          }
+        }
+        /* maybe the next oc allows it */
       }
-    }	  
+    }
 
     if ( 0 != rc ) {
-	  char errtext[ BUFSIZ ];
+      char errtext[ BUFSIZ ];
       char ebuf[ BUFSIZ ];
       char ebuf2[ BUFSIZ ];
       LDAPDebug( LDAP_DEBUG_ANY,
-		 "Entry \"%s\" -- attribute \"%s\" not allowed\n",
-		 escape_string( slapi_entry_get_dn_const(e), ebuf ),
-		 escape_string( type, ebuf2 ),
-		 0);
-
-	  if (pb) {
-		PR_snprintf( errtext, sizeof( errtext ),
-		 "attribute \"%s\" not allowed\n",
-		 escape_string( type, ebuf2 ) );
-		slapi_pblock_set( pb, SLAPI_PB_RESULT_TEXT, errtext );
-	  }
+         "Entry \"%s\" -- attribute \"%s\" not allowed\n",
+         escape_string( slapi_entry_get_dn_const(e), ebuf ),
+         escape_string( type, ebuf2 ),
+         0);
+
+      if (pb) {
+        PR_snprintf( errtext, sizeof( errtext ),
+         "attribute \"%s\" not allowed\n",
+         escape_string( type, ebuf2 ) );
+        slapi_pblock_set( pb, SLAPI_PB_RESULT_TEXT, errtext );
+      }
     }
     
     return rc;
@@ -922,6 +927,19 @@
 	return rc;
 }
 
+static void
+oc_delete_all_nolock( void )
+{
+	struct objclass	*oc, *pnext;
+
+	oc = g_get_global_oc_nolock();
+	for (pnext = oc->oc_next; oc;
+		 oc = pnext, pnext = oc?oc->oc_next:NULL) {
+		oc_free( &oc );
+	}
+	g_set_global_oc_nolock ( NULL );
+}
+
 
 /*
  * Compare two objectclass definitions for equality.  Return PR_TRUE if
@@ -1411,6 +1429,7 @@
   struct attr_enum_wrapper aew;
   struct syntax_enum_wrapper sew;
   int enquote_sup_oc = config_get_enquote_sup_oc();
+  PRUint32 schema_flags = 0;
   int user_defined_only = 0;
   char **allowed, **required;
   char *mr_desc, *mr_name, *oc_description;
@@ -1420,7 +1439,8 @@
   vals[0] = &val;
   vals[1] = NULL;
 
-  slapi_pblock_get(pb, SLAPI_SCHEMA_USER_DEFINED_ONLY, (void*)&user_defined_only);
+  slapi_pblock_get(pb, SLAPI_SCHEMA_FLAGS, (void*)&schema_flags);
+  user_defined_only = (schema_flags & DSE_SCHEMA_USER_DEFINED_ONLY) ? 1 : 0;
   
   attrlist_delete (&pschema_info_e->e_attrs, "objectclasses");
   attrlist_delete (&pschema_info_e->e_attrs, "attributetypes"); 
@@ -1908,11 +1928,11 @@
 static int
 refresh_user_defined_schema( Slapi_PBlock *pb, Slapi_Entry *pschema_info_e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg /* not used */ )
 {
-	int user_defined_only = 1;
 	int rc;
 	Slapi_PBlock *mypbptr = pb;
 	Slapi_PBlock mypb;
 	const CSN *schema_csn;
+	PRUint32 schema_flags = DSE_SCHEMA_USER_DEFINED_ONLY;
 
 	pblock_init(&mypb);
 
@@ -1924,7 +1944,7 @@
 		mypbptr = &mypb;
 	}
 
-	slapi_pblock_set(mypbptr, SLAPI_SCHEMA_USER_DEFINED_ONLY, &user_defined_only);
+	slapi_pblock_set(mypbptr, SLAPI_SCHEMA_FLAGS, &schema_flags);
 	rc = read_schema_dse(mypbptr, pschema_info_e, NULL, returncode, returntext, NULL);
 	schema_csn = g_get_global_schema_csn();
 	if (NULL != schema_csn) {
@@ -2197,7 +2217,7 @@
   int status = 0;
   
   for (i = 0; LDAP_SUCCESS == status && mod->mod_bvalues[i]; i++) {
-	int nolock = 0; /* lock global resources during normal operation */
+	PRUint32 nolock = 0; /* lock global resources during normal operation */
 	attr_ldif = (char *) mod->mod_bvalues[i]->bv_val;
 
 	status = read_at_ldif(attr_ldif, NULL, errorbuf, errorbufsize,
@@ -2221,13 +2241,14 @@
  */
 static int
 add_oc_internal(struct objclass *pnew_oc, char *errorbuf, size_t errorbufsize,
-		int schema_ds4x_compat )
+		int schema_ds4x_compat, PRUint32 flags )
 {
 	struct objclass *oldoc_by_name, *oldoc_by_oid, *psup_oc = NULL;
 	int redefined_oc = 0, rc=0;
 	asyntaxinfo *pasyntaxinfo = 0;
 
-	oc_lock_write();
+	if (!(flags & DSE_SCHEMA_LOCKED))
+		oc_lock_write();
 
 	oldoc_by_name = oc_find_nolock (pnew_oc->oc_name);
 	oldoc_by_oid = oc_find_nolock (pnew_oc->oc_oid);
@@ -2296,13 +2317,14 @@
 	}
 	
 	/* check to see if the objectclass name is valid */
-	if (!rc && schema_check_name ( pnew_oc->oc_name, PR_FALSE,
-				errorbuf, errorbufsize ) == 0 ) {
+	if (!rc && !(flags & DSE_SCHEMA_NO_CHECK) &&
+		schema_check_name ( pnew_oc->oc_name, PR_FALSE, errorbuf, errorbufsize )
+			== 0 ) {
 		rc = schema_ds4x_compat ? LDAP_OPERATIONS_ERROR : LDAP_INVALID_SYNTAX;
 	}
 
 	/* check to see if the oid is valid */
-	if (!rc)
+	if (!rc && !(flags & DSE_SCHEMA_NO_CHECK))
 	{
 	    struct sizedbuffer *psbOcOid, *psbOcName;
 	
@@ -2320,8 +2342,9 @@
 	}
 
 	/* check to see if the oc's attributes are valid */
-	if (!rc && schema_check_oc_attrs ( pnew_oc, errorbuf, errorbufsize,
-									   0 /* don't strip options */ ) == 0 ) {
+	if (!rc && !(flags & DSE_SCHEMA_NO_CHECK) &&
+		schema_check_oc_attrs ( pnew_oc, errorbuf, errorbufsize,
+								0 /* don't strip options */ ) == 0 ) {
 		rc = schema_ds4x_compat ? LDAP_OPERATIONS_ERROR : LDAP_INVALID_SYNTAX;
 	}
 	/* insert new objectclass exactly where the old one one in the linked list*/
@@ -2338,7 +2361,8 @@
 		oc_update_inheritance_nolock( pnew_oc );
 	}
 
-	oc_unlock();
+	if (!(flags & DSE_SCHEMA_LOCKED))
+		oc_unlock();
 	return rc;
 }
 
@@ -2470,7 +2494,7 @@
 		}
 
 		if ( LDAP_SUCCESS != (rc = add_oc_internal(pnew_oc, errorbuf,
-					errorbufsize, schema_ds4x_compat))) {
+					errorbufsize, schema_ds4x_compat, 0/* no restriction */))) {
 			oc_free( &pnew_oc );
 			return rc;
 		}
@@ -2541,7 +2565,7 @@
 		struct objclass *addocp = NULL;
 
 		if ( LDAP_SUCCESS != ( rc = read_oc_ldif( mod->mod_bvalues[i]->bv_val,
-					&newocp, errorbuf, errorbufsize, 1 /* no locking */,
+					&newocp, errorbuf, errorbufsize, DSE_SCHEMA_NO_GLOCK,
 					1 /* user defined */, 0 /* no DS 4.x compat issues */ ))) {
 			rc = LDAP_INVALID_SYNTAX;
 			goto clean_up_and_return;
@@ -2695,7 +2719,12 @@
  *     oc                : pointer write the objectclass to
  *     errorbuf          : buffer to write any errors to
  *     is_user_defined   : if non-zero, force objectclass to be user defined
- *     nolock            : if non-zero, assume oc_lock_*() has been called.
+ *     schema_flags      : Any or none of the following bits could be set
+ *                         DSE_SCHEMA_NO_CHECK -- schema won't be checked
+ *                         DSE_SCHEMA_NO_GLOCK -- don't lock global resources
+ *                         DSE_SCHEMA_LOCKED   -- already locked with
+ *                                                slapi_load_schemafile_lock;
+ *                                                no further lock needed
  *     schema_ds4x_compat: if non-zero, act like Netscape DS 4.x
  *
  * Returns: an LDAP error code
@@ -2708,8 +2737,9 @@
  */
 static int
 read_oc_ldif ( const char *input, struct objclass **oc, char *errorbuf,
-		size_t errorbufsize, int nolock, int is_user_defined,
-		int schema_ds4x_compat ) {
+		size_t errorbufsize, PRUint32 schema_flags, int is_user_defined,
+		int schema_ds4x_compat )
+{
   int i, j, num_origins;
   const char *pstart, *nextinput;
   struct objclass *pnew_oc, *psup_oc;
@@ -2848,7 +2878,7 @@
   flags |= get_flag_keyword( schema_obsolete_with_spaces,
 			OC_FLAG_OBSOLETE, &nextinput, keyword_strstr_fn );
 
-  if (!nolock) {
+  if (!(schema_flags & DSE_SCHEMA_NO_GLOCK)) {
 	oc_lock_read();		/* needed because we access the superior oc */
   }
 
@@ -3005,7 +3035,7 @@
 	OrigAllowedAttrsArray = charray_dup ( AllowedAttrsArray );
   }
 
-  if (!nolock) {
+  if (!(schema_flags & DSE_SCHEMA_NO_GLOCK)) {
 	  oc_unlock();	/* we are done accessing superior oc (psup_oc) */
   }
 
@@ -3108,9 +3138,14 @@
  * if asipp is NULL, the attribute type is added to the global set of schema.
  * if asipp is not NULL, the AT is not added but *asipp is set.
  * 
- * if nolock is true, locking of global resources is turned off; this saves
- * time during initialization since the server operates in single threaded
- * mode at that time.
+ *    schema_flags: Any or none of the following bits could be set
+ *        DSE_SCHEMA_NO_CHECK -- schema won't be checked
+ *        DSE_SCHEMA_NO_GLOCK -- locking of global resources is turned off;
+ *                               this saves time during initialization since 
+ *                               the server operates in single threaded mode 
+ *                               at that time or in slapi_load_schemafile_lock.
+ *        DSE_SCHEMA_LOCKED   -- already locked with slapi_load_schemafile_lock;
+ *                               no further lock needed
  *
  * if is_user_defined is true, force attribute type to be user defined.
  *
@@ -3118,26 +3153,26 @@
 */
 static int
 read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
-		size_t errorbufsize, int nolock, int is_user_defined,
-		int schema_ds4x_compat, int is_remote)
+        size_t errorbufsize, PRUint32 schema_flags, int is_user_defined,
+        int schema_ds4x_compat, int is_remote)
 {
-	char *pStart, *pEnd;
-	char *pOid, *pSyntax, *pSuperior, *pMREquality, *pMROrdering, *pMRSubstring;
-	const char *nextinput;
-	struct sizedbuffer *psbAttrName= sizedbuffer_construct(BUFSIZ);
-	struct sizedbuffer *psbAttrDesc= sizedbuffer_construct(BUFSIZ);
-	int status = 0;
-	int syntaxlength;
-	char **attr_names = NULL;
-	char *first_attr_name = NULL;
-	char **attr_origins = NULL;
-	int num_names = 0;
-	int num_origins = 0;
-	unsigned long flags = SLAPI_ATTR_FLAG_OVERRIDE;
-	const char *ss = 0;
-	struct asyntaxinfo	*tmpasip;
-	int invalid_syntax_error;
-	schema_strstr_fn_t keyword_strstr_fn;
+    char *pStart, *pEnd;
+    char *pOid, *pSyntax, *pSuperior, *pMREquality, *pMROrdering, *pMRSubstring;
+    const char *nextinput;
+    struct sizedbuffer *psbAttrName= sizedbuffer_construct(BUFSIZ);
+    struct sizedbuffer *psbAttrDesc= sizedbuffer_construct(BUFSIZ);
+    int status = 0;
+    int syntaxlength;
+    char **attr_names = NULL;
+    char *first_attr_name = NULL;
+    char **attr_origins = NULL;
+    int num_names = 0;
+    int num_origins = 0;
+    unsigned long flags = SLAPI_ATTR_FLAG_OVERRIDE;
+    const char *ss = 0;
+    struct asyntaxinfo    *tmpasip;
+    int invalid_syntax_error;
+    schema_strstr_fn_t keyword_strstr_fn;
 
   /*
    * From RFC 2252 section 4.2:
@@ -3183,174 +3218,174 @@
    *   2. use a case-insensitive compare when looking for keywords, e.g., DESC
    */
 
-	if ( schema_ds4x_compat ) {
-		keyword_strstr_fn = PL_strcasestr;
-		invalid_syntax_error = LDAP_OPERATIONS_ERROR;
-	} else {
-		keyword_strstr_fn = PL_strstr;
-		invalid_syntax_error = LDAP_INVALID_SYNTAX;
-	}
+    if ( schema_ds4x_compat ) {
+        keyword_strstr_fn = PL_strcasestr;
+        invalid_syntax_error = LDAP_OPERATIONS_ERROR;
+    } else {
+        keyword_strstr_fn = PL_strstr;
+        invalid_syntax_error = LDAP_INVALID_SYNTAX;
+    }
 
-	if (nolock)
-		flags |= SLAPI_ATTR_FLAG_NOLOCKING;
+    if (schema_flags & DSE_SCHEMA_NO_GLOCK)
+        flags |= SLAPI_ATTR_FLAG_NOLOCKING;
 
-	psbAttrName->buffer[0] = '\0';
-	psbAttrDesc->buffer[0] = '\0';
-	pOid = pSyntax = pSuperior = NULL;
-	pMREquality = pMROrdering = pMRSubstring = NULL;
+    psbAttrName->buffer[0] = '\0';
+    psbAttrDesc->buffer[0] = '\0';
+    pOid = pSyntax = pSuperior = NULL;
+    pMREquality = pMROrdering = pMRSubstring = NULL;
     syntaxlength = SLAPI_SYNTAXLENGTH_NONE;
 
-	nextinput = input;
+    nextinput = input;
 
-	/* get the OID */
+    /* get the OID */
         pOid = get_tagged_oid( "(", &nextinput, keyword_strstr_fn );
 
-	if (NULL == pOid) {
-	  schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
-				  input, "Missing or invalid OID" );
-	  status = invalid_syntax_error;
-	  goto done;
-	}
-
-	if ( schema_ds4x_compat || (strcasecmp(pOid, "NAME") == 0))
-		nextinput = input;
-
-	/* look for the NAME (single or list of names) */
-	if ( (pStart = (*keyword_strstr_fn) ( nextinput, "NAME ")) != NULL ) {
-		pStart += 5;
-		sizedbuffer_allocate(psbAttrName,strlen(pStart)+1);
-		strcpy ( psbAttrName->buffer, pStart);
-		if (*pStart == '(')
-			pEnd = strchr(psbAttrName->buffer, ')');
-		else
-			pEnd = strchr(psbAttrName->buffer+1, '\'');
-		if (pEnd)
-			*(pEnd+1) = 0;
-		nextinput = pStart + strlen(psbAttrName->buffer) + 1;
-		attr_names = parse_qdescrs(psbAttrName->buffer, &num_names);
-		if ( NULL != attr_names ) {
-			first_attr_name = attr_names[0];
-		} else { /* NAME followed by nothing violates syntax */
-			schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
-									input, "Missing or invalid attribute name" );
-			status = invalid_syntax_error;
-			goto done;
-		}
-	}
+    if (NULL == pOid) {
+      schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
+                  input, "Missing or invalid OID" );
+      status = invalid_syntax_error;
+      goto done;
+    }
 
-	if ( schema_ds4x_compat ) nextinput = input;
+    if ( schema_ds4x_compat || (strcasecmp(pOid, "NAME") == 0))
+        nextinput = input;
 
-    /*
-	 * if the attribute ldif doesn't have an OID, we'll make the oid 
-	 * attrname-oid 
-	 */ 
-	if ( (strcasecmp ( pOid, "NAME" ) == 0) && (first_attr_name)) { 
-		slapi_ch_free_string( &pOid ); 
-		pOid = slapi_ch_smprintf("%s-oid", first_attr_name ); 
-	} 
-
-	/* look for the optional DESCription */
-	if ( (pStart = (*keyword_strstr_fn) ( nextinput, "DESC '")) != NULL ) {
-		pStart += 6;
-		sizedbuffer_allocate(psbAttrDesc,strlen(pStart));
-		strcpy ( psbAttrDesc->buffer, pStart);
-		if ( (pEnd = strchr (psbAttrDesc->buffer, '\'' )) != NULL ){
-			*pEnd ='\0';
-		}
-		nextinput = pStart + strlen(psbAttrDesc->buffer) + 1;
-	}
-
-	if ( schema_ds4x_compat ) nextinput = input;
-
-	/* look for the optional OBSOLETE marker */
-	flags |= get_flag_keyword( schema_obsolete_with_spaces,
-			SLAPI_ATTR_FLAG_OBSOLETE, &nextinput, keyword_strstr_fn );
-
-	if ( schema_ds4x_compat ) nextinput = input;
-
-	/* look for the optional SUPerior type */
-	pSuperior = get_tagged_oid( "SUP ", &nextinput, keyword_strstr_fn );
-
-	if ( schema_ds4x_compat ) nextinput = input;
-
-	/* look for the optional matching rules */
-	pMREquality = get_tagged_oid( "EQUALITY ", &nextinput, keyword_strstr_fn );
-	if ( schema_ds4x_compat ) nextinput = input;
-	pMROrdering = get_tagged_oid( "ORDERING ", &nextinput, keyword_strstr_fn );
-	if ( schema_ds4x_compat ) nextinput = input;
-	pMRSubstring = get_tagged_oid( "SUBSTR ", &nextinput, keyword_strstr_fn );
-	if ( schema_ds4x_compat ) nextinput = input;
-
-	/* look for the optional SYNTAX */
-	if ( NULL != ( pSyntax = get_tagged_oid( "SYNTAX ", &nextinput,
-			keyword_strstr_fn ))) {
-		/*
-		 * Check for an optional {LEN}, which if present indicates a
-		 * suggested maximum size for values of this attribute type.
-		 *
-		 * XXXmcs: we do not enforce length restrictions, but we do read
-		 * and include them in the subschemasubentry.
-		 */
-		if ( (pEnd = strchr ( pSyntax, '{')) != NULL /* balance } */ ) {
-			*pEnd = '\0';
-			syntaxlength = atoi( pEnd + 1 );
-		}
-	}
-
-	if ( schema_ds4x_compat ) nextinput = input;
+    /* look for the NAME (single or list of names) */
+    if ( (pStart = (*keyword_strstr_fn) ( nextinput, "NAME ")) != NULL ) {
+        pStart += 5;
+        sizedbuffer_allocate(psbAttrName,strlen(pStart)+1);
+        strcpy ( psbAttrName->buffer, pStart);
+        if (*pStart == '(')
+            pEnd = strchr(psbAttrName->buffer, ')');
+        else
+            pEnd = strchr(psbAttrName->buffer+1, '\'');
+        if (pEnd)
+            *(pEnd+1) = 0;
+        nextinput = pStart + strlen(psbAttrName->buffer) + 1;
+        attr_names = parse_qdescrs(psbAttrName->buffer, &num_names);
+        if ( NULL != attr_names ) {
+            first_attr_name = attr_names[0];
+        } else { /* NAME followed by nothing violates syntax */
+            schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
+                                    input, "Missing or invalid attribute name" );
+            status = invalid_syntax_error;
+            goto done;
+        }
+    }
 
-	/* look for the optional SINGLE-VALUE marker */
-	flags |= get_flag_keyword( " SINGLE-VALUE ",
-			SLAPI_ATTR_FLAG_SINGLE, &nextinput, keyword_strstr_fn );
+    if ( schema_ds4x_compat ) nextinput = input;
 
-	if ( schema_ds4x_compat ) nextinput = input;
+    /*
+     * if the attribute ldif doesn't have an OID, we'll make the oid 
+     * attrname-oid 
+     */ 
+    if ( (strcasecmp ( pOid, "NAME" ) == 0) && (first_attr_name)) { 
+        slapi_ch_free_string( &pOid ); 
+        pOid = slapi_ch_smprintf("%s-oid", first_attr_name ); 
+    } 
 
-	/* look for the optional COLLECTIVE marker */
-	flags |= get_flag_keyword( schema_collective_with_spaces,
-			SLAPI_ATTR_FLAG_COLLECTIVE, &nextinput, keyword_strstr_fn );
+    /* look for the optional DESCription */
+    if ( (pStart = (*keyword_strstr_fn) ( nextinput, "DESC '")) != NULL ) {
+        pStart += 6;
+        sizedbuffer_allocate(psbAttrDesc,strlen(pStart));
+        strcpy ( psbAttrDesc->buffer, pStart);
+        if ( (pEnd = strchr (psbAttrDesc->buffer, '\'' )) != NULL ){
+            *pEnd ='\0';
+        }
+        nextinput = pStart + strlen(psbAttrDesc->buffer) + 1;
+    }
 
-	if ( schema_ds4x_compat ) nextinput = input;
+    if ( schema_ds4x_compat ) nextinput = input;
 
-	/* look for the optional NO-USER-MODIFICATION marker */
-	flags |= get_flag_keyword( schema_nousermod_with_spaces,
-			SLAPI_ATTR_FLAG_NOUSERMOD, &nextinput, keyword_strstr_fn );
+    /* look for the optional OBSOLETE marker */
+    flags |= get_flag_keyword( schema_obsolete_with_spaces,
+            SLAPI_ATTR_FLAG_OBSOLETE, &nextinput, keyword_strstr_fn );
+
+    if ( schema_ds4x_compat ) nextinput = input;
+
+    /* look for the optional SUPerior type */
+    pSuperior = get_tagged_oid( "SUP ", &nextinput, keyword_strstr_fn );
+
+    if ( schema_ds4x_compat ) nextinput = input;
+
+    /* look for the optional matching rules */
+    pMREquality = get_tagged_oid( "EQUALITY ", &nextinput, keyword_strstr_fn );
+    if ( schema_ds4x_compat ) nextinput = input;
+    pMROrdering = get_tagged_oid( "ORDERING ", &nextinput, keyword_strstr_fn );
+    if ( schema_ds4x_compat ) nextinput = input;
+    pMRSubstring = get_tagged_oid( "SUBSTR ", &nextinput, keyword_strstr_fn );
+    if ( schema_ds4x_compat ) nextinput = input;
+
+    /* look for the optional SYNTAX */
+    if ( NULL != ( pSyntax = get_tagged_oid( "SYNTAX ", &nextinput,
+            keyword_strstr_fn ))) {
+        /*
+         * Check for an optional {LEN}, which if present indicates a
+         * suggested maximum size for values of this attribute type.
+         *
+         * XXXmcs: we do not enforce length restrictions, but we do read
+         * and include them in the subschemasubentry.
+         */
+        if ( (pEnd = strchr ( pSyntax, '{')) != NULL /* balance } */ ) {
+            *pEnd = '\0';
+            syntaxlength = atoi( pEnd + 1 );
+        }
+    }
 
-	if ( schema_ds4x_compat ) nextinput = input;
+    if ( schema_ds4x_compat ) nextinput = input;
 
-	/* look for the optional USAGE */
-	if (NULL != (ss = (*keyword_strstr_fn)(nextinput, " USAGE "))) {
-		ss += 7;
-		ss = skipWS(ss);
-		if (ss) {
-			if ( !PL_strncmp(ss, "directoryOperation",
-					strlen("directoryOperation"))) {
-				flags |= SLAPI_ATTR_FLAG_OPATTR;
-			}
-			if ( NULL == ( nextinput = strchr( ss, ' ' ))) {
-				nextinput = ss + strlen(ss);
-			}
-		}
-	}
+    /* look for the optional SINGLE-VALUE marker */
+    flags |= get_flag_keyword( " SINGLE-VALUE ",
+            SLAPI_ATTR_FLAG_SINGLE, &nextinput, keyword_strstr_fn );
+
+    if ( schema_ds4x_compat ) nextinput = input;
+
+    /* look for the optional COLLECTIVE marker */
+    flags |= get_flag_keyword( schema_collective_with_spaces,
+            SLAPI_ATTR_FLAG_COLLECTIVE, &nextinput, keyword_strstr_fn );
+
+    if ( schema_ds4x_compat ) nextinput = input;
+
+    /* look for the optional NO-USER-MODIFICATION marker */
+    flags |= get_flag_keyword( schema_nousermod_with_spaces,
+            SLAPI_ATTR_FLAG_NOUSERMOD, &nextinput, keyword_strstr_fn );
+
+    if ( schema_ds4x_compat ) nextinput = input;
+
+    /* look for the optional USAGE */
+    if (NULL != (ss = (*keyword_strstr_fn)(nextinput, " USAGE "))) {
+        ss += 7;
+        ss = skipWS(ss);
+        if (ss) {
+            if ( !PL_strncmp(ss, "directoryOperation",
+                    strlen("directoryOperation"))) {
+                flags |= SLAPI_ATTR_FLAG_OPATTR;
+            }
+            if ( NULL == ( nextinput = strchr( ss, ' ' ))) {
+                nextinput = ss + strlen(ss);
+            }
+        }
+    }
 
-	if ( schema_ds4x_compat ) nextinput = input;
+    if ( schema_ds4x_compat ) nextinput = input;
 
-	/* X-ORIGIN list */
-	attr_origins = parse_origin_list( nextinput, &num_origins,
-			schema_user_defined_origin );
+    /* X-ORIGIN list */
+    attr_origins = parse_origin_list( nextinput, &num_origins,
+            schema_user_defined_origin );
 
-	/* Do some sanity checking to make sure everything was read correctly */
-	
-	if (NULL == pOid) {
-		schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
-				first_attr_name, "Missing OID" );
-		status = invalid_syntax_error;
-	}
-	if (!status && (!attr_names || !num_names)) {
-		schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
-				first_attr_name,
-				"Missing name (OID is \"%s\")", pOid );
-		status = invalid_syntax_error;
-	}
+    /* Do some sanity checking to make sure everything was read correctly */
+    
+    if (NULL == pOid) {
+        schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
+                first_attr_name, "Missing OID" );
+        status = invalid_syntax_error;
+    }
+    if (!status && (!attr_names || !num_names)) {
+        schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
+                first_attr_name,
+                "Missing name (OID is \"%s\")", pOid );
+        status = invalid_syntax_error;
+    }
 
     if (!status && (NULL != pSuperior)) {
         struct asyntaxinfo *asi_parent;
@@ -3369,7 +3404,7 @@
             char *pso = plugin_syntax2oid(asi_parent->asi_plugin);
             
             if (pso) {
-				slapi_ch_free ((void **)&pSyntax);
+                slapi_ch_free ((void **)&pSyntax);
                 pSyntax = slapi_ch_strdup(pso);
                 LDAPDebug (LDAP_DEBUG_TRACE,
                     "Inheriting syntax %s from parent type %s\n",
@@ -3380,6 +3415,7 @@
                     "Missing parent attribute syntax OID");
                 status = invalid_syntax_error;
             }
+            attr_syntax_return( asi_parent );
         }
     }
     /* 
@@ -3401,135 +3437,137 @@
         }
     }
 
-	if (!status && (NULL == pSyntax)) {
-		schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
-				first_attr_name, "Missing attribute syntax OID");
-		status = invalid_syntax_error;
+    if (!status && (NULL == pSyntax)) {
+        schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
+                first_attr_name, "Missing attribute syntax OID");
+        status = invalid_syntax_error;
 
-	}
-	
-	if (!status && (plugin_syntax_find ( pSyntax ) == NULL) ) {
-		schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
-				first_attr_name, "Unknown attribute syntax OID \"%s\"",
-				pSyntax );
-		status = invalid_syntax_error;
-	}
-
-	if (!status) {
-		struct objclass *poc;
-		/* check to make sure that the OID isn't being used by an objectclass */
-		oc_lock_read();
-		poc = oc_find_oid_nolock( pOid );
-		if ( poc != NULL) {
-			schema_create_errormsg( errorbuf, errorbufsize,
-					schema_errprefix_at, first_attr_name,
-					"The OID \"%s\" is also used by the object class \"%s\"",
-					pOid, poc->oc_name);
-			status = LDAP_TYPE_OR_VALUE_EXISTS;
-		}
-		oc_unlock();
-	}
+    }
+    
+    if (!status && (plugin_syntax_find ( pSyntax ) == NULL) ) {
+        schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at,
+                first_attr_name, "Unknown attribute syntax OID \"%s\"",
+                pSyntax );
+        status = invalid_syntax_error;
+    }
 
-	if (!status && !element_is_user_defined( attr_origins )) {
-		if ( is_user_defined ) {
-			/* add missing user defined origin string */
-			charray_add( &attr_origins,
-						slapi_ch_strdup( schema_user_defined_origin[0] ));
-			++num_origins;
-		} else {
-			flags |= SLAPI_ATTR_FLAG_STD_ATTR;
-		}
-	}
+    if (!status) {
+        struct objclass *poc;
+        /* check to make sure that the OID isn't being used by an objectclass */
+        if (!(schema_flags & DSE_SCHEMA_LOCKED))
+            oc_lock_read();
+        poc = oc_find_oid_nolock( pOid );
+        if ( poc != NULL) {
+            schema_create_errormsg( errorbuf, errorbufsize,
+                    schema_errprefix_at, first_attr_name,
+                    "The OID \"%s\" is also used by the object class \"%s\"",
+                    pOid, poc->oc_name);
+            status = LDAP_TYPE_OR_VALUE_EXISTS;
+        }
+        if (!(schema_flags & DSE_SCHEMA_LOCKED))
+            oc_unlock();
+    }
 
-	if (!status) {
-		int ii;
-		/* check to see if the attribute name is valid */
-		for (ii = 0; !status && (ii < num_names); ++ii) {
-			if ( schema_check_name(attr_names[ii], PR_TRUE, errorbuf,
-					errorbufsize) == 0 ) {
-				status = invalid_syntax_error;
-			}
-			else if (!(flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
-					 attr_syntax_exists(attr_names[ii])) {
-				schema_create_errormsg( errorbuf, errorbufsize,
-					schema_errprefix_at, attr_names[ii],
-					"Could not be added because it already exists" );
-				status = LDAP_TYPE_OR_VALUE_EXISTS;
-			}
-		}
-	}
+    if (!status && !element_is_user_defined( attr_origins )) {
+        if ( is_user_defined ) {
+            /* add missing user defined origin string */
+            charray_add( &attr_origins,
+                        slapi_ch_strdup( schema_user_defined_origin[0] ));
+            ++num_origins;
+        } else {
+            flags |= SLAPI_ATTR_FLAG_STD_ATTR;
+        }
+    }
 
-	if (!status) {
-		if ( schema_check_oid ( first_attr_name, pOid, PR_TRUE, errorbuf,
-				errorbufsize ) == 0 ) {
-			status = invalid_syntax_error;
-		}
-	}
+    if (!(schema_flags & DSE_SCHEMA_NO_CHECK) && !status) {
+        int ii;
+        /* check to see if the attribute name is valid */
+        for (ii = 0; !status && (ii < num_names); ++ii) {
+            if ( schema_check_name(attr_names[ii], PR_TRUE, errorbuf,
+                    errorbufsize) == 0 ) {
+                status = invalid_syntax_error;
+            }
+            else if (!(flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
+                     attr_syntax_exists(attr_names[ii])) {
+                schema_create_errormsg( errorbuf, errorbufsize,
+                    schema_errprefix_at, attr_names[ii],
+                    "Could not be added because it already exists" );
+                status = LDAP_TYPE_OR_VALUE_EXISTS;
+            }
+        }
+    }
 
-	if (!status) {
-		struct asyntaxinfo	*tmpasi;
-
-		if (!(flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
-			( NULL != ( tmpasi = attr_syntax_get_by_oid(pOid)))) {
-			schema_create_errormsg( errorbuf, errorbufsize,
-				schema_errprefix_at, first_attr_name,
-				"Could not be added because the OID \"%s\" is already in use",
-				pOid);
-			status = LDAP_TYPE_OR_VALUE_EXISTS;
-			attr_syntax_return( tmpasi );
-		}
-	}
+    if (!(schema_flags & DSE_SCHEMA_NO_CHECK) && !status) {
+        if ( schema_check_oid ( first_attr_name, pOid, PR_TRUE, errorbuf,
+                errorbufsize ) == 0 ) {
+            status = invalid_syntax_error;
+        }
+    }
 
-	
-	if (!status) {
-		status = attr_syntax_create( pOid, attr_names, num_names,
-				*psbAttrDesc->buffer == '\0' ? NULL : psbAttrDesc->buffer,
-				pSuperior,
-				pMREquality, pMROrdering, pMRSubstring, attr_origins,
-				pSyntax, syntaxlength, flags, &tmpasip );
-	}
-
-	if (!status) {
-		if ( NULL != asipp ) {
-			*asipp = tmpasip;	/* just return it */
-		} else {				/* add the new attribute to the global store */
-			status = attr_syntax_add( tmpasip );
-			if ( LDAP_SUCCESS != status ) {
-				if ( 0 != (flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
-							LDAP_TYPE_OR_VALUE_EXISTS == status ) {
-					/*
-					 * This can only occur if the name and OID don't match the
-					 * attribute we are trying to override (all other cases of
-					 * "type or value exists" were trapped above).
-					 */
-					schema_create_errormsg( errorbuf, errorbufsize,
-							schema_errprefix_at, first_attr_name,
-							"Does not match the OID \"%s\". Another attribute"
-							" type is already using the name or OID.", pOid);
-				} else {
-					schema_create_errormsg( errorbuf, errorbufsize,
-							schema_errprefix_at, first_attr_name,
-							"Could not be added (OID is \"%s\")", pOid );
-				}
-				attr_syntax_free( tmpasip );
-			}
-		}
-	}
+    if (!status) {
+        struct asyntaxinfo    *tmpasi;
+
+        if (!(flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
+            ( NULL != ( tmpasi = attr_syntax_get_by_oid(pOid)))) {
+            schema_create_errormsg( errorbuf, errorbufsize,
+                schema_errprefix_at, first_attr_name,
+                "Could not be added because the OID \"%s\" is already in use",
+                pOid);
+            status = LDAP_TYPE_OR_VALUE_EXISTS;
+            attr_syntax_return( tmpasi );
+        }
+    }
+
+    
+    if (!status) {
+        status = attr_syntax_create( pOid, attr_names, num_names,
+                *psbAttrDesc->buffer == '\0' ? NULL : psbAttrDesc->buffer,
+                pSuperior,
+                pMREquality, pMROrdering, pMRSubstring, attr_origins,
+                pSyntax, syntaxlength, flags, &tmpasip );
+    }
+
+    if (!status) {
+        if ( NULL != asipp ) {
+            *asipp = tmpasip;    /* just return it */
+        } else {                /* add the new attribute to the global store */
+            status = attr_syntax_add( tmpasip );
+            if ( LDAP_SUCCESS != status ) {
+                if ( 0 != (flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
+                            LDAP_TYPE_OR_VALUE_EXISTS == status ) {
+                    /*
+                     * This can only occur if the name and OID don't match the
+                     * attribute we are trying to override (all other cases of
+                     * "type or value exists" were trapped above).
+                     */
+                    schema_create_errormsg( errorbuf, errorbufsize,
+                            schema_errprefix_at, first_attr_name,
+                            "Does not match the OID \"%s\". Another attribute"
+                            " type is already using the name or OID.", pOid);
+                } else {
+                    schema_create_errormsg( errorbuf, errorbufsize,
+                            schema_errprefix_at, first_attr_name,
+                            "Could not be added (OID is \"%s\")", pOid );
+                }
+                attr_syntax_free( tmpasip );
+            }
+        }
+    }
 
  done:
-	/* free everything */
-	free_qdlist(attr_names, num_names);
-	free_qdlist(attr_origins, num_origins);
-	sizedbuffer_destroy(psbAttrName);
-	sizedbuffer_destroy(psbAttrDesc);
-	slapi_ch_free((void **)&pOid);
-	slapi_ch_free((void **)&pSuperior);
-	slapi_ch_free((void **)&pMREquality);
-	slapi_ch_free((void **)&pMROrdering);
-	slapi_ch_free((void **)&pMRSubstring);
-	slapi_ch_free((void **)&pSyntax);
+    /* free everything */
+    free_qdlist(attr_names, num_names);
+    free_qdlist(attr_origins, num_origins);
+    sizedbuffer_destroy(psbAttrName);
+    sizedbuffer_destroy(psbAttrDesc);
+    slapi_ch_free((void **)&pOid);
+    slapi_ch_free((void **)&pSuperior);
+    slapi_ch_free((void **)&pMREquality);
+    slapi_ch_free((void **)&pMROrdering);
+    slapi_ch_free((void **)&pMRSubstring);
+    slapi_ch_free((void **)&pSyntax);
 
-	return status;
+    return status;
 }
 
 
@@ -3911,96 +3949,122 @@
  * Initialize attributes and objectclasses from the schema 
  *
  * Note that this function removes all values for `attributetypes'
- *		and `objectclasses' attributes from the entry `e'.
+ *        and `objectclasses' attributes from the entry `e'.
  *
  * returntext is always at least SLAPI_DSE_RETURNTEXT_SIZE bytes in size.
  */
 int
 load_schema_dse(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *ignored,
-				int *returncode, char *returntext, void *arg)
+                int *returncode, char *returntext, void *arg)
 {
-	Slapi_Attr *attr = 0;
-	int nolock = 1; /* don't lock global resources during initialization */
-	int primary_file = 0;	/* this is the primary (writeable) schema file */
-	int schema_ds4x_compat = config_get_ds4_compatible_schema();
+    Slapi_Attr *attr = 0;
+    int primary_file = 0;    /* this is the primary (writeable) schema file */
+    int schema_ds4x_compat = config_get_ds4_compatible_schema();
+    PRUint32 flags = *(PRUint32 *)arg;
+    flags |= DSE_SCHEMA_NO_GLOCK; /* don't lock global resources
+                                     during initialization */
 
-	*returncode = 0;
+    *returncode = 0;
 
-	/*
-	 * Note: there is no need to call schema_lock_write() here because this
-   	 * function is only called during server startup.
-	 */
+    /*
+     * Note: there is no need to call schema_lock_write() here because this
+        * function is only called during server startup.
+     */
 
-	slapi_pblock_get( pb, SLAPI_DSE_IS_PRIMARY_FILE, &primary_file );
+    slapi_pblock_get( pb, SLAPI_DSE_IS_PRIMARY_FILE, &primary_file );
 
-	if (!slapi_entry_attr_find(e, "attributetypes", &attr) && attr)
-	{
-		/* enumerate the values in attr */
-		Slapi_Value *v = 0;
-		int index = 0;
-		for (index = slapi_attr_first_value(attr, &v);
-			 v && (index != -1);
-			 index = slapi_attr_next_value(attr, index, &v))
-		{
-			const char *s = slapi_value_get_string(v);
-			if (!s)
-				continue;
-			if ((*returncode = read_at_ldif(s, NULL, returntext,
-						SLAPI_DSE_RETURNTEXT_SIZE, nolock,
-						primary_file /* force user defined? */,
-						schema_ds4x_compat, 0)) != 0)
-				break;
-		}
-		slapi_entry_attr_delete(e, "attributetypes");
-	}
+    if (!slapi_entry_attr_find(e, "attributetypes", &attr) && attr)
+    {
+        /* enumerate the values in attr */
+        Slapi_Value *v = 0;
+        int index = 0;
+        for (index = slapi_attr_first_value(attr, &v);
+             v && (index != -1);
+             index = slapi_attr_next_value(attr, index, &v))
+        {
+            const char *s = slapi_value_get_string(v);
+            if (!s)
+                continue;
+            if (flags & DSE_SCHEMA_NO_LOAD)
+            {
+                struct asyntaxinfo *tmpasip = NULL;
+                if ((*returncode = read_at_ldif(s, &tmpasip, returntext,
+                        SLAPI_DSE_RETURNTEXT_SIZE, flags,
+                        primary_file /* force user defined? */,
+                        schema_ds4x_compat, 0)) != 0)
+                    break;
+                attr_syntax_free( tmpasip );    /* trash it */
+            }
+            else
+            {
+                if ((*returncode = read_at_ldif(s, NULL, returntext,
+                        SLAPI_DSE_RETURNTEXT_SIZE, flags,
+                        primary_file /* force user defined? */,
+                        schema_ds4x_compat, 0)) != 0)
+                    break;
+            }
+        }
+        slapi_entry_attr_delete(e, "attributetypes");
+    }
 
-	if (*returncode)
-		return SLAPI_DSE_CALLBACK_ERROR;
+    if (*returncode)
+        return SLAPI_DSE_CALLBACK_ERROR;
 
-	if (!slapi_entry_attr_find(e, "objectclasses", &attr) && attr)
-	{
-		/* enumerate the values in attr */
-		Slapi_Value *v = 0;
-		int index = 0;
-		for (index = slapi_attr_first_value(attr, &v);
-			 v && (index != -1);
-			 index = slapi_attr_next_value(attr, index, &v))
-		{
-			struct objclass *oc = 0;
-			const char *s = slapi_value_get_string(v);
-			if (!s)
-				continue;
-			if ( LDAP_SUCCESS != (*returncode = read_oc_ldif(s, &oc, returntext,
-						SLAPI_DSE_RETURNTEXT_SIZE, nolock,
-						primary_file /* force user defined? */,
-						schema_ds4x_compat))) {
-				break;
-			}
-			if ( LDAP_SUCCESS != (*returncode = add_oc_internal(oc, returntext,
-						SLAPI_DSE_RETURNTEXT_SIZE, schema_ds4x_compat))) {
-				oc_free( &oc );
-				break;
-			}
-		}
-		slapi_entry_attr_delete(e, "objectclasses");
-	}
+    if (!slapi_entry_attr_find(e, "objectclasses", &attr) && attr)
+    {
+        /* enumerate the values in attr */
+        Slapi_Value *v = 0;
+        int index = 0;
+        for (index = slapi_attr_first_value(attr, &v);
+             v && (index != -1);
+             index = slapi_attr_next_value(attr, index, &v))
+        {
+            struct objclass *oc = 0;
+            const char *s = slapi_value_get_string(v);
+            if (!s)
+                continue;
+            if ( LDAP_SUCCESS != (*returncode = read_oc_ldif(s, &oc, returntext,
+                        SLAPI_DSE_RETURNTEXT_SIZE, flags,
+                        primary_file /* force user defined? */,
+                        schema_ds4x_compat))) {
+                break;
+            }
+            if (flags & DSE_SCHEMA_NO_LOAD)
+            {
+                /* we don't load the objectclase; free it */
+                oc_free( &oc );
+            }
+            else
+            {
+                if ( LDAP_SUCCESS !=
+                        (*returncode = add_oc_internal(oc, returntext,
+                        SLAPI_DSE_RETURNTEXT_SIZE, schema_ds4x_compat,
+                        flags))) {
+                    oc_free( &oc );
+                    break;
+                }
+            }
+        }
+        slapi_entry_attr_delete(e, "objectclasses");
+    }
 
-	/* Set the schema CSN */
-	if (!slapi_entry_attr_find(e, "nsschemacsn", &attr) && attr)
-	{
-		Slapi_Value *v = NULL;
-		slapi_attr_first_value(attr, &v);
-		if (NULL != v) {
-			const char *s = slapi_value_get_string(v);
-			if (NULL != s) {
-				CSN *csn = csn_new_by_string(s);
-				g_set_global_schema_csn(csn);
-			}
-		}
-	}
+    /* Set the schema CSN */
+    if (!(flags & DSE_SCHEMA_NO_LOAD) &&
+        !slapi_entry_attr_find(e, "nsschemacsn", &attr) && attr)
+    {
+        Slapi_Value *v = NULL;
+        slapi_attr_first_value(attr, &v);
+        if (NULL != v) {
+            const char *s = slapi_value_get_string(v);
+            if (NULL != s) {
+                CSN *csn = csn_new_by_string(s);
+                g_set_global_schema_csn(csn);
+            }
+        }
+    }
 
-	return (*returncode == LDAP_SUCCESS) ? SLAPI_DSE_CALLBACK_OK
-			: SLAPI_DSE_CALLBACK_ERROR;
+    return (*returncode == LDAP_SUCCESS) ? SLAPI_DSE_CALLBACK_OK
+            : SLAPI_DSE_CALLBACK_ERROR;
 }
 
 /*
@@ -4010,30 +4074,51 @@
  * schema entry into it.
  * 
  * Returns 1 for OK, 0 for Fail.
+ *
+ * schema_flags:
+ * DSE_SCHEMA_NO_LOAD      -- schema won't get loaded
+ * DSE_SCHEMA_NO_CHECK     -- schema won't be checked
+ * DSE_SCHEMA_NO_BACKEND   -- don't add as backend
+ * DSE_SCHEMA_LOCKED       -- already locked; no further lock needed
+
  */
-int
-init_schema_dse(const char *configdir)
+static int
+init_schema_dse_ext(char *schemadir, Slapi_Backend *be,
+				struct dse **local_pschemadse, PRUint32 schema_flags)
 {
-    int rc= 1; /* OK */
-	char *schemadir = 0;
+	int rc= 1; /* OK */
 	char *userschemafile = 0;
 	char *userschematmpfile = 0;
 	char **filelist = 0;
+	char *myschemadir = NULL;
 	Slapi_DN schema;
 
+	if (NULL == local_pschemadse)
+	{
+		return 0;	/* cannot proceed; return failure */
+	}
+
 	slapi_sdn_init_dn_byref(&schema,"cn=schema");
 
-	schemadir = config_get_schemadir();
-	if (NULL == schemadir) {
-		/* schemadir info is not configured, let's use the default place */
-		schemadir = slapi_ch_smprintf("%s/%s", configdir, SCHEMA_SUBDIR_NAME);
+	/* get schemadir if not given */
+	if (NULL == schemadir)
+	{
+		myschemadir = config_get_schemadir();
+		if (NULL == myschemadir)
+		{
+			return 0;	/* cannot proceed; return failure */
+		}
+	}
+	else
+	{
+		myschemadir = schemadir;
 	}
 
-	filelist = get_priority_filelist(schemadir, ".*ldif$");
+	filelist = get_priority_filelist(myschemadir, ".*ldif$");
 	if (!filelist || !*filelist)
 	{
 		slapi_log_error(SLAPI_LOG_FATAL, "schema",
-				"No schema files were found in the directory %s\n", schemadir);
+			"No schema files were found in the directory %s\n", myschemadir);
 		free_filelist(filelist);
 		rc = 0;
 	}
@@ -4046,21 +4131,26 @@
 		userschematmpfile = slapi_ch_smprintf("%s.tmp", userschemafile);
 	}
 
-    if(rc && (pschemadse==NULL))
-    {
-        pschemadse= dse_new_with_filelist(userschemafile,userschematmpfile, NULL, NULL, 
-										  schemadir,filelist);
-		PR_ASSERT(pschemadse);
-        if ((rc= (pschemadse!=NULL)) != 0)
-			dse_register_callback(pschemadse,DSE_OPERATION_READ,DSE_FLAG_PREOP,&schema,
-								  LDAP_SCOPE_BASE,NULL,
-								  load_schema_dse,NULL);
-		slapi_ch_free((void**)&userschematmpfile);
-    }
-	slapi_ch_free((void**)&schemadir);
+	if(rc)
+	{
+		*local_pschemadse = dse_new_with_filelist(userschemafile,
+						userschematmpfile, NULL, NULL, myschemadir, filelist);
+	}
+	PR_ASSERT(*local_pschemadse);
+	if ((rc = (*local_pschemadse != NULL)) != 0)
+	{
+		/* pass schema_flags as arguments */
+		dse_register_callback(*local_pschemadse,
+								  DSE_OPERATION_READ, DSE_FLAG_PREOP, &schema,
+								  LDAP_SCOPE_BASE, NULL,
+								  load_schema_dse, (void *)&schema_flags);
+	}
+	slapi_ch_free_string(&userschematmpfile);
+	if (NULL == schemadir)
+		slapi_ch_free_string(&myschemadir); /* allocated in this function */
 
-    if(rc)
-    {
+	if(rc)
+	{
 		char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE] = {0};
 		int dont_write = 1;
 		int merge = 1;
@@ -4073,14 +4163,30 @@
 		slapi_pblock_set(&pb, SLAPI_DSE_MERGE_WHEN_ADDING, (void*)&merge);
 		/* use the non duplicate checking str2entry */
 		slapi_pblock_set(&pb, SLAPI_DSE_DONT_CHECK_DUPS, (void*)&dont_dup_check);
+		/* borrow the task flag space */
+		slapi_pblock_set(&pb, SLAPI_SCHEMA_FLAGS, (void*)&schema_flags);
 
 		/* add the objectclass attribute so we can do some basic schema
 		   checking during initialization; this will be overridden when
 		   its "real" definition is read from the schema conf files */
-		rc = read_at_ldif("attributeTypes: ( 2.5.4.0 NAME 'objectClass' "
+		if (schema_flags & DSE_SCHEMA_NO_LOAD)
+		{
+			struct asyntaxinfo *tmpasip = NULL;
+			rc = read_at_ldif("attributeTypes: ( 2.5.4.0 NAME 'objectClass' "
 						  "DESC 'Standard schema for LDAP' SYNTAX "
 						  "1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 2252' )",
-						  NULL, errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, 1, 0, 0, 0);
+						  &tmpasip, errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+						  DSE_SCHEMA_NO_GLOCK|schema_flags, 0, 0, 0);
+			attr_syntax_free( tmpasip );	/* trash it */
+		}
+		else
+		{
+			rc = read_at_ldif("attributeTypes: ( 2.5.4.0 NAME 'objectClass' "
+						  "DESC 'Standard schema for LDAP' SYNTAX "
+						  "1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 2252' )",
+						  NULL, errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+						  DSE_SCHEMA_NO_GLOCK|schema_flags, 0, 0, 0);
+		}
 		if (rc)
 		{
 			slapi_log_error(SLAPI_LOG_FATAL, "schema", "Could not add"
@@ -4088,39 +4194,69 @@
 				errorbuf);
 		}
 
-		rc = dse_read_file(pschemadse, &pb);
-    }
+		rc = dse_read_file(*local_pschemadse, &pb);
+	}
 
-	if (rc)
+	if (rc && !(schema_flags & DSE_SCHEMA_NO_BACKEND))
 	{
 		/* make sure the schema is normalized */
-		normalize_oc();
+		if (schema_flags & DSE_SCHEMA_LOCKED)
+			normalize_oc_nolock();
+		else
+			normalize_oc();
 
 		/* register callbacks */
-		dse_register_callback(pschemadse,SLAPI_OPERATION_SEARCH,DSE_FLAG_PREOP,&schema,
-							  LDAP_SCOPE_BASE,NULL,read_schema_dse,NULL);
-		dse_register_callback(pschemadse,SLAPI_OPERATION_MODIFY,DSE_FLAG_PREOP,&schema,
-							  LDAP_SCOPE_BASE,NULL,modify_schema_dse,NULL);
-		dse_register_callback(pschemadse,SLAPI_OPERATION_DELETE,DSE_FLAG_PREOP,&schema,
-							  LDAP_SCOPE_BASE,NULL,dont_allow_that,NULL);
-		dse_register_callback(pschemadse,DSE_OPERATION_WRITE,DSE_FLAG_PREOP,&schema,
-							  LDAP_SCOPE_BASE,NULL,refresh_user_defined_schema,
-							  NULL);
+		dse_register_callback(*local_pschemadse, SLAPI_OPERATION_SEARCH,
+							  DSE_FLAG_PREOP,&schema, LDAP_SCOPE_BASE,
+							  NULL, read_schema_dse, NULL);
+		dse_register_callback(*local_pschemadse, SLAPI_OPERATION_MODIFY,
+							  DSE_FLAG_PREOP,&schema, LDAP_SCOPE_BASE,
+							  NULL, modify_schema_dse, NULL);
+		dse_register_callback(*local_pschemadse, SLAPI_OPERATION_DELETE,
+							  DSE_FLAG_PREOP, &schema, LDAP_SCOPE_BASE,
+							  NULL,dont_allow_that,NULL);
+		dse_register_callback(*local_pschemadse, DSE_OPERATION_WRITE,
+							  DSE_FLAG_PREOP, &schema, LDAP_SCOPE_BASE,
+							  NULL, refresh_user_defined_schema, NULL);
 
 		if (rc) {
-			Slapi_Backend	*be;
-
-			/* add as a backend */
-			be= be_new_internal(pschemadse,"DSE", "schema-internal"); /* JCM - should be a #define */
-			be_addsuffix(be,&schema);
+			if (NULL == be) {	/* be is not given. select it */
+				be = slapi_be_select_by_instance_name( DSE_SCHEMA );
+			}
+			if (NULL == be) {	/* first time */
+				/* add as a backend */
+				be = be_new_internal(*local_pschemadse, "DSE", DSE_SCHEMA);
+				be_addsuffix(be, &schema);
+			} else {					/* schema file reload */
+				struct slapdplugin *backend_plugin = NULL;
+				be_replace_dse_internal(be, *local_pschemadse);
+
+				/* ldbm has some internal attributes to be added */
+				backend_plugin = plugin_get_by_name("ldbm database");
+				if (backend_plugin) {
+					(backend_plugin->plg_add_schema)( NULL );
+				}
+			}
 		}
 	}
 
 	slapi_sdn_done(&schema);
-    return rc;
+	return rc;
 }
 
-
+int
+init_schema_dse(const char *configdir)
+{
+	char *schemadir = config_get_schemadir();
+	int rc = 0;
+	if (NULL == schemadir)
+	{
+		schemadir = slapi_ch_smprintf("%s/%s", configdir, SCHEMA_SUBDIR_NAME);
+	}
+	rc = init_schema_dse_ext(schemadir, NULL, &pschemadse, 0);
+	slapi_ch_free_string(&schemadir);
+	return rc;
+}
 
 /*
  * Look for `keyword' within `*inputp' and return the flag_value if found
@@ -4713,3 +4849,115 @@
 
 	oc_unlock();
 }
+
+void
+schema_expand_objectclasses_nolock( Slapi_Entry *e )
+{
+	Slapi_Attr		*sa;
+	Slapi_Value		**va;
+	const char		*dn = slapi_entry_get_dn_const( e );
+	int				i;
+
+	if ( 0 != slapi_entry_attr_find( e, SLAPI_ATTR_OBJECTCLASS, &sa )) {
+		return;		/* no OC values -- nothing to do */
+	}
+
+	va = attr_get_present_values( sa );
+
+	if ( va == NULL || va[0] == NULL ) {
+		return;		/* no OC values -- nothing to do */
+	}
+
+	/*
+	 * This loop relies on the fact that bv_expand_one_oc()
+	 * always adds to the end
+	 */
+	for ( i = 0; va[i] != NULL; ++i ) {
+		if ( NULL != slapi_value_get_string(va[i]) ) {
+			va_expand_one_oc( dn, &va, slapi_value_get_string(va[i]) );
+		}
+	}
+  
+	/* top must always be present */
+	va_expand_one_oc( dn, &va, "top" );
+
+	/*
+	 * Reset the present values in the set because we may have realloc'd it.
+	 * Note that this is the counterpart to the attr_get_present_values()
+	 * call we made above... nothing new has been allocated, but sa holds
+	 * a pointer to the original (pre realloc) va.
+	 */
+	sa->a_present_values.va = va;
+}
+
+/* lock to protect both objectclass and schema_dse */
+static void
+slapi_load_schemafile_lock()
+{
+	oc_lock_write();
+	schema_dse_lock_write();
+}
+
+static void
+slapi_load_schemafile_unlock()
+{
+	schema_dse_unlock();
+	oc_unlock();
+}
+
+/* API to validate the schema files */
+int
+slapi_validate_schema_files(char *schemadir)
+{
+	struct dse *my_pschemadse = NULL;
+	int rc = init_schema_dse_ext(schemadir, NULL, &my_pschemadse,
+			DSE_SCHEMA_NO_LOAD | DSE_SCHEMA_NO_BACKEND);
+	dse_destroy(my_pschemadse);
+	if (rc)
+		return LDAP_SUCCESS;
+	else {
+		slapi_log_error( SLAPI_LOG_FATAL, "schema_reload",
+				"schema file validation failed\n" );
+		return LDAP_OBJECT_CLASS_VIOLATION;
+	}
+}
+
+/* 
+ * API to reload the schema files.
+ * Rule: this function is called when slapi_validate_schema_files is passed.
+ *       Schema checking is skipped in this function.
+ */
+int
+slapi_reload_schema_files(char *schemadir)
+{
+	int rc = LDAP_SUCCESS;
+	struct dse *my_pschemadse = NULL;
+	/* get be to lock */
+	Slapi_Backend *be = slapi_be_select_by_instance_name( DSE_SCHEMA );
+
+	if (NULL == be)
+	{
+		slapi_log_error( SLAPI_LOG_FATAL, "schema_reload",
+				"schema file reload failed\n" );
+		return LDAP_LOCAL_ERROR;
+	}
+	slapi_be_Wlock(be);	/* be lock must be outer of schemafile lock */
+	slapi_load_schemafile_lock();
+	attr_syntax_delete_all();
+	oc_delete_all_nolock();
+	rc = init_schema_dse_ext(schemadir, be, &my_pschemadse,
+			   DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_LOCKED);
+	if (rc) {
+		dse_destroy(pschemadse);
+		pschemadse = my_pschemadse;
+		slapi_load_schemafile_unlock();
+		slapi_be_Unlock(be);
+		return LDAP_SUCCESS;
+	} else {
+		slapi_load_schemafile_unlock();
+		slapi_be_Unlock(be);
+		slapi_log_error( SLAPI_LOG_FATAL, "schema_reload",
+				"schema file reload failed\n" );
+		return LDAP_LOCAL_ERROR;
+	}
+}


Index: schemaparse.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/schemaparse.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- schemaparse.c	10 Nov 2006 23:45:40 -0000	1.5
+++ schemaparse.c	4 Jun 2008 22:22:55 -0000	1.6
@@ -254,6 +254,24 @@
 	oc_unlock();
 }
 
+void
+normalize_oc_nolock( void )
+{
+	struct objclass	*oc;
+
+	for ( oc = g_get_global_oc_nolock(); oc != NULL; oc = oc->oc_next ) {
+	  LDAPDebug (LDAP_DEBUG_PARSE, 
+				 "normalize_oc: normalizing '%s'\n", oc->oc_name, 0, 0);
+	  /* required attributes */
+	  normalize_list( oc->oc_required );
+	  normalize_list( oc->oc_orig_required );
+	  
+	  /* optional attributes */
+	  normalize_list( oc->oc_allowed );
+	  normalize_list( oc->oc_orig_allowed );
+	}
+}
+
 /*
  * oc_update_inheritance_nolock: 
  * If an objectclass is redefined, we need to make sure that any objectclasses


Index: slap.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slap.h,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- slap.h	16 May 2008 16:46:49 -0000	1.32
+++ slap.h	4 Jun 2008 22:22:55 -0000	1.33
@@ -776,7 +776,8 @@
 			IFP	plg_un_db_register_oc_callback; /* Register a function to call when a operation is applied to a given ObjectClass */
 			IFP	plg_un_db_init_instance;  /* initializes new db instance */
 			IFP	plg_un_db_wire_import;    /* fast replica update */
-			IFP	plg_un_db_verify;	  /* verify db files */
+			IFP	plg_un_db_add_schema;     /* add schema */
+			IFP	plg_un_db_verify;	      /* verify db files */
 		} plg_un_db;
 #define plg_bind		plg_un.plg_un_db.plg_un_db_bind
 #define plg_unbind		plg_un.plg_un_db.plg_un_db_unbind
@@ -808,6 +809,7 @@
 #define plg_rmdb		plg_un.plg_un_db.plg_un_db_rmdb
 #define plg_init_instance       plg_un.plg_un_db.plg_un_db_init_instance
 #define plg_wire_import         plg_un.plg_un_db.plg_un_db_wire_import
+#define plg_add_schema          plg_un.plg_un_db.plg_un_db_add_schema
 
 		/* extended operation plugin structure */
 		struct plg_un_protocol_extension {
@@ -1414,7 +1416,9 @@
 								   after the schema and syntax and matching rule plugins are
 								   running */
 	int pb_dse_is_primary_file;	/* for read callbacks: non-zero for primary file */
-	int pb_schema_user_defined_only; /* return user defined schema only */
+	int pb_schema_flags; 		/* schema flags */
+								/* . check/load info (schema reload task) */
+								/* . refresh user defined schema */
 
 	/* NEW in 5.0 for getting back the backend result in frontend */
 	int pb_result_code;			/* operation result code */


Index: slapi-plugin.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi-plugin.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- slapi-plugin.h	30 May 2008 15:39:00 -0000	1.21
+++ slapi-plugin.h	4 Jun 2008 22:22:55 -0000	1.22
@@ -217,6 +217,7 @@
    has the RDN as an attribute of the entry, and has all values for a
    given attribute type listed contiguously. */
 #define SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF 128
+#define SLAPI_STR2ENTRY_NO_SCHEMA_LOCK       256
 
 char *slapi_entry2str_with_options( Slapi_Entry *e, int *len, int options );
 /* Options for slapi_entry2str_with_options() */
@@ -1431,7 +1432,7 @@
 #define SLAPI_DSE_IS_PRIMARY_FILE		289
 
 /* internal schema flags */
-#define SLAPI_SCHEMA_USER_DEFINED_ONLY		285
+#define SLAPI_SCHEMA_FLAGS					285
 
 /* urp flags */
 #define SLAPI_URP_NAMING_COLLISION_DN	286


Index: slapi-private.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi-private.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- slapi-private.h	3 Apr 2008 16:52:46 -0000	1.21
+++ slapi-private.h	4 Jun 2008 22:22:55 -0000	1.22
@@ -648,6 +648,8 @@
 
 void be_set_sizelimit(Slapi_Backend * be, int sizelimit);
 void be_set_timelimit(Slapi_Backend * be, int timelimit);
+int be_isdeleted( const Slapi_Backend *be );
+
 
 /* used by mapping tree to delay sending of result code when several 
  * backend are parsed 
@@ -857,6 +859,7 @@
 #define SLAPI_PLUGIN_DB_WIRE_IMPORT_FN		234
 #define SLAPI_PLUGIN_DB_UPGRADEDB_FN		235
 #define SLAPI_PLUGIN_DB_DBVERIFY_FN			236
+#define SLAPI_PLUGIN_DB_ADD_SCHEMA_FN		237
 /* database plugin-specific parameters */
 #define SLAPI_PLUGIN_DB_NO_ACL        		250
 #define SLAPI_PLUGIN_DB_RMDB_FN         	280
@@ -1073,6 +1076,17 @@
 int slapi_config_register_callback(int operation, int flags, const char *base, int scope, const char *filter, dseCallbackFn fn, void *fn_arg);
 int slapi_config_remove_callback(int operation, int flags, const char *base, int scope, const char *filter, dseCallbackFn fn);
 int config_is_slapd_lite( void );
+void schema_expand_objectclasses_nolock( Slapi_Entry *e );
+
+#define DSE_SCHEMA_NO_LOAD           0x0001  /* schema won't get loaded */
+#define DSE_SCHEMA_NO_CHECK          0x0002  /* schema won't be checked */
+#define DSE_SCHEMA_NO_BACKEND        0x0004  /* don't add as backend */
+
+#define DSE_SCHEMA_NO_GLOCK          0x0010  /* don't lock global resources */
+#define DSE_SCHEMA_LOCKED            0x0020  /* already locked with
+                                              * slapi_load_schemafile_lock;
+                                              * no further lock needed */
+#define DSE_SCHEMA_USER_DEFINED_ONLY 0x0100  /* refresh user defined schema */
 
 #define SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY 0
 #define SLAPI_RTN_BIT_FETCH_PARENT_ENTRY 1




More information about the Fedora-directory-commits mailing list