// File: yangwanyuan[P]HLKVDS/src/GcManager.cc
// Function: hlkvds::GcManager::BackGC()
void GcManager::BackGC() {
    std::unique_lock < std::mutex > lck_gc(gcMtx_, std::defer_lock);

    uint32_t seg_size = vol_->GetSegmentSize();
    uint64_t data_theory_size = idxMgr_->GetDataTheorySize();
    uint32_t theory_seg_num = data_theory_size / seg_size + 1;

    uint32_t free_seg_num = vol_->GetTotalFreeSegs();
    uint32_t total_seg_num = vol_->GetNumberOfSeg();
    uint32_t used_seg_num = total_seg_num - free_seg_num;
    if (used_seg_num == 0 || theory_seg_num > used_seg_num) {
        return;
    }

    //upper water threshold
    if ( (double)free_seg_num / (double)total_seg_num > CAPACITY_THRESHOLD_TODO_GC) {
        return;
    }

    double waste_rate = 1 - ((double) theory_seg_num / (double) used_seg_num);

    __DEBUG("Begin do Background GC! waste_rate is %f, data_theory_size = %lu", waste_rate, data_theory_size);
    if (waste_rate > options_.gc_upper_level) {
        while (waste_rate > options_.gc_lower_level && used_seg_num > 1) {
            lck_gc.lock();
            std::multimap < uint32_t, uint32_t > cands_map;
            vol_->SortSegsByUtils(cands_map, options_.seg_full_rate);

            //TODO: Maybe some bug here!!!!!
            if (cands_map.empty() || theory_seg_num > used_seg_num) {
                lck_gc.unlock();
                break;
            }
            uint32_t total_free = doMerge(cands_map);
            cands_map.clear();

            data_theory_size = idxMgr_->GetDataTheorySize();
            theory_seg_num = data_theory_size / seg_size + 1;

            used_seg_num = vol_->GetTotalUsedSegs();

            waste_rate = 1 - ((double) theory_seg_num / (double) used_seg_num);
            __DEBUG("done once backgroud GC, total free %u segments, data_theory_size = %lu, theory_seg_num = %u, used_seg_num = %u, seg_size = %u, waste_rate is %f",total_free, data_theory_size, theory_seg_num, used_seg_num, seg_size, waste_rate);
            lck_gc.unlock();
        } __DEBUG("waste_rate lower than the GC_LOWER_LEVEL, end Background GC! waste_rate = %f", waste_rate);
    } __DEBUG("Finsh do Background GC! waste_rate is %f", waste_rate);
}

// Assembly:
subq $0xd8, %rsp
movq %rdi, 0xd0(%rsp)
movq 0xd0(%rsp), %rsi
movq %rsi, 0x40(%rsp)
addq $0x18, %rsi
leaq 0xc0(%rsp), %rdi
callq 0x16db0
movq 0x40(%rsp), %rax
movq (%rax), %rdi
callq 0x234a0
movl %eax, 0x48(%rsp)
jmp 0x227f0
movq 0x40(%rsp), %rax
movl 0x48(%rsp), %ecx
movl %ecx, 0xb8(%rsp)
movq 0x8(%rax), %rdi
callq 0x26fe0
movq %rax, 0x38(%rsp)
jmp 0x22810
movq 0x38(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0xa0(%rsp), %rax
movl 0xb8(%rsp), %ecx
xorl %edx, %edx
divq %rcx
movq %rax, %rcx
movq 0x40(%rsp), %rax
incl %ecx
movl %ecx, 0x9c(%rsp)
movq (%rax), %rdi
callq 0x510f0
movl %eax, 0x34(%rsp)
jmp 0x22850
movq 0x40(%rsp), %rax
movl 0x34(%rsp), %ecx
movl %ecx, 0x98(%rsp)
movq (%rax), %rdi
callq 0x16d50
movl %eax, 0x30(%rsp)
jmp 0x2286e
movl 0x30(%rsp), %eax
movl %eax, 0x94(%rsp)
movl 0x94(%rsp), %eax
subl 0x98(%rsp), %eax
movl %eax, 0x90(%rsp)
cmpl $0x0, 0x90(%rsp)
je 0x228a8
movl 0x9c(%rsp), %eax
cmpl 0x90(%rsp), %eax
jbe 0x228d1
movl $0x1, 0x8c(%rsp)
jmp 0x22b2e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb0(%rsp)
movl %eax, 0xac(%rsp)
jmp 0x22b43
movl 0x98(%rsp), %eax
cvtsi2sd %rax, %xmm0
movl 0x94(%rsp), %eax
cvtsi2sd %rax, %xmm1
divsd %xmm1, %xmm0
movsd 0x3026b(%rip), %xmm1    # 0x52b60
ucomisd %xmm1, %xmm0
jbe 0x2290b
movl $0x1, 0x8c(%rsp)
jmp 0x22b2e
movq 0x40(%rsp), %rax
movl 0x9c(%rsp), %ecx
cvtsi2sd %rcx, %xmm1
movl 0x90(%rsp), %ecx
cvtsi2sd %rcx, %xmm0
divsd %xmm0, %xmm1
movsd 0x30234(%rip), %xmm0    # 0x52b68
subsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x80(%rsp), %xmm0
movq 0x10(%rax), %rax
ucomisd 0x28(%rax), %xmm0
jbe 0x22b23
jmp 0x2295b
movq 0x40(%rsp), %rax
movsd 0x80(%rsp), %xmm0
movq 0x10(%rax), %rcx
xorl %eax, %eax
ucomisd 0x30(%rcx), %xmm0
movb %al, 0x2f(%rsp)
jbe 0x22989
cmpl $0x1, 0x90(%rsp)
seta %al
movb %al, 0x2f(%rsp)
movb 0x2f(%rsp), %al
testb $0x1, %al
jne 0x22996
jmp 0x22b21
leaq 0xc0(%rsp), %rdi
callq 0x16dd0
jmp 0x229a5
leaq 0x50(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x234b0
movq 0x40(%rsp), %rax
movq 0x20(%rsp), %rsi
movq (%rax), %rdi
movq 0x10(%rax), %rax
movsd 0x20(%rax), %xmm0
callq 0x51130
jmp 0x229d1
leaq 0x50(%rsp), %rdi
callq 0x234c0
testb $0x1, %al
jne 0x229ef
movl 0x9c(%rsp), %eax
cmpl 0x90(%rsp), %eax
jbe 0x22a31
leaq 0xc0(%rsp), %rdi
callq 0x16e30
jmp 0x229fe
movl $0x3, 0x8c(%rsp)
jmp 0x22b03
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb0(%rsp)
movl %eax, 0xac(%rsp)
leaq 0x50(%rsp), %rdi
callq 0x234f0
jmp 0x22b43
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x21ee0
movl %eax, 0x1c(%rsp)
jmp 0x22a46
movl 0x1c(%rsp), %eax
movl %eax, 0x4c(%rsp)
leaq 0x50(%rsp), %rdi
callq 0x234e0
movq 0x40(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0x26fe0
movq %rax, 0x10(%rsp)
jmp 0x22a6d
movq 0x10(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0xa0(%rsp), %rax
movl 0xb8(%rsp), %ecx
xorl %edx, %edx
divq %rcx
movq %rax, %rcx
movq 0x40(%rsp), %rax
incl %ecx
movl %ecx, 0x9c(%rsp)
movq (%rax), %rdi
callq 0x51110
movl %eax, 0xc(%rsp)
jmp 0x22aad
movl 0xc(%rsp), %eax
movl %eax, 0x90(%rsp)
movl 0x9c(%rsp), %eax
cvtsi2sd %rax, %xmm1
movl 0x90(%rsp), %eax
cvtsi2sd %rax, %xmm0
divsd %xmm0, %xmm1
movsd 0x3008c(%rip), %xmm0    # 0x52b68
subsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0x16e30
jmp 0x22af8
movl $0x0, 0x8c(%rsp)
leaq 0x50(%rsp), %rdi
callq 0x234f0
movl 0x8c(%rsp), %eax
testl %eax, %eax
je 0x22b1c
jmp 0x22b1a
jmp 0x22b21
jmp 0x2295b
jmp 0x22b23
movl $0x0, 0x8c(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0x15c30
addq $0xd8, %rsp
retq
leaq 0xc0(%rsp), %rdi
callq 0x15c30
movq 0xb0(%rsp), %rdi
callq 0x8820
nopl (%rax)