// File: /workspace/github_c_makefile_star2_O0/deplinenoise[P]tundra/src/ScanCache.cpp
// Function: t2::ScanCacheSave(t2::ScanCache*, char const*, t2::MemAllocHeap*)
bool ScanCacheSave(ScanCache* self, const char* fn, MemAllocHeap* heap)
{
  TimingScope timing_scope(nullptr, &g_Stats.m_ScanCacheSaveTime);
  ProfilerScope prof_scope("Tundra SaveScanCache", 0);

  MemAllocLinear* scratch = self->m_Allocator;

  MemAllocLinearScope scratch_scope(scratch);

  HashTable<BinaryLocator, kFlagPathStrings> string_pool;
  HashTableInit(&string_pool, heap);

  ScanCacheWriter writer;
  ScanCacheWriterInit(&writer, heap);

  // Save new view of the scan cache
  //
  // Algorithm:
  // 
  // - Get all records from the dynamic table (stuff we put in this session)
  const uint32_t      record_count = self->m_RecordCount;
  ScanCache::Record **dyn_records  = LinearAllocateArray<ScanCache::Record*>(scratch, record_count);

  {
    uint32_t records_out = 0;
    for (uint32_t ti = 0, tsize = self->m_TableSize; ti < tsize; ++ti)
    {
      ScanCache::Record* chain = self->m_Table[ti];
      while (chain)
      {
        dyn_records[records_out++] = chain;
        chain                      = chain->m_Next;
      }
    }

    CHECK(records_out == record_count);
  }

  // - Sort these records in key order (by SHA-1 hash)
  std::sort(dyn_records, dyn_records + record_count, SortRecordsByHash);

  const ScanData       *scan_data      = self->m_FrozenData;
  uint32_t              frozen_count   = scan_data ? scan_data->m_EntryCount : 0;
  const HashDigest     *frozen_digests = scan_data ? scan_data->m_Keys.Get() : nullptr;
  const ScanCacheEntry *frozen_entries = scan_data ? scan_data->m_Data.Get() : nullptr;
  const uint64_t       *frozen_times   = scan_data ? scan_data->m_AccessTimes.Get() : nullptr;
  const uint8_t        *frozen_access  = self->m_FrozenAccess;

  const uint64_t now = time(nullptr);

  // Keep old entries for a week.
  const uint64_t timestamp_cutoff = now - 60 * 60 * 24 * 7;

  auto key_dynamic = [=](size_t index) -> const HashDigest* { return &dyn_records[index]->m_Key; };
  auto key_frozen = [=](size_t index) { return frozen_digests + index; };

  auto save_dynamic = [&writer, dyn_records, now, &string_pool](size_t index)
  {
    SaveRecord(
        &writer,
        &string_pool,
        &dyn_records[index]->m_Key,
        dyn_records[index]->m_Includes,
        dyn_records[index]->m_IncludeCount,
        dyn_records[index]->m_FileTimestamp,
        now);
  };

  auto save_frozen = [&](size_t index)
  {
    uint64_t timestamp = frozen_times[index];
    if (frozen_access[index])
      timestamp = now;

    if (timestamp > timestamp_cutoff)
    {
      SaveRecord(
          &writer,
          &string_pool,
          frozen_digests + index, 
          frozen_entries[index].m_IncludedFiles.GetArray(),
          frozen_entries[index].m_IncludedFiles.GetCount(),
          frozen_entries[index].m_FileTimestamp,
          timestamp);
    }
  };

  TraverseSortedArrays(record_count, save_dynamic, key_dynamic, frozen_count, save_frozen, key_frozen);

  self->m_FrozenData = nullptr;

  bool result = ScanCacheWriterFlush(&writer, fn);

  ScanCacheWriterDestroy(&writer);

  HashTableDestroy(&string_pool);

  return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x320, %rsp            # imm = 0x320
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
leaq 0x14e12(%rip), %rdx     # 0x2f590
addq $0x10, %rdx
xorl %eax, %eax
movl %eax, -0x270(%rbp)
movl %eax, %esi
leaq -0x30(%rbp), %rdi
callq 0x7220
movl -0x270(%rbp), %edx
leaq 0xacb1(%rip), %rsi      # 0x25453
leaq -0x34(%rbp), %rdi
callq 0x67e0
jmp 0x1a7ad
movq -0x8(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rsi
leaq -0x60(%rbp), %rdi
callq 0x6e40
jmp 0x1a7c8
movq -0x18(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x1b920
jmp 0x1a7da
movq -0x18(%rbp), %rsi
leaq -0x118(%rbp), %rdi
callq 0x1acb0
jmp 0x1a7ec
movq -0x8(%rbp), %rax
movl 0x50(%rax), %eax
movl %eax, -0x11c(%rbp)
movq -0x50(%rbp), %rdi
movl -0x11c(%rbp), %eax
movl %eax, %esi
callq 0x1b950
movq %rax, -0x278(%rbp)
jmp 0x1a813
movq -0x278(%rbp), %rax
movq %rax, -0x128(%rbp)
movl $0x0, -0x12c(%rbp)
movl $0x0, -0x130(%rbp)
movq -0x8(%rbp), %rax
movl 0x54(%rax), %eax
movl %eax, -0x134(%rbp)
movl -0x130(%rbp), %eax
cmpl -0x134(%rbp), %eax
jae 0x1a902
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movl -0x130(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, -0x140(%rbp)
cmpq $0x0, -0x140(%rbp)
je 0x1a8ec
movq -0x140(%rbp), %rdx
movq -0x128(%rbp), %rax
movl -0x12c(%rbp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, -0x12c(%rbp)
movl %ecx, %ecx
movq %rdx, (%rax,%rcx,8)
movq -0x140(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x140(%rbp)
jmp 0x1a86d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1ac9b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1ac92
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x6f50
jmp 0x1ac92
jmp 0x1a8ee
movl -0x130(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x130(%rbp)
jmp 0x1a842
jmp 0x1a904
jmp 0x1a906
jmp 0x1a908
movq -0x128(%rbp), %rdi
movl -0x11c(%rbp), %eax
leaq (%rdi,%rax,8), %rsi
leaq 0x4c0(%rip), %rdx       # 0x1ade0
callq 0x1b980
jmp 0x1a927
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x148(%rbp)
cmpq $0x0, -0x148(%rbp)
je 0x1a951
movq -0x148(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x27c(%rbp)
jmp 0x1a95b
xorl %eax, %eax
movl %eax, -0x27c(%rbp)
jmp 0x1a95b
movl -0x27c(%rbp), %eax
movl %eax, -0x14c(%rbp)
cmpq $0x0, -0x148(%rbp)
je 0x1a99a
movq -0x148(%rbp), %rdi
addq $0x8, %rdi
callq 0x162e0
movq %rax, -0x288(%rbp)
jmp 0x1a98a
movq -0x288(%rbp), %rax
movq %rax, -0x290(%rbp)
jmp 0x1a9a5
xorl %eax, %eax
movq %rax, -0x290(%rbp)
jmp 0x1a9a5
movq -0x290(%rbp), %rax
movq %rax, -0x158(%rbp)
cmpq $0x0, -0x148(%rbp)
je 0x1a9e6
movq -0x148(%rbp), %rdi
addq $0xc, %rdi
callq 0x1b780
movq %rax, -0x298(%rbp)
jmp 0x1a9d6
movq -0x298(%rbp), %rax
movq %rax, -0x2a0(%rbp)
jmp 0x1a9f1
xorl %eax, %eax
movq %rax, -0x2a0(%rbp)
jmp 0x1a9f1
movq -0x2a0(%rbp), %rax
movq %rax, -0x160(%rbp)
cmpq $0x0, -0x148(%rbp)
je 0x1aa32
movq -0x148(%rbp), %rdi
addq $0x10, %rdi
callq 0x1b9d0
movq %rax, -0x2a8(%rbp)
jmp 0x1aa22
movq -0x2a8(%rbp), %rax
movq %rax, -0x2b0(%rbp)
jmp 0x1aa3d
xorl %eax, %eax
movq %rax, -0x2b0(%rbp)
jmp 0x1aa3d
movq -0x2b0(%rbp), %rax
movq %rax, -0x168(%rbp)
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rax
movq %rax, -0x170(%rbp)
xorl %eax, %eax
movl %eax, %edi
callq 0x3310
movq %rax, -0x178(%rbp)
movq -0x178(%rbp), %rax
addq $-0x93a80, %rax         # imm = 0xFFF6C580
movq %rax, -0x180(%rbp)
movq -0x128(%rbp), %rax
movq %rax, -0x188(%rbp)
movq -0x158(%rbp), %rax
movq %rax, -0x190(%rbp)
leaq -0x118(%rbp), %rcx
movq %rcx, -0x1b0(%rbp)
movq -0x128(%rbp), %rax
movq %rax, -0x1a8(%rbp)
movq -0x178(%rbp), %rax
movq %rax, -0x1a0(%rbp)
leaq -0x90(%rbp), %rax
movq %rax, -0x198(%rbp)
leaq -0x168(%rbp), %rdx
movq %rdx, -0x1f0(%rbp)
leaq -0x170(%rbp), %rdx
movq %rdx, -0x1e8(%rbp)
leaq -0x178(%rbp), %rdx
movq %rdx, -0x1e0(%rbp)
leaq -0x180(%rbp), %rdx
movq %rdx, -0x1d8(%rbp)
movq %rcx, -0x1d0(%rbp)
movq %rax, -0x1c8(%rbp)
leaq -0x158(%rbp), %rax
movq %rax, -0x1c0(%rbp)
leaq -0x160(%rbp), %rax
movq %rax, -0x1b8(%rbp)
movl -0x11c(%rbp), %eax
movl %eax, %edi
movups -0x1b0(%rbp), %xmm0
movups -0x1a0(%rbp), %xmm1
movaps %xmm1, -0x200(%rbp)
movaps %xmm0, -0x210(%rbp)
movq -0x188(%rbp), %rax
movq %rax, -0x218(%rbp)
movl -0x14c(%rbp), %eax
movl %eax, %edx
movups -0x1f0(%rbp), %xmm0
movups -0x1e0(%rbp), %xmm1
movups -0x1d0(%rbp), %xmm2
movups -0x1c0(%rbp), %xmm3
movaps %xmm3, -0x230(%rbp)
movaps %xmm2, -0x240(%rbp)
movaps %xmm1, -0x250(%rbp)
movaps %xmm0, -0x260(%rbp)
movq -0x190(%rbp), %rax
movq %rax, -0x268(%rbp)
movq -0x218(%rbp), %rsi
movq -0x268(%rbp), %rcx
movaps -0x260(%rbp), %xmm0
movaps -0x250(%rbp), %xmm1
movaps -0x240(%rbp), %xmm2
movaps -0x230(%rbp), %xmm3
movq %rsp, %rax
movups %xmm3, 0x50(%rax)
movups %xmm2, 0x40(%rax)
movups %xmm1, 0x30(%rax)
movups %xmm0, 0x20(%rax)
movaps -0x210(%rbp), %xmm0
movaps -0x200(%rbp), %xmm1
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0x1ae10
jmp 0x1ac0d
movq -0x8(%rbp), %rax
movq $0x0, (%rax)
movq -0x10(%rbp), %rsi
leaq -0x118(%rbp), %rdi
callq 0x1aef0
movb %al, -0x2b1(%rbp)
jmp 0x1ac30
movb -0x2b1(%rbp), %al
andb $0x1, %al
movb %al, -0x269(%rbp)
leaq -0x118(%rbp), %rdi
callq 0x1afc0
jmp 0x1ac4c
leaq -0x90(%rbp), %rdi
callq 0x1ba10
jmp 0x1ac5a
movb -0x269(%rbp), %al
movb %al, -0x2b2(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x6f50
leaq -0x34(%rbp), %rdi
callq 0x6980
leaq -0x30(%rbp), %rdi
callq 0x7270
movb -0x2b2(%rbp), %al
andb $0x1, %al
addq $0x320, %rsp            # imm = 0x320
popq %rbp
retq
leaq -0x34(%rbp), %rdi
callq 0x6980
leaq -0x30(%rbp), %rdi
callq 0x7270
movq -0x40(%rbp), %rdi
callq 0x35c0
nopl (%rax)