IPC-Locker
view release on metacpan or search on metacpan
lib/IPC/Locker/Server.pm view on Meta::CPAN
$send .= "owner $clientvar->{owner}\n";
$send .= "locked $clientvar->{locked}\n";
$send .= "lockname $clientvar->{locks}[0]\n" if $clientvar->{locked};
$send .= "error $clientvar->{error}\n" if $clientvar->{error};
$send .= "\n\n"; # End of group. Some day we may not always send EOF immediately
return client_send ($clientvar, $send);
}
sub client_lock_list {
my $clientvar = shift || die;
_timelog("c$clientvar->{client_num}: Locklist!\n") if $Debug;
while (my ($lockname, $lock) = each %Locks) {
if (!$lock->{locked}) {
_timelog("c$clientvar->{client_num}: Note unlocked lock $lockname\n") if $Debug;
next;
}
client_send ($clientvar, "lock $lockname $lock->{owner}\n");
}
return client_send ($clientvar, "\n\n");
}
sub client_lock {
# Client wants this lock, return true if delayed transaction
my $clientvar = shift || die;
# Fast case, see if there are any non-allocated locks
foreach my $lockname (@{$clientvar->{locks}}) {
_timelog("c$clientvar->{client_num}: check $lockname\n") if $Debug;
my $locki = locki_find ($lockname);
if ($locki && $locki->{owner} ne $clientvar->{user}) {
# See if the user's machine can clear it
if ($locki->{autounlock} && $clientvar->{autounlock}) {
# The 2 is for supports DEAD_PID added in version 1.480
# Older clients will ignore it.
client_send ($clientvar, "autounlock_check $locki->{lock} $locki->{hostname} $locki->{pid} 2\n");
}
# Try to have timer/exister clear up existing lock
locki_recheck($locki,undef); # locki maybe deleted
} else {
if (!$clientvar->{locked}) { # Unlikely - some async path established the lock
# Know there's a free lock; for speed, munge request to point to only it
$clientvar->{locks} = [$lockname];
last;
}
}
}
# Create lock requests
my $first_locki = undef;
foreach my $lockname (@{$clientvar->{locks}}) {
_timelog("c$clientvar->{client_num}: new $lockname\n") if $Debug;
# Create new request. If it can be serviced, this will
# establish the lock and send status back.
my $locki = locki_new_request($lockname, $clientvar);
$first_locki ||= $locki;
# Done if found free lock
last if $clientvar->{locked};
}
# All locks busy?
if ($clientvar->{locked}) {
# Done, and we already sent client_status when the lock was made
return 0;
} elsif (!$clientvar->{block}) {
# All busy, and user wants non-blocking, just send status
client_status($clientvar);
return 0;
} else {
# All busy, we need to block the user's request and tell the user
if (!$clientvar->{told_locked} && $first_locki) {
$clientvar->{told_locked} = 1;
client_send ($clientvar, "print_waiting $first_locki->{owner}\n");
}
# Either need to wait for timeout, or someone else to return key
return 1; # Exit loop and check if can lock later
}
}
sub client_break {
my $clientvar = shift || die;
# The locki may be deleted by this call
foreach my $lockname (@{$clientvar->{locks}}) {
if (my $locki = locki_find ($lockname)) {
if ($locki->{locked}) {
_timelog("c$clientvar->{client_num}: broke lock $locki->{locks} User $clientvar->{user}\n") if $Debug;
client_send ($clientvar, "print_broke $locki->{owner}\n");
locki_unlock ($locki); # locki may be deleted
}
}
}
client_status ($clientvar);
}
sub client_unlock {
my $clientvar = shift || die;
# Client request to unlock the given lock
# The locki may be deleted by this call
$clientvar->{locked} = 0;
foreach my $lockname (@{$clientvar->{locks}}) {
if (my $locki = locki_find ($lockname)) {
if ($locki->{owner} eq $clientvar->{user}) {
_timelog("c$clientvar->{client_num}: Unlocked $locki->{lock} User $clientvar->{user}\n") if $Debug;
locki_unlock ($locki); # locki may be deleted
} else {
# Doesn't hold lock but might be waiting for it.
_timelog("c$clientvar->{client_num}: Waiter count: ".$#{$locki->{waiters}}."\n") if $Debug;
for (my $n=0; $n <= $#{$locki->{waiters}}; $n++) {
if ($locki->{waiters}[$n]{user} eq $clientvar->{user}) {
_timelog("c$clientvar->{client_num}: Dewait $locki->{lock} User $clientvar->{user}\n") if $Debug;
splice @{$locki->{waiters}}, $n, 1;
}
}
}
}
}
client_status ($clientvar);
}
sub client_send {
# Send a string to the client, return 1 if success
my $clientvar = shift || die;
my $msg = shift;
my $clientfh = $clientvar->{socket};
return 0 if (!$clientfh);
_timelog_split("c$clientvar->{client_num}: RESP $clientfh",
(' 'x24)."c$clientvar->{client_num}: RES ", $msg) if $Debug;
$SIG{PIPE} = 'IGNORE';
( run in 1.127 second using v1.01-cache-2.11-cpan-39bf76dae61 )