git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v6 02/39] api-lockfile: revise and expand the documentation

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
Sep 30, 2014, 10:53 UTC
Message-ID
<542A8B90.50507@alum.mit.edu>
In-Reply-To
<xmqqlhp68c69.fsf@gitster.dls.corp.google.com>
On 09/26/2014 08:33 PM, Junio C Hamano wrote:
Show 29 quoted lines
> Michael Haggerty <mhagger@alum.mit.edu> writes:
> 
>> Document a couple more functions and the flags argument as used by
>> hold_lock_file_for_update() and hold_lock_file_for_append().
>> Reorganize the document to make it more accessible.
>>
>> Helped-by: Jonathan Nieder <jrnieder@gmail.com>
>> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
>> ---
>>  Documentation/technical/api-lockfile.txt | 199 ++++++++++++++++++++++---------
>>  1 file changed, 145 insertions(+), 54 deletions(-)
> 
> Nicely done.
> 
>> +* Mutual exclusion and atomic file updates. When we want to change a
>> +  file, we create a lockfile `<filename>.lock`, write the new file
>> +  contents into it, and then rename the lockfile to its final
>> +  destination `<filename>`. We create the `<filename>.lock` file with
>> +  `O_CREAT|O_EXCL` so that we can notice and fail if somebody else has
>> +  already locked the file.
> 
> 
> You may want to say
> 
> 	then atomically rename the lockfile to its final destination
> 	to commit the changes and unlock the file.
> 
> here; that way, your mention of "commit" in the next paragraph would
> become easier to understand.
Good; will change.
Show 17 quoted lines
>> [...]
>> +Calling sequence
>> +----------------
>> +
>> +The caller:
>> +
>> +* Allocates a variable `struct lock_file lock` in the bss section or
>> +  heap, initialized to zeros. It cannot be an auto variable allocated
>> +  on the stack. Because the `lock_file` structure is used in an
>> +  `atexit(3)` handler, its storage has to stay throughout the life of
>> +  the program, even after the file changes have been committed or
>> +  rolled back.
> 
> It is easier to read if you pushed the second sentence (which is a
> rephrase of the first one) and third sentence (which explains why
> the second sentence is true) out of line as a side-note, I think, or
> probably remove them from here (see below).

I was being repetitive because I didn't want the docs to depend on the user remembering what the "bss" section is (which, technically, is also not part of the C standard). I think a better way would be to just not mention "bss section" at all and reword the rest. Maybe something like

  The caller:
  * Allocates a variable `struct lock_file lock`, initialized to zeros.
    Because the `lock_file` structure is used in an `atexit(3)` handler,
    its storage has to remain valid throughout the life of the program;
    e.g., it should be a static variable or space allocated on the heap.
Better?
Show 29 quoted lines
>> +* Attempts to create a lockfile by passing that variable and the path
>> +  of the final destination (e.g. `$GIT_DIR/index`) to
>> +  `hold_lock_file_for_update` or `hold_lock_file_for_append`.
>> +
>> +* Writes new content for the destination file by writing to the file
>> +  descriptor returned by those functions (also available via
>> +  `lock->fd`).
>> +
>> +When finished writing, the caller can:
>> +
>> +* Close the file descriptor and rename the lockfile to its final
>> +  destination by calling `commit_lock_file`.
>> +
>> +* Close the file descriptor and remove the lockfile by calling
>> +  `rollback_lock_file`.
>> +
>> +* Close the file descriptor without removing or renaming the lockfile
>> +  by calling `close_lock_file`, and later call `commit_lock_file` or
>> +  `rollback_lock_file`.
>> +
>> +At this point, the `lock_file` object must not be freed or altered,
>> +because it is still registered in the `lock_file_list`. However, it
>> +may be reused; just pass it to another call of
>> +`hold_lock_file_for_update` or `hold_lock_file_for_append`.
> 
> It feels a bit conflicting between "must not be freed or ALTERED"
> and "it may be REUSED".  Drop "or altered" to reduce confusion?  And
> this repeats the third sentence I suggested to remove from the first
> paragraph (above 'see below' refers here).

The purpose of "or altered" is to make sure that users don't imagine that they should memset() the structure to zeros or something before reusing it (especially since the "caller" instructions earlier say that the object should be "initialized to zeros").

Would it help if I change
    s/altered/altered by the caller/
?
I will also drop "because it is still registered in the `lock_file_list`".
Show 5 quoted lines
> Is it allowed to tell the name of this lock_file to other people and
> let them read from it?  The answer is yes but it is not obvious from
> this description.
> 
> Also mention how the above interact with reopen_lock_file() here?

I'll take a stab at it, though TBH I haven't really studied the use case for reopen_lock_file(). You might be better able to provide insight into this topic.

Show 6 quoted lines
>> +If the program exits before you have called one of `commit_lock_file`,
>> +`rollback_lock_file`, or `close_lock_file`, an `atexit(3)` handler
>> +will close and remove the lockfile, essentially rolling back any
>> +uncommitted changes.
> 
> s/essentially //;
Done.
Show 10 quoted lines
>> +Error handling
>> +--------------
>> +
>> +The `hold_lock_file_*` functions return a file descriptor on success
>> +or -1 on failure (unless `LOCK_DIE_ON_ERROR` is used; see below). On
>> +errors, `errno` describes the reason for failure. Errors can be
>> +handled by passing `errno` to one of the following helper functions:
> 
> s/handled by/reported by/; probably.  None of these will help you
> "handle" errors in the sense to (attempt to) recover from it.
Done.

