view release on metacpan or search on metacpan
get_av|5.006000|5.003007|p
getc|5.003007||Viu
get_c_backtrace|5.021001||Vi
get_c_backtrace_dump|5.021001||V
get_context|5.006000|5.006000|nu
getc_unlocked|5.003007||Viu
get_cv|5.006000|5.003007|p
get_cvn_flags|5.009005|5.003007|p
get_cvs|5.011000|5.003007|p
getcwd_sv|5.007002|5.007002|
get_db_sub|||iu
PERL_MALLOC_WRAP|5.009002|5.009002|Vn
PerlMem_calloc|5.006000||Viu
PerlMem_free|5.005000||Viu
PerlMem_free_lock|5.006000||Viu
PerlMem_get_lock|5.006000||Viu
PerlMem_is_locked|5.006000||Viu
PerlMem_malloc|5.005000||Viu
PERL_MEMORY_DEBUG_HEADER_SIZE|5.019009||Viu
PerlMemParse_calloc|5.006000||Viu
PerlMemParse_free|5.006000||Viu
PerlMemParse_free_lock|5.006000||Viu
PerlMemParse_get_lock|5.006000||Viu
PerlMemParse_is_locked|5.006000||Viu
PerlMemParse_malloc|5.006000||Viu
PerlMemParse_realloc|5.006000||Viu
PerlMem_realloc|5.005000||Viu
PerlMemShared_calloc|5.006000||Viu
PerlMemShared_free|5.006000||Viu
PerlMemShared_free_lock|5.006000||Viu
PerlMemShared_get_lock|5.006000||Viu
PerlMemShared_is_locked|5.006000||Viu
PerlMemShared_malloc|5.006000||Viu
PerlMemShared_realloc|5.006000||Viu
PERL_MG_UFUNC|5.007001||Viu
Perl_modf|5.006000|5.006000|n
PERL_MULTICONCAT_HEADER_SIZE|5.027006||Viu
putc|5.003007||Viu
put_charclass_bitmap_innards|5.021004||Viu
put_charclass_bitmap_innards_common|5.023008||Viu
put_charclass_bitmap_innards_invlist|5.023008||Viu
put_code_point|5.021004||Viu
putc_unlocked|5.003007||Viu
putenv|5.005000||Viu
put_range|5.019009||Viu
putw|5.003007||Viu
pv_display|5.006000|5.003007|p
pv_escape|5.009004|5.003007|p
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Crypto/Exchange/Binance/Spot/API.pm view on Meta::CPAN
response => {
key => 'balances',
row => {
coin => 'asset',
available => 'free',
in_order => 'locked',
},
row_filter => sub {
my ($self, $row) = @_;
if ($row->{available} == 0 && $row->{in_order} == 0) {
return 'next';
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Crypto/NanoRPC.pm view on Meta::CPAN
wallet_frontiers => [ 'wallet' ],
wallet_history => [ 'wallet', [ 'modified_since' ] ],
wallet_info => [ 'wallet' ],
wallet_ledger => [ 'wallet', [ 'representative', 'weight', 'pending', 'modified_since' ] ],
wallet_lock => [ 'wallet' ],
wallet_locked => [ 'wallet' ],
wallet_pending => [ 'wallet', 'count', [ 'threshold', 'source', 'include_active', 'include_only_confirmed' ] ],
wallet_representative => [ 'wallet' ],
wallet_representative_set => [ 'wallet', 'representative', [ 'update_existing_accounts' ] ],
wallet_republish => [ 'wallet', 'count' ],
wallet_work_get => [ 'wallet' ],
lib/Crypto/NanoRPC.pm view on Meta::CPAN
account_balance account_block_count account_get account_history account_info account_key account_representative account_weight accounts_balances accounts_frontiers accounts_pending active_difficulty available_supply block_account block_count block_co...
=head2 Wallet RPCs
account_create account_list account_move account_remove account_representative_set accounts_create password_change password_enter password_valid receive receive_minimum receive_minimum_set search_pending search_pending_all send wallet_add wallet_add_...
=head2 Unit Conversion RPCs
krai_from_raw krai_to_raw mrai_from_raw mrai_to_raw rai_from_raw rai_to_raw
view all matches for this distribution
view release on metacpan or search on metacpan
lib/CtrlO/Crypt/XkcdPassword/Wordlist/eff_large.pm view on Meta::CPAN
unlisted
unlit
unlivable
unloaded
unloader
unlocked
unlocking
unlovable
unloved
unlovely
unloving
view all matches for this distribution
view release on metacpan or search on metacpan
bin/pmix/pmix view on Meta::CPAN
h - displays this Help screen
b - toggles Big mode (with all channel options)
S - toggles Stereo mode (for all channels that support it)
m - toggles Muting
o - toggles current channel as Only audible channel
a - toggles locked slider bar across All channels
t - toggles display of Title bar
I - toggles display of soundcard device Info
C - toggles Centering of soundcard device info
s - Save all current channel values to ~/.${name}rc
l - Load ~/.${name}rc into current channel values
view all matches for this distribution
view release on metacpan or search on metacpan
----------------------------
revision 0.1 locked by: corliss;
date: 2002/11/14 19:17:24; author: corliss; state: Exp;
--Initial revision
view all matches for this distribution
view release on metacpan or search on metacpan
----------------------------
revision 1.997 locked by: corliss;
date: 2002/11/14 18:22:59; author: corliss; state: Exp; lines: +124 -6
--Added window management array and functions
--POD updates
--Form windows are now set to syncok
--Subforms now return focus to parent form after last widget
----------------------------
revision 1.996 locked by: corliss;
date: 2002/11/04 01:01:46; author: corliss; state: Exp; lines: +293 -105
--Added subform support
--Reworked slightly for new Curses::Widgets internals
--Removed touchwin calls
--Added ALTFBASE for loading subforms from different namespace
All form descendents:
--Adjusted internal geometry calculations to reflect new API behaviour
----------------------------
revision 1.995 locked by: corliss;
date: 2002/10/22 18:21:36; author: corliss;
--Added support for alternate namespace searching for widgets
--Added form autocenter support for non-derived forms
--Added DONTSWITCH directive to keep focus on the same widget
--Now passing default colours to all the widgets that don't explicitly
view all matches for this distribution
view release on metacpan or search on metacpan
----------------------------
revision 1.997 locked by: corliss;
date: 2002/11/14 01:30:19; author: corliss; state: Exp; lines: +34 -7
--POD fixes
--Compatibility fix for curses without attr_get/attr_set functions
--Introduction of the multi-column list box
ListBox:
--Checking for defined code reference before attempting to execute
TextMemo:
--Changed arrow placement to go by window bounds to make inherited
behaviour more predictable
----------------------------
revision 1.996 locked by: corliss;
date: 2002/11/03 23:25:01; author: corliss; state: Exp; lines: +450 -75
--Added test_colour function
--Added DEFAULTFG and DEFAULTBG scalars
--Removed hard coded black:white colour pair, now detecting
actual colours
--Fixed underline mode to correctly underline entire field, instead
of just text
--Added regex to accept only printable characters as part of the value
--Fixed bugs in cursor placement and scrolling
----------------------------
revision 1.995 locked by: corliss;
date: 2002/10/22 18:00:23; author: corliss;
--Added Menu and Label widgets
--Auto-applying the list length based on list entries was getting lost
at times in the ComboBox. Fixed.
--Popup wouldn't show up in the right location on combos on newwins that
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Cyrillic.pm view on Meta::CPAN
=back
=head1 Environment Variable
This software uses the flock function for exclusive control. The execution of the
program is blocked until it becomes possible to read or write the file.
You can have it not block in the flock function by defining environment variable
CHAR_NONBLOCK.
Example:
view all matches for this distribution
view release on metacpan or search on metacpan
# Get/set "closed" flag (when not set produces "*", or "splat" files):
my $is_closed = $item->closed();
$item->closed($is_closed);
# Get/set "locked" flag (when set produces ">" locked files):
my $is_locked = $item->locked();
$item->locked($is_locked);
# Get/set track location of first sector of file:
my $track = $item->track();
$item->track($track);
}
return (ord ($self->[$I_CLOSED]) & 0b10000000) == 0b10000000;
}
=head2 locked
Get "locked" flag:
my $is_locked = $item->locked();
Returns true when "locked" flag is set, and false otherwise.
Set "locked" flag:
$item->locked($is_locked);
When "locked" flag is set, it produces ">" locked files.
=cut
sub locked {
my ($self, $is_locked) = @_;
if (defined $is_locked) {
if (ref $is_locked) {
die q{Invalid "locked" flag};
}
my $locked_bit = $is_locked ? 0b01000000 : 0b00000000;
$self->[$I_LOCKED] = chr ((ord ($self->[$I_LOCKED]) & 0b10111111) | $locked_bit);
}
return (ord ($self->[$I_LOCKED]) & 0b01000000) == 0b01000000;
}
my $stdout = select $fh;
if ($as_petscii) {
my $type = $self->type_to_string($self->type(), 1);
my $closed = $self->closed() ? 0x20 : 0x2a; # "*"
my $locked = $self->locked() ? 0x3c : 0x20; # "<"
my $track = sprintf "%2d", $self->track();
my $sector = sprintf "%2d", $self->sector();
my $size = ascii_to_petscii($self->size());
my $name = sprintf "\"%s\"", $self->name(padding_with_a0 => 0);
$name =~ s/\x00//g; # align file type string to the right column
if ($verbose) {
printf "%-4d %-18s%c%s%c %s %s\n", $size, $name, $closed, $type, $locked, $track, $sector;
}
else {
printf "%-4d %-18s%c%s%c\n", $size, $name, $closed, $type, $locked;
}
}
else {
my $type = $self->type_to_string($self->type());
my $closed = $self->closed() ? ord ' ' : ord '*';
my $locked = $self->locked() ? ord '<' : ord ' ';
my $track = sprintf "%2d", petscii_to_ascii $self->track();
my $sector = sprintf "%2d", petscii_to_ascii $self->sector();
my $size = $self->size();
my $name = sprintf "\"%s\"", petscii_to_ascii($self->name(padding_with_a0 => 0));
$name =~ s/\x00//g; # align file type string to the right column
if ($verbose) {
printf "%-4d %-18s%c%s%c %s %s\n", $size, $name, $closed, $type, $locked, $track, $sector;
}
else {
printf "%-4d %-18s%c%s%c\n", $size, $name, $closed, $type, $locked;
}
}
select $stdout;
my $closed = $self->closed();
die unless defined $closed;
$test->closed($closed);
my $locked = $self->locked();
die unless defined $locked;
$test->locked($locked);
my $track = $self->track();
die unless defined $track;
$test->track($track);
view all matches for this distribution
view release on metacpan or search on metacpan
Dir/Entry.pm view on Meta::CPAN
my $file_type = ord (substr $bytes, 0x00, 0x01);
# Get the actual filetype:
my $type = $file_type & 7;
# Get closed flag (not set produces "*", or "splat" files):
my $closed = $file_type & 0x80;
# Get locked flag (set produces ">" locked files):
my $locked = $file_type & 0x40;
# Get track/sector location of first sector of file:
my $track = ord (substr $bytes, 0x01, 0x01);
my $sector = ord (substr $bytes, 0x02, 0x01);
# Get 16 character filename (in PETASCII, padded with $A0):
my $rawname = substr $bytes, 0x03, 0x10;
Dir/Entry.pm view on Meta::CPAN
my $size = ord (substr $bytes, 0x1D, 0x01) << 8 | ord (substr $bytes, 0x1C, 0x01);
# Store directory entry details in a hash:
my $dirEntry = {
'TYPE' => $type,
'CLOSED' => $closed,
'LOCKED' => $locked,
'TRACK' => $track,
'SECTOR' => $sector,
'NAME' => $name,
'SIDE_TRACK' => $side_track,
'SIDE_SECTOR' => $side_sector,
Dir/Entry.pm view on Meta::CPAN
my @bytes = ();
# Get detailed file information stored within this object instance:
my $dirEntry = $self->{'DETAILS'};
my $type = $dirEntry->{'TYPE'};
my $closed = $dirEntry->{'CLOSED'};
my $locked = $dirEntry->{'LOCKED'};
my $track = $dirEntry->{'TRACK'};
my $sector = $dirEntry->{'SECTOR'};
my $name = $dirEntry->{'NAME'};
my $side_track = $dirEntry->{'SIDE_TRACK'} || 0x00;
my $side_sector = $dirEntry->{'SIDE_SECTOR'} || 0x00;
my $record_length = $dirEntry->{'RECORD_LENGTH'} || 0x00;
my $size = $dirEntry->{'SIZE'};
# Byte $00 - File type:
$bytes[0x00] = chr ($type | ($locked ? 0x40 : 0x00) | ($closed ? 0x80 : 0x00));
# Byte $01 - Track location of first sector of file:
$bytes[0x01] = chr ($track);
# Byte $02 - Sector location of first sector of file:
$bytes[0x02] = chr ($sector);
# Bytes $03..$12 - 16 character filename (in PETASCII, padded with $A0):
Dir/Entry.pm view on Meta::CPAN
croak "An illegal closed flag: ${closed}" unless $closed == 0 || $closed == 1;
$self->{'DETAILS'}->{'CLOSED'} = $closed;
return $closed;
}
=head2 get_locked
Get "Locked" flag (when set produces ">" locked files):
my $locked = $entryObj->get_locked();
Returns true when "Locked" flag is set, and false otherwise.
=cut
sub get_locked {
my $self = shift;
my $locked = $self->{'DETAILS'}->{'LOCKED'};
return $locked ? 1 : 0;
}
=head2 get_track
Get track location of first sector of file:
Dir/Entry.pm view on Meta::CPAN
$args = {} unless defined $args;
my $verbose = $args->{verbose};
# Get detailed file information stored within this object instance:
my $type = $self->get_type();
my $closed = $self->get_closed() ? ord ' ' : ord '*';
my $locked = $self->get_locked() ? ord '<' : ord ' ';
my $size = $self->get_size();
my $track = sprintf '%2d', $self->get_track();
my $sector = sprintf '%2d', $self->get_sector();
# Get filename convert to ASCII and add quotes:
my $name = $self->get_name(1);
my $quotename = sprintf "\"%s\"", $name;
# Print directory entry:
if ($verbose) {
printf $fh "%-4d %-18s%c%s%c %s %s\n", $size, $quotename, $closed, $type, $locked, $track, $sector;
}
else {
printf $fh "%-4d %-18s%c%s%c\n", $size, $quotename, $closed, $type, $locked;
}
}
=head1 BUGS
view all matches for this distribution
view release on metacpan or search on metacpan
lib/D64/Disk/Image.pm view on Meta::CPAN
my $rawname = substr $buffer, $offset + 5;
my $name = $d64->name_from_rawname($rawname);
my $type = $file_type & 7;
my $closed = $file_type & 0x80;
my $locked = $file_type & 0x40;
my $size = ord (substr $buffer, $offset + 31, 1) << 8 | ord (substr $buffer, $offset + 30, 1);
# Convert to ASCII and add quotes:
$name = $d64->petscii_to_ascii($name);
my $quotename = sprintf "\"%s\"", $name;
# Print directory entry:
printf "%-4d %-18s%c%s%c\n", $size, $quotename, $closed ? ord ' ' : ord '*', $file_types[$type], $locked ? ord '<' : ord ' ';
}
}
}
# Print number of blocks free:
view all matches for this distribution
view release on metacpan or search on metacpan
=head2 $db->release;
=head2 ag_db_release($db);
Unlocks I<current record> if it is locked; I<current record> becomes
undefined.
=head2 $db->seek(key => "key", create => 1, size => $size);
=head2 ag_db_newrec($db, "key", $size);
=head2 $db->drop;
=head2 ag_db_delrec
Deletes I<current record> which must be locked.
=head2 $db->next(lock => 1);
=head2 ag_readnext($db);
view all matches for this distribution
view release on metacpan or search on metacpan
lib/DB/Object/Constraint/Check.pm view on Meta::CPAN
=head1 SYNOPSIS
use DB::Object::Constraint::Check;
my $check = DB::Object::Constraint::Check->new(
expr => q{CHECK (status::text ~* '^(active|inactive|locked|pending|protected|removed|suspended)$'::text)},
fields => [qw( status )],
name => 'chk_users_status',
) || die( DB::Object::Constraint::Check->error, "\n" );
=head1 VERSION
view all matches for this distribution
view release on metacpan or search on metacpan
sample/db2_check_lock.pl view on Meta::CPAN
#!/usr/bin/perl5
#
# db2_check_lock - Check for blocked applications, optionally kill
#
# $Id: db2_check_lock.pl,v 145.1 2007/11/20 21:51:24 biersma Exp $
#
use strict;
sample/db2_check_lock.pl view on Meta::CPAN
print "No active databases. Nothing to do.\n";
exit(0);
}
my %agent_ids; # Agent Id -> Appl node
my %blocked_apps; # Agent Id -> Agent Id (blocked -> lock owner)
my $no_long_blocked = 0; # No of jobs blocked for > block time
my $now = time();
foreach my $node ($snap->findNodes('APPL')) {
#print $node->Format(); exit(0);
#
sample/db2_check_lock.pl view on Meta::CPAN
next if (defined $args{D} && lc $args{D} ne lc $db_name);
my $agent_id = $node->findValue('APPL_INFO/AGENT_ID');
$agent_ids{$agent_id} = $node;
my $is_blocked = $node->findValue('LOCKS_WAITING');
next unless ($is_blocked);
my $blocker = $node->findValue('LOCK_WAIT/AGENT_ID_HOLDING_LK');
$blocked_apps{$agent_id} = $blocker;
my $start = $node->findValue('LOCK_WAIT/LOCK_WAIT_START_TIME/SECONDS');
if (($now - $start) > $args{t}) {
$no_long_blocked++;
}
}
if ($args{k}) {
my $agent_id = $args{k};
sample/db2_check_lock.pl view on Meta::CPAN
my $db_name = $appl_node->findValue('APPL_INFO/DB_NAME');
DB2::Admin::->ForceApplications($agent_id);
exit(0);
}
unless ($no_long_blocked) {
print "No applications are blocked for over $args{t} seconds\n";
exit(0);
}
if (0) {
#
# Fake a tree
#
$blocked_apps{4} = 5;
$blocked_apps{5} = 6;
$blocked_apps{6} = 8;
$blocked_apps{7} = 8;
# $blocked_apps{8} = 5; # Deadlock
}
#
# See if we can compute a blocking tree
#
my %lock_owner; # Blocked -> Final lock owner
my %lock_children; # Lock owner -> Child -> 1
BLOCKED:
foreach my $agent_id (keys %blocked_apps) {
my $blocker = $blocked_apps{$agent_id};
my $parent = $blocked_apps{$blocker};
if (defined $parent) {
#print "Have lock hierarchy: $agent_id -> $blocker -> $parent\n";
while (defined $blocked_apps{$parent}) {
if ($parent == $blocker) {
print "Deadlock detected ($agent_id -> $blocker ... $blocker)\n";
next BLOCKED;
}
$parent = $blocked_apps{$parent};
}
$lock_owner{$agent_id} = $parent;
$lock_children{$parent}{$agent_id} = 1;
} else {
$lock_owner{$agent_id} = $blocker;
sample/db2_check_lock.pl view on Meta::CPAN
my ($lock_owner) = @_;
print STDERR "Generate alert for [$lock_owner]\n"
if ($args{d});
my $owner_node = $agent_ids{$lock_owner};
my $no_blocked = keys %{ $lock_children{$lock_owner} };
#
# Alert should look like: Error: Server NYPIBA4 agent id 71 has been
# blocking X applications since Aug 17 2004 2:00AM
#
my $since;
foreach my $blocked (keys %{ $lock_children{$lock_owner} }) {
my $appl_node = $agent_ids{$blocked};
my $start = $appl_node->findValue('LOCK_WAIT/LOCK_WAIT_START_TIME/SECONDS');
#print "Have [$blocked] lock wait start time [$start] [" . localtime($start) . "]\n";
if (! defined $since || $start < $since) {
$since = $start;
}
}
my @time_elems = localtime($since);
sample/db2_check_lock.pl view on Meta::CPAN
$time_elems[5] + 1900,
$time_elems[4] + 1,
$time_elems[3],
$time_elems[2],
$time_elems[1]);
my $alert = "Server $ENV{DB2INSTANCE} agent id $lock_owner has been blocking $no_blocked applications since $display_time";
my $now = localtime(time);
my $dbname = $owner_node->findValue('APPL_INFO/DB_NAME');
$dbname =~ s/\s+$//;
my @descendants = keys %{ $lock_children{$lock_owner} };
my @direct_children;
foreach my $id (@descendants) {
next unless ($blocked_apps{$id} == $lock_owner);
push @direct_children, $id;
}
my %blocked_tables;
my %schema_names;
foreach my $id (@direct_children) {
my $node = $agent_ids{$id};
foreach my $wl ($node->findNodes('LOCK_WAIT')) {
my $schema = $wl->findValue('TABLE_SCHEMA');
$schema =~ s/\s+$//;
$schema_names{$schema} = 1;
my $table = $wl->findValue('TABLE_NAME');
$table =~ s/\s+$//;
$blocked_tables{"$schema.$table"} = 1;
}
}
my $table_list = join(', ', sort keys %blocked_tables);
my $desc = "$ENV{DB2INSTANCE}.$dbname";
my $email = <<_END_HEADER_;
Please be advised that there is blocking in $desc.
sample/db2_check_lock.pl view on Meta::CPAN
$email .= "For an explanation of the status column, go to:\n";
$email .= "http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/admin/r0001162.htm\n";
$email .= "\n";
#
# Show at most 10 blocked processes
#
if (@descendants > 10) {
$email .= "There are " . scalar(@descendants) . " processes being blocked\n";
$email .= "The first 10 blocked processes are listed below\n";
$email .= '#' x 20 . "\n";
$email .= display_agents(@descendants[0..9]);
$email .= "\n";
} else {
$email .= "The following processes are being blocked:\n";
$email .= '#' x 20 . "\n";
$email .= display_agents(@descendants);
$email .= "\n";
}
sample/db2_check_lock.pl view on Meta::CPAN
}
my $hostproc = $values->{'CLIENT_PID'};
my $status = $values->{'APPL_STATUS'};
my $block_start = $appl_node->
findValue('LOCK_WAIT/LOCK_WAIT_START_TIME/SECONDS');
my $time_blocked = (defined $block_start ?
$snap_time - $block_start : 'n/a');
#
# For multi-tier apps, add the TP Monitor information if
# available.
sample/db2_check_lock.pl view on Meta::CPAN
if ($values->{TPMON_CLIENT_APP} =~ /\S/) {
$program .= " (for $values->{TPMON_CLIENT_APP})";
}
$table->row($id, $userid, $cmd, $program, $hostname,
$hostproc, $status, $time_blocked);
}
return $table->render(120);
}
sample/db2_check_lock.pl view on Meta::CPAN
[ -d ]
=head1 DESCRIPTION
This script performs a database instance snapshot to determine
blocking. If any agent process is blocked for over a specified time,
an email is generated with information on the blocking process and its
victims. Optionally, the blocking agent process can be killed. This
script must be run on the database server.
This script first gets an application snapshot with basic locking
information. If the C<-k> parameter is specified, the script verifies
whather the specified agent id still exists and still is holding a
lock. If so, the application is forced.
In the absence of a C<-k> parameter, the script verifies whether any
applications is blocked for over the specified time (taken from the
JobParams table, defaulting to 120 seconds). If not, the script takes
no action.
If there is long blocking, the script find the responsible agent
process by following the lock chain. For each responsible agent, an
view all matches for this distribution
view release on metacpan or search on metacpan
appropriate handle and its dependent handles. For example, you cannot create a connection handle
without creating an environment handle first (which is the connection handle's dependent handle --
got it? :).
Use DtfHdlSetAttribute() to change the value of an attribute. A handle's attributes can only be
modified when the handle is not in locked state. A handle assumes the locked state by creating
dependent handles on it. For example, the creation of a connection handle causes the environment
handle to assume locked state. Additionally, a connection handle assumes locked state when it
undergoes a transition into connected state (a user connects).
S< >I<ATTRIBUTE TYPES>
view all matches for this distribution
view release on metacpan or search on metacpan
{
case SE_NOREC:
dbd_st_finish (sth, imp_sth);
break;
case SE_LOCKEDREC:
set_error (sth, "Fetch: record locked");
break;
default:
set_error(sth, "Fetch: error");
break;
}
view all matches for this distribution
view release on metacpan or search on metacpan
{
case SE_NOREC:
dbd_st_finish (sth, imp_sth);
break;
case SE_LOCKEDREC:
set_error (sth, "Fetch: record locked");
break;
default:
set_error(sth, "Fetch: error");
break;
}
view all matches for this distribution
view release on metacpan or search on metacpan
dbd-illustra.pod view on Meta::CPAN
per-transaction by executing a C<SET TRANSACTION ISOLATION LEVEL x>
statement where I<x> is the name of the isolation level required.
The default locking behavior is for readers to block writers.
Rows returned by a SELECT statement can be locked to prevent them from
being changed
by another transaction, by including "LOCK=EXCLUSIVE" or "LOCK=UPDATE" in the
optimizer hints for a given table:
SELECT * FROM xyz USING(LOCK=UPDATE) WHERE xid = 'abc'
view all matches for this distribution
view release on metacpan or search on metacpan
lib/DBD/Informix/Summary.pm view on Meta::CPAN
The default locking behaviour for reading and writing depends on the
isolation level, the way the table was defined, and on whether the
database was created with transactions enabled or not.
Rows returned by a SELECT statement can be locked to prevent them being
changed by another transaction, by appending C<FOR UPDATE> to the select
statement. Optionally, you can specify a column list in parentheses
after the C<FOR UPDATE> clause.
The C<LOCK TABLE table_name IN lock_mode> statement can be used to
apply an explicit lock on a table. The lock mode can be C<SHARED> or
C<EXCLUSIVE>. There are constraints on when tables can be unlocked,
and when locks can be applied. Row/Page locking occurs with cursors
C<FOR UPDATE>. In some types of database, some cursors are implicitly
created C<FOR UPDATE>.
view all matches for this distribution
view release on metacpan or search on metacpan
lib/DBD/MVS_FTPSQL.pm view on Meta::CPAN
gets different results each time (nonrepetable read phenomena).
=item Uncommitted Read (UR)
With this isolation levels the transaction (almost) doesn't acquire locks and
doesn't check if the data that is retrieving is locked.
This, at the price of risking reading non committed data,
leads to two main advantages:
=over 2
lib/DBD/MVS_FTPSQL.pm view on Meta::CPAN
as illustrated by the following example:
SELECT * FROM SYSIBM.SYSDUMMY1 WITH UR
When using IBM FTP CS as a medium to submit queries, there are two main limitations
that affect your control over the way the data is locked and
isolated between concurrent processes. These limitations are:
=over 2
=item *
view all matches for this distribution
view release on metacpan or search on metacpan
t/021_DBD_Mock_Session.t view on Meta::CPAN
return 'BAD PASSWORD';
}
# otherwise ...
else {
# we must update the login failures, and lock the account
$dbh->do("UPDATE users SET login_failures = (login_failures + 1), locked = 1 WHERE user_id = $user_id"); return 'USER ACCOUNT LOCKED';
}
}
else {
return 'USERNAME NOT FOUND';
}
t/021_DBD_Mock_Session.t view on Meta::CPAN
{
statement => qr/SELECT user_id, login_failures FROM users WHERE username = \'.*?\'/, #'
results => [[ 'user_id', 'login_failures' ], [ 1, 4 ]]
},
{
statement => sub { $_[0] eq "UPDATE users SET login_failures = (login_failures + 1), locked = 1 WHERE user_id = 1" },
results => []
}
));
isa_ok($lock_user_account, 'DBD::Mock::Session');
is($lock_user_account->name(), 'lock_user_account', '... got the right name');
my $dbh = DBI->connect('dbi:Mock:', '', '');
$dbh->{mock_session} = $lock_user_account;
is(Login::Test::login($dbh, 'user', '****'), 'USER ACCOUNT LOCKED', '... username is found, and the password is wrong, and the user account is now locked');
}
# now check some errors
{
view all matches for this distribution
view release on metacpan or search on metacpan
examples/thrtest.pl view on Meta::CPAN
}
elsif ($action == 1 && !$cursor1)
{
$cursor1 -> finish if ($cursor1) ;
$cursor1 = $dbh->prepare("SELECT userID, authHandler, password
FROM thrtest1 WHERE login = ? and locked IS NULL
ORDER BY password");
die "db error $DBI::errstr" if (!$doerr && $DBI::errstr) ;
}
elsif ($action == 2 && !$cursor2)
{
examples/thrtest.pl view on Meta::CPAN
}
elsif ($action == 4 && $cursor1 && $login)
{
#$cursor1 -> finish if ($cursor1) ;
#$cursor1 = $dbh->prepare("SELECT userID, authHandler, password
# FROM thrtest1 WHERE login = ? and locked IS NULL
# ORDER BY password");
#
$cursor1->execute($login) ;
$cursor1->bind_columns(\($userID, $authHandler, $passwd));
$cursor1->fetch;
examples/thrtest.pl view on Meta::CPAN
eval {
$dbh -> do ('drop table thrtest1') ;
$dbh -> do ('drop table thrtest2') ;
} ;
my $c = q{ create table thrtest1 (userID varchar(80), authHandler varchar(80), password varchar(80), login varchar(80), lastLogin date, locked int) } ;
$dbh -> do ($c) ;
my $c = q{ create table thrtest2 (handlerID varchar(80), authMode varchar(80), data varchar(80)) } ;
view all matches for this distribution
view release on metacpan or search on metacpan
t/14threads.t view on Meta::CPAN
#trade dbh between threads
my @thr;
my @sem;
use Thread::Semaphore;
# create locked semaphores
for my $i ( 0 .. 2 ) {
push @sem, Thread::Semaphore->new(0);
}
undef $last_session;
view all matches for this distribution
view release on metacpan or search on metacpan
if (0==strcmp(word, "local")) return DBDPG_TRUE;
if (0==strcmp(word, "localtime")) return DBDPG_TRUE;
if (0==strcmp(word, "localtimestamp")) return DBDPG_TRUE;
if (0==strcmp(word, "location")) return DBDPG_TRUE;
if (0==strcmp(word, "lock")) return DBDPG_TRUE;
if (0==strcmp(word, "locked")) return DBDPG_TRUE;
if (0==strcmp(word, "logged")) return DBDPG_TRUE;
if (0==strcmp(word, "mapping")) return DBDPG_TRUE;
if (0==strcmp(word, "match")) return DBDPG_TRUE;
if (0==strcmp(word, "materialized")) return DBDPG_TRUE;
if (0==strcmp(word, "maxvalue")) return DBDPG_TRUE;
view all matches for this distribution
view release on metacpan or search on metacpan
lib/DBD/PgLite.pm view on Meta::CPAN
my $sn = lc(shift);
my $dbh = getDbh();
# Create sequence table if it does not exist
my $check_tbl = "select name from sqlite_master where name = ? and type = 'table'";
unless ($dbh->selectrow_array($check_tbl, {}, 'pglite_seq')) {
$dbh->do("create table pglite_seq (sequence_name text primary key, last_value int, is_locked int, is_called int)");
}
my $check_seq = "select sequence_name from pglite_seq where sequence_name = ?";
# Autocreate sequence if it does not exist
unless ($dbh->selectrow_array($check_seq,{},$sn)) {
$dbh->do("insert into pglite_seq (sequence_name, last_value, is_locked, is_called) values (?,?,?,?)",
{}, $sn, 1, 1, 0);
# Find a matching table, if possible, and set last_value based on that
my $tn = $sn;
$tn =~ s/_seq$//;
my ($val,$col) = (0,'');
lib/DBD/PgLite.pm view on Meta::CPAN
if (int($val) > 0) {
$dbh->do("update pglite_seq set last_value = ?, is_called = 1 where sequence_name = ?",
{}, int($val), $sn);
}
# unlock sequence before we continue
$dbh->do("update pglite_seq set is_locked = 0 where sequence_name = ?",{},$sn);
}
return $dbh;
}
lib/DBD/PgLite.pm view on Meta::CPAN
sub _nextval {
my $sn = lc(shift);
my $dbh = _seq_init($sn);
my $tries;
while (1) {
my $rc = $dbh->do("update pglite_seq set last_value = last_value + 1, is_locked = 1 where sequence_name = ? and is_locked = 0 and is_called = 1",{},$sn);
last if $rc && $rc > 0;
$rc = $dbh->do("update pglite_seq set is_locked = 1 where sequence_name = ? and is_locked = 0 and is_called = 0",{},$sn);
last if $rc && $rc > 0;
Time::HiRes::sleep(0.05);
die "Too many tries trying to update sequence '$sn' - need manual fix?" if ++$tries > 20;
}
my $sval = $dbh->selectrow_array("select last_value from pglite_seq where sequence_name = ?",{},$sn);
$dbh->do("update pglite_seq set is_locked = 0, is_called = 1 where sequence_name = ? and is_locked = 1",{},$sn);
setLastval($sn);
setCurrval($sn,$sval);
return $sval;
}
lib/DBD/PgLite.pm view on Meta::CPAN
$called = 1 unless defined($called);
$called = $called ? 1 : 0;
my $dbh = _seq_init($sn);
my $tries;
while (1) {
my $rc = $dbh->do("update pglite_seq set last_value = ?, is_called = ? where sequence_name = ? and is_locked = 0",
{}, $val, $called, $sn);
last if $rc && $rc > 0;
Time::HiRes::sleep(0.05);
die "Too many tries trying to update sequence '$sn' - need manual fix?" if ++$tries > 20;
}
view all matches for this distribution
view release on metacpan or search on metacpan
benchmarks/server-cfg view on Meta::CPAN
# 1 question should be retried
#
sub abort_if_fatal_error
{
return 1 if ($DBI::errstr =~ /Table locked by another cursor/);
return 0;
}
sub small_rollback_segment
{
benchmarks/server-cfg view on Meta::CPAN
# 1 question should be retried
#
sub abort_if_fatal_error
{
return 1 if ($DBI::errstr =~ /Table locked by another cursor/);
return 0;
}
sub small_rollback_segment
{
view all matches for this distribution
view release on metacpan or search on metacpan
}
int
dbd_dr_init( SV *drh )
/********************/
// Called once when each driver object is created and locked so there
// is no concurrent access.
{
dTHX;
D_imp_drh( drh );
}
int
dbd_dr_destroy( SV *drh )
/***********************/
// Called once when each driver object is created and locked so there
// is no concurrent access.
{
dTHX;
D_imp_drh( drh );
if( DBIc_IMPSET( imp_drh ) ) {
view all matches for this distribution
view release on metacpan or search on metacpan
lib/DBD/SQLcipher.pm view on Meta::CPAN
When you use L<File::Temp> to create a temporary file/directory for
SQLcipher databases, you need to remember:
=over 4
=item tempfile may be locked exclusively
You may want to use C<tempfile()> to create a temporary database
filename for DBD::SQLcipher, but as noted in L<File::Temp>'s POD,
this file may have an exclusive lock under some operating systems
(notably Mac OSX), and result in a "database is locked" error.
To avoid this, set EXLOCK option to false when you call tempfile().
($fh, $filename) = tempfile($template, EXLOCK => 0);
=item CLEANUP may not work unless a database is disconnected
view all matches for this distribution
view release on metacpan or search on metacpan
/* beginning-of-error-codes */
#define SQLITE_ERROR 1 /* Generic error */
#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
#define SQLITE_BUSY 5 /* The database file is locked */
#define SQLITE_LOCKED 6 /* A table in the database is locked */
#define SQLITE_NOMEM 7 /* A malloc() failed */
#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
** disrupt the operation of the specialized VFSes that do require it.
**
** <li>[[SQLITE_FCNTL_COMMIT_PHASETWO]]
** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite
** and sent to the VFS after a transaction has been committed immediately
** but before the database is unlocked. VFSes that do not need this signal
** should silently ignore this opcode. Applications should not call
** [sqlite3_file_control()] with this opcode as doing so may disrupt the
** operation of the specialized VFSes that do require it.
**
** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
** </ul>
**
** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as
** was given on the corresponding lock.
**
** The xShmLock method can transition between unlocked and SHARED or
** between unlocked and EXCLUSIVE. It cannot transition between SHARED
** and EXCLUSIVE.
*/
#define SQLITE_SHM_UNLOCK 1
#define SQLITE_SHM_LOCK 2
#define SQLITE_SHM_SHARED 4
**
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
** that might be invoked with argument P whenever
** an attempt is made to access a database table associated with
** [database connection] D when another thread
** or process has the table locked.
** The sqlite3_busy_handler() interface is used to implement
** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
**
** ^If the busy callback is NULL, then [SQLITE_BUSY]
** is returned immediately upon encountering the lock. ^If the busy callback
** busy handler.
** Consider a scenario where one process is holding a read lock that
** it is trying to promote to a reserved lock and
** a second process is holding a reserved lock that it is trying
** to promote to an exclusive lock. The first process cannot proceed
** because it is blocked by the second and the second process cannot
** proceed because it is blocked by the first. If both processes
** invoke the busy handlers, neither will make any progress. Therefore,
** SQLite returns [SQLITE_BUSY] for the first process, hoping that this
** will induce the first process to release its read lock and allow
** the second process to proceed.
**
/*
** CAPI3REF: Set A Busy Timeout
** METHOD: sqlite3
**
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
** for a specified amount of time when a table is locked. ^The handler
** will sleep multiple times until at least "ms" milliseconds of sleeping
** have accumulated. ^After at least "ms" milliseconds of sleeping,
** the handler returns 0 which causes [sqlite3_step()] to return
** [SQLITE_BUSY].
**
**
** See Also: [Using the SQLite Online Backup API]
**
** ^SQLite holds a write transaction open on the destination database file
** for the duration of the backup operation.
** ^The source database is read-locked only while it is being read;
** it is not locked continuously for the entire backup operation.
** ^Thus, the backup may be performed on a live source database without
** preventing other database connections from
** reading or writing to the source database while the backup is underway.
**
** ^(To perform a backup operation:
** on the destination file. ^The exclusive lock is not released until either
** sqlite3_backup_finish() is called or the backup operation is complete
** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to
** sqlite3_backup_step() obtains a [shared lock] on the source database that
** lasts for the duration of the sqlite3_backup_step() call.
** ^Because the source database is not locked between calls to
** sqlite3_backup_step(), the source database may be modified mid-way
** through the backup process. ^If the source database is modified by an
** external process or via a database connection other than the one being
** used by the backup operation, then the backup will be automatically
** restarted by the next call to sqlite3_backup_step(). ^If the source
** See Also: [Using the SQLite Unlock Notification Feature].
**
** ^Shared-cache locks are released when a database connection concludes
** its current transaction, either by committing it or rolling it back.
**
** ^When a connection (known as the blocked connection) fails to obtain a
** shared-cache lock and SQLITE_LOCKED is returned to the caller, the
** identity of the database connection (the blocking connection) that
** has locked the required resource is stored internally. ^After an
** application receives an SQLITE_LOCKED error, it may call the
** sqlite3_unlock_notify() method with the blocked connection handle as
** the first argument to register for a callback that will be invoked
** when the blocking connections current transaction is concluded. ^The
** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
** call that concludes the blocking connections transaction.
**
** there is a chance that the blocking connection will have already
** concluded its transaction by the time sqlite3_unlock_notify() is invoked.
** If this happens, then the specified callback is invoked immediately,
** from within the call to sqlite3_unlock_notify().)^
**
** ^If the blocked connection is attempting to obtain a write-lock on a
** shared-cache table, and more than one other connection currently holds
** a read-lock on the same table, then SQLite arbitrarily selects one of
** the other connections to use as the blocking connection.
**
** ^(There may be at most one unlock-notify callback registered by a
** blocked connection. If sqlite3_unlock_notify() is called when the
** blocked connection already has a registered unlock-notify callback,
** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
** called with a NULL pointer as its second argument, then any existing
** unlock-notify callback is canceled. ^The blocked connections
** unlock-notify callback may also be canceled by closing the blocked
** connection using [sqlite3_close()].
**
** The unlock-notify callback is not reentrant. If an application invokes
** any sqlite3_xxx API functions from within an unlock-notify callback, a
** crash or deadlock may be the result.
** it an array of void* context pointers. The first argument passed to
** an unlock-notify callback is a pointer to an array of void* pointers,
** and the second is the number of entries in the array.
**
** When a blocking connections transaction is concluded, there may be
** more than one blocked connection that has registered for an unlock-notify
** callback. ^If two or more such blocked connections have specified the
** same callback function, then instead of invoking the callback function
** multiple times, it is invoked once with the set of void* context pointers
** specified by the blocked connections bundled together into an array.
** This gives the application an opportunity to prioritize any actions
** related to the set of unblocked database connections.
**
** <b>Deadlock Detection</b>
**
** Assuming that after registering for an unlock-notify callback a
** database waits for the callback to be issued before taking any further
** action (a reasonable assumption), then using this API may cause the
** application to deadlock. For example, if connection X is waiting for
** connection Y's transaction to be concluded, and similarly connection
** Y is waiting on connection X's transaction, then neither connection
** will proceed and the system may remain deadlocked indefinitely.
**
** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock
** detection. ^If a given call to sqlite3_unlock_notify() would put the
** system in a deadlocked state, then SQLITE_LOCKED is returned and no
** unlock-notify callback is registered. The system is said to be in
** a deadlocked state if connection A has registered for an unlock-notify
** callback on the conclusion of connection B's transaction, and connection
** B has itself registered for an unlock-notify callback when connection
** A's transaction is concluded. ^Indirect deadlock is also detected, so
** the system is also considered to be deadlocked if connection B has
** registered for an unlock-notify callback on the conclusion of connection
** C's transaction, where connection C is waiting on connection A. ^Any
** number of levels of indirection are allowed.
**
** <b>The "DROP TABLE" Exception</b>
** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in
** the special "DROP TABLE/INDEX" case, the extended error code is just
** SQLITE_LOCKED.)^
*/
SQLITE_API int sqlite3_unlock_notify(
sqlite3 *pBlocked, /* Waiting connection */
void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */
void *pNotifyArg /* Argument to pass to xNotify */
);
*/
sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */
sqlite3 *pUnlockConnection; /* Connection to watch for unlock */
void *pUnlockArg; /* Argument to xUnlockNotify */
void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
#endif
#ifdef SQLITE_USER_AUTHENTICATION
sqlite3_userauth auth; /* User authentication information */
#endif
};
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*);
SQLITE_PRIVATE void sqlite3Put4byte(u8*, u32);
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
SQLITE_PRIVATE void sqlite3ConnectionBlocked(sqlite3 *, sqlite3 *);
SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db);
SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db);
#else
#define sqlite3ConnectionBlocked(x,y)
#define sqlite3ConnectionUnlocked(x)
#define sqlite3ConnectionClosed(x)
#endif
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *);
){
int rc;
DO_OS_MALLOC_TEST(0);
/* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
** reaching the VFS. */
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
assert( rc==SQLITE_OK || pFile->pMethods==0 );
return rc;
}
static int winMutex_isInit = 0;
static int winMutex_isNt = -1; /* <0 means "need to query" */
/* As the winMutexInit() and winMutexEnd() functions are called as part
** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
** "interlocked" magic used here is probably not strictly necessary.
*/
static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0;
SQLITE_API int sqlite3_win32_is_nt(void); /* os_win.c */
SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
static int winMutexInit(void){
/* The first to increment to 1 does actual initialization */
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
int i;
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
#if SQLITE_OS_WINRT
InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0);
#else
}
static int winMutexEnd(void){
/* The first to decrement to 0 does actual shutdown
** (which should be the last to shutdown.) */
if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
if( winMutex_isInit==1 ){
int i;
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
}
}
#endif
p = &winMutex_staticMutexes[iType-2];
#ifdef SQLITE_DEBUG
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
InterlockedCompareExchange(&p->trace, 1, 0);
#endif
#endif
break;
}
}
** locks on the corresponding inode. There is one locking structure
** per inode, so if the same inode is opened twice, both unixFile structures
** point to the same locking structure. The locking structure keeps
** a reference count (so we will know when to delete it) and a "cnt"
** field that tells us its internal lock status. cnt==0 means the
** file is unlocked. cnt==-1 means the file has an exclusive lock.
** cnt>0 means there are cnt shared locks on the file.
**
** Any attempt to lock or unlock a file first checks the locking
** structure. The fcntl() system call is only invoked to set a
** POSIX lock if the internal lock structure transitions between
** a locked and an unlocked state.
**
** But wait: there are yet more problems with POSIX advisory locks.
**
** If you close a file descriptor that points to a file that has locks,
** all locks on that file that are owned by the current process are
** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
** byte', each single bytes at well known offsets, and the 'shared byte
** range', a range of 510 bytes at a well known offset.
**
** To obtain a SHARED lock, a read-lock is obtained on the 'pending
** byte'. If this is successful, 'shared byte range' is read-locked
** and the lock on the 'pending byte' released. (Legacy note: When
** SQLite was first developed, Windows95 systems were still very common,
** and Widnows95 lacks a shared-lock capability. So on Windows95, a
** single randomly selected by from the 'shared byte range' is locked.
** Windows95 is now pretty much extinct, but this work-around for the
** lack of shared-locks on Windows95 lives on, for backwards
** compatibility.)
**
** A process may only obtain a RESERVED lock after it has a SHARED lock.
azFileLock(eFileLock)));
return SQLITE_OK;
}
/* Make sure the locking sequence is correct.
** (1) We never move from unlocked to anything higher than shared lock.
** (2) SQLite never explicitly requests a pendig lock.
** (3) A shared lock is always held when a reserve lock is requested.
*/
assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
assert( eFileLock!=PENDING_LOCK );
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
**
** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
** the byte range is divided into 2 parts and the first part is unlocked then
** set to a read lock, then the other part is simply unlocked. This works
** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to
** remove the write lock on a region when a read lock is set.
*/
static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
unixFile *pFile = (unixFile*)id;
** to a non-zero value otherwise *pResOut is set to zero. The return value
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
**
** In dotfile locking, either a lock exists or it does not. So in this
** variation of CheckReservedLock(), *pResOut is set to true if any lock
** is held on the file and false if the file is unlocked.
*/
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
int rc = SQLITE_OK;
int reserved = 0;
unixFile *pFile = (unixFile*)id;
pFile->eFileLock = eFileLock;
rc = SQLITE_OK;
goto sem_end_lock;
}
/* lock semaphore now but bail out when already locked. */
if( sem_trywait(pSem)==-1 ){
rc = SQLITE_BUSY;
goto sem_end_lock;
}
struct ByteRangeLockPB2
{
unsigned long long offset; /* offset to first byte to lock */
unsigned long long length; /* nbr of bytes to lock */
unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
unsigned char unLockFlag; /* 1 = unlock, 0 = lock */
unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */
int fd; /* file desc to assoc this lock with */
};
** AFP filesystem.
**
** Return SQLITE_OK on success, SQLITE_BUSY on failure.
*/
static int afpSetLock(
const char *path, /* Name of the file to be locked or unlocked */
unixFile *pFile, /* Open file descriptor on path */
unsigned long long offset, /* First byte to be locked */
unsigned long long length, /* Number of bytes to lock */
int setLockFlag /* True to set lock. False to clear lock */
){
struct ByteRangeLockPB2 pb;
int err;
azFileLock(eFileLock)));
return SQLITE_OK;
}
/* Make sure the locking sequence is correct
** (1) We never move from unlocked to anything higher than shared lock.
** (2) SQLite never explicitly requests a pendig lock.
** (3) A shared lock is always held when a reserve lock is requested.
*/
assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
assert( eFileLock!=PENDING_LOCK );
char *zFilename; /* Name of the mmapped file */
int hShm; /* Open file descriptor */
int szRegion; /* Size of shared-memory regions */
u16 nRegion; /* Size of array apRegion */
u8 isReadonly; /* True if read-only */
u8 isUnlocked; /* True if no DMS lock held */
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
#ifdef SQLITE_DEBUG
u8 exclMask; /* Mask of exclusive locks held */
/*
** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
** take it now. Return SQLITE_OK if successful, or an SQLite error
** code otherwise.
**
** If the DMS cannot be locked because this is a readonly_shm=1
** connection and no other process already holds a lock, return
** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
*/
static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
struct flock lock;
int rc = SQLITE_OK;
lock.l_type = F_WRLCK;
if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) {
rc = SQLITE_IOERR_LOCK;
}else if( lock.l_type==F_UNLCK ){
if( pShmNode->isReadonly ){
pShmNode->isUnlocked = 1;
rc = SQLITE_READONLY_CANTINIT;
}else{
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
/* The first connection to attach must truncate the -shm file. We
** truncate to 3 bytes (an arbitrary small number, less than the
}
p = pDbFd->pShm;
pShmNode = p->pShmNode;
sqlite3_mutex_enter(pShmNode->pShmMutex);
if( pShmNode->isUnlocked ){
rc = unixLockSharedMemory(pDbFd, pShmNode);
if( rc!=SQLITE_OK ) goto shmpage_out;
pShmNode->isUnlocked = 0;
}
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
assert( pShmNode->pInode==pDbFd->pInode );
assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
/*
** Change the lock state for a shared-memory segment.
**
** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
** different here than in posix. In xShmLock(), one can go from unlocked
** to shared and back or from unlocked to exclusive and back. But one may
** not go from shared to exclusive or from exclusive to shared.
*/
static int unixShmLock(
sqlite3_file *fd, /* Database file holding the shared memory */
int ofst, /* First lock to acquire or release */
int n, /* Number of locks to acquire or release */
int flags /* What to do with the lock */
){
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
unixShm *p = pDbFd->pShm; /* The shared memory being locked */
unixShm *pX; /* For looping over all siblings */
unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
int rc = SQLITE_OK; /* Result code */
u16 mask; /* Mask of locks to take or release */
break;
}
}
/* Get the exclusive locks at the system level. Then if successful
** also mark the local connection as being locked.
*/
if( rc==SQLITE_OK ){
rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
if( rc==SQLITE_OK ){
assert( (p->sharedMask & mask)==0 );
struct statfs fsInfo;
struct flock lockInfo;
if( !filePath ){
/* If filePath==NULL that means we are dealing with a transient file
** that does not need to be locked. */
return &nolockIoMethods;
}
if( statfs(filePath, &fsInfo) != -1 ){
if( fsInfo.f_flags & MNT_RDONLY ){
return &nolockIoMethods;
){
struct flock lockInfo;
if( !filePath ){
/* If filePath==NULL that means we are dealing with a transient file
** that does not need to be locked. */
return &nolockIoMethods;
}
/* Test if fcntl() is supported and use POSIX style locks.
** Otherwise fall back to the named semaphore method.
#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
/*
** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
** is really just a macro that uses a compiler intrinsic (e.g. x64).
** So do not try to make this is into a redefinable interface.
*/
#if defined(InterlockedCompareExchange)
{ "InterlockedCompareExchange", (SYSCALL)0, 0 },
#define osInterlockedCompareExchange InterlockedCompareExchange
#else
{ "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent)
#endif /* defined(InterlockedCompareExchange) */
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
{ "UuidCreate", (SYSCALL)UuidCreate, 0 },
#else
{ "UuidCreate", (SYSCALL)0, 0 },
** NOTE: The WinRT sub-platform is always assumed to be based on the NT
** kernel.
*/
return 1;
#elif SQLITE_WIN32_GETVERSIONEX
if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
#if defined(SQLITE_WIN32_HAS_ANSI)
OSVERSIONINFOA sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
osGetVersionExA(&sInfo);
osInterlockedCompareExchange(&sqlite3_os_type,
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
#elif defined(SQLITE_WIN32_HAS_WIDE)
OSVERSIONINFOW sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
osGetVersionExW(&sInfo);
osInterlockedCompareExchange(&sqlite3_os_type,
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
#endif
}
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
#elif SQLITE_TEST
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
#else
/*
** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
** deprecated are always assumed to be based on the NT kernel.
*/
winFile hFile; /* File handle from winOpen */
int szRegion; /* Size of shared-memory regions */
int nRegion; /* Size of array apRegion */
u8 isReadonly; /* True if read-only */
u8 isUnlocked; /* True if no DMS lock held */
struct ShmRegion {
HANDLE hMap; /* File handle from CreateFileMapping */
void *pMap;
} *aRegion;
#define WINSHM_RDLCK 2
#define WINSHM_WRLCK 3
static int winShmSystemLock(
winShmNode *pFile, /* Apply locks to this open shared-memory segment */
int lockType, /* WINSHM_UNLCK, WINSHM_RDLCK, or WINSHM_WRLCK */
int ofst, /* Offset to first byte to be locked/unlocked */
int nByte /* Number of bytes to lock or unlock */
){
int rc = 0; /* Result code form Lock/UnlockFileEx() */
/* Access to the winShmNode object is serialized by the caller */
/*
** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
** take it now. Return SQLITE_OK if successful, or an SQLite error
** code otherwise.
**
** If the DMS cannot be locked because this is a readonly_shm=1
** connection and no other process already holds a lock, return
** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
*/
static int winLockSharedMemory(winShmNode *pShmNode){
int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1);
if( rc==SQLITE_OK ){
if( pShmNode->isReadonly ){
pShmNode->isUnlocked = 1;
winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
return SQLITE_READONLY_CANTINIT;
}else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){
winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
int ofst, /* First lock to acquire or release */
int n, /* Number of locks to acquire or release */
int flags /* What to do with the lock */
){
winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
winShm *p = pDbFd->pShm; /* The shared memory being locked */
winShm *pX; /* For looping over all siblings */
winShmNode *pShmNode = p->pShmNode;
int rc = SQLITE_OK; /* Result code */
u16 mask; /* Mask of locks to take or release */
break;
}
}
/* Get the exclusive locks at the system level. Then if successful
** also mark the local connection as being locked.
*/
if( rc==SQLITE_OK ){
rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, ofst+WIN_SHM_BASE, n);
if( rc==SQLITE_OK ){
assert( (p->sharedMask & mask)==0 );
pShm = pDbFd->pShm;
}
pShmNode = pShm->pShmNode;
sqlite3_mutex_enter(pShmNode->mutex);
if( pShmNode->isUnlocked ){
rc = winLockSharedMemory(pShmNode);
if( rc!=SQLITE_OK ) goto shmpage_out;
pShmNode->isUnlocked = 0;
}
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
if( pShmNode->nRegion<=iRegion ){
struct ShmRegion *apNew; /* New aRegion[] array */
**
**
** OPEN:
**
** The pager starts up in this state. Nothing is guaranteed in this
** state - the file may or may not be locked and the database size is
** unknown. The database may not be read or written.
**
** * No read or write transaction is active.
** * Any lock, or no lock at all, may be held on the database file.
** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
**
** This is usually safe. If an xUnlock fails or appears to fail, there may
** be a few redundant xLock() calls or a lock may be held for longer than
** required, but nothing really goes wrong.
**
** The exception is when the database file is unlocked as the pager moves
** from ERROR to OPEN state. At this point there may be a hot-journal file
** in the file-system that needs to be rolled back (as part of an OPEN->SHARED
** transition, by the same pager or any other). If the call to xUnlock()
** fails at this point and the pager is left holding an EXCLUSIVE lock, this
** can confuse the call to xCheckReservedLock() call made later as part
** This function is a no-op if the pager is in exclusive mode and not
** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN
** state.
**
** If the pager is not in exclusive-access mode, the database file is
** completely unlocked. If the file is unlocked and the file-system does
** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
** closed (if it is open).
**
** If the pager is in ERROR state when this function is called, the
** contents of the pager cache are discarded before switching back to
** for certain that original page contents are synced into the main rollback
** journal. Otherwise, a power loss might leave modified data in the
** database file without an entry in the rollback journal that can
** restore the database to its original form. Two conditions must be
** met before writing to the database files. (1) the database must be
** locked. (2) we know that the original page content is fully synced
** in the main journal either because the page is not in cache or else
** the page is marked as needSync==0.
**
** 2008-04-14: When attempting to vacuum a corrupt database file, it
** is possible to fail a statement on a database that does not yet exist.
*pExists = 0;
if( !jrnlOpen ){
rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
}
if( rc==SQLITE_OK && exists ){
int locked = 0; /* True if some process holds a RESERVED lock */
/* Race condition here: Another process might have been holding the
** the RESERVED lock and have a journal open at the sqlite3OsAccess()
** call above, but then delete the journal and drop the lock before
** we get to the following sqlite3OsCheckReservedLock() call. If that
** is the case, this routine might think there is a hot journal when
** in fact there is none. This results in a false-positive which will
** be dealt with by the playback routine. Ticket #3883.
*/
rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
if( rc==SQLITE_OK && !locked ){
Pgno nPage; /* Number of pages in database file */
assert( pPager->tempFile==0 );
rc = pagerPagecount(pPager, &nPage);
if( rc==SQLITE_OK ){
/*
** Set or release locks on the WAL. Locks are either shared or exclusive.
** A lock cannot be moved directly between shared and exclusive - it must go
** through the unlocked state first.
**
** In locking_mode=EXCLUSIVE, all of these routines become no-ops.
*/
static int walLockShared(Wal *pWal, int lockIdx){
int rc;
i64 nSize; /* Size of log file */
u32 aFrameCksum[2] = {0, 0};
int iLock; /* Lock offset to lock for checkpoint */
/* Obtain an exclusive lock on all byte in the locking range not already
** locked by the caller. The caller is guaranteed to have locked the
** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
** If successful, the same bytes that are locked here are unlocked before
** this function returns.
*/
assert( pWal->ckptLock==1 || pWal->ckptLock==0 );
assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
int mxI; /* Index of largest aReadMark[] value */
int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
u32 mxFrame; /* Wal frame to lock to */
assert( pWal->readLock<0 ); /* Not currently locked */
/* useWal may only be set for read/write connections */
assert( (pWal->readOnly & WAL_SHM_RDONLY)==0 || useWal==0 );
/* Take steps to avoid spinning forever if there is a protocol error.
struct Btree {
sqlite3 *db; /* The database connection holding this btree */
BtShared *pBt; /* Sharable content of this btree */
u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
u8 sharable; /* True if we can share pBt with another db */
u8 locked; /* True if db currently has pBt locked */
u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */
int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
int nBackup; /* Number of backup operations reading this btree */
u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
Btree *pNext; /* List of other sharable Btrees from the same db */
#if SQLITE_THREADSAFE
/*
** Obtain the BtShared mutex associated with B-Tree handle p. Also,
** set BtShared.db to the database handle associated with p and the
** p->locked boolean to true.
*/
static void lockBtreeMutex(Btree *p){
assert( p->locked==0 );
assert( sqlite3_mutex_notheld(p->pBt->mutex) );
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3_mutex_enter(p->pBt->mutex);
p->pBt->db = p->db;
p->locked = 1;
}
/*
** Release the BtShared mutex associated with B-Tree handle p and
** clear the p->locked boolean.
*/
static void SQLITE_NOINLINE unlockBtreeMutex(Btree *p){
BtShared *pBt = p->pBt;
assert( p->locked==1 );
assert( sqlite3_mutex_held(pBt->mutex) );
assert( sqlite3_mutex_held(p->db->mutex) );
assert( p->db==pBt->db );
sqlite3_mutex_leave(pBt->mutex);
p->locked = 0;
}
/* Forward reference */
static void SQLITE_NOINLINE btreeLockCarefully(Btree *p);
** If the object is not sharable, then no mutex is ever required
** and this routine is a no-op. The underlying mutex is non-recursive.
** But we keep a reference count in Btree.wantToLock so the behavior
** of this interface is recursive.
**
** To avoid deadlocks, multiple Btrees are locked in the same order
** by all database connections. The p->pNext is a list of other
** Btrees belonging to the same database connection as the p Btree
** which need to be locked after p. If we cannot get a lock on
** p, then first unlock all of the others on p->pNext, then wait
** for the lock to become available on p, then relock all of the
** subsequent Btrees that desire a lock.
*/
SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){
assert( p->pNext==0 || p->pNext->db==p->db );
assert( p->pPrev==0 || p->pPrev->db==p->db );
assert( p->sharable || (p->pNext==0 && p->pPrev==0) );
/* Check for locking consistency */
assert( !p->locked || p->wantToLock>0 );
assert( p->sharable || p->wantToLock==0 );
/* We should already hold a lock on the database connection */
assert( sqlite3_mutex_held(p->db->mutex) );
/* Unless the database is sharable and unlocked, then BtShared.db
** should already be set correctly. */
assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db );
if( !p->sharable ) return;
p->wantToLock++;
if( p->locked ) return;
btreeLockCarefully(p);
}
/* This is a helper function for sqlite3BtreeLock(). By moving
** complex, but seldom used logic, out of sqlite3BtreeLock() and
** want without having to go through the ascending lock
** procedure that follows. Just be sure not to block.
*/
if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
p->pBt->db = p->db;
p->locked = 1;
return;
}
/* To avoid deadlock, first release all locks with a larger
** BtShared address. Then acquire our lock. Then reacquire
** order.
*/
for(pLater=p->pNext; pLater; pLater=pLater->pNext){
assert( pLater->sharable );
assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt );
assert( !pLater->locked || pLater->wantToLock>0 );
if( pLater->locked ){
unlockBtreeMutex(pLater);
}
}
lockBtreeMutex(p);
for(pLater=p->pNext; pLater; pLater=pLater->pNext){
** B-Tree is not marked as sharable.
**
** This routine is used only from within assert() statements.
*/
SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){
assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 );
assert( p->sharable==0 || p->locked==0 || p->db==p->pBt->db );
assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->pBt->mutex) );
assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->db->mutex) );
return (p->sharable==0 || p->locked);
}
#endif
/*
assert( iDb>=0 && iDb<db->nDb );
if( !sqlite3_mutex_held(db->mutex) ) return 0;
if( iDb==1 ) return 1;
p = db->aDb[iDb].pBt;
assert( p!=0 );
return p->sharable==0 || p->locked==1;
}
#endif /* NDEBUG */
#else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */
/*
/* If some other connection is holding an exclusive lock, the
** requested lock may not be obtained.
*/
if( pBt->pWriter!=p && (pBt->btsFlags & BTS_EXCLUSIVE)!=0 ){
sqlite3ConnectionBlocked(p->db, pBt->pWriter->db);
return SQLITE_LOCKED_SHAREDCACHE;
}
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
/* The condition (pIter->eLock!=eLock) in the following if(...)
** only be a single writer).
*/
assert( pIter->eLock==READ_LOCK || pIter->eLock==WRITE_LOCK );
assert( eLock==READ_LOCK || pIter->pBtree==p || pIter->eLock==READ_LOCK);
if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){
sqlite3ConnectionBlocked(p->db, pIter->pBtree->db);
if( eLock==WRITE_LOCK ){
assert( p==pBt->pWriter );
pBt->btsFlags |= BTS_PENDING;
}
return SQLITE_LOCKED_SHAREDCACHE;
/* If there are still other outstanding references to the shared-btree
** structure, return now. The remainder of this procedure cleans
** up the shared-btree.
*/
assert( p->wantToLock==0 && p->locked==0 );
if( !p->sharable || removeFromSharingList(pBt) ){
/* The pBt is no longer on the sharing list, so we can access
** it without having to hold the mutex.
**
** Clean out and delete the BtShared object.
sqlite3_free(pBt);
}
#ifndef SQLITE_OMIT_SHARED_CACHE
assert( p->wantToLock==0 );
assert( p->locked==0 );
if( p->pPrev ) p->pPrev->pNext = p->pNext;
if( p->pNext ) p->pNext->pPrev = p->pPrev;
#endif
sqlite3_free(p);
** Get a reference to pPage1 of the database file. This will
** also acquire a readlock on that file.
**
** SQLITE_OK is returned on success. If the file is not a
** well-formed database file, then SQLITE_CORRUPT is returned.
** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM
** is returned if we run out of memory.
*/
static int lockBtree(BtShared *pBt){
int rc; /* Result code from subfunctions */
MemPage *pPage1; /* Page 1 of the database file */
** sqlite3BtreeInsert()
** sqlite3BtreeDelete()
** sqlite3BtreeUpdateMeta()
**
** If an initial attempt to acquire the lock fails because of lock contention
** and the database was previously unlocked, then invoke the busy handler
** if there is one. But if there was previously a read-lock, do not
** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is
** returned when there is already a read-lock in order to avoid a deadlock.
**
** Suppose there are two processes A and B. A has a read lock and B has
** a reserved lock. B tries to promote to exclusive but is blocked because
** of A's read lock. A tries to promote to reserved but is blocked by B.
** One or the other of the two processes must give way or there can be
** no progress. By returning SQLITE_BUSY and not invoking the busy callback
** when A already has a read lock, we encourage A to give up and let B
** proceed.
*/
break;
}
}
}
if( pBlock ){
sqlite3ConnectionBlocked(p->db, pBlock);
rc = SQLITE_LOCKED_SHAREDCACHE;
goto trans_begun;
}
}
#endif
return 0;
}
#endif
/* Lock the source database handle. The destination database
** handle is not locked in this routine, but it is locked in
** sqlite3_backup_step(). The user is required to ensure that no
** other thread accesses the destination handle for the duration
** of the backup operation. Any attempt to use the destination
** database connection while a backup is in progress may cause
** a malfunction or a deadlock.
if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
bCloseTrans = 1;
}
/* If the destination database has not yet been locked (i.e. if this
** is the first call to backup_step() for the current backup operation),
** try to set its page size to the same as the source database. This
** is especially important on ZipVFS systems, as in that case it is
** not possible to create a database file that uses one page size by
** writing to it with another. */
if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){
rc = SQLITE_NOMEM;
}
/* Lock the destination database, if it is not locked already. */
if( SQLITE_OK==rc && p->bDestLocked==0
&& SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
(int*)&p->iDestSchema))
){
p->bDestLocked = 1;
}
#endif
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
/*
** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
*/
static SQLITE_NOINLINE void vdbeLeave(Vdbe *p){
int i;
sqlite3 *db;
Db *aDb;
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
}
/* If the auto-commit flag is set to true, then any locks that were held
** by connection db have now been released. Call sqlite3ConnectionUnlocked()
** to invoke any required unlock-notify callbacks.
*/
if( db->autoCommit ){
sqlite3ConnectionUnlocked(db);
}
assert( db->nVdbeActive>0 || db->autoCommit==0 || db->nStatement==0 );
return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK);
}
** on which the lock is acquired. A readlock is obtained if P3==0 or
** a write lock if P3==1.
**
** P2 contains the root-page of the table to lock.
**
** P4 contains a pointer to the name of the table being locked. This is only
** used to generate an error message if the lock cannot be obtained.
*/
case OP_TableLock: {
u8 isWriteLock = (u8)pOp->p3;
if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommit) ){
assert( isWriteLock==0 || isWriteLock==1 );
rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
if( rc ){
if( (rc&0xFF)==SQLITE_LOCKED ){
const char *z = pOp->p4.z;
sqlite3VdbeError(p, "database table is locked: %s", z);
}
goto abort_due_to_error;
}
}
break;
sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
fprintf(stderr, "%lld:bg%d %s\n", t, iTask, zEvent);
}
static void vdbeSorterBlockDebug(
SortSubtask *pTask,
int bBlocked,
const char *zEvent
){
if( bBlocked ){
i64 t;
sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
fprintf(stderr, "%lld:main %s\n", t, zEvent);
}
}
if( i<2 ){
sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
goto detach_error;
}
if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
goto detach_error;
}
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
/*
** The TableLock structure is only used by the sqlite3TableLock() and
** codeTableLocks() functions.
*/
struct TableLock {
int iDb; /* The database containing the table to be locked */
int iTab; /* The root page of the table to be locked */
u8 isWriteLock; /* True for write lock. False for a read lock */
const char *zLockName; /* Name of the table */
};
/*
** Record the fact that we want to lock a table at run-time.
**
** The table to be locked has root page iTab and is found in database iDb.
** A read or a write lock can be taken depending on isWritelock.
**
** This routine just records the fact that the lock is desired. The
** code to make the lock occur is generated by a later call to
** codeTableLocks() which occurs during sqlite3FinishCoding().
*/
SQLITE_PRIVATE void sqlite3TableLock(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database containing the table to lock */
int iTab, /* Root page number of the table to be locked */
u8 isWriteLock, /* True for a write lock */
const char *zName /* Name of the table to be locked */
){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
int i;
int nBytes;
TableLock *p;
sqlite3OomFault(pToplevel->db);
}
}
/*
** Code an OP_TableLock instruction for each table locked by the
** statement (configured by calls to sqlite3TableLock()).
*/
static void codeTableLocks(Parse *pParse){
int i;
Vdbe *pVdbe;
/*
** Report the current state of file logs for all databases
*/
case PragTyp_LOCK_STATUS: {
static const char *const azLockName[] = {
"unlocked", "shared", "reserved", "pending", "exclusive"
};
int i;
pParse->nMem = 2;
for(i=0; i<db->nDb; i++){
Btree *pBt;
if( pBt ){
assert( sqlite3BtreeHoldsMutex(pBt) );
rc = sqlite3BtreeSchemaLocked(pBt);
if( rc ){
const char *zDb = db->aDb[i].zDbSName;
sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
testcase( db->flags & SQLITE_ReadUncommit );
goto end_prepare;
}
}
}
/*
** Rerun the compilation of a statement after a schema change.
**
** If the statement is successfully recompiled, return SQLITE_OK. Otherwise,
** if the statement cannot be recompiled because another connection has
** locked the sqlite3_master table, return SQLITE_LOCKED. If any other error
** occurs, return SQLITE_SCHEMA.
*/
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){
int rc;
sqlite3_stmt *pNew;
pDb = &db->aDb[nDb];
assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
pTemp = pDb->pBt;
/* The call to execSql() to attach the temp database has left the file
** locked (as there was more than one active statement when the transaction
** to read the schema was concluded. Unlock it here so that this doesn't
** cause problems for the call to BtreeSetPageSize() below. */
sqlite3BtreeCommit(pTemp);
nRes = sqlite3BtreeGetOptimalReserve(pMain);
/*
** Lock the virtual table so that it cannot be disconnected.
** Locks nest. Every lock should have a corresponding unlock.
** If an unlock is omitted, resources leaks will occur.
**
** If a disconnect is attempted while a virtual table is locked,
** the disconnect is deferred until all locks have been removed.
*/
SQLITE_PRIVATE void sqlite3VtabLock(VTable *pVTab){
pVTab->nRef++;
}
/* SQLITE_OK */ "not an error",
/* SQLITE_ERROR */ "SQL logic error",
/* SQLITE_INTERNAL */ 0,
/* SQLITE_PERM */ "access permission denied",
/* SQLITE_ABORT */ "query aborted",
/* SQLITE_BUSY */ "database is locked",
/* SQLITE_LOCKED */ "database table is locked",
/* SQLITE_NOMEM */ "out of memory",
/* SQLITE_READONLY */ "attempt to write a readonly database",
/* SQLITE_INTERRUPT */ "interrupted",
/* SQLITE_IOERR */ "disk I/O error",
/* SQLITE_CORRUPT */ "database disk image is malformed",
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
/*
** Public interfaces:
**
** sqlite3ConnectionBlocked()
** sqlite3ConnectionUnlocked()
** sqlite3ConnectionClosed()
** sqlite3_unlock_notify()
*/
#define assertMutexHeld() \
** Head of a linked list of all sqlite3 objects created by this process
** for which either sqlite3.pBlockingConnection or sqlite3.pUnlockConnection
** is not NULL. This variable may only accessed while the STATIC_MASTER
** mutex is held.
*/
static sqlite3 *SQLITE_WSD sqlite3BlockedList = 0;
#ifndef NDEBUG
/*
** This function is a complex assert() that verifies the following
** properties of the blocked connections list:
**
** 1) Each entry in the list has a non-NULL value for either
** pUnlockConnection or pBlockingConnection, or both.
**
** 2) All entries in the list that share a common value for
** xUnlockNotify are grouped together.
**
** 3) If the argument db is not NULL, then none of the entries in the
** blocked connections list have pUnlockConnection or pBlockingConnection
** set to db. This is used when closing connection db.
*/
static void checkListProperties(sqlite3 *db){
sqlite3 *p;
for(p=sqlite3BlockedList; p; p=p->pNextBlocked){
int seen = 0;
sqlite3 *p2;
/* Verify property (1) */
assert( p->pUnlockConnection || p->pBlockingConnection );
/* Verify property (2) */
for(p2=sqlite3BlockedList; p2!=p; p2=p2->pNextBlocked){
if( p2->xUnlockNotify==p->xUnlockNotify ) seen = 1;
assert( p2->xUnlockNotify==p->xUnlockNotify || !seen );
assert( db==0 || p->pUnlockConnection!=db );
assert( db==0 || p->pBlockingConnection!=db );
}
#else
# define checkListProperties(x)
#endif
/*
** Remove connection db from the blocked connections list. If connection
** db is not currently a part of the list, this function is a no-op.
*/
static void removeFromBlockedList(sqlite3 *db){
sqlite3 **pp;
assertMutexHeld();
for(pp=&sqlite3BlockedList; *pp; pp = &(*pp)->pNextBlocked){
if( *pp==db ){
*pp = (*pp)->pNextBlocked;
break;
}
}
}
/*
** Add connection db to the blocked connections list. It is assumed
** that it is not already a part of the list.
*/
static void addToBlockedList(sqlite3 *db){
sqlite3 **pp;
assertMutexHeld();
for(
pp=&sqlite3BlockedList;
*pp && (*pp)->xUnlockNotify!=db->xUnlockNotify;
pp=&(*pp)->pNextBlocked
);
db->pNextBlocked = *pp;
*pp = db;
}
/*
** Obtain the STATIC_MASTER mutex.
** cache. pOther is found by looking at db->pBlockingConnection.
**
** If there is no blocking connection, the callback is invoked immediately,
** before this routine returns.
**
** If pOther is already blocked on db, then report SQLITE_LOCKED, to indicate
** a deadlock.
**
** Otherwise, make arrangements to invoke xNotify when pOther drops
** its locks.
**
sqlite3_mutex_enter(db->mutex);
enterMutex();
if( xNotify==0 ){
removeFromBlockedList(db);
db->pBlockingConnection = 0;
db->pUnlockConnection = 0;
db->xUnlockNotify = 0;
db->pUnlockArg = 0;
}else if( 0==db->pBlockingConnection ){
rc = SQLITE_LOCKED; /* Deadlock detected. */
}else{
db->pUnlockConnection = db->pBlockingConnection;
db->xUnlockNotify = xNotify;
db->pUnlockArg = pArg;
removeFromBlockedList(db);
addToBlockedList(db);
}
}
leaveMutex();
assert( !db->mallocFailed );
sqlite3ErrorWithMsg(db, rc, (rc?"database is deadlocked":0));
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
** This function is called while stepping or preparing a statement
** associated with connection db. The operation will return SQLITE_LOCKED
** to the user because it requires a lock that will not be available
** until connection pBlocker concludes its current transaction.
*/
SQLITE_PRIVATE void sqlite3ConnectionBlocked(sqlite3 *db, sqlite3 *pBlocker){
enterMutex();
if( db->pBlockingConnection==0 && db->pUnlockConnection==0 ){
addToBlockedList(db);
}
db->pBlockingConnection = pBlocker;
leaveMutex();
}
/*
** This function is called when
** the transaction opened by database db has just finished. Locks held
** by database connection db have been released.
**
** This function loops through each entry in the blocked connections
** list and does the following:
**
** 1) If the sqlite3.pBlockingConnection member of a list entry is
** set to db, then set pBlockingConnection=0.
**
** 2) If the sqlite3.pUnlockConnection member of a list entry is
** set to db, then invoke the configured unlock-notify callback and
** set pUnlockConnection=0.
**
** 3) If the two steps above mean that pBlockingConnection==0 and
** pUnlockConnection==0, remove the entry from the blocked connections
** list.
*/
SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db){
void (*xUnlockNotify)(void **, int) = 0; /* Unlock-notify cb to invoke */
int nArg = 0; /* Number of entries in aArg[] */
sqlite3 **pp; /* Iterator variable */
void **aArg; /* Arguments to the unlock callback */
void **aDyn = 0; /* Dynamically allocated space for aArg[] */
void *aStatic[16]; /* Starter space for aArg[]. No malloc required */
aArg = aStatic;
enterMutex(); /* Enter STATIC_MASTER mutex */
/* This loop runs once for each entry in the blocked-connections list. */
for(pp=&sqlite3BlockedList; *pp; /* no-op */ ){
sqlite3 *p = *pp;
/* Step 1. */
if( p->pBlockingConnection==db ){
p->pBlockingConnection = 0;
** allocate a larger array from the heap has failed.
**
** This is a difficult situation to handle. Returning an error
** code to the caller is insufficient, as even if an error code
** is returned the transaction on connection db will still be
** closed and the unlock-notify callbacks on blocked connections
** will go unissued. This might cause the application to wait
** indefinitely for an unlock-notify callback that will never
** arrive.
**
** Instead, invoke the unlock-notify callback with the context
p->pUnlockArg = 0;
}
/* Step 3. */
if( p->pBlockingConnection==0 && p->pUnlockConnection==0 ){
/* Remove connection p from the blocked connections list. */
*pp = p->pNextBlocked;
p->pNextBlocked = 0;
}else{
pp = &p->pNextBlocked;
}
}
if( nArg!=0 ){
xUnlockNotify(aArg, nArg);
leaveMutex(); /* Leave STATIC_MASTER mutex */
}
/*
** This is called when the database connection passed as an argument is
** being closed. The connection is removed from the blocked list.
*/
SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
sqlite3ConnectionUnlocked(db);
enterMutex();
removeFromBlockedList(db);
checkListProperties(db);
leaveMutex();
}
#endif
view all matches for this distribution