.\" Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .if !\nF .nr F 0 .if \nF>0 \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Lucy::Docs::FileLocking 3pm" .TH Lucy::Docs::FileLocking 3pm "2017-08-02" "perl v5.26.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Lucy::Docs::FileLocking \- Manage indexes on shared volumes. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 3 \& use Sys::Hostname qw( hostname ); \& my $hostname = hostname() or die "Can\*(Aqt get unique hostname"; \& my $manager = Lucy::Index::IndexManager\->new( host => $hostname ); \& \& # Index time: \& my $indexer = Lucy::Index::Indexer\->new( \& index => \*(Aq/path/to/index\*(Aq, \& manager => $manager, \& ); \& \& # Search time: \& my $reader = Lucy::Index::IndexReader\->open( \& index => \*(Aq/path/to/index\*(Aq, \& manager => $manager, \& ); \& my $searcher = Lucy::Search::IndexSearcher\->new( index => $reader ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Normally, index locking is an invisible process. Exclusive write access is controlled via lockfiles within the index directory and problems only arise if multiple processes attempt to acquire the write lock simultaneously; search-time processes do not ordinarily require locking at all. .PP On shared volumes, however, the default locking mechanism fails, and manual intervention becomes necessary. .PP Both read and write applications accessing an index on a shared volume need to identify themselves with a unique \f(CW\*(C`host\*(C'\fR id, e.g. hostname or ip address. Knowing the host id makes it possible to tell which lockfiles belong to other machines and therefore must not be removed when the lockfile's pid number appears not to correspond to an active process. .PP At index-time, the danger is that multiple indexing processes from different machines which fail to specify a unique \f(CW\*(C`host\*(C'\fR id can delete each others' lockfiles and then attempt to modify the index at the same time, causing index corruption. The search-time problem is more complex. .PP Once an index file is no longer listed in the most recent snapshot, Indexer attempts to delete it as part of a post\-\fIcommit()\fR cleanup routine. It is possible that at the moment an Indexer is deleting files which it believes no longer needed, a Searcher referencing an earlier snapshot is in fact using them. The more often that an index is either updated or searched, the more likely it is that this conflict will arise from time to time. .PP Ordinarily, the deletion attempts are not a problem. On a typical unix volume, the files will be deleted in name only: any process which holds an open filehandle against a given file will continue to have access, and the file won't actually get vaporized until the last filehandle is cleared. Thanks to \*(L"delete on last close semantics\*(R", an Indexer can't truly delete the file out from underneath an active Searcher. On Windows, where file deletion fails whenever any process holds an open handle, the situation is different but still workable: Indexer just keeps retrying after each commit until deletion finally succeeds. .PP On \s-1NFS,\s0 however, the system breaks, because \s-1NFS\s0 allows files to be deleted out from underneath active processes. Should this happen, the unlucky read process will crash with a \*(L"Stale \s-1NFS\s0 filehandle\*(R" exception. .PP Under normal circumstances, it is neither necessary nor desirable for IndexReaders to secure read locks against an index, but for \s-1NFS\s0 we have to make an exception. LockFactory's \fImake_shared_lock()\fR method exists for this reason; supplying an IndexManager instance to IndexReader's constructor activates an internal locking mechanism using \fImake_shared_lock()\fR which prevents concurrent indexing processes from deleting files that are needed by active readers. .PP Since shared locks are implemented using lockfiles located in the index directory (as are exclusive locks), reader applications must have write access for read locking to work. Stale lock files from crashed processes are ordinarily cleared away the next time the same machine \*(-- as identified by the \f(CW\*(C`host\*(C'\fR parameter \*(-- opens another IndexReader. (The classic technique of timing out lock files is not feasible because search processes may lie dormant indefinitely.) However, please be aware that if the last thing a given machine does is crash, lock files belonging to it may persist, preventing deletion of obsolete index data.