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

Re: [PATCH v2 12/19] read-cache: read index-v5

From
Duy Nguyen <pclouds@gmail.com>
Date
Aug 8, 2013, 02:00 UTC
Message-ID
<CACsJy8C4r=5K3ZdzNnNJ95xS3_xnsTSH2bUyLJ+rwRv4Jxo2zw@mail.gmail.com>
In-Reply-To
<87r4exsj14.fsf@gmail.com>
On Wed, Jul 17, 2013 at 3:11 PM, Thomas Gummerer <t.gummerer@gmail.com> wrote:
Show 71 quoted lines
> Duy Nguyen <pclouds@gmail.com> writes:
>
> [..]
>
>>> +static int read_entries(struct index_state *istate, struct directory_entry **de,
>>> +                       unsigned int *entry_offset, void **mmap,
>>> +                       unsigned long mmap_size, unsigned int *nr,
>>> +                       unsigned int *foffsetblock)
>>> +{
>>> +       struct cache_entry *head = NULL, *tail = NULL;
>>> +       struct conflict_entry *conflict_queue;
>>> +       struct cache_entry *ce;
>>> +       int i;
>>> +
>>> +       conflict_queue = NULL;
>>> +       if (read_conflicts(&conflict_queue, *de, mmap, mmap_size) < 0)
>>> +               return -1;
>>> +       for (i = 0; i < (*de)->de_nfiles; i++) {
>>> +               if (read_entry(&ce,
>>> +                              *de,
>>> +                              entry_offset,
>>> +                              mmap,
>>> +                              mmap_size,
>>> +                              foffsetblock) < 0)
>>> +                       return -1;
>>> +               ce_queue_push(&head, &tail, ce);
>>> +               *foffsetblock += 4;
>>> +
>>> +               /*
>>> +                * Add the conflicted entries at the end of the index file
>>> +                * to the in memory format
>>> +                */
>>> +               if (conflict_queue &&
>>> +                   (conflict_queue->entries->flags & CONFLICT_CONFLICTED) != 0 &&
>>> +                   !cache_name_compare(conflict_queue->name, conflict_queue->namelen,
>>> +                                       ce->name, ce_namelen(ce))) {
>>> +                       struct conflict_part *cp;
>>> +                       cp = conflict_queue->entries;
>>> +                       cp = cp->next;
>>> +                       while (cp) {
>>> +                               ce = convert_conflict_part(cp,
>>> +                                               conflict_queue->name,
>>> +                                               conflict_queue->namelen);
>>> +                               ce_queue_push(&head, &tail, ce);
>>> +                               conflict_part_head_remove(&cp);
>>> +                       }
>>> +                       conflict_entry_head_remove(&conflict_queue);
>>> +               }
>>
>> I start to wonder if separating staged entries is a good idea. It
>> seems to make the code more complicated. The good point about conflict
>> section at the end of the file is you can just truncate() it out.
>> Another way is putting staged entries in fileentries, sorted
>> alphabetically then by stage number, and a flag indicating if the
>> entry is valid. When you remove resolve an entry, just set the flag to
>> invalid (partial write), so that read code will skip it.
>>
>> I think this approach is reasonably cheap (unless there are a lot of
>> conflicts) and it simplifies this piece of code. truncate() may be
>> overrated anyway. In my experience, I "git add <path>" as soon as I
>> resolve <path> (so that "git diff" shrinks). One entry at a time, one
>> index write at a time. I don't think I ever resolve everything then
>> "git add -u .", which is where truncate() shines because staged
>> entries are removed all at once. We should optimize for one file
>> resolution at a time, imo.
>
> Thanks for your comments.  I'll address the other ones once we decided
> to do with the conflicts.
>
> It does make the code quite a bit more complicated, but also has one
> advantage that you overlooked.

I did overlook, although my goal is to keep the code simpler, not more comlicated. The thinking is if we can find everything in fileentries table, the code here is simplified, so..

Show 8 quoted lines
> We wouldn't truncate() when resolving
> the conflicts.  The resolve undo data is stored with the conflicts and
> therefore we could just flip a bit and set the stage of the cache-entry
> in the main index to 0 (always once we got partial writing).  This can
> be fast both in case we resolve one entry at a time and when we resolve
> a lot of entries.  The advantage is even bigger when we resolve one
> entry at a time, when we otherwise would have to re-write the index for
> each conflict resolution.

If I understand it correctly, filentries can only contain stage-0 or stage-1 entries, "stage > 0" entries are stored in conflict data. Once a conflict is solved, you update the stage-1 entry in fileentries, turning it to stage-0 and recalculate the entry checksum. Conflict data remains there to function as the old REUC extension. Correct?

First of all, if that's true, we only need 1 bit for stage in fileentries table.

Secondly, you may get away with looking up to conflict data in this function by storing all stages in fileentries (now we need 2-bit stage), replicated in conflict data for reuc function. When you resolve conflict, you flip stage-1 to stage-0, and flip (a new bit) to mark stage-2 entry invalid so the code knows to skip it. Next time the index is rewritten, invalid entries are removed, but we still have old stage entries in conflict data. The flipping business is pretty much what you plan anyway, but the reading code does not need to look at both fileentries and conflict data at the same time.

What do you think?
-- 
Duy
Previous: Thomas GummererNext: Thomas Gummerer
Message 31 of 51 in “Index-v5”
  1. 00/19 Index-v5Thomas Gummerer, Jul 12, 2013
  2. 01/19 t2104: Don't fail for index versions other than [23]Thomas Gummerer, Jul 12, 2013
  3. 02/19 read-cache: split index file version specific functionalityThomas Gummerer, Jul 12, 2013
  4. 03/19 read-cache: move index v2 specific functions to their own fileThomas Gummerer, Jul 12, 2013
  5. Duy NguyenJul 14, 2013
  6. Thomas GummererJul 19, 2013
  7. 04/19 read-cache: Re-read index if index file changedThomas Gummerer, Jul 12, 2013
  8. 05/19 Add documentation for the index apiThomas Gummerer, Jul 12, 2013
  9. 06/19 read-cache: add index reading apiThomas Gummerer, Jul 12, 2013
  10. Duy NguyenJul 14, 2013
  11. 07/19 make sure partially read index is not changedThomas Gummerer, Jul 12, 2013
  12. Duy NguyenJul 14, 2013
  13. Thomas GummererJul 17, 2013
  14. 08/19 grep.c: Use index apiThomas Gummerer, Jul 12, 2013
  15. Duy NguyenJul 14, 2013
  16. Thomas GummererJul 15, 2013
  17. 09/19 ls-files.c: use index apiThomas Gummerer, Jul 12, 2013
  18. Duy NguyenJul 14, 2013
  19. Thomas GummererJul 17, 2013
  20. 10/19 documentation: add documentation of the index-v5 file formatThomas Gummerer, Jul 12, 2013
  21. Duy NguyenJul 14, 2013
  22. Thomas GummererJul 17, 2013
  23. Duy NguyenAug 4, 2013
  24. Thomas GummererAug 4, 2013
  25. 11/19 read-cache: make in-memory format aware of stat_crcThomas Gummerer, Jul 12, 2013
  26. 12/19 read-cache: read index-v5Thomas Gummerer, Jul 12, 2013
  27. Duy NguyenJul 14, 2013
  28. Thomas GummererAug 7, 2013
  29. Duy NguyenJul 15, 2013
  30. Thomas GummererJul 17, 2013
  31. Duy NguyenAug 8, 2013
  32. Thomas GummererAug 8, 2013
  33. Thomas GummererAug 9, 2013
  34. Thomas GummererAug 7, 2013
  35. Duy NguyenAug 8, 2013
  36. 13/19 read-cache: read resolve-undo dataThomas Gummerer, Jul 12, 2013
  37. 14/19 read-cache: read cache-tree in index-v5Thomas Gummerer, Jul 12, 2013
  38. 15/19 read-cache: write index-v5Thomas Gummerer, Jul 12, 2013
  39. 16/19 read-cache: write index-v5 cache-tree dataThomas Gummerer, Jul 12, 2013
  40. 17/19 read-cache: write resolve-undo data for index-v5Thomas Gummerer, Jul 12, 2013
  41. 18/19 update-index.c: rewrite index when index-version is givenThomas Gummerer, Jul 12, 2013
  42. 19/19 p0003-index.sh: add perf test for the index formatsThomas Gummerer, Jul 12, 2013
  43. Duy NguyenJul 14, 2013
  44. Thomas GummererJul 15, 2013
  45. Duy NguyenJul 15, 2013
  46. Thomas GummererJul 17, 2013
  47. Junio C HamanoJul 17, 2013
  48. Thomas GummererJul 19, 2013
  49. Junio C HamanoJul 19, 2013
  50. Ramsay JonesJul 16, 2013
  51. Thomas GummererJul 17, 2013

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.