<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">p.MsoNormal,p.MsoNoSpacing{margin:0}</style>
</head>
<body><div style="font-family:Arial;">It's become clear trying to fix the Xapian locking mess that we actually want two locks, like we have for mailboxes.  A namelock that is long lasting and doesn't block regular indexing or searching, but guarantees that things won't be deleted out underneath, and the existing short term locks on xapianactive that are used to guarantee clean reads and safe indexing.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">Xapian Locking:<br></div>
<div style="font-family:Arial;">---<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">* Xapian per-user NAMELOCK (shared or exclusive)<br></div>
<div style="font-family:Arial;">* xapianactive file lock (shared or exclusive)<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">Shared namelock holds the following invariants:<br></div>
<div style="font-family:Arial;">* xapianactive file contents are not changed<br></div>
<div style="font-family:Arial;">* directories mentioned in xapianactive are not cleaned up<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">Xapianactive exclusive lock holds the following invariants:<br></div>
<div style="font-family:Arial;">* owner may write to first database mentioned in xapianactive<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">Xapianactive shared lock holds:<br></div>
<div style="font-family:Arial;">* all databases in xapianactive are readable and a consistent<br></div>
<div style="font-family:Arial;">  read can be made across all of them, even with multiple requests<br></div>
<div style="font-family:Arial;">  while the lock is held.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">Locking orders:<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">SHARED case:<br></div>
<div style="font-family:Arial;">* user conversations db <=== possibly reversible with SHARED xapian namelock<br></div>
<div style="font-family:Arial;">* SHARED xapian namelock<br></div>
<div style="font-family:Arial;">* xapianactive lock (shared to search, exclusive to write)<br></div>
<div style="font-family:Arial;">* cyrus.index may be locked either side of the xapianactive lock, because the<br></div>
<div style="font-family:Arial;">  conversationsdb lock protects it from races.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">EXCLUSIVE case:<br></div>
<div style="font-family:Arial;">* EXCLUSIVE xapian namelock<br></div>
<div style="font-family:Arial;">  -> that's it.  While you've got this, you can add or delete items from<br></div>
<div style="font-family:Arial;">     the xapianactive file, and delete paths on disk for directories that<br></div>
<div style="font-family:Arial;">     you have removed (either during or after locking).  No other locks are<br></div>
<div style="font-family:Arial;">     permitted.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">If you hold a SHARED xapian namelock, you may write to a .NEW folder for a<br></div>
<div style="font-family:Arial;">xapianactive entry that you created without taking any additional locks,<br></div>
<div style="font-family:Arial;">because nothing can clean it under you, and nothing else can read it.  This<br></div>
<div style="font-family:Arial;">is how the repack case works.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">---------------------------------<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">Places that will need to be changed:<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">begin_search: needs to take a SHARED namelock before taking a SHARED xapianactive lock.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">end_search: needs to release the namelock after unlocking the activefile.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">begin_mailbox_update: needs to take a SHARED namelock before taking an EXCLUSIVE xapianactive lock.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">end_mailbox_update: needs to release the namelock.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">list_files: needs to take a SHARED namelock and release it again.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">delete_user: needs to take an EXCLUSIVE namelock as well as the existing EXCLUSIVE xapianactive lock.<br></div>
<div style="font-family:Arial;"><div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">compact_dbs: this is the complex one!<br></div>
<div style="font-family:Arial;"><div style="font-family:Arial;"><br></div>
</div>
<div style="font-family:Arial;"><div style="font-family:Arial;">1) take an EXCLUSIVE namelock while doing the following:<br></div>
<div style="font-family:Arial;">   -> add a new first target tier:number to the xapianactive file (always temp)<br></div>
<div style="font-family:Arial;">   -> add a new tier:number target to the tail of the xapianactive file (squatter -z option)<br></div>
<div style="font-family:Arial;">2) release the EXCLUSIVE namelock<br></div>
<div style="font-family:Arial;">3) take a SHARED namelock and SHARED xapianactive lock to read the contents of the xapianactive file and make sure we didn't lose a race.<br></div>
<div style="font-family:Arial;">4) release the SHARED xapianactive lock.<br></div>
<div style="font-family:Arial;">5) compact or reindex into target:number xapian.<number>.NEW directory (see above, this is safe without locks)<br></div>
<div style="font-family:Arial;">6) release the SHARED namelock<br></div>
<div style="font-family:Arial;">7) take an EXCLUSIVE namelock and check again that we have the same xapianactive contents, if we lost the race here, we still need to delete all the xapian.<number>.NEW and abort.<br></div>
<div style="font-family:Arial;">8)  rename xapian.<number>.NEW to xapian.<number><br></div>
<div style="font-family:Arial;">9) remove the source tier:number entries from xapianactive<br></div>
<div style="font-family:Arial;">10) release the EXCLUSIVE namelock.<br></div>
<div style="font-family:Arial;">11) take a SHARED namelock<br></div>
<div style="font-family:Arial;">12) It's now safe to delete all the directories which were source tier:number, as well as any other directory not mentioned in xapianactive any more.<br></div>
<div style="font-family:Arial;">13) release everything, you're done :)<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;"><br></div>
</div>
</div>
<div id="sig56629417"><div class="signature">--<br></div>
<div class="signature">  Bron Gondwana, CEO, FastMail Pty Ltd<br></div>
<div class="signature">  brong@fastmailteam.com<br></div>
<div class="signature"><br></div>
</div>
<div style="font-family:Arial;"><br></div>
</body>
</html>