Thanks for your suggestions! Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
Previous: Junio C HamanoNext: Junio C Hamano
Message 5 of 55 in “Lockfile correctness and refactoring”
  1. 00/39 Lockfile correctness and refactoringMichael Haggerty, Sep 26, 2014
  2. 01/39 unable_to_lock_die(): rename function from unable_to_lock_index_die()Michael Haggerty, Sep 26, 2014
  3. 02/39 api-lockfile: revise and expand the documentationMichael Haggerty, Sep 26, 2014
  4. Junio C HamanoSep 26, 2014
  5. Michael HaggertySep 30, 2014
  6. Junio C HamanoSep 30, 2014
  7. Michael HaggertyOct 1, 2014
  8. Junio C HamanoSep 26, 2014
  9. Michael HaggertySep 30, 2014
  10. Jeff KingSep 30, 2014
  11. Junio C HamanoSep 30, 2014
  12. Michael HaggertyOct 1, 2014
  13. 03/39 close_lock_file(): exit (successfully) if file is already closedMichael Haggerty, Sep 26, 2014
  14. 04/39 rollback_lock_file(): do not clear filename redundantlyMichael Haggerty, Sep 26, 2014
  15. 05/39 rollback_lock_file(): exit early if lock is not activeMichael Haggerty, Sep 26, 2014
  16. 06/39 rollback_lock_file(): set fd to -1Michael Haggerty, Sep 26, 2014
  17. 07/39 lockfile: unlock file if lockfile permissions cannot be adjustedMichael Haggerty, Sep 26, 2014
  18. 08/39 hold_lock_file_for_append(): release lock on errorsMichael Haggerty, Sep 26, 2014
  19. 09/39 lock_file(): always initialize and register lock_file objectMichael Haggerty, Sep 26, 2014
  20. 10/39 lockfile.c: document the various states of lock_file objectsMichael Haggerty, Sep 26, 2014
  21. 11/39 cache.h: define constants LOCK_SUFFIX and LOCK_SUFFIX_LENMichael Haggerty, Sep 26, 2014
  22. 12/39 delete_ref_loose(): don't muck around in the lock_file's filenameMichael Haggerty, Sep 26, 2014
  23. 13/39 prepare_index(): declare return value to be (const char *)Michael Haggerty, Sep 26, 2014
  24. 14/39 write_packed_entry_fn(): convert cb_data into a (const int *)Michael Haggerty, Sep 26, 2014
  25. 15/39 lock_file(): exit early if lockfile cannot be openedMichael Haggerty, Sep 26, 2014
  26. 16/39 remove_lock_file(): call rollback_lock_file()Michael Haggerty, Sep 26, 2014
  27. 17/39 commit_lock_file(): inline temporary variableMichael Haggerty, Sep 26, 2014
  28. 18/39 commit_lock_file(): die() if called for unlocked lockfile objectMichael Haggerty, Sep 26, 2014
  29. 19/39 close_lock_file(): if close fails, roll backMichael Haggerty, Sep 26, 2014
  30. 20/39 commit_lock_file(): rollback lock file on failure to renameMichael Haggerty, Sep 26, 2014
  31. 21/39 api-lockfile: document edge casesMichael Haggerty, Sep 26, 2014
  32. 22/39 dump_marks(): remove a redundant call to rollback_lock_file()Michael Haggerty, Sep 26, 2014
  33. 23/39 git_config_set_multivar_in_file(): avoid call to rollback_lock_file()Michael Haggerty, Sep 26, 2014
  34. 24/39 lockfile: avoid transitory invalid statesMichael Haggerty, Sep 26, 2014
  35. 25/39 struct lock_file: declare some fields volatileMichael Haggerty, Sep 26, 2014
  36. 26/39 try_merge_strategy(): remove redundant lock_file allocationMichael Haggerty, Sep 26, 2014
  37. 27/39 try_merge_strategy(): use a statically-allocated lock_file objectMichael Haggerty, Sep 26, 2014
  38. Junio C HamanoSep 26, 2014
  39. Michael HaggertySep 30, 2014
  40. Junio C HamanoSep 30, 2014
  41. 28/39 commit_lock_file(): use a strbuf to manage temporary spaceMichael Haggerty, Sep 26, 2014
  42. 29/39 Change lock_file::filename into a strbufMichael Haggerty, Sep 26, 2014
  43. 30/39 resolve_symlink(): use a strbuf for internal scratch spaceMichael Haggerty, Sep 26, 2014
  44. 31/39 resolve_symlink(): take a strbuf parameterMichael Haggerty, Sep 26, 2014
  45. 32/39 trim_last_path_component(): replace last_path_elm()Michael Haggerty, Sep 26, 2014
  46. 33/39 Extract a function commit_lock_file_to()Michael Haggerty, Sep 26, 2014
  47. 34/39 Rename LOCK_NODEREF to LOCK_NO_DEREFMichael Haggerty, Sep 26, 2014
  48. 35/39 lockfile.c: rename static functionsMichael Haggerty, Sep 26, 2014
  49. 36/39 get_locked_file_path(): new functionMichael Haggerty, Sep 26, 2014
  50. 37/39 hold_lock_file_for_append(): restore errno before returningMichael Haggerty, Sep 26, 2014
  51. 38/39 Move read_index() definition to read-cache.cMichael Haggerty, Sep 26, 2014
  52. 39/39 lockfile.h: extract new header file for the functions in lockfile.cMichael Haggerty, Sep 26, 2014
  53. Junio C HamanoSep 26, 2014
  54. Michael HaggertySep 30, 2014
  55. Junio C HamanoSep 26, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.