--合服逻辑

--[=[
    0.一般在跨服上进行合服, 所以需要把merge目录下所有文件更新到跨服上

    1.更新MergeServerDefine.MERGE_DB_TB中要合并的数据库, 并备份数据库, 方法见 MergeServerDefine

    2.[可选] 先执行一次start.sh, 再杀掉所有游戏服的进程。因为重启游戏服时会根据条件删除一些数据, 这样合服时要处理的数据就少了一些。
        比较前面的游戏服的邮件数据可能有异常, 可先执行/server/cleanExpireMail.sh清理下异常的邮件(需要修改脚本中数据库范围)

    3.将跨服的bin*文件 的/script 目录下的启动文件Main.lua暂时改为其他名字, MainMerger改为Main.lua，合服完毕后再改回来。

    4.检查MergeServerDefine中的MERGE_DB_TB数据库名是否正确, 如果正确则和正常启动游戏一样启动游戏服, 开始进行合服

    5.查看日志oss_merge, 是否有报错, 如果有报错则还原数据, 恢复见方法见 MergeServerDefine

    6.修改mysql区服列表的 port, dbName, megre_server字段, 被合服的 port 和 dbname 要改为目标服一样, 被合服的 megre_server字段更新为1。
        sql见sdk数据库下查询中的updateMergeServerData(需要修改数据库范围)

    7.修改linux上被合服的bin*文件名, 防止 start.sh 启动时会把被合服也启动起来。脚本见/server/changebinName.sh  (需要修改脚本中范围)

    8.合服完毕, 将步骤3修过的文件名改回原来的名字, 执行start.sh 启动游戏服。

]=]



local LuaMongo = _G.lua_mongo
local Config = require("Config")
local Log = require("common.Log")
local MergeServerDefine = require("merge.MergeServerDefine")
local MoZhuExcel = require("excel.mozhu")
local MailExcel = require("excel.mail")
local TowerConfig = require("excel.huanjingTower").huanjingTower
local Util = require("common.Util")
local ItemDefine = require("bag.ItemDefine")
local HuanJingTowerLogic = require("huanjingTower.HuanjingTowerLogic")
local GodsAreaConfig = require("excel.godsArea")


local primaryKeyTable = {}

--重复_id缓存表
local repeatIdTb = {}

--目标服和被合服所有玩家的名字缓存表
local allNameTb = {}

--同名数据
local repeatName2Data = {}

local num = 0


--次元魔珠数据缓存表
local mozhuDbCache = { roleList = {}, unionList = {}}

--烟花加成时间
local firesTimeCache = 0


--恶魔之塔最高层数
local towerMaxLevel = 0
local towerHeadCache = {}
local TOWER_LV_HEAD_MAX =  HuanJingTowerLogic.TOWER_LV_HEAD_MAX


--创建一个mongo连接实例
local function clientMongoDb(addr)
    addr = addr or Config.DB_IP
    LuaMongo.client(addr)
end

--切换数据库
local function chooseMongoDb(dbName)
    if not dbName or dbName == "" then
        print(string.format("数据库名错误, dbName = %s\n", dbName))
        return
    end
	LuaMongo.auth(dbName, Config.DB_USER, Config.DB_PASS)
end

--生成新的 _id
local function generateNewId()
    local newId = LuaMongo.id()
    return newId
end

--清理部分缓存数据
local function cleanCache()
    primaryKeyTable = {}
    repeatIdTb = {}
    allNameTb = {}
    repeatName2Data = {}
    mozhuDbCache = { roleList = {}, unionList = {}}
    firesTimeCache = 0
    towerHeadCache = {}
end

--写日志
local function writeLog(tag, targetDb, sourceDb, sourceColl, info1, info2, docId, errInfo)
    local logInfo = string.format("tag: %s, targetDb: %s, sourceDb: %s, sourceColl: %s, info1: %s, info2: %s, docId: %s, errInfo: %s",
    tag, targetDb, sourceDb, sourceColl, info1, info2, docId, errInfo)

    Log.write(Log.LOGID_OSS_MERGE, logInfo)
end


local function writeLog2(logStr)
    Log.write(Log.LOGID_OSS_MERGE, logStr)
end

-------------------------------------------------------------需要单独处理的部分数据---------------------------------------------------------------------

