gunnar: server/perl-kolab/lib/Kolab LDAP.pm,1.3,1.4
cvs at kolab.org
cvs at kolab.org
Tue Jul 1 16:10:46 CEST 2008
Author: gunnar
Update of /kolabrepository/server/perl-kolab/lib/Kolab
In directory doto:/tmp/cvs-serv20229/perl-kolab/lib/Kolab
Modified Files:
LDAP.pm
Log Message:
kolab/issue2827 (Deleting users does not work reliably)
Index: LDAP.pm
===================================================================
RCS file: /kolabrepository/server/perl-kolab/lib/Kolab/LDAP.pm,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- LDAP.pm 4 Feb 2008 16:40:18 -0000 1.3
+++ LDAP.pm 1 Jul 2008 14:10:44 -0000 1.4
@@ -38,7 +38,6 @@
use Kolab::Cyrus;
use Digest::SHA1 qw(sha1);
use MIME::Base64 qw(encode_base64);
-use vars qw(%uid_db %gyard_db %newuid_db %gyard_ts_db %quota_db);
require Exporter;
@@ -71,49 +70,236 @@
our $user_timestamp = "";
our $sf_timestamp = "";
our $group_timestamp = "";
+our $db_statedir = '';
+our %newuid_db;
sub startup
{
- my $statedir = shift;
+ my $statedir = shift || '';
Kolab::log('L', 'Starting up');
+ if (!$db_statedir && $statedir) {
+ $db_statedir = $statedir;
+ }
+
+}
+
+sub shutdown
+{
+ Kolab::log('L', 'Shutting down');
+}
+
+sub uidcacheOpen
+{
Kolab::log('L', 'Opening mailbox uid cache DB');
- if (!dbmopen(%uid_db, "$statedir/mailbox-uidcache.db", 0666)) {
+ my %uid_db;
+ if (!dbmopen(%uid_db, "$db_statedir/mailbox-uidcache.db", 0666)) {
Kolab::log('L', 'Unable to open mailbox uid cache DB', KOLAB_ERROR);
exit(1);
}
+ return \%uid_db;
+}
+
+sub uidcacheClose (\%)
+{
+ my ($uid_db) = @_;
+ dbmclose(%{$uid_db});
+ untie %{$uid_db};
+}
+
+sub uidcacheStore
+{
+ my $guid = shift;
+ my $uid = shift;
+
+ my $uid_db = uidcacheOpen();
+
+ ${$uid_db}{$guid} = $uid;
+
+ uidcacheClose(%$uid_db);
+}
+
+sub uidcacheFetch
+{
+ my $guid = shift;
+
+ my $uid_db = uidcacheOpen();
+
+ my $uid = ${$uid_db}{$guid} || '';
+
+ uidcacheClose(%$uid_db);
+
+ return $uid;
+}
+
+sub uidcacheDelete
+{
+ my $guid = shift;
+
+ my $uid_db = uidcacheOpen();
+
+ delete ${$uid_db}{$guid};
+
+ uidcacheClose(%$uid_db);
+}
+
+sub graveyardOpen
+{
Kolab::log('L', 'Opening graveyard uid/timestamp cache DB');
- if (!dbmopen(%gyard_db, "$statedir/graveyard-uidcache.db", 0666)) {
+ my %gyard_db;
+ if (!dbmopen(%gyard_db, "$db_statedir/graveyard-uidcache.db", 0666)) {
Kolab::log('L', 'Unable to open graveyard uid cache DB', KOLAB_ERROR);
exit(1);
}
- if (!dbmopen(%gyard_ts_db, "$statedir/graveyard-tscache.db", 0666)) {
+ my %gyard_ts_db;
+ if (!dbmopen(%gyard_ts_db, "$db_statedir/graveyard-tscache.db", 0666)) {
Kolab::log('L', 'Unable to open graveyard timestamp cache DB', KOLAB_ERROR);
exit(1);
}
+ return \(%gyard_db, %gyard_ts_db);
+}
+
+sub graveyardClose (\%\%)
+{
+ my ($gyard_db, $gyard_ts_db) = @_;
+
+ dbmclose(%$gyard_db);
+ dbmclose(%$gyard_ts_db);
+
+ untie %$gyard_db;
+ untie %$gyard_ts_db;
+}
+
+sub graveyardRessurect
+{
+ my $guid = shift;
+ my $uid = shift;
+
+ my $gyard_db;
+ my $gyard_ts_db;
+ ($gyard_db, $gyard_ts_db) = graveyardOpen();
+
+ my $oldgyarduid = $$gyard_db{$guid} || '';
+ if ($oldgyarduid) {
+ # The object needs to be resurrected!
+ if ($oldgyarduid ne $uid) {
+ Kolab::log('L', "Resurrected object `$uid' already exists as `$oldgyarduid'; refusing to create", KOLAB_WARN);
+ } else {
+ Kolab::log('L', "Object `$uid' has been resurrected", KOLAB_DEBUG);
+ }
+ # Remove the object from the graveyard
+ delete $$gyard_db{$guid};
+ delete $$gyard_ts_db{$guid};
+ }
+
+ graveyardClose(%$gyard_db, %$gyard_ts_db);
+
+ return $oldgyarduid;
+}
+
+sub graveyardStore
+{
+ my $guid = shift;
+ my $uid = shift;
+
+ my $gyard_db;
+ my $gyard_ts_db;
+ ($gyard_db, $gyard_ts_db) = graveyardOpen();
+
+ $$gyard_db{$guid} = $uid;
+ $$gyard_ts_db{$guid} = time;
+
+ graveyardClose(%$gyard_db, %$gyard_ts_db);
+}
+
+sub graveyardCleanup
+{
+ my $guid = shift;
+ my $uid = shift;
+
+ my $gyard_db;
+ my $gyard_ts_db;
+ ($gyard_db, $gyard_ts_db) = graveyardOpen();
+
+ my $now = time;
+ my $period = $Kolab::config{'gyard_deletion_period'} * 60;
+ Kolab::log('L', 'Gravekeeping (period = ' . $Kolab::config{'gyard_deletion_period'} . ' minutes)');
+ foreach $guid (keys %$gyard_ts_db) {
+ if ($now - $$gyard_ts_db{$guid} > $period) {
+ Kolab::log('L', "Clearing graveyard database entry `" . $$gyard_db{$guid} . "'");
+ #Kolab::Cyrus::deleteMailbox($cyrus, $$gyard_db{$guid}, 0);
+ delete $$gyard_ts_db{$guid};
+ delete $$gyard_db{$guid};
+ }
+ }
+ graveyardClose(%$gyard_db, %$gyard_ts_db);
+}
+
+sub quotaOpen
+{
Kolab::log('L', 'Opening mailbox quota cache DB');
- if (!dbmopen(%quota_db, "$statedir/mailbox-quotacache.db", 0666)) {
+ my %quota_db;
+ if (!dbmopen(%quota_db, "$db_statedir/mailbox-quotacache.db", 0666)) {
Kolab::log('L', 'Unable to open mailbox quota cache DB', KOLAB_ERROR);
exit(1);
}
+
+ return \%quota_db;
}
-sub shutdown
+sub quotaClose (\%)
{
- Kolab::log('L', 'Shutting down');
+ my ($quota_db) = @_;
- dbmclose(%uid_db);
- dbmclose(%gyard_db);
- dbmclose(%quota_db);
+ dbmclose(%$quota_db);
+ untie $quota_db;
+}
+
+sub quotaStore
+{
+ my $guid = shift;
+ my $quota = shift;
+
+ my $quota_db = quotaOpen();
+
+ $$quota_db{$guid} = $quota;
+
+ quotaClose(%$quota_db);
+}
+
+sub quotaFetch
+{
+ my $guid = shift;
+
+ my $quota_db = quotaOpen();
+
+ my $quota = $$quota_db{$guid} || 0;
+
+ quotaClose(%$quota_db);
+
+ return $quota;
+}
+
+sub quotaDelete
+{
+ my $guid = shift;
+
+ my $quota_db = quotaOpen();
+
+ delete $$quota_db{$guid};
+
+ quotaClose(%$quota_db);
}
+
+
sub create
{
my $ip = shift;
@@ -303,7 +489,7 @@
my $guid = $object->get_value($Kolab::config{$p . '_field_guid'});
Kolab::log('L', "GUID attribute `" . $Kolab::config{$p . '_field_guid'} . "' is `$guid'", KOLAB_DEBUG);
- my $olduid = $uid_db{$guid} || '';
+ my $olduid = uidcacheFetch($guid);
if ($olduid) {
# We have records of the object
$newuid_db{$guid} = $olduid if ($sync);
@@ -316,23 +502,13 @@
# Nothing changed; nothing to do
} else {
# No official records - check the graveyard
- my $oldgyarduid = $gyard_db{$guid} || '';
+ my $oldgyarduid = graveyardRessurect($guid, $uid);
if ($oldgyarduid) {
- # The object needs to be resurrected!
- if ($oldgyarduid ne $uid) {
- Kolab::log('L', "Resurrected object `$uid' already exists as `$oldgyarduid'; refusing to create", KOLAB_WARN);
- } else {
- Kolab::log('L', "Object `$uid' has been resurrected", KOLAB_DEBUG);
- }
-
- # Remove the object from the graveyard
- if ($sync) { $newuid_db{$guid} = $oldgyarduid; } else { $uid_db{$guid} = $oldgyarduid; }
- delete $gyard_db{$guid};
- delete $gyard_ts_db{$guid};
+ if ($sync) { $newuid_db{$guid} = $oldgyarduid; } else { uidcacheStore($guid, $oldgyarduid); }
} else {
Kolab::log('L', "Creating user `$uid' corresponding to GUID `$guid'", KOLAB_DEBUG);
# We have a object that we have no previous record of, so create everything
- if ($sync) { $newuid_db{$guid} = $uid; } else { $uid_db{$guid} = $uid; }
+ if ($sync) { $newuid_db{$guid} = $uid; } else { uidcacheStore($guid, $uid); }
Kolab::Cyrus::createMailbox($cyrus, $uid, ($p eq 'sf' ? 1 : 0));
if( $p eq 'sf' ){
my $foldertype = lc($object->get_value('kolabfoldertype'));
@@ -374,13 +550,13 @@
my $quota = $object->get_value($Kolab::config{$p . '_field_quota'});
defined($quota) or ($quota = 0);
- my $oldquota = $quota_db{$guid} || 0;
+ my $oldquota = quotaFetch($guid);
if( $quota != $oldquota ) {
- Kolab::Cyrus::setQuota($cyrus, $uid, $quota*1024, ($p eq 'sf' ? 1 : 0));
- if( $quota == 0 ) {
- delete $quota_db{$guid};
+ Kolab::Cyrus::setQuota($cyrus, $uid, $quota*1024, ($p eq 'sf' ? 1 : 0));
+ if( $quota == 0 ) {
+ quotaDelete{$guid};
} else {
- $quota_db{$guid} = $quota;
+ quotaStore($guid, $quota);
}
}
Kolab::log('L', "createObject() done", KOLAB_DEBUG );
@@ -506,15 +682,15 @@
}
my $guid = $object->get_value($Kolab::config{$p . '_field_guid'});
- my $uid = $uid_db{$guid} || 0;
+ my $uid = uidcacheFetch($guid);
if (!$uid) {
Kolab::log('L', 'Deleted object not found in mboxcache, returning', KOLAB_DEBUG);
return;
}
Kolab::Cyrus::deleteMailbox($cyrus, $uid, ($p eq 'sf' ? 1 : 0));
- delete $uid_db{$guid};
- delete $quota_db{$guid};
+ uidcacheDelete($guid);
+ quotaDelete($guid);
return 1;
}
@@ -551,30 +727,24 @@
delete $objects{$newuid_db{$guid}} if (exists $objects{$newuid_db{$guid}});
}
+ my $uid_db = uidcacheOpen();
# Any mailboxes left should be sent to the graveyard; these are mailboxes
# without a corresponding LDAP object, yet we were never informed of their
# deletion, i.e. either we missed the deletion notification or there was
# an error when iterating through the objects (Lost connection, invalid DNs)
- foreach $guid (keys %uid_db) {
- if (defined $uid_db{$guid} && exists $objects{$uid_db{$guid}}) {
- $gyard_db{$guid} = $uid_db{$guid};
- $gyard_ts_db{$guid} = time;
+ foreach $guid (keys %$uid_db) {
+ if (defined $$uid_db{$guid} && exists $objects{$$uid_db{$guid}}) {
+ graveyardStore($guid, $$uid_db{$guid});
}
}
+ uidcacheClose(%$uid_db);
- my $now = time;
- my $period = $Kolab::config{'gyard_deletion_period'} * 60;
- Kolab::log('L', 'Gravekeeping (period = ' . $Kolab::config{'gyard_deletion_period'} . ' minutes)');
- foreach $guid (keys %gyard_ts_db) {
- if ($now - $gyard_ts_db{$guid} > $period) {
- Kolab::log('L', "Clearing graveyard database entry `" . $gyard_db{$guid} . "'");
- #Kolab::Cyrus::deleteMailbox($cyrus, $gyard_db{$guid}, 0);
- delete $gyard_ts_db{$guid};
- delete $gyard_db{$guid};
- }
- }
+ graveyardCleanup();
- %uid_db = %newuid_db;
+ my $newuid;
+ foreach $newuid (keys %newuid_db) {
+ uidcacheStore($newuid, $newuid_db{$newuid});
+ }
syncDomains();
More information about the commits
mailing list