// File: /workspace/github_cpp_makefile_star2_O2/SeanChao[P]KV-Store/kvstore.cc
// Function: KVStore::compaction(int)
void KVStore::compaction(int level) {
    std::clog << "run compaction on level " << level << std::endl;
    // range statistics
    int nextLv = level + 1;
    int nextLvPos = -1;        // index of insertion point of indexTable in next
                               // level, -1 indicates no assignment yet
    std::vector<Location> id;  // location of tables to be merged
    uint64_t min = UINT64_MAX;
    uint64_t max = 0;
    if (level == 0) {
        uint64_t t0Min = indexTableList[0].front().key;
        uint64_t t1Min = indexTableList[1].front().key;
        uint64_t t0Max = indexTableList[0].back().key;
        uint64_t t1Max = indexTableList[1].back().key;
        uint64_t t2Min = indexTableList[2].front().key;
        uint64_t t2Max = indexTableList[2].back().key;
        min = std::min({t0Min, t1Min, t2Min});
        max = std::max({t0Max, t1Max, t2Max});
        // std::clog << "[lv0]compaction range " << min << " " << max <<
        // std::endl;
        id.push_back(Location(0, 2));
        id.push_back(Location(0, 1));
        id.push_back(Location(0, 0));
    } else {
        // selects exceeding files and merges them into next level
        int more = fileNum[level] - levelSizeLim(level);
        // counts the range of keys in the last file of current level
        for (int i = 0; i < more; i++) {
            int tabId = getIndex(level, levelSizeLim(level) + i);
            uint64_t tMin = indexTableList[tabId].front().key;
            uint64_t tMax = indexTableList[tabId].back().key;
            if (tMin < min) min = tMin;
            max = tMax > max ? tMax : max;
            id.push_back(Location(level, levelSizeLim(level) + i));
        }
    }
    // looks for key range overlapped files
    int delFiles = 0;
    for (int i = 0; fileNum.size() > (size_t)nextLv && i < fileNum[nextLv];
         i++) {
        int tabId = getIndex(nextLv, i);
        uint64_t tMin = indexTableList[tabId].front().key;
        uint64_t tMax = indexTableList[tabId].back().key;
        if (!(tMax < min || max < tMin)) {
            id.push_back(Location(nextLv, i));
            delFiles++;
            // if (nextLvPos == -1) nextLvPos = i;
        }
        if (tMax < min) nextLvPos = i + 1;
    }
    // merge
    std::vector<Pair> all;
    for (size_t i = 0; i < id.size(); i++) {
        // reads ssTable and build pair vector
        std::vector<Pair> t = readSsTable(id[i].level, id[i].id);
        all = merge(all, t);
    }
    // std::clog << "Merged all data: " << std::endl;
    // for (auto &i : all)
    // std::clog << "\t" << i.key << ":\t" << std::string(i.val, 0, 50)
    // << std::endl;
    // update state: removes indexTable from memory, updates fileNum
    for (int i = (int)id.size() - 1; i >= 0; i--) {
        indexTableList.erase(indexTableList.begin() + getIndex(id[i]));
        fileNum[id[i].level]--;
        if (!std::filesystem::remove(resolvePath(id[i])))
            std::clog << "error deleting " << resolvePath(id[i]) << std::endl;
    }
    // slice merged data and write to disk
    // program state is updated in call to writeSsTable
    uint64_t size = 0;
    std::vector<Pair> tmp;
    if (nextLvPos == -1) nextLvPos = 0;
    // renames all file in nextLv to avoid rename hazard
    renameLevel(nextLv, 0);
    for (auto &i : all) {
        size += i.val.length() + DATA_CONST_SIZE;
        tmp.push_back(i);
        if (size >= MEM_TABLE_SIZE_MAX || i.key == all.back().key) {
            writeSsTable(tmp, Location(nextLv, nextLvPos++), true);
            size = 0;
            tmp.clear();
        }
    }
    renameLevel(nextLv, 1);
    // call compaction on next level if necessary
    if (fileNum[nextLv] > levelSizeLim(nextLv)) compaction(nextLv);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x118, %rsp            # imm = 0x118
movl %esi, %r14d
movq %rdi, %rbx
movq 0x9326(%rip), %rdi      # 0xefa8
leaq 0x46db(%rip), %rsi      # 0xa364
callq 0x3270
movq %rax, %rdi
movl %r14d, %esi
callq 0x33c0
movq %rax, %rdi
callq 0x3160
leal 0x1(%r14), %r12d
xorps %xmm0, %xmm0
movaps %xmm0, 0x20(%rsp)
andq $0x0, 0x30(%rsp)
testl %r14d, %r14d
movq %r14, 0x70(%rsp)
movl %r12d, 0x14(%rsp)
je 0x5d70
pushq $0x1
popq %rbp
movslq %r14d, %rax
movq 0x60(%rbx), %rcx
movl (%rcx,%rax,4), %r14d
movl %r12d, %ecx
shll %cl, %ebp
subl %ebp, %r14d
xorl %ecx, %ecx
testl %r14d, %r14d
movl $0x0, %eax
movq %rax, 0x18(%rsp)
cmovlel %ecx, %r14d
pushq $-0x1
popq %rax
movq %rax, 0x8(%rsp)
subl $0x1, %r14d
jb 0x5e25
movq %rbx, %rdi
movq 0x70(%rsp), %r12
movl %r12d, %esi
movl %ebp, %edx
callq 0x69ae
cltq
movq 0x40(%rbx), %rcx
imulq $0x18, %rax, %rax
movq (%rcx,%rax), %rdx
movq 0x8(%rcx,%rax), %rax
movq (%rdx), %r13
movq -0x10(%rax), %r15
movl %r12d, 0x40(%rsp)
movl %ebp, 0x44(%rsp)
leaq 0x20(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x8bc2
movq 0x8(%rsp), %rax
cmpq %rax, %r13
cmovbq %r13, %rax
movq %rax, 0x8(%rsp)
movq 0x18(%rsp), %rax
cmpq %rax, %r15
cmovaq %r15, %rax
movq %rax, 0x18(%rsp)
incl %ebp
movl 0x14(%rsp), %r12d
jmp 0x5cf7
movq 0x40(%rbx), %rax
movq (%rax), %rcx
movq 0x8(%rax), %rdx
movq (%rcx), %rcx
movq 0x18(%rax), %rsi
movq (%rsi), %rsi
movq -0x10(%rdx), %r14
movq 0x20(%rax), %rdx
movq -0x10(%rdx), %r15
movq 0x30(%rax), %rdx
movq (%rdx), %rdx
movq 0x38(%rax), %rax
movq -0x10(%rax), %r13
leaq 0x40(%rsp), %rdi
movq %rcx, (%rdi)
movq %rsi, 0x8(%rdi)
movq %rdx, 0x10(%rdi)
pushq $0x3
popq %rsi
callq 0x769f
movq %rax, 0x8(%rsp)
leaq 0x40(%rsp), %rdi
movq %r14, (%rdi)
movq %r15, 0x8(%rdi)
movq %r13, 0x10(%rdi)
pushq $0x3
popq %rsi
callq 0x76ae
movq %rax, 0x18(%rsp)
movabsq $0x200000000, %rax      # imm = 0x200000000
leaq 0x40(%rsp), %rsi
movq %rax, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x8bc2
movabsq $0x100000000, %rax      # imm = 0x100000000
leaq 0x40(%rsp), %rsi
movq %rax, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x8bc2
leaq 0x40(%rsp), %rsi
andq $0x0, (%rsi)
leaq 0x20(%rsp), %rdi
callq 0x8bc2
movslq %r12d, %r13
leaq 0x40(%rbx), %rax
movq %rax, 0xa8(%rsp)
pushq $-0x1
popq %rax
xorl %ebp, %ebp
leaq 0x40(%rsp), %r15
movq %rax, 0x78(%rsp)
movq 0x60(%rbx), %rax
movq 0x68(%rbx), %rcx
subq %rax, %rcx
sarq $0x2, %rcx
cmpq %r13, %rcx
jbe 0x5eba
cmpl (%rax,%r13,4), %ebp
jge 0x5eba
movq %rbx, %rdi
movl %r12d, %esi
movl %ebp, %edx
callq 0x69ae
movslq %eax, %rcx
movq 0x40(%rbx), %rax
imulq $0x18, %rcx, %rcx
movq 0x8(%rax,%rcx), %rdx
movq -0x10(%rdx), %r14
cmpq 0x8(%rsp), %r14
jb 0x5ea9
movq (%rax,%rcx), %rax
movq 0x18(%rsp), %rcx
cmpq (%rax), %rcx
jb 0x5ea9
movl %r12d, 0x40(%rsp)
movl %ebp, 0x44(%rsp)
leaq 0x20(%rsp), %rdi
movq %r15, %rsi
callq 0x8bc2
incl %ebp
cmpq 0x8(%rsp), %r14
movq 0x78(%rsp), %rax
cmovbl %ebp, %eax
jmp 0x5e3e
movq %r13, 0xa0(%rsp)
xorps %xmm0, %xmm0
leaq 0x80(%rsp), %rax
movaps %xmm0, (%rax)
andq $0x0, 0x10(%rax)
xorl %r13d, %r13d
leaq 0x100(%rsp), %rbp
leaq 0xe8(%rsp), %r14
leaq 0xc8(%rsp), %r15
movq 0x20(%rsp), %rax
movq 0x28(%rsp), %r12
subq %rax, %r12
sarq $0x3, %r12
cmpq %r12, %r13
jae 0x5f80
movl (%rax,%r13,8), %edx
movl 0x4(%rax,%r13,8), %ecx
leaq 0x40(%rsp), %r12
movq %r12, %rdi
movq %rbx, %rsi
callq 0x63ac
movq %rbp, %rdi
leaq 0x80(%rsp), %rsi
callq 0x76be
movq %r14, %rdi
movq %r12, %rsi
callq 0x76be
movq %r15, %rdi
movq %rbp, %rdx
movq %r14, %rcx
callq 0x69dc
leaq 0x80(%rsp), %rdi
movq %r15, %rsi
callq 0x8dd8
movq %r15, %rdi
callq 0x7516
movq %r14, %rdi
callq 0x7516
movq %rbp, %rdi
callq 0x7516
movq %r12, %rdi
callq 0x7516
incq %r13
jmp 0x5ef0
movl %r12d, %eax
leaq -0x8(,%rax,8), %rbp
leaq 0xc8(%rsp), %r15
leaq 0x40(%rsp), %r13
testl %r12d, %r12d
jle 0x6067
movq 0x40(%rbx), %r14
movq 0x20(%rsp), %rsi
addq %rbp, %rsi
movq %rbx, %rdi
callq 0x69a2
cltq
imulq $0x18, %rax, %rsi
addq %r14, %rsi
movq 0xa8(%rsp), %rdi
callq 0x7718
movq 0x20(%rsp), %rdx
movslq (%rdx,%rbp), %rax
addq %rbp, %rdx
movq 0x60(%rbx), %rcx
decl (%rcx,%rax,4)
movq %r15, %rdi
movq %rbx, %rsi
callq 0x660e
movq %r13, %rdi
movq %r15, %rsi
pushq $0x2
popq %rdx
callq 0x7588
movq %r13, %rdi
callq 0x3210
movl %eax, %r14d
movq %r13, %rdi
callq 0x740e
movq %r15, %rdi
callq 0x3438
testb %r14b, %r14b
jne 0x605b
movq 0x8f8a(%rip), %rdi      # 0xefa8
leaq 0x4358(%rip), %rsi      # 0xa37d
callq 0x3270
movq %rax, %r14
movq 0x20(%rsp), %rdx
addq %rbp, %rdx
movq %r13, %rdi
movq %rbx, %rsi
callq 0x660e
movq %r14, %rdi
movq %r13, %rsi
callq 0x3240
movq %rax, %rdi
callq 0x3160
movq %r13, %rdi
callq 0x3438
decl %r12d
addq $-0x8, %rbp
jmp 0x5f98
xorps %xmm0, %xmm0
movaps %xmm0, 0x40(%rsp)
andq $0x0, 0x50(%rsp)
xorl %ebp, %ebp
movq %rbx, %rdi
movl 0x14(%rsp), %r14d
movl %r14d, %esi
xorl %edx, %edx
callq 0x579c
movq 0x78(%rsp), %r13
cmpl $-0x1, %r13d
cmovel %ebp, %r13d
movq 0x80(%rsp), %r15
movq 0x88(%rsp), %rax
movq %rax, 0x8(%rsp)
movl %r14d, %eax
movq %rax, 0x18(%rsp)
leaq 0x40(%rsp), %r12
cmpq 0x8(%rsp), %r15
je 0x613e
movq 0x18(%r15), %r14
movq %r12, %rdi
movq %r15, %rsi
callq 0x771e
addq %r14, %rbp
addq $0x28, %rbp
cmpq $0x1fffff, %rbp         # imm = 0x1FFFFF
ja 0x60ef
movq (%r15), %rax
movq 0x88(%rsp), %rcx
cmpq -0x30(%rcx), %rax
jne 0x6135
leaq 0xb0(%rsp), %rdi
movq %r12, %rsi
callq 0x76be
movq %r13, %rdx
shlq $0x20, %rdx
addq 0x18(%rsp), %rdx
movq %rbx, %rdi
leaq 0xb0(%rsp), %r14
movq %r14, %rsi
xorl %ecx, %ecx
callq 0x6624
incl %r13d
movq %r14, %rdi
callq 0x7516
movq %r12, %rdi
callq 0x774a
xorl %ebp, %ebp
addq $0x30, %r15
jmp 0x60b8
pushq $0x1
popq %rbp
movq %rbx, %rdi
movl 0x14(%rsp), %r14d
movl %r14d, %esi
movl %ebp, %edx
callq 0x579c
movq 0x70(%rsp), %rcx
addb $0x2, %cl
shll %cl, %ebp
movq 0x60(%rbx), %rax
movq 0xa0(%rsp), %rcx
cmpl %ebp, (%rax,%rcx,4)
jle 0x6179
movq %rbx, %rdi
movl %r14d, %esi
callq 0x5c64
leaq 0x40(%rsp), %rdi
callq 0x7516
leaq 0x80(%rsp), %rdi
callq 0x7516
leaq 0x20(%rsp), %rdi
callq 0x8b8e
addq $0x118, %rsp            # imm = 0x118
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x61be
jmp 0x61be
jmp 0x61be
jmp 0x61be
jmp 0x61be
jmp 0x622d
jmp 0x61be
jmp 0x6226
jmp 0x6226
movq %rax, %rbx
jmp 0x6247
movq %rax, %rbx
leaq 0xb0(%rsp), %rdi
jmp 0x621f
jmp 0x6226
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
jmp 0x61f9
movq %rax, %rbx
jmp 0x61f1
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x740e
leaq 0xc8(%rsp), %rdi
callq 0x3438
jmp 0x623a
jmp 0x6226
movq %rax, %rbx
leaq 0xe8(%rsp), %rdi
callq 0x7516
jmp 0x6217
movq %rax, %rbx
leaq 0x100(%rsp), %rdi
callq 0x7516
jmp 0x6230
movq %rax, %rbx
jmp 0x623a
jmp 0x622d
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x7516
leaq 0x80(%rsp), %rdi
callq 0x7516
leaq 0x20(%rsp), %rdi
callq 0x8b8e
movq %rbx, %rdi
callq 0x33e0
nop