---------------------------------次元魔蛛/梼杌------------------------------------
local MozhuQueryFiles = { [MergeServerDefine.KEY_CIYUAN_MOZHU] = 1}
--读取
local function loadMoZhuDB(sourceDb, collectionName)
    local targetCollection = sourceDb .. collectionName
    LuaMongo.find(targetCollection, nil, MozhuQueryFiles)

    local data = {}
    if not LuaMongo.next(data) then
		return nil
	end

    local targetMoZhuData = data.ciyuanMoZhu
    for uuid, roleData in pairs(targetMoZhuData.role or {}) do
        mozhuDbCache.roleList[uuid] = roleData
    end

    for uuid, unionData in pairs(targetMoZhuData.union or {}) do
        mozhuDbCache.unionList[uuid] = unionData
        num = num + 1
    end
end

--随机词条
local function randomCiTiao(data)
    local weekTime = Util.getWeekStartTime(os.time())
    -- if data.citiaoTime and data.citiaoTime == weekTime then
    --     return
    -- end

    data.citiao = {}
    local citiao_rare_max

    if not citiao_rare_max then
        -- 防止策划删减 词条
        citiao_rare_max = 0
        for k, v in pairs(MoZhuExcel.citiao) do
            if v then
                citiao_rare_max = citiao_rare_max + v.quanzhong
            end
        end
    end

    local getRare = 0
    for i=1, 1 do
        local random = math.random(1, citiao_rare_max - getRare)
        for k, v in pairs(MoZhuExcel.citiao) do
            if not data.citiao[k] and random <= v.quanzhong then
                data.citiao[k] = i
                getRare = getRare + v.quanzhong
                break
            elseif not data.citiao[k] then
                -- 防止循环最后一个是 已经随机过的  导致 随机不出来
                random = random - v.quanzhong
            end
        end
    end
    data.citiaoTime = weekTime
end

--初始化魔珠db
local function initMoZhuDB(data)
    data.time = os.time()
    data.unionRank = {}
    data.roleRank = {}
    data.role = {}
    data.union= {}

    --词条
    randomCiTiao(data)
end

--插入
local function updateTargetMoZhuDB(targetDb)
    local collectionName = MergeServerDefine.COLLECTIONS[3]
    local targetCollection = targetDb .. collectionName

    LuaMongo.find(targetCollection, nil, MozhuQueryFiles)
    local data = {}
    if not LuaMongo.next(data) then
        return
	end
    

    if not data.ciyuanMoZhu then
        data.ciyuanMoZhu = {}
        initMoZhuDB(data.ciyuanMoZhu)
    end

    local targetMoZhuData = data.ciyuanMoZhu
    local roleRankLen = #targetMoZhuData.roleRank
    local unionRankLen = #targetMoZhuData.unionRank

    --玩家
    for uuid, roleData in pairs(mozhuDbCache.roleList) do
        targetMoZhuData.role[uuid] = roleData

        roleRankLen = roleRankLen + 1
        targetMoZhuData.roleRank[roleRankLen] = uuid
    end

    --公会
    for uuid, unionData in pairs(mozhuDbCache.unionList) do
        targetMoZhuData.union[uuid] = unionData

        unionRankLen = unionRankLen + 1
        targetMoZhuData.unionRank[unionRankLen] = uuid
    end

    --排序
    table.sort(targetMoZhuData.roleRank, function(a, b)
        local roleA = targetMoZhuData.role[a]
        local roleB = targetMoZhuData.role[b]
        return roleA.hurt > roleB.hurt
    end)

    table.sort(targetMoZhuData.unionRank, function(a, b)
        local unionA = targetMoZhuData.union[a]
        local unionB = targetMoZhuData.union[b]
        if unionA.hurt > unionB.hurt then
            return true
        elseif unionA.hurt == unionB.hurt then
            return unionA.time < unionB.time
        end
        return false
    end)

    --更新
	LuaMongo.update(targetCollection, {}, {
        ["$set"] = {
            [MergeServerDefine.KEY_CIYUAN_MOZHU] = targetMoZhuData
        },
    })

    mozhuDbCache = nil
end


----------------------------------烟花加成时间------------------------------------
local FireQueryFiles = { [MergeServerDefine.KEY_FIREWORKBONUS_TIME] = 1}

--读取
local function loadFireTimeData(sourceDb, collectionName)
    local targetCollection = sourceDb .. collectionName
    LuaMongo.find(targetCollection, nil, FireQueryFiles)

    local data = {}
    if not LuaMongo.next(data) then
		return nil
	end

    local now = os.time()
    local ti = data.fireWorksBonusTime
    if ti and ti > now then
        firesTimeCache = firesTimeCache + (ti - now)
    end
