+static void
+at_delete_names( AttributeType *at )
+{
+ char **names = at->sat_names;
+
+ while (*names) {
+ struct aindexrec tmpair, *air;
+
+ ber_str2bv( *names, 0, 0, &tmpair.air_name );
+ tmpair.air_at = at;
+ air = (struct aindexrec *)avl_delete( &attr_index,
+ (caddr_t)&tmpair, attr_index_cmp );
+ assert( air != NULL );
+ ldap_memfree( air );
+ names++;
+ }
+}
+
+/* Mark the attribute as deleted, remove from list, and remove all its
+ * names from the AVL tree. Leave the OID in the tree.
+ */
+void
+at_delete( AttributeType *at )
+{
+ at->sat_flags |= SLAP_AT_DELETED;
+
+ LDAP_STAILQ_REMOVE(&attr_list,at,slap_attribute_type,sat_next);
+
+ at_delete_names( at );
+}
+
+static void
+at_clean( AttributeType *a )
+{
+ if ( a->sat_equality ) {
+ MatchingRule *mr;
+
+ mr = mr_find( a->sat_equality->smr_oid );
+ assert( mr != NULL );
+ if ( mr != a->sat_equality ) {
+ ch_free( a->sat_equality );
+ a->sat_equality = NULL;
+ }
+ }
+
+ assert( a->sat_syntax != NULL );
+ if ( a->sat_syntax != NULL ) {
+ Syntax *syn;
+
+ syn = syn_find( a->sat_syntax->ssyn_oid );
+ assert( syn != NULL );
+ if ( syn != a->sat_syntax ) {
+ ch_free( a->sat_syntax );
+ a->sat_syntax = NULL;
+ }
+ }
+
+ if ( a->sat_oidmacro ) ldap_memfree( a->sat_oidmacro );
+ if ( a->sat_subtypes ) ldap_memfree( a->sat_subtypes );
+}
+
+static void
+at_destroy_one( void *v )
+{
+ struct aindexrec *air = v;
+ AttributeType *a = air->air_at;
+
+ at_clean( a );
+ ad_destroy(a->sat_ad);
+ ldap_pvt_thread_mutex_destroy(&a->sat_ad_mutex);
+ ldap_attributetype_free((LDAPAttributeType *)a);
+ ldap_memfree(air);
+}
+