[prev in list] [next in list] [prev in thread] [next in thread] 

List:       perl-ldap-dev
Subject:    Re: deleting a whole subtree
From:       192.100.124.27
Date:       2004-10-26 7:36:16
Message-ID: sm3c023p8v.fsf () spade ! ntc ! nokia ! com
[Download RAW message or body]

>>>>> "Kurt" == Kurt D Zeilenga <Kurt@OpenLDAP.org> writes:

Kurt> At 02:12 AM 3/23/2004, Claude wrote:
>> Is walking bottom-up through a subtree deleting each leaf entry the
>> best way to delete the entire subtree?

Kurt> Well, by "walking bottom-up", I assume you mean using one-level
Kurt> searches to walk down and then delete entries on the way up.
Kurt> A better way, I think, is to do a single subtree search and
Kurt> then blast deletes for all leafs.  As you get responses back,
Kurt> issue deletes for entry that becomes (by prior deletes) a
Kurt> leaf.

Kurt> There are non-portable extensions that you might experiment
Kurt> with.  But I suggest you stir clear of them.  Besides being
Kurt> non-portable, the extensions I've seen so far don't support
Kurt> distributed directories.  (That is, the subtree may not
Kurt> necessarily be held within one context.)

Kurt> Kurt 

Does the code below correspond to what you had in mind? wipeEntries is
reentrant and exits as soon as there are no more entries holding the
attribute 'hasSubordinates' set to false or... if the tree is too
deep.

I am not sure this last condition is needed after all, since the
requirement is to delete a whole subtree no matter how big or deep it
is. 

Furthermore, $deep does not reflect the depth of the tree from root
downward but rather from the deepest leaf upward which is a rather odd
way to express the depth. Exiting on a depth overflow leaves the
tree in a rather unpleasant state.

I am open to suggestions and improvement ideas.

I tested it with Netscape 6.11 and Sun ONE 5.2. Distributed
directories were out of my scope. For now.

use Net::LDAP;

my $ldap = Net::LDAP->new( $LDAPhost, async => 0 )
  or die "- Cannot create LDAP object: $@";
my $msg = $ldap->bind( $usr, password => $pwd );

$msg->code && die " - Cannot bind $usr to $LDAPhost: ", $msg->error  ;

wipeEntries( $ldap );

$msg = $ldap->unbind;


my $loop = 0;
my $depth = 20;

sub wipeEntries( $ ) {
  die "- subtree depth $depth exceeded, exiting\n"
    unless ( $loop++ < $depth );
  
  my $ldap = shift @_;
  my $filter = '(objectClass=*)';

  my $msg = $ldap->search(
			  base   => $base,
			  scope  => 'sub', # base, one, sub
			  filter => $filter,
			  attrs  => [ 'hasSubordinates' ],
			 );
  my $max = $msg->count;

  print "- Found $max service entries in subtree $base:";

  # don't delete topmost entry (last to become a leaf)
  return unless ( $max > 1 );

  for ( my $i = 0 ; $i < $max ; $i++ ) {
    my $entry = $msg->entry( $i );
    my $val = $entry->get_value( 'hasSubordinates' );
    if ( $val =~ /false/i ) {
      print join( ' ', $i, $entry->dn(), "\n" );
      $entry->delete();
      my $msg1 = $entry->update( $ldap );
      $msg1->code && die "- Cannot delete entry: ", $msg->error, "\n";
    }
  }
  wipeEntries( $ldap );
}
-- 
        Claude
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic