// File: xx01cyx[P]LSM-Tree/kvstore.cc
// Function: KVStore::mergeAndWriteToDisk(std::shared_ptr<SSTable> const&, std::vector<std::shared_ptr<SSTable>, std::allocator<std::shared_ptr<SSTable>>> const&, unsigned long, std::unordered_map<unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<std::pair<unsigned long const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>> const&)
vector<SSTPtr> KVStore::mergeAndWriteToDisk(const SSTPtr& upperLevelSST, const vector<SSTPtr>& lowerLevelSSTs,
                                            TimeStamp maxTimeStamp, const KVPair& data) {

    // Initialize.

    vector<SSTPtr> newSSTs;
    vector<LsmKey> sortedKeys;
    size_t currentSize = HEADER_SIZE + BLOOM_FILTER_SIZE;
    size_t upperKeyNumber = upperLevelSST->getKeyNumber();
    size_t upperIndex = 0;
    size_t lowerKeyNumber;
    size_t lowerIndex;
    size_t lowerLevel = upperLevelSST->getLevel() + 1;
    KeyRefLessThan keyRefLessThan;

    // Function for merging and writing data to the disk. Used in 2-way merge below.

    auto merge = [&](const SSTPtr& sst, size_t& index) {
        LsmKey key = sst->getDataIndexes()[index].key;
        const LsmValue& value = data.at(key);
        if ((lowerLevel != ssTables.size() || value != DELETE_SIGN)
            && !sortedKeys.empty() && sortedKeys.back() != key) {
            size_t sizeIncrement = DATA_INDEX_SIZE + value.size();
            if (currentSize + sizeIncrement > MAX_SSTABLE_SIZE) {
                newSSTs.push_back(generateNewSST(sortedKeys, data, lowerLevel, maxTimeStamp));
                sortedKeys.clear();
                currentSize = HEADER_SIZE + BLOOM_FILTER_SIZE;
            }
            sortedKeys.push_back(key);
            currentSize += sizeIncrement;
        }
        index++;
    };

    // 2-way merge sort and write data to the disk.

    for (const auto& lowerLevelSST : lowerLevelSSTs) {

        lowerIndex = 0;
        lowerKeyNumber = lowerLevelSST->getKeyNumber();

        if (sortedKeys.empty()) {
            LsmKey upperKey = upperLevelSST->getDataIndexes()[0].key;
            LsmKey lowerKey = lowerLevelSST->getDataIndexes()[0].key;
            if ((upperKey < lowerKey) ||
                (upperKey == lowerKey && upperLevelSST->getTimeStamp() < lowerLevelSST->getTimeStamp()))
                sortedKeys.push_back(upperKey);
            else
                sortedKeys.push_back(lowerKey);
        }

        while (upperIndex != upperKeyNumber && lowerIndex != lowerKeyNumber) {
            KeyRef upperKeyRef = make_pair(upperLevelSST, upperIndex);
            KeyRef lowerKeyRef = make_pair(lowerLevelSST, lowerIndex);

            if (keyRefLessThan(upperKeyRef, lowerKeyRef))
                merge(upperLevelSST, upperIndex);
            else
                merge(lowerLevelSST, lowerIndex);
        }

        while (lowerIndex != lowerKeyNumber)
            merge(lowerLevelSST, lowerIndex);
    }

    while (upperIndex != upperKeyNumber)
        merge(upperLevelSST, upperIndex);

    // Pack the remaining data into an SST.

    if (!sortedKeys.empty())
        newSSTs.push_back(generateNewSST(sortedKeys, data, lowerLevel, maxTimeStamp));

    return newSSTs;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1d0, %rsp            # imm = 0x1D0
movq %rdi, -0x190(%rbp)
movq %rdi, %rax
movq %rax, -0x188(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x180(%rbp)
movb $0x0, -0x31(%rbp)
callq 0x15ef0
leaq -0x50(%rbp), %rdi
callq 0x6410
movq $0x2820, -0x58(%rbp)    # imm = 0x2820
movq -0x18(%rbp), %rdi
callq 0xd330
movq %rax, %rdi
callq 0x9920
movq %rax, -0x178(%rbp)
jmp 0x142a3
movq -0x178(%rbp), %rax
movq %rax, -0x60(%rbp)
movq $0x0, -0x78(%rbp)
movq -0x18(%rbp), %rdi
callq 0xd330
movq %rax, %rdi
callq 0x98a0
movq %rax, -0x198(%rbp)
jmp 0x142d0
movq -0x190(%rbp), %rax
movq -0x180(%rbp), %rcx
movq -0x198(%rbp), %rdx
addq $0x1, %rdx
movq %rdx, -0x90(%rbp)
movq -0x30(%rbp), %rdx
movq %rdx, -0xd0(%rbp)
leaq -0x90(%rbp), %rdx
movq %rdx, -0xc8(%rbp)
movq %rcx, -0xc0(%rbp)
leaq -0x50(%rbp), %rcx
movq %rcx, -0xb8(%rbp)
leaq -0x58(%rbp), %rcx
movq %rcx, -0xb0(%rbp)
movq %rax, -0xa8(%rbp)
leaq -0x28(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0xd8(%rbp)
movq -0xd8(%rbp), %rdi
callq 0x169d0
movq %rax, -0xe0(%rbp)
movq -0xd8(%rbp), %rdi
callq 0x16a00
movq %rax, -0xe8(%rbp)
leaq -0xe0(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
callq 0x16a30
testb $0x1, %al
jne 0x14385
jmp 0x1468b
leaq -0xe0(%rbp), %rdi
callq 0x16a70
movq %rax, -0xf0(%rbp)
movq $0x0, -0x88(%rbp)
movq -0xf0(%rbp), %rdi
callq 0xd330
movq %rax, %rdi
callq 0x9920
movq %rax, -0x1a0(%rbp)
jmp 0x143c0
movq -0x1a0(%rbp), %rax
movq %rax, -0x80(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x16c70
testb $0x1, %al
jne 0x143dd
jmp 0x14528
movq -0x18(%rbp), %rdi
callq 0xd330
movq %rax, %rsi
leaq -0x110(%rbp), %rdi
callq 0x9940
jmp 0x143f7
xorl %eax, %eax
movl %eax, %esi
leaq -0x110(%rbp), %rdi
movq %rdi, -0x1b0(%rbp)
callq 0x9b90
movq -0x1b0(%rbp), %rdi
movq (%rax), %rax
movq %rax, -0x1a8(%rbp)
callq 0x9b30
movq -0x1a8(%rbp), %rax
movq %rax, -0xf8(%rbp)
movq -0xf0(%rbp), %rdi
callq 0xd330
movq %rax, %rsi
leaq -0x130(%rbp), %rdi
callq 0x9940
jmp 0x1444f
leaq -0x130(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x9b90
movq (%rax), %rax
movq %rax, -0x1b8(%rbp)
leaq -0x130(%rbp), %rdi
callq 0x9b30
movq -0x1b8(%rbp), %rax
movq %rax, -0x118(%rbp)
movq -0xf8(%rbp), %rax
cmpq -0x118(%rbp), %rax
jb 0x144ed
movq -0xf8(%rbp), %rax
cmpq -0x118(%rbp), %rax
jne 0x14512
movq -0x18(%rbp), %rdi
callq 0xd330
movq %rax, %rdi
callq 0x98c0
movq %rax, -0x1c0(%rbp)
jmp 0x144bd
movq -0xf0(%rbp), %rdi
callq 0xd330
movq %rax, %rdi
callq 0x98c0
movq %rax, -0x1c8(%rbp)
jmp 0x144da
movq -0x1c0(%rbp), %rax
movq -0x1c8(%rbp), %rcx
cmpq %rcx, %rax
jae 0x14512
leaq -0x50(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x6430
jmp 0x144ff
jmp 0x14526
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
jmp 0x1472f
leaq -0x50(%rbp), %rdi
leaq -0x118(%rbp), %rsi
callq 0x6430
jmp 0x14524
jmp 0x14526
jmp 0x14528
jmp 0x1452a
movq -0x78(%rbp), %rcx
xorl %eax, %eax
cmpq -0x60(%rbp), %rcx
movb %al, -0x1c9(%rbp)
je 0x14550
movq -0x88(%rbp), %rax
cmpq -0x80(%rbp), %rax
setne %al
movb %al, -0x1c9(%rbp)
movb -0x1c9(%rbp), %al
testb $0x1, %al
jne 0x1455f
jmp 0x1464b
movq -0x18(%rbp), %rsi
leaq -0x148(%rbp), %rdi
leaq -0x78(%rbp), %rdx
callq 0x16dc0
jmp 0x14575
movq -0xf0(%rbp), %rsi
leaq -0x160(%rbp), %rdi
leaq -0x88(%rbp), %rdx
callq 0x16dc0
jmp 0x14591
leaq -0x91(%rbp), %rdi
leaq -0x148(%rbp), %rsi
leaq -0x160(%rbp), %rdx
callq 0x16e00
movb %al, -0x1ca(%rbp)
jmp 0x145b3
movb -0x1ca(%rbp), %al
testb $0x1, %al
jne 0x145bf
jmp 0x145ff
movq -0x18(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
leaq -0x78(%rbp), %rdx
callq 0x14770
jmp 0x145d5
jmp 0x1461d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
jmp 0x1463a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x160(%rbp), %rdi
callq 0x16b60
jmp 0x1463a
movq -0xf0(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
leaq -0x88(%rbp), %rdx
callq 0x14770
jmp 0x1461b
jmp 0x1461d
leaq -0x160(%rbp), %rdi
callq 0x16b60
leaq -0x148(%rbp), %rdi
callq 0x16b60
jmp 0x1452a
leaq -0x148(%rbp), %rdi
callq 0x16b60
jmp 0x1472f
jmp 0x1464d
movq -0x88(%rbp), %rax
cmpq -0x80(%rbp), %rax
je 0x14678
movq -0xf0(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
leaq -0x88(%rbp), %rdx
callq 0x14770
jmp 0x14676
jmp 0x1464d
jmp 0x1467a
leaq -0xe0(%rbp), %rdi
callq 0x16ba0
jmp 0x14369
jmp 0x1468d
movq -0x78(%rbp), %rax
cmpq -0x60(%rbp), %rax
je 0x146af
movq -0x18(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
leaq -0x78(%rbp), %rdx
callq 0x14770
jmp 0x146ad
jmp 0x1468d
leaq -0x50(%rbp), %rdi
callq 0x16c70
testb $0x1, %al
jne 0x1471a
movq -0x30(%rbp), %rdx
movq -0x90(%rbp), %rcx
movq -0x28(%rbp), %r8
leaq -0x170(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x13980
jmp 0x146dd
movq -0x190(%rbp), %rdi
leaq -0x170(%rbp), %rsi
callq 0x168d0
jmp 0x146f2
leaq -0x170(%rbp), %rdi
callq 0xd350
jmp 0x1471a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x170(%rbp), %rdi
callq 0xd350
jmp 0x1472f
movb $0x1, -0x31(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x69d0
testb $0x1, -0x31(%rbp)
jne 0x14752
jmp 0x14746
leaq -0x50(%rbp), %rdi
callq 0x69d0
movq -0x190(%rbp), %rdi
callq 0x163c0
jmp 0x14762
movq -0x190(%rbp), %rdi
callq 0x163c0
movq -0x188(%rbp), %rax
addq $0x1d0, %rsp            # imm = 0x1D0
popq %rbp
retq
movq -0x68(%rbp), %rdi
callq 0x4560
nopl (%rax,%rax)