end

--更新目标库
local function updateTargetFireTimeDB(targetDb)
    if firesTimeCache > 0 then
        local collectionName = MergeServerDefine.COLLECTIONS[3]
        local targetCollection = targetDb .. collectionName

        LuaMongo.find(targetCollection, nil, FireQueryFiles)
        local data = {}
        if not LuaMongo.next(data) then
            return
        end

        local now = os.time()
        local ti = data.fireWorksBonusTime
        if not ti or ti < now then
            ti = now + firesTimeCache
        else
            ti = ti + firesTimeCache
        end

        local maxTime = now + MergeServerDefine.FIRE_MAX_TIME
        ti = math.min(ti, maxTime)

        --更新
	    LuaMongo.update(targetCollection, {}, {
            ["$set"] = {
                [MergeServerDefine.KEY_FIREWORKBONUS_TIME] = ti
            },
        })
    end

end




----------------------------------恶魔之塔------------------------------------
local queryTowerByLv = { lv = nil }
local queryTowerFiles = { headList = 1 }

local function calcTblLen(tb)
    local len = 0
    for _,_ in pairs(tb) do
        len = len + 1
    end
    return len
end

--加载目标库中tower集合中所有文档的headList
local function loadTowerHeadData(targetDb)
    local collectionName = MergeServerDefine.COLLECTIONS[16]
    local targetCollection = targetDb .. collectionName

    towerMaxLevel = #TowerConfig
    for i=1,towerMaxLevel do
        queryTowerByLv.lv = i
        LuaMongo.find(targetCollection, queryTowerByLv, queryTowerFiles) -- 后续优化: 一次全部读取或者批量读取

        local data = {}
        if LuaMongo.next(data) then
            towerHeadCache[i] = {
                subNum = TOWER_LV_HEAD_MAX,
                headList = data.headList
            }

            if data.headList and next(data.headList) then
                local len = calcTblLen(data.headList)

                if len < TOWER_LV_HEAD_MAX then
                    towerHeadCache[i].subNum = TOWER_LV_HEAD_MAX - len
                end
            end
        end
    end
end

-- 把源库tower集合中的headList插入到目标库的headList中
local function insertTargetTowerHeadCache(sourceDb, coll)
    local targetCollection = sourceDb .. coll

    for i=1,towerMaxLevel do
        towerHeadCache[i] = towerHeadCache[i] or {subNum = TOWER_LV_HEAD_MAX, headList = {}}
        local subNum = towerHeadCache[i] and towerHeadCache[i].subNum or 0
        if subNum > 0 then
            queryTowerByLv.lv = i
            LuaMongo.find(targetCollection, queryTowerByLv, queryTowerFiles)

            local data = {}
            if LuaMongo.next(data) then
                local headData = data.headList
                if headData and next(headData) then

                    towerHeadCache[i].headList = towerHeadCache[i].headList or {}
                    local targetHeadList = towerHeadCache[i].headList

                    for k,v in pairs(headData) do
                        targetHeadList[k] = v

                        subNum = subNum - 1
                        if subNum <= 0 then
                            break
                        end
                    end

                    towerHeadCache[i].subNum = subNum
                    towerHeadCache[i].isChange = true
                end
            end
        end
    end
end

--更新目标库的headList
local function updateTargetTowerHeadDB(targetDb)
    local collectionName = MergeServerDefine.COLLECTIONS[16]
    local targetCollection = targetDb .. collectionName

    for i=1,#towerHeadCache do
        local data = towerHeadCache[i]
        if data.isChange then
            --更新
            queryTowerByLv.lv = i
            LuaMongo.update(targetCollection, queryTowerByLv, { ["$set"] = { headList = data.headList }})
        end
    end
end





---------------------------------------玩家同名------------------------------
local NameQueryFiles = { ["name"] = 1 }

--加载目标库所有玩家的名字
local function loadTargetCharName(targetDb)
    local collectionName = MergeServerDefine.COLLECTIONS[1]
    local targetCollection = targetDb .. collectionName

    LuaMongo.find(targetCollection, nil, NameQueryFiles)

    while true do
        local data = {}
        if not LuaMongo.next(data) then
            break
        end
        allNameTb[data.name] = '1'
    end
end

--得到一个邮件数据
local mailConfig = MailExcel.mail[MergeServerDefine.MAIL_ID]
local function frontMail(receiverUuid)
    local mail = {}
	mail.type = 1
	mail.receiverUuid = receiverUuid
	mail.title = mailConfig.title
	mail.content =  mailConfig.content
	mail.read = nil
	mail.senderName = mailConfig.title
    mail.head = 0
    mail.fbTime = nil
    mail.fbContent = nil
    mail.time = os.time()
    mail.get = nil
    mail.flag = 1
    mail.items = { { ItemDefine.ITEM_ZUANSHI_ID, MergeServerDefine.MAIL_NUM } }
    return mail
end


--给因同名而修改名字的玩家发送补偿邮件
local function sendRepeatNameMail(targetDb)
    local coll = MergeServerDefine.COLLECTIONS[2]
    local targetCollection = targetDb .. coll

    for oldName, v in pairs(repeatName2Data) do
        local mail = frontMail(v.uuid)
        local _, err = pcall(LuaMongo.insert, targetCollection, mail)

        writeLog(MergeServerDefine.CHANGENAME_TAG, targetDb, v.sourceDb, coll, oldName, v.newName, v.uuid, err or "")
    end
end


--------------------------------更新合服时间------------------------------------
local function updateMergeTime(targetDb)
    local targetCollection = targetDb .. MergeServerDefine.COLLECTIONS[3]
    local now = os.time()
    LuaMongo.update(targetCollection, {}, {
        ["$set"] = {
            [MergeServerDefine.KEY_MERGE_TIME] = now
        },
    })
end


--------------------------------诸神圣域-----------------------------------------

-- 删掉诸神圣域称号
local function deleteGodsAreaChenghao(db)
    local chenghaoId = 0
    for _, rankCfg in ipairs(GodsAreaConfig.rankList) do
        if db.chenghaoList and db.chenghaoList[rankCfg.chenghaoID] then
            chenghaoId = rankCfg.chenghaoID
            break
        end
    end

    if chenghaoId ~= 0 then
        db.chenghaoList[chenghaoId] = nil

        if db.chenghao and db.chenghao == chenghaoId then
            db.chenghao = nil
        end

        local logStr = string.format("删除诸神圣域称号, 玩家newUniqueTag: %s, chenghaoId: %d", db.newUniqueTag, chenghaoId)
        writeLog2(logStr)
    end
end

-------------------------------------------------------------------------------------





-----------------------------------------------------char集合中_id的重复检测和处理-------------------------------------------------

--用于检测不同数据库的char集合中的_id是否有重复, 一般来说通过mongo生成的_id基本不会重复(暂时不用)
local function primaryKeyRepeatCheck()
    print("================================检查char集合_id的重复性开始=======================================\n")

    local collectionName = MergeServerDefine.COLLECTIONS[1]
    for k, dbName in ipairs(MergeServerDefine.MERGE_DB_TB) do
        local targetCollection = dbName .. collectionName
        LuaMongo.find(targetCollection, nil, nil, {_id = 1})
        while true do
            local data = {}
            if not LuaMongo.next(data) then
                break
            end
            if k ~= 1 then
                if primaryKeyTable[data._id] then
                    repeatIdTb[data._id] = generateNewId()

                    Log.write(Log.LOGID_OSS_MERGE, string.format("result: %s, targetColl: %s, repeatId: %s, newId: %s",
                    "Repeat", targetCollection, data._id, repeatIdTb[data._id]))
                else
                    primaryKeyTable[data._id] = '1'
                end
            else
                primaryKeyTable[data._id] = '1'
            end
        end
    end
    print("================================检查char集合_id的重复性结束=======================================\n")
end

--好友集合
local function handleFriend(data)
    if repeatIdTb[data.uuid1] then
        data.uuid1 = repeatIdTb[data.uuid1]
    end

    if repeatIdTb[data.uuid2] then
        data.uuid2 = repeatIdTb[data.uuid2]
    end
end

--邮件集合
local function handleMail(data)
    if repeatIdTb[data.receiverUuid] then
        data.receiverUuid = repeatIdTb[data.receiverUuid]
    end
end

--公会集合
local function handleUnion(data)
    local tb = {}
    for id, v in pairs(data.member) do
        if repeatIdTb[id] then
            tb[id] = v
        end
    end

    for id, v in pairs(tb) do
        data.member[id] = nil
        data.member[repeatIdTb[id]] = v
    end


    tb = {}
    for id, v in pairs(data.apply) do
        if repeatIdTb[id] then
            tb[id] = v
        end
    end

    for id, v in pairs(tb) do
        data.apply[id] = nil
        data.apply[repeatIdTb[id]] = v
    end

    if data.presidentUuid and repeatIdTb[data.presidentUuid] then
        data.presidentUuid = repeatIdTb[data.presidentUuid]
    end
end

--星空争霸集合
local function handleStar(data)
    if repeatIdTb[data.uuid] then
        data.uuid = repeatIdTb[data.uuid]
    end
end

--单人竞技场集合
local function handleJJC(data)
    if not data.monsterOutID and repeatIdTb[data._id] then
        data._id = repeatIdTb[data._id]
    end
end

--战斗视频集合
local function handleVideo(data)
    local uuid = data.combatInfo.attacker.uuid
    if repeatIdTb[uuid] then
        data.combatInfo.attacker.uuid = repeatIdTb[uuid]
    end
end

----------------------------------------------------合并数据----------------------------------------------------------

local function dbCheck()
    if #MergeServerDefine.MERGE_DB_TB ~= #MergeServerDefine.MERGE_CHECK_TB then
        print("=================数据异常=============")
        return
    end

    for idx, dbArray in ipairs(MergeServerDefine.MERGE_DB_TB) do
        local checkArray = MergeServerDefine.MERGE_CHECK_TB[idx]
        if not checkArray or #checkArray ~= #dbArray then
            print(string.format("数据库数量与检查数量不相同"))
            return
        end

        for i, dbName in ipairs(dbArray) do
            local chackTb = checkArray[i]
            if not chackTb then
                print(string.format("检查表中缺失数据, idx1: %d, idx2: %d", idx, i))
                return
            end

            local channelId = chackTb[1]
            local serverId = chackTb[2]
            local opType = chackTb[3]

            if i == 1 and opType ~= 0 then
                print(string.format("检查表错误, idx1: %d, idx2: %d", idx, i))
                return
            end

            if i > 1 and opType == 0 then
                print(string.format("检查表错误, idx1: %d, idx2: %d", idx, i))
                return
            end


            local dbNameNum = (MergeServerDefine.CHANNEL_2_DBNUMBER[channelId] or 0) + serverId
            local correctDBName = MergeServerDefine.DB_NAME_STR .. dbNameNum
            if dbName ~= correctDBName then
                print(string.format("数据库名错误, idx1: %d, idx2: %d", idx, i))
                return
            end
        end
    end

    return true
end


local writeQueue = {}
local function flushWriteQueue()
    for _, task in ipairs(writeQueue) do
        local ok, err = pcall(LuaMongo.insert, task.collection, task.data)
        if not ok then
            Log.write(Log.LOGID_OSS_MERGE, task.collection, err)
        end
    end
    writeQueue = {}
end

-- 每积累100条数据批量写入
local function bufferedInsert(collection, data)
    table.insert(writeQueue, {collection=collection, data=data})
    if #writeQueue >= 100 then
        flushWriteQueue()
    end
end


local function processCollection(sourceDb, targetDb, coll)
    local sourceCollection = sourceDb .. coll
    local targetCollection = targetDb .. coll

    local errNum = 0
    local allNum = 0
    LuaMongo.find(sourceCollection, nil, {})
    while true do
        local data = {}
        if not LuaMongo.next(data) then
            break
        end


        --直接插入目标库
        local ok, err = pcall(LuaMongo.insert, targetCollection, data)
        if not ok then
            errNum = errNum + 1
            writeLog(MergeServerDefine.ERR_TAG, targetDb, sourceDb, coll, 1, 1, data._id, err)
        end

        allNum = allNum + 1
    end

    writeLog(MergeServerDefine.SUCC_TAG, targetDb, sourceDb, coll, allNum, errNum, "", "")
end



--合并char集合
local function processCharColl(sourceDb, targetDb, coll, sourceDbTp)
    local sourceCollection = sourceDb .. coll
    local targetCollection = targetDb .. coll

    local errNum = 0
    local allNum = 0
    LuaMongo.find(sourceCollection, nil, {})
    while true do
        local data = {}
        if not LuaMongo.next(data) then
            break
        end

        --同名检测
        if allNameTb[data.name] then
            num = num + 1
            local newName = MergeServerDefine.NEW_NAME .. num

            --统计数据
            repeatName2Data[data.name] = {
                uuid = data._id,
                newName = newName,
                sourceDb = sourceDb,
            }

            --改名
            data.name = newName
        end
        allNameTb[data.name] = '1'

        -- 诸神圣域称号处理
        if sourceDbTp == 2 then
            deleteGodsAreaChenghao(data)
        end


        --插入目标库
        local ok, err = pcall(LuaMongo.insert, targetCollection, data)
        if not ok then
            errNum = errNum + 1
            writeLog(MergeServerDefine.ERR_TAG, targetDb, sourceDb, coll, 1, 1, data._id, err)
        end

        allNum = allNum + 1
    end

    writeLog(MergeServerDefine.SUCC_TAG, targetDb, sourceDb, coll, allNum, errNum, "", "")
end


local function startMergeServer(dbArray)
    assert(dbArray and next(dbArray), "====数据错误====")

    cleanCache()

    --目标集合数据库名
    local targetDb = dbArray[1][1]

    loadTargetCharName(targetDb)

    loadTowerHeadData(targetDb)


    for i = 2, #dbArray do
        -- local moveOhtherCS = false
        -- local checkTb = MergeServerDefine.MERGE_CHECK_TB[idx][i]
        -- if checkTb[3] == 2 then
        --     moveOhtherCS = true
        -- end

        local sourceDb = dbArray[i][1]
        local opType = dbArray[i][2]
        LuaMongo.auth(sourceDb, Config.DB_USER, Config.DB_PASS)

        for _, coll in ipairs(MergeServerDefine.COLLECTIONS) do
            if not MergeServerDefine.NO_INSERT_COLLECTIONS[coll] then

                print(string.format("=============开始合并集合, 目标数据库: %s, 源数据库:%s, 集合:%s\n", targetDb, sourceDb, coll))

                if coll == MergeServerDefine.COLLECTIONS[1] then
                    processCharColl(sourceDb, targetDb, coll, opType)
                elseif coll == MergeServerDefine.COLLECTIONS[3] then
                    loadMoZhuDB(sourceDb, coll)
                    loadFireTimeData(sourceDb, coll)
                elseif coll == MergeServerDefine.COLLECTIONS[16] then
                    insertTargetTowerHeadCache(sourceDb, coll)
                else
                    processCollection(sourceDb, targetDb, coll)
                end

                -- _G.collectgarbage("collect")
            end
        end
    end

    --处理那些需要单独处理的数据
    updateTargetMoZhuDB(targetDb)

    updateTargetFireTimeDB(targetDb)

    sendRepeatNameMail(targetDb)

    updateTargetTowerHeadDB(targetDb)

    updateMergeTime(targetDb)
end


local function getDBInfo()
    for _, chanelId in ipairs(Config.SVR_CHANEL) do
        if MergeServerDefine.MERGE_CHECK_TB[chanelId] then
            return MergeServerDefine.MERGE_CHECK_TB[chanelId]
        end
    end
end

local concatTb = { [1] = MergeServerDefine.DB_NAME_STR }
local function generateDBName(dbInfo)
    local channelId = dbInfo[1]
    local serverId = dbInfo[2]
    local opType = dbInfo[3]
    local dbName_Number = MergeServerDefine.CHANNEL_2_DBNUMBER[channelId] + serverId

    concatTb[2] = dbName_Number
    local finalName = table.concat(concatTb)

    print("======generateDBName:", finalName, opType)

    return finalName, opType
end

local function generateDBArray()
    local dbBaseInfo = getDBInfo()
    if not dbBaseInfo or not next(dbBaseInfo) then
        return
    end

    local dbNameTb = {}

    for k, infoArray in ipairs(dbBaseInfo) do
        dbNameTb[k] = dbNameTb[k] or {}
        local dbTb = dbNameTb[k]

        for _, dbInfo in ipairs(infoArray) do
            local dbName, opType = generateDBName(dbInfo)
            if not dbName or not opType then
                return
            end

            dbTb[#dbTb+1] = {dbName, opType}
        end
    end

    return dbNameTb
end



--合服开始函数
function Start()
    -- if not dbCheck() then
    --     return
    -- end


    local dbArray = generateDBArray()
    if not dbArray or not next(dbArray) then
        print("生成合服数据库列表失败")
        return
    end

    --创建mongo连接实例
    clientMongoDb()

    --检查char集合_id的重复性
    --primaryKeyRepeatCheck()


    print("========================合服开始=====================")


    -- for i, dbList in ipairs(MergeServerDefine.MERGE_DB_TB) do
    --     startMergeServer(dbList, i)
    -- end

    for _, dbList in ipairs(dbArray) do
        startMergeServer(dbList)
    end


    print("========================合服结束=====================")
end















