// File: yangwanyuan[P]HLKVDS/src/GcManager.cc
// Function: hlkvds::GcManager::doMerge(std::multimap<unsigned int, unsigned int, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, unsigned int>>>&)
uint32_t GcManager::doMerge(std::multimap<uint32_t, uint32_t> &cands_map) {

    bool ret;
    std::vector < uint32_t > free_seg_vec;
    uint32_t last_seg_id = 0;
    bool need_flag = false;
    uint32_t total_free = 0;

    std::list<KVSlice*> slice_list;
    std::list<KVSlice*> recycle_list;

    std::list<KVSlice*>::iterator slice_iter;

    //handle first segment
    SegForSlice *seg_first = new SegForSlice(vol_, idxMgr_);
    for (std::multimap<uint32_t, uint32_t>::iterator iter = cands_map.begin(); iter
            != cands_map.end(); ++iter) {
        uint32_t seg_id = iter->second;
        ret = loadKvList(seg_id, slice_list);
        if (!ret) {
            continue;
        }

        for (slice_iter = slice_list.begin(); slice_iter != slice_list.end();) {
            KVSlice* slice = *slice_iter;
            if (seg_first->TryPut(slice)) {
                seg_first->Put(slice);
                recycle_list.push_back(*slice_iter);
                slice_list.erase(slice_iter++);
            } else {
                need_flag = true;
                break;
            }
        }

        if (need_flag) {
            last_seg_id = seg_id;
            break;
        } else {
            free_seg_vec.push_back(seg_id);
        }
    }

    uint32_t seg_first_id;
    vol_->AllocForGC(seg_first_id);
    seg_first->SetSegId(seg_first_id);
    ret = seg_first->WriteSegToDevice();
    if (!ret) {
        __ERROR("Write First GC segment to device failed, free 0 segments");
        delete seg_first;
        vol_->FreeForFailed(seg_first_id);
        cleanKvList(recycle_list);
        cleanKvList(slice_list);
        return total_free;
    }

    uint32_t free_size = seg_first->GetFreeSize();
    vol_->Use(seg_first_id, free_size);

    seg_first->UpdateToIndex();

    //clean work for first segment
    for (std::vector<uint32_t>::iterator iter = free_seg_vec.begin(); iter
            != free_seg_vec.end(); ++iter) {
        vol_->FreeForGC(*iter);
    }
    delete seg_first;
    cleanKvList(recycle_list);

    total_free = free_seg_vec.size() - 1;

    if (!need_flag) {
        __DEBUG("All fragment segment merge to 1 segment, and free %d segments", total_free);
        return total_free;
    }

    //handle second segment
    SegForSlice *seg_second = new SegForSlice(vol_, idxMgr_);
    uint32_t seg_second_id;
    vol_->AllocForGC(seg_second_id);

    for (slice_iter = slice_list.begin(); slice_iter != slice_list.end(); ++slice_iter) {
        KVSlice* slice = *slice_iter;
        seg_second->Put(slice);
    }

    seg_second->SetSegId(seg_second_id);
    ret = seg_second->WriteSegToDevice();
    if (!ret) {
        __ERROR("Write Second GC segment to device failed, but First Segment is completed, free %d segments", total_free);
        delete seg_second;
        vol_->FreeForFailed(seg_second_id);
        cleanKvList(slice_list);
        return total_free;
    }

    free_size = seg_second->GetFreeSize();
    vol_->Use(seg_second_id, free_size);

    seg_second->UpdateToIndex();
    vol_->FreeForGC(last_seg_id);

    //clean work for second segment
    delete seg_second;
    cleanKvList(slice_list);

    __DEBUG("Multiple fragment segments merge to 2 segment, and free %d segments", total_free);

    return total_free;
}

// Assembly:
subq $0x198, %rsp            # imm = 0x198
movq %rdi, 0x188(%rsp)
movq %rsi, 0x180(%rsp)
movq 0x188(%rsp), %rax
movq %rax, 0x60(%rsp)
leaq 0x160(%rsp), %rdi
callq 0x23510
movl $0x0, 0x15c(%rsp)
movb $0x0, 0x15b(%rsp)
movl $0x0, 0x154(%rsp)
leaq 0x138(%rsp), %rdi
callq 0x23520
leaq 0x120(%rsp), %rdi
callq 0x23520
leaq 0x118(%rsp), %rdi
callq 0x23530
movl $0x50, %edi
callq 0x84f0
movq %rax, 0x68(%rsp)
jmp 0x21f67
movq 0x68(%rsp), %rdi
movq 0x60(%rsp), %rax
movq (%rax), %rsi
movq 0x8(%rax), %rdx
callq 0x432f0
jmp 0x21f7f
movq 0x68(%rsp), %rax
movq %rax, 0x110(%rsp)
movq 0x180(%rsp), %rdi
callq 0x23550
movq %rax, 0xf8(%rsp)
movq 0x180(%rsp), %rdi
callq 0x235a0
movq %rax, 0xf0(%rsp)
leaq 0xf8(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
callq 0x23580
testb $0x1, %al
jne 0x21fd4
jmp 0x221d1
leaq 0xf8(%rsp), %rdi
callq 0x235d0
movq 0x60(%rsp), %rdi
movl 0x4(%rax), %eax
movl %eax, 0xec(%rsp)
movl 0xec(%rsp), %esi
leaq 0x138(%rsp), %rdx
callq 0x22df0
movb %al, 0x5f(%rsp)
jmp 0x2200a
movb 0x5f(%rsp), %al
andb $0x1, %al
movb %al, 0x17f(%rsp)
testb $0x1, 0x17f(%rsp)
jne 0x22062
jmp 0x221bf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
jmp 0x22770
movq 0x68(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
callq 0x84b0
jmp 0x22770
leaq 0x138(%rsp), %rdi
callq 0x16410
movq %rax, 0xe0(%rsp)
movq 0xe0(%rsp), %rax
movq %rax, 0x118(%rsp)
leaq 0x138(%rsp), %rdi
callq 0x16460
movq %rax, 0xd8(%rsp)
leaq 0x118(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x16440
testb $0x1, %al
jne 0x220ba
jmp 0x2218a
leaq 0x118(%rsp), %rdi
callq 0x16490
movq (%rax), %rax
movq %rax, 0xd0(%rsp)
movq 0x110(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x418e0
movb %al, 0x5e(%rsp)
jmp 0x220ed
movb 0x5e(%rsp), %al
testb $0x1, %al
jne 0x220fa
jmp 0x2217b
movq 0x110(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x41960
jmp 0x22111
leaq 0x118(%rsp), %rdi
callq 0x16490
movq %rax, %rsi
leaq 0x120(%rsp), %rdi
callq 0x235f0
jmp 0x22130
leaq 0x118(%rsp), %rdi
xorl %esi, %esi
callq 0x164c0
movq %rax, 0xc0(%rsp)
leaq 0xc8(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x23680
movq 0xc8(%rsp), %rsi
leaq 0x138(%rsp), %rdi
callq 0x23630
movq %rax, 0xb8(%rsp)
jmp 0x22185
movb $0x1, 0x15b(%rsp)
jmp 0x2218a
jmp 0x22087
testb $0x1, 0x15b(%rsp)
je 0x221a4
movl 0xec(%rsp), %eax
movl %eax, 0x15c(%rsp)
jmp 0x221d1
leaq 0x160(%rsp), %rdi
leaq 0xec(%rsp), %rsi
callq 0x236a0
jmp 0x221bb
jmp 0x221bd
jmp 0x221bf
leaq 0xf8(%rsp), %rdi
callq 0x23710
jmp 0x21fa1
movq 0x60(%rsp), %rax
movq (%rax), %rdi
leaq 0xb4(%rsp), %rsi
callq 0x51190
jmp 0x221e8
movq 0x110(%rsp), %rdi
movl 0xb4(%rsp), %esi
callq 0x164f0
jmp 0x221fe
movq 0x110(%rsp), %rdi
callq 0x41bb0
movb %al, 0x5d(%rsp)
jmp 0x22211
movb 0x5d(%rsp), %al
andb $0x1, %al
movb %al, 0x17f(%rsp)
testb $0x1, 0x17f(%rsp)
jne 0x22321
jmp 0x2222e
movq 0x4eda3(%rip), %rax     # 0x70fd8
movq (%rax), %rax
movq %rax, 0x50(%rsp)
callq 0x8480
movq 0x50(%rsp), %rdi
movq %rax, %rdx
leaq 0x30260(%rip), %rsi     # 0x524b1
leaq 0x30919(%rip), %rcx     # 0x52b71
leaq 0x3091a(%rip), %r8      # 0x52b79
movl $0xb7, %r9d
movb $0x0, %al
callq 0x86f0
movq 0x4ed65(%rip), %rax     # 0x70fd8
movq (%rax), %rdi
leaq 0x3090d(%rip), %rsi     # 0x52b8a
movb $0x0, %al
callq 0x86f0
movq 0x4ed4d(%rip), %rax     # 0x70fd8
movq (%rax), %rdi
leaq 0x30b30(%rip), %rsi     # 0x52dc5
movb $0x0, %al
callq 0x86f0
jmp 0x2229e
movq 0x110(%rsp), %rax
movq %rax, 0x48(%rsp)
cmpq $0x0, %rax
je 0x222c5
movq 0x48(%rsp), %rdi
callq 0x43240
movq 0x48(%rsp), %rdi
callq 0x84b0
movq 0x60(%rsp), %rax
movq (%rax), %rdi
movl 0xb4(%rsp), %esi
callq 0x511c0
jmp 0x222db
movq 0x60(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0x22f00
jmp 0x222ef
movq 0x60(%rsp), %rdi
leaq 0x138(%rsp), %rsi
callq 0x22f00
jmp 0x22303
movl 0x154(%rsp), %eax
movl %eax, 0x194(%rsp)
movl $0x1, 0xb0(%rsp)
jmp 0x2273a
movq 0x110(%rsp), %rdi
callq 0x16540
movl %eax, 0x44(%rsp)
jmp 0x22334
movq 0x60(%rsp), %rax
movl 0x44(%rsp), %ecx
movl %ecx, 0xac(%rsp)
movq (%rax), %rdi
movl 0xb4(%rsp), %esi
movl 0xac(%rsp), %edx
callq 0x51220
jmp 0x2235c
movq 0x110(%rsp), %rdi
callq 0x43330
jmp 0x2236b
leaq 0x160(%rsp), %rdi
callq 0x23740
movq %rax, 0xa0(%rsp)
leaq 0x160(%rsp), %rdi
callq 0x237b0
movq %rax, 0x98(%rsp)
leaq 0xa0(%rsp), %rdi
leaq 0x98(%rsp), %rsi
callq 0x23770
testb $0x1, %al
jne 0x223b0
jmp 0x223e9
movq 0x60(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x38(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0x237e0
movq 0x38(%rsp), %rdi
movl (%rax), %esi
callq 0x511f0
jmp 0x223d8
jmp 0x223da
leaq 0xa0(%rsp), %rdi
callq 0x237f0
jmp 0x22380
movq 0x110(%rsp), %rax
movq %rax, 0x30(%rsp)
cmpq $0x0, %rax
je 0x22410
movq 0x30(%rsp), %rdi
callq 0x43240
movq 0x30(%rsp), %rdi
callq 0x84b0
movq 0x60(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0x22f00
jmp 0x22424
leaq 0x160(%rsp), %rdi
callq 0x23810
subq $0x1, %rax
movl %eax, 0x154(%rsp)
testb $0x1, 0x15b(%rsp)
jne 0x22464
movl 0x154(%rsp), %eax
movl %eax, 0x194(%rsp)
movl $0x1, 0xb0(%rsp)
jmp 0x2273a
movl $0x50, %edi
callq 0x84f0
movq %rax, 0x28(%rsp)
jmp 0x22475
movq 0x28(%rsp), %rdi
movq 0x60(%rsp), %rax
movq (%rax), %rsi
movq 0x8(%rax), %rdx
callq 0x432f0
jmp 0x2248d
movq 0x60(%rsp), %rax
movq 0x28(%rsp), %rcx
movq %rcx, 0x90(%rsp)
movq (%rax), %rdi
leaq 0x8c(%rsp), %rsi
callq 0x51190
jmp 0x224b1
leaq 0x138(%rsp), %rdi
callq 0x16410
movq %rax, 0x80(%rsp)
movq 0x80(%rsp), %rax
movq %rax, 0x118(%rsp)
leaq 0x138(%rsp), %rdi
callq 0x16460
movq %rax, 0x78(%rsp)
leaq 0x118(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x16440
testb $0x1, %al
jne 0x22500
jmp 0x2255d
leaq 0x118(%rsp), %rdi
callq 0x16490
movq (%rax), %rax
movq %rax, 0x70(%rsp)
movq 0x90(%rsp), %rdi
movq 0x70(%rsp), %rsi
callq 0x41960
jmp 0x22529
jmp 0x2252b
leaq 0x118(%rsp), %rdi
callq 0x23830
jmp 0x224d6
movq 0x28(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x108(%rsp)
movl %eax, 0x104(%rsp)
callq 0x84b0
jmp 0x22770
movq 0x90(%rsp), %rdi
movl 0x8c(%rsp), %esi
callq 0x164f0
jmp 0x22573
movq 0x90(%rsp), %rdi
callq 0x41bb0
movb %al, 0x27(%rsp)
jmp 0x22586
movb 0x27(%rsp), %al
andb $0x1, %al
movb %al, 0x17f(%rsp)
testb $0x1, 0x17f(%rsp)
jne 0x22689
jmp 0x225a3
movq 0x4ea2e(%rip), %rax     # 0x70fd8
movq (%rax), %rax
movq %rax, 0x18(%rsp)
callq 0x8480
movq 0x18(%rsp), %rdi
movq %rax, %rdx
leaq 0x2feeb(%rip), %rsi     # 0x524b1
leaq 0x305a4(%rip), %rcx     # 0x52b71
leaq 0x305a5(%rip), %r8      # 0x52b79
movl $0xe0, %r9d
movb $0x0, %al
callq 0x86f0
movq 0x4e9f0(%rip), %rax     # 0x70fd8
movq (%rax), %rdi
movl 0x154(%rsp), %edx
leaq 0x305ca(%rip), %rsi     # 0x52bc3
movb $0x0, %al
callq 0x86f0
movq 0x4e9d1(%rip), %rax     # 0x70fd8
movq (%rax), %rdi
leaq 0x307b4(%rip), %rsi     # 0x52dc5
movb $0x0, %al
callq 0x86f0
jmp 0x2261a
movq 0x90(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x22641
movq 0x10(%rsp), %rdi
callq 0x43240
movq 0x10(%rsp), %rdi
callq 0x84b0
movq 0x60(%rsp), %rax
movq (%rax), %rdi
movl 0x8c(%rsp), %esi
callq 0x511c0
jmp 0x22657
movq 0x60(%rsp), %rdi
leaq 0x138(%rsp), %rsi
callq 0x22f00
jmp 0x2266b
movl 0x154(%rsp), %eax
movl %eax, 0x194(%rsp)
movl $0x1, 0xb0(%rsp)
jmp 0x2273a
movq 0x90(%rsp), %rdi
callq 0x16540
movl %eax, 0xc(%rsp)
jmp 0x2269c
movq 0x60(%rsp), %rax
movl 0xc(%rsp), %ecx
movl %ecx, 0xac(%rsp)
movq (%rax), %rdi
movl 0x8c(%rsp), %esi
movl 0xac(%rsp), %edx
callq 0x51220
jmp 0x226c4
movq 0x90(%rsp), %rdi
callq 0x43330
jmp 0x226d3
movq 0x60(%rsp), %rax
movq (%rax), %rdi
movl 0x15c(%rsp), %esi
callq 0x511f0
jmp 0x226e9
movq 0x90(%rsp), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x2270d
movq (%rsp), %rdi
callq 0x43240
movq (%rsp), %rdi
callq 0x84b0
movq 0x60(%rsp), %rdi
leaq 0x138(%rsp), %rsi
callq 0x22f00
jmp 0x22721
movl 0x154(%rsp), %eax
movl %eax, 0x194(%rsp)
movl $0x1, 0xb0(%rsp)
leaq 0x120(%rsp), %rdi
callq 0x23850
leaq 0x138(%rsp), %rdi
callq 0x23850
leaq 0x160(%rsp), %rdi
callq 0x23860
movl 0x194(%rsp), %eax
addq $0x198, %rsp            # imm = 0x198
retq
leaq 0x120(%rsp), %rdi
callq 0x23850
leaq 0x138(%rsp), %rdi
callq 0x23850
leaq 0x160(%rsp), %rdi
callq 0x23860
movq 0x108(%rsp), %rdi
callq 0x8820
nopw %cs:(%rax,%rax)