From 6ff08684b0b23e03d1b839d505ca6f19f889cebc Mon Sep 17 00:00:00 2001
From: hch <305670599@qq.com>
Date: 星期五, 28 九月 2018 12:55:48 +0800
Subject: [PATCH] 3647 【后端】思璞游戏SDK接入-动态字段被转化为小写问题

---
 db/PyMongoDataServer/Config/DBConfig.py         |  295 ++
 db/PyMongoDataServer/LogicProcess/UserCtrlDB.py | 5750 +++++++++++++++++++++++++++++++++++++++++++++++++++
 db/PyMongoDataServer/Common/CommFunc.py         |  567 +++++
 3 files changed, 6,612 insertions(+), 0 deletions(-)

diff --git a/db/PyMongoDataServer/Common/CommFunc.py b/db/PyMongoDataServer/Common/CommFunc.py
new file mode 100644
index 0000000..5c55fbc
--- /dev/null
+++ b/db/PyMongoDataServer/Common/CommFunc.py
@@ -0,0 +1,567 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#
+#
+##@package CommFunc.py
+# @todo: 公共调用函数集
+# @author:eggxp
+# @date 2010-01-01 00:00
+# @version 1.8
+#
+# 修改时间 修改人 修改内容
+# @change: "2010-01-19 16:35"  zb  修改公共函数的一个错误,解决小喇叭输入'瞾'字会导致客户端弹框的问题
+# @change: "2010-01-29 11:45"  chenxuewei  修改公共函数ReplaceBig5AppointSign(srcStr,sign,desSign)的一个错误,解决字符串srcStr最后一个字节的字符替换问题
+# @change: "2010-04-02 17:45"  zb  添加公共函数ToDWORD()
+# @change: "2010-04-02 20:30"  zb  将ReadBYTE()/ReadDWORD()/ReadDWORD(),改成无符号数读取
+# @change: "2010-09-27 15:55"  chenxuewei  将WriteBYTE()/WriteDWORD()/WriteDWORD(),改成自动转化有无符号数写入
+#
+# @change: "2011-03-15 17:20"  Alee 与GameWorld中的函数重复
+# @change: "2016-07-18 19:00"  hxp 增加GetPlatformAccID
+# @change: "2017-07-04 15:00"  hxp 增加获取玩家所属平台主服ID
+#
+#---------------------------------------------------------------------
+#导入
+import os
+import struct
+import string
+import math
+import datetime
+import subprocess
+
+DBConfig = __import__('Config.DBConfig')
+#---------------------------------------------------------------------
+#全局变量
+
+MODULE_NAME = "cmd_mail"
+
+VER = "2017-07-04 15:00"
+
+
+## 用于发包,当封包是DWORD的时候
+#  @param num 数字
+#  @return 有符号数字
+#  @remarks 函数详细说明:用于发包,当封包是DWORD的时候,转换为有符号数
+def ToDWORD( num ):
+    if num >= 0:
+        return num
+    return num + 4294967296
+
+## 将hex转化成二进制对应的字符串,用于发包
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:将hex转化成二进制对应的字符串,用于发包
+def HexToBin (hexStr):
+    returnStr = ''
+    hexStrLen = len(hexStr)
+    for i in [j for j in range(hexStrLen) if j%2==0]:
+        returnStr += chr(string.atoi(hexStr[i:i+2],16))
+    return returnStr
+
+#获取异常信息#(try:...except:..GetExceptionInfo())
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def GetExceptionInfo():
+    import traceback
+    return traceback.format_exc()
+
+
+#执行cmd指令
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def RunCmd(curCmd):
+    pipe = subprocess.Popen(['cmd', ""], shell = False,
+                                 stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
+    pipe.stdin.write('%s\n'%curCmd)
+    pipe.stdin.close()
+    retStr = pipe.stdout.read()
+    retStr += pipe.stderr.read()
+    print retStr
+    return retStr
+
+
+#取得代码中真实的字符串(如参数srcStr是'\n',会得到回车符)
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def GetCodeStr(srcStr):
+    desStr = srcStr.replace("'", "\\'")
+    cmd = "desStr='" + desStr + "'"
+    exec(cmd)
+    return desStr 
+
+
+#python写文件:
+#    f = file('c:\\fuck.txt', 'a')
+#    f.write(mapObsData)
+
+#等待输入: raw_input()
+
+#创建Socket
+#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
+#s.bind(('192.168.0.81', 6112))
+#s.listen(1)
+
+#获得子目录:
+#os.path.abspath
+
+#等待输入:
+#raw_input()
+
+#得到本目录:
+#os.getcwd()
+
+#得到参数:
+#os.sys.argv
+
+#得到python路径
+#os.sys.executable
+
+#运行外部文件/结束外部文件
+#processID = os.spawnl(os.P_NOWAIT, pythonPath, '-p', os.path.join(curPath, 'test.py'))
+#win32api.TerminateProcess(processID, 0)
+
+
+#python的读取/写入库
+
+#------------------------读取 
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def ReadBYTE(buf, pos):
+    curValue = struct.unpack_from('B', buf, pos)
+    pos += 1
+    return curValue[0], pos
+
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def ReadWORD(buf, pos):
+    curValue = struct.unpack_from('H', buf, pos)
+    pos += 2  
+    return curValue[0], pos
+
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def ReadDWORD(buf, pos):
+    curValue = struct.unpack_from('I', buf, pos)  
+    pos += 4
+    return curValue[0], pos
+
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def ReadFloat(buf, pos):
+    curValue = struct.unpack_from('f', buf, pos)  
+    pos += 4
+    return curValue[0], pos
+
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def ReadDouble(buf, pos):
+    curValue = struct.unpack_from('d', buf, pos)  
+    pos += 8
+    return curValue[0], pos
+
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def ReadString(buf, pos, _len):
+    curValue = struct.unpack_from('%ds'%_len, buf, pos)
+    pos += _len  
+    return curValue[0], pos
+
+
+#----------------------写入
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def Pack(sign, value):
+    
+    if value < 0:
+        sign = sign.lower()
+    else:
+        sign = sign.upper()
+    
+    return struct.pack(sign, value)
+        
+        
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def WriteBYTE(buf, value):
+    buf += Pack('B', value)
+    return buf
+
+
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def WriteWORD(buf, value):
+    buf += Pack('H', value)
+    return buf
+
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def WriteDWORD(buf, value):
+    buf += Pack('I', value)
+    return buf
+
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def WriteFloat(buf, value):
+    buf += struct.pack('f', value)
+    return buf
+
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def WriteDouble(buf, value):
+    buf += struct.pack('d', value)
+    return buf
+
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def WriteString(buf, len, value):
+    buf += struct.pack('%ds'%len, value)
+    return buf
+
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def GetDistance(srcX, srcY, destX, destY):
+    return math.sqrt(pow(srcX - destX, 2) + pow(srcY - destY, 2))
+    
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def MovePos(srcX, srcY, destX, destY, curMoveDist):
+    if curMoveDist == 0:
+        return  srcX, srcY
+    
+    totalDist = GetDistance(srcX, srcY, destX, destY)
+    if totalDist == 0:
+        return  srcX, srcY
+    
+    resultX = curMoveDist / float(totalDist) * (destX - srcX) + srcX
+    resultY = curMoveDist / float(totalDist) * (destY - srcY) + srcY
+    return resultX, resultY 
+    
+
+##测试代码:
+#strs = '美香是猪'
+#buf = ''
+#buf = WriteString(buf, len(strs), strs)
+#value, pos = ReadString(buf, 0, len(strs))
+#print value
+
+#获得当前系统时间
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def GetCurrentDataTimeStr():
+    curTime = datetime.datetime.today()
+    curTimeStr = str(curTime)
+    curTimeStr = curTimeStr.split(".")[0]
+    return curTimeStr
+
+
+#字符串转换为整型, 如果不能转换, 返回默认值
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def ToIntDef(input, defValue = 0):
+    try:
+        result = int(input)
+        return result
+    except ValueError:
+        return defValue
+    
+#16进制颜色转换
+#"#FFFFFF"--"255,255,255"
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def HcToSc(h):
+    h="0x"+h[1:7]
+    red=string.atoi(h[:2]+h[2:4], base=16)
+    green=string.atoi(h[:2]+h[4:6], base=16)
+    blue=string.atoi(h[:2]+h[6:8], base=16)
+    cStr=str(red)+","+str(green)+","+str(blue)
+    return cStr
+
+#"255,255,255"--"#FFFFFF"
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def ScToHc(s):
+    red=hex(string.atoi(s.split(",")[0]))[2:]
+    green=hex(string.atoi(s.split(",")[1]))[2:]
+    blue=hex(string.atoi(s.split(",")[2]))[2:]
+    hStr="#"+str(red+green+blue)
+    return hStr
+
+#16进制转换
+#"0xFFFFFF"--"255,255,255"
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def HdToSd(h):
+    red=string.atoi(h[0:2]+h[2:4], base=16)
+    green=string.atoi(h[0:2]+h[4:6], base=16)
+    blue=string.atoi(h[0:2]+h[6:8], base=16)
+    cStr=str(red)+","+str(green)+","+str(blue)
+    return cStr
+
+#"255,255,255"--"0xFFFFFF"
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def SdToHd(s):
+    red=hex(string.atoi(s.split(",")[0]))[2:]
+    green=hex(string.atoi(s.split(",")[1]))[2:]
+    blue=hex(string.atoi(s.split(",")[2]))[2:]
+    hStr="0x"+str(red+green+blue)
+    return hStr
+
+#提示除零错误的EVAL
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def SafeEval(value):
+    try:
+        return eval(value)
+    except ZeroDivisionError:
+        return "Division is Zero"
+
+##生成指定文件(如par:r'E:\开发版本\Data\logo\formName1.log')
+#def MakeAppointFile(par):
+#    dir = os.path.dirname(par)  # 获得文件目录
+#    os.makedirs(dir)  # 创建多级目录
+#    file = open(os.path.basename(par),'w')
+#    file.close()
+#
+##在指定目录根据当前时间生成新目录(如par:r'E:\开发版本\Data\logo')
+#def MakeCurTimeDir(par):
+#    if not os.path.exists(par):  # 传进来的目录不存在
+#        return
+#    path=par+'\\'+str(datetime.datetime.today()).split()[0]
+#    if not os.path.exists(path):  # 文件夹是否存在,不存在则创建
+#        os.mkdir(path)  # 创建文件夹
+        
+#生成指定目录(如par:r'E:\开发版本\Data\logo')
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def MakeAppointDir(par):
+    if not isinstance(par,str):
+        return
+    pathList=par.split('\\')
+    path=pathList[0]
+    for i in range(1,len(pathList)):
+        path+='\\'+pathList[i]
+        if not os.path.exists(path):  # 文件夹是否存在,不存在则创建
+            os.mkdir(path)  # 创建文件夹
+                
+#生成指定文件(如par:r'E:\开发版本\Data\logo\formName1.log')
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def MakeAppointFile(par):
+    if not isinstance(par,str):
+        return
+    pathList=par.split('\\')
+    path=pathList[0]
+    for i in range(1,len(pathList)):
+        path+='\\'+pathList[i]
+        if i==len(pathList)-1:
+            file=open(path,'w')
+            file.close()
+        else:
+            if not os.path.exists(path):  # 文件夹是否存在,不存在则创建
+                os.mkdir(path)  # 创建文件夹
+
+#在指定目录根据当前时间生成新目录(如par:r'E:\开发版本\Data\logo')
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def MakeCurTimeDir(par):
+    if not os.path.exists(par):  # 传进来的目录不存在
+        return
+    path=par+'\\'+str(datetime.datetime.today()).split()[0]
+    if not os.path.exists(path):  # 文件夹是否存在,不存在则创建
+        os.mkdir(path)  # 创建文件夹
+
+
+#得到替换后的字符串(参数:string是需要替换的字符串;varlist为不定参,为替换内容)
+#如GetReplaceString('str%s%s','str1','str2','str3','str4'),return结果为'strstr1str2'
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def GetReplaceString(string,*varlist):
+    if '%' not in string:
+        return string
+    repalceCount = len(varlist)  # 替换次数
+    newStr = string
+    if '%%' in string:
+        newStr = string.replace('%%','')  # 去除字符串str内的'%%'
+    needReplaceCount = newStr.count('%')  # 字符串newStr内的'%'个数,即需要替换的次数
+    if repalceCount < needReplaceCount:
+        tempList = list(varlist)
+        for i in range(needReplaceCount-repalceCount):
+            tempList.append(0)
+        replaceTuple= tuple(tempList)
+        #告诉调用者,参数传少了
+        return 'func:GetReplaceString();error:the parameter lack'
+#        return string%replaceTuple
+        
+    replaceTuple = tuple(varlist[:needReplaceCount])
+    return string%replaceTuple
+
+
+#将unicode编码转换成中文字符(参数:"#19968"-"#40869"之间)
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def UnicodeStrToGBKStr(U_STR):#如输入"#23435",获得返回值"宋"
+    import re
+    RegularExpression="#[0-9]+"
+    if not re.match(RegularExpression,U_STR):
+        return U_STR
+    UnicodeNum=int(U_STR[1:])
+    CODEC="GBK"
+    try:
+        unicode_string=eval("u'\u%s'"%((hex(UnicodeNum))[2:]))
+        GBK_str=unicode_string.encode(CODEC)
+    except:
+        return U_STR
+    return GBK_str
+   
+   
+#用指定字符desSign替换繁体字符串srcStr的指定单字节字符sign
+## 
+#  @param 参数
+#  @return 返回值
+#  @remarks 函数详细说明:
+def ReplaceBig5AppointSign(srcStr,sign,desSign):
+    
+    isContinue = False
+    desStr = ''
+    
+    for i in range( len(srcStr) ):
+            
+        if isContinue:
+            #如果最后两个字节刚好是一个繁体字,则倒数第二个字节时会判定,最后一个字节则在此跳过
+            isContinue = False
+            continue
+        
+        #已到字符串最后一个字节,操作完跳出循环
+        if i == len(srcStr)-1:
+            
+            if srcStr[i] == sign:
+                #替换
+                desStr = desStr + desSign
+            else:
+                desStr = desStr + srcStr[i]
+            
+            break  # 跳出循环
+        
+        if 129 <= ord(srcStr[i]) <= 254:  # 判断是否在Big5高位字节范围内
+            
+            if 64 <= ord(srcStr[i+1]) <= 126 or 161 <= ord(srcStr[i+1]) <= 254:  # 判断是否Big5低位字节范围内
+                isContinue = True  # 下次判断高字节时,可跳过一次循环
+                desStr = desStr + srcStr[i:i+2]
+            else:
+                #不在Big5低位字节范围内
+                if srcStr[i] == sign:
+                    #替换
+                    desStr = desStr + desSign
+                else:
+                    desStr = desStr + srcStr[i]
+        else:
+            #不在Big5高位字节范围内
+            if srcStr[i] == sign:
+                #替换
+                desStr = desStr + desSign
+            else:
+                desStr = desStr + srcStr[i]
+        
+    return desStr
+
+
+Def_AccID_Split_Sign = "@"
+##玩家游戏账号格式: 平台账号@平台名@s区服ID, 平台账号可能带@,如邮箱yhlz123@qq.com@173on_lan@s519
+
+def GetPlayerMainServerID(accIDPlatform):
+    # 玩家合服后所属主服ID
+    # @param accIDPlatform: 玩家账号所属的平台
+    # 获取平台在该服务器所对应的主服ID, 如果没有配置默认取ServerID
+    key = "%sMainServerID" % accIDPlatform.lower()
+    if hasattr(DBConfig, key):
+        return getattr(DBConfig, key)
+    if hasattr(DBConfig, "ServerID"):
+        return int(getattr(DBConfig, "ServerID")[1:])
+    return 0
+
+##获取玩家所属区服ID
+def GetPlayerServerID(gameAccID):
+    infoList = gameAccID.split(Def_AccID_Split_Sign)
+    return 0 if len(infoList) < 3 else int(infoList[-1][1:])
+
+##获取玩家账号所属平台
+def GetPlayerPlatform(gameAccID):
+    infoList = gameAccID.split(Def_AccID_Split_Sign)
+    return "" if len(infoList) < 3 else infoList[-2]
+
+##获取平台账号
+def GetPlatformAccID(gameAccID):
+    infoList = gameAccID.split(Def_AccID_Split_Sign)
+    paInfoList = infoList[:-2]
+    platformAccID = Def_AccID_Split_Sign.join(paInfoList)
+    return platformAccID
+
+##登录key 如思璞
+def GetLoginKey(gameAccID):
+    infoList = gameAccID.split(Def_AccID_Split_Sign)
+    accIDPlatform = "" if len(infoList) < 3 else infoList[-2]
+    key = "%s_LoginKey" % accIDPlatform.lower()
+    if hasattr(DBConfig, key):
+        return getattr(DBConfig, key)
+    
+    return ""
diff --git a/db/PyMongoDataServer/Config/DBConfig.py b/db/PyMongoDataServer/Config/DBConfig.py
new file mode 100644
index 0000000..27abc41
--- /dev/null
+++ b/db/PyMongoDataServer/Config/DBConfig.py
@@ -0,0 +1,295 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+#-------------------------------------------------------------------------------
+#
+
+#from Common import mylog
+from DBCommon import GlobalFunctions
+import traceback
+import ConfigParser
+import os
+
+from DBCommon import error
+#mylog = __import__('Common.mylog')
+from Common import mylog
+
+#DB配置字典
+#格式:keyname:[defvalue, secionname],新增配置只要在下面字典定义中新增一行即可
+#用法,import模块后,直接DBConfig.开关名称 即可
+
+###PyMongoDataServer.ini###
+#运维必须修改的配置项
+BaseConfig ={
+#connect section
+#"PyMongoDBPort":[16899, "connect"],            #PyMongoDBServer端口  CenterGate    用的端口
+#"PyMongoDBPort_CreateRole":[16900, "connect"], #PyMongoDBServer端口  CreateRole    用的端口
+#"PyMongoDBPort_GMTool":[16901, "connect"],     #PyMongoDBServer端口  GMTool        用的端口
+
+#"USER_DB_PORT":[27017, "connect"], #MongoDB端口
+"USER_DB_IP":["localhost", "connect"], #MongoDB IP
+"USER_DB_NAME":["GameUser", "connect"], #MongoDB Name#    
+
+#"SYS_DB_PORT":[27017, "connect"],#MongoDB端口
+"SYS_DB_IP":["localhost", "connect"], #MongoDB IP
+"SYS_DB_NAME":["GameSys", "connect"], #MongoDB Name
+
+#"LOG_DB_PORT":[27017, "connect"],#MongoDB端口
+"LOG_DB_IP":["localhost", "connect"], #MongoDB IP
+"LOG_DB_NAME":["GameLog", "connect"], #MongoDB Name   
+
+#platform section
+"PlatformName":["", "platform"], #平台
+"ServerID":["", "platform"], #区服ID
+
+#ID 分配服务器设置
+"UseIDDispatchServer":[0, "IDDispatch"],   #启用ID分配服务器开关
+"IDDispatchServerIP":["localhost", "IDDispatch"],  #ID分配服务器 域名
+"IDDispatchServerPort":[8001, "IDDispatch"],       #ID分配服务器 端口
+"IDDispatchPlayeIDLimit":[100, "IDDispatch"],       #PlayerID预分配数量下限
+#"IDDispatchFamilyIDLimit":[30, "IDDispatch"],       #FamilyID预分配数量下限---在GameServer判断通知
+
+#账号验证
+"CheckTokenUrl":["", "CheckAccID"],
+
+
+#事件回报和定时处理
+"OpenErrLogReport":[0,"OpenErrLogReport"],                     #开启回报错误数量
+"PlatformName":["9377","platform"],                            #ZoneName       
+"ServerID":["s1","platform"],                                  #OperatorID
+"AppId":["AppId1","EventReport"],                              #AppId
+"Key":["7ded96779343f198de9b95a05a0704c9","EventReport"],      #Secret
+"SessionGUID":["sid1","EventReport"],                          #SessionID
+"ProductID":["pid1","EventReport"],                            #ProductID
+"ErrLogReportEventID":[22222,"EventReport"],                    #回报错误数量事件ID
+"ErrLogReportInterval":[60000,"EventReport"],                #回报错误数量间隔
+"ReportUrl":["","EventReport"],                        # 数据汇报地址 
+
+"LoginKey":["","SPGame"]                        # 思璞游戏登录key
+}
+
+###config\\config.ini###
+dbconfig = {
+#auth section
+"userdb_user":['', "auth"],
+"userdb_pwd":['', 'auth'],
+"sysdb_user":['', "auth"],
+"sysdb_pwd":['', 'auth'],
+"logdb_user":['', "auth"],
+"logdb_pwd":['', 'auth'],  
+  
+#connect section
+"ConnectionQueueSize":[1, "connect"],
+"PyMongoDBPort":[16899, "connect"],                #PyMongoDBServer端口  CenterGate    用的端口
+"PyMongoDBPort_CreateRole":[16900, "connect"],     #PyMongoDBServer端口  CreateRole    用的端口
+"PyMongoDBPort_GMTool":[16901, "connect"],         #PyMongoDBServer端口  GMTool        用的端口
+"MergePort":[16902, "connect"],                   #跨服接口端口
+
+"USER_DB_PORT":[27017, "connect"], #MongoDB端口
+#"USER_DB_IP":["localhost", "connect"], #MongoDB IP
+#"USER_DB_NAME":["GameUser", "connect"], #MongoDB Name
+#
+"SYS_DB_PORT":[27017, "connect"],#MongoDB端口
+#"SYS_DB_IP":["localhost", "connect"], #MongoDB IP
+#"SYS_DB_NAME":["GameSys", "connect"], #MongoDB Name
+#
+"LOG_DB_PORT":[27017, "connect"],#MongoDB端口
+#"LOG_DB_IP":["localhost", "connect"], #MongoDB IP
+#"LOG_DB_NAME":["GameLog", "connect"], #MongoDB Name
+
+#encoding
+"base64":[1, "encoding"],    #是否对字符串进行BASE64编码
+"encoding":['gbk', "encoding"],    #字符串编码,在base64为False时有效
+
+#merge
+"randPswLen":[8, "merge"],                   #合服生成随机密码长度,不得超过32
+"randPswHasDigit":[True, "merge"],           #随机密码是否包含数字
+"randPswHasLowLetter":[True, "merge"],       #随机密码是否包含小写字符
+"randPswHasUpperLetter":[True, "merge"],     #随机密码是否包含大写字符
+"randPswHasSpecialChar":[False, "merge"],    #随机密码是否包含特殊字符
+
+#config section
+"MultiThreading":[False,"config"], #主main是否开启多线程
+"checkSID":[False, "config"], #是否进行SID校验
+"TryCntOnWriteFail":[3, 'config'], #存储失败后,尝试次数, 默认3次
+"IsOpenDbSaveServer":[False, 'config'], #是否打开mongoDBSaveServer
+"maxReconnectCnt":[100, 'config'],
+"UploadSysTables":[False, "config"],
+#"MainLogPath":["D:\\ServerLog", "config"],
+
+"EventShellEnable":[False, "config"],       #是否启用EventShellDLL发送流向记录 
+"EventShellIP":["127.0.0.1", "config"],     #事件接口服务器的IP地址 
+"EventShellPort":[60000, "config"],         #事件接口服务器的端口号 
+"EventShellGroupID":[0,"config"],           #本服务器的服务器组标识 
+"EventShellServerID":[0,"config"],          #本服务器的ID 
+"EventShellHeartInterval":[60000, "config"],#连接事件接口服务器心跳时间间隔(ms)
+"EventShellDllPath":["EventToInterfaceDll.dll", "config"],#指定事件接口服务器Dll地址
+"EventShellDllLogPath":["D:\\ServerLog", "config"],
+
+"IsOpenLogDBFileSave":[False, 'config'], #是否打开LogDB文件保存
+"LogDB_EventShell_Save":[True, 'config'], #LogDB保存通过EventShell保存(如果要使用该功能,一定要关闭IsOpenLogDBFileSave,并开启EventShellEnable和配置相关网络参数)
+"PackSave":[True, 'config'],                #是否打开打包保存
+"StartProfile":[True, 'config'],            #是否开启性能评测
+"ProfileThreshold":[100, 'config'],         #性能阀值,默认100毫秒,超过则输出一条日志
+"ProfileQueueThresholdMax":[100, 'config'],    #性能统计队列上限,超过此上限触发写一条日志
+"ProfileQueueThresholdMin":[10, 'config'],    #性能统计队列下限,低于此上限触发写一条日志
+
+#env section
+"Python_Ver":["2.7.2", "environment"],
+"PyMongo_Ver":["2.5.1", "environment"],
+"MongoDB_Ver":["2.4.3", "environment"],
+"MongoDB_Bits":[64, "environment"],
+
+#InnerParam
+"PLAYERID_FEED":[10000, "InnerParam"],
+"PLAYERID_STEP":[1, 'InnerParam'],
+"LOGINDEX_FEED":[0, "InnerParam"], #tagDBMapServerInfo日志索引种子起始
+"LOGINDEX_STEP":[1, 'InnerParam'],  #tagDBMapServerInfo日志索引增量
+"LOGDB_LOGINDEX_FEED":[0, 'InnerParam'],#tagDBPlayerLog日志索引种子起始
+"LOGDB_LOGINDEX_STEP":[1, 'InnerParam'],#tagDBPlayerLog日志索引增量
+"LOGDB_SvrStatus_fldIndex_FEED":[0, 'InnerParam'],#SvrStatus日志索引种子起始
+"LOGDB_SvrStatus_fldIndex_STEP":[1, 'InnerParam'],#SvrStatus日志索引增量
+"LOGDB_AccForbiddenLog_StateID_FEED":[0, 'InnerParam'], #AccForbiddenLog日志索引种子起始 
+"LOGDB_AccForbiddenLog_StateID_STEP":[1, 'InnerParam'], #AccForbiddenLog日志索引增量  
+"LOGDB_tagDBServerMoneyLog_LogIndex_FEED":[0, 'InnerParam'], #tagDBServerMoneyLog 日志索引种子起始
+"LOGDB_tagDBServerMoneyLog_LogIndex_STEP":[1, 'InnerParam'], #tagDBServerMoneyLog 日志索引增量
+"LOGDB_tagDBApexKickLog_KickLogIndex_FEED":[0, 'InnerParam'], #tagDBApexKickLog 日志索引种子起始
+"LOGDB_tagDBApexKickLog_KickLogIndex_STEP":[1, 'InnerParam'], #tagDBApexKickLog 日志索引增量
+"LOGDB_tagDBGateServerIP_LogIndex_FEED":[0, 'InnerParam'], #tagDBGateServerIP 日志索引种子起始
+"LOGDB_tagDBGateServerIP_LogIndex_STEP":[1, 'InnerParam'], #tagDBGateServerIP 日志索引增量
+"LOGDB_tagDBHugeTrade_TradeIndex_FEED":[0, 'InnerParam'], #tagDBHugeTrade 日志索引种子起始
+"LOGDB_tagDBHugeTrade_TradeIndex_STEP":[1, 'InnerParam'], #tagDBHugeTrade 日志索引增量
+"LOGDB_tagDBPlayerSaveCoinLog_LogIndex_FEED":[0, 'InnerParam'], #tagDBPlayerSaveCoinLog 日志索引种子起始
+"LOGDB_tagDBPlayerSaveCoinLog_LogIndex_STEP":[1, 'InnerParam'], #tagDBPlayerSaveCoinLog 日志索引增量
+"LOGDB_tagDBServerKickLog_LogIndex_FEED":[0, 'InnerParam'], #tagDBServerKickLog 日志索引种子起始
+"LOGDB_tagDBServerKickLog_LogIndex_STEP":[1, 'InnerParam'], #tagDBServerKickLog 日志索引增量
+"LOGDB_tagDBTalkTraceLog_LogIndex_FEED":[0, 'InnerParam'], #tagDBTalkTraceLog 日志索引种子起始
+"LOGDB_tagDBTalkTraceLog_LogIndex_STEP":[1, 'InnerParam'], #tagDBTalkTraceLog 日志索引增量
+"tagExpiation_ExpiationIndex_FEED":[0, 'InnerParam'], #tagExpiation 索引种子起始
+"tagExpiation_ExpiationIndex_STEP":[1, 'InnerParam'], #tagExpiation 索引增量
+"tagPetExpiation_ExpiationIndex_FEED":[0, 'InnerParam'], #tagPetExpiation 索引种子起始
+"tagPetExpiation_ExpiationIndex_STEP":[1, 'InnerParam'], #tagPetExpiation 索引增量
+"tagDBImpeach_ImpeachIndex_FEED":[0, 'InnerParam'], #tagDBImpeach 索引种子起始
+"tagDBImpeach_ImpeachIndex_STEP":[1, 'InnerParam'], #tagDBImpeach 索引增量
+"tagDBCoinChangeLog_LogIndex_FEED":[0, 'InnerParam'], #tagDBCoinChangeLog 索引种子起始
+"tagDBCoinChangeLog_LogIndex_STEP":[1, 'InnerParam'], #tagDBCoinChangeLog 索引增量
+} 
+
+
+def ReadCongfigValue(config, secname, keyname, defvalue):
+    try:
+        if config.has_option(secname, keyname):
+            value = config.get(secname, keyname)
+#            if type(defvalue) == str:
+#                value = type(defvalue)(value)
+            if type(defvalue) == bool:
+                value = type(defvalue)(int(value))
+            else:
+                value = type(defvalue)(value)
+        else:return defvalue  
+    except:
+        msg = error.formatMsg('error', error.ERROR_NO_18, 'config = %s, secname = %s, keyname = %s, defvalue = %s\n%s'%(config, secname, keyname, defvalue, traceback.format_exc()))
+        mylog.error(msg)
+        return None 
+#    print value
+    return value
+    
+def ReadDBConfig():
+    try:
+        self_module = __import__(__name__)
+        config = ConfigParser.ConfigParser()
+        
+        #读取数据库配置文件config\\config.ini
+        config.read(os.path.join(GlobalFunctions.getAppPath(), 'config\\config.ini'))      
+        for k, v in dbconfig.items(): 
+            value = ReadCongfigValue(config, v[1], k, v[0])
+            if value == None:return False
+            setattr(self_module, k, value)
+        
+        #读取数据库配置文件PyMongoDataServer.ini
+        config.read(os.path.join(GlobalFunctions.getAppPath(), 'PyMongoDataServer.ini'))      
+        for k, v in BaseConfig.items(): 
+            value = ReadCongfigValue(config, v[1], k, v[0])
+            if value == None:return False
+            setattr(self_module, k, value)
+        #动态加载有配置平台合服主服的平台主服ID
+        sectionName = "platform"
+        if config.has_section(sectionName):
+            optionsList = config.options(sectionName)
+            # 注意options 已经是小写 调用也只能用小写
+            for k in optionsList:
+                if "mainserverid" in k:
+                    value = ReadCongfigValue(config, sectionName, k, 0)
+                    if value:
+                        setattr(self_module, k, value)
+                elif "loginkey" in k:
+                    value = ReadCongfigValue(config, sectionName, k, 0)
+                    if value:
+                        setattr(self_module, k, value)
+                        
+        #检查并解密mongodb的登录用户名和密码
+        #userdb
+        if not self_module.userdb_user:
+            msg = error.formatMsg('DeployError', error.ERROR_NO_19, "user db mongodb longin user name is empty!")
+            mylog.DeployError(msg, True)
+            return False
+        
+        if self_module.userdb_pwd:
+            ret, self_module.userdb_pwd = GlobalFunctions.GetEncodePsw(self_module.userdb_pwd)
+            if not ret:
+                msg = error.formatMsg('DeployError', error.ERROR_NO_20, "Decrypt userdb_pwd faied.")
+                mylog.DeployError(msg, True)  
+                return False
+        else:
+            msg = error.formatMsg('DeployError', error.ERROR_NO_21, "user db mongodb longin pwd is empty!")
+            mylog.DeployError(msg, True)  
+            return False
+        
+        #sysdb
+        if not self_module.sysdb_user:
+            msg = error.formatMsg('DeployError', error.ERROR_NO_22, "sys db mongodb longin user name is empty!")
+            mylog.DeployError(msg, True)
+            return False
+        
+        if self_module.sysdb_pwd:
+            ret, self_module.sysdb_pwd = GlobalFunctions.GetEncodePsw(self_module.sysdb_pwd)
+            if not ret:
+                msg = error.formatMsg('DeployError', error.ERROR_NO_23, "Decrypt sysdb_pwd faied.")
+                mylog.DeployError(msg, True)  
+                return False
+        else:
+            msg = error.formatMsg('DeployError', error.ERROR_NO_24, "sys db mongodb longin pwd is empty!")
+            mylog.DeployError(msg, True)  
+            return False
+        
+        #logdb
+        if not self_module.logdb_user:
+            msg = error.formatMsg('DeployError', error.ERROR_NO_25, "log db mongodb longin user name is empty!")
+            mylog.DeployError(msg, True)  
+            return False
+        
+        if self_module.logdb_pwd:
+            ret, self_module.logdb_pwd = GlobalFunctions.GetEncodePsw(self_module.logdb_pwd)
+            if not ret:
+                msg = error.formatMsg('DeployError', error.ERROR_NO_26, "Decrypt logdb_pwd faied.")
+                mylog.DeployError(msg, True) 
+                return False
+        else:
+            msg = error.formatMsg('DeployError', error.ERROR_NO_27, "log db mongodb longin pwd is empty!") 
+            mylog.DeployError(msg, True)
+            return False   
+    except:
+        msg = error.formatMsg('error', error.ERROR_NO_28, '%s'%traceback.format_exc()) 
+        mylog.error(msg)
+        return False    
+    return True
+
+dbconfig_init = False
+
+if not dbconfig_init:
+    if not ReadDBConfig():
+        msg = error.formatMsg('fatal', error.ERROR_NO_29, "Init config failed.")
+        mylog.fatal(msg)
+    dbconfig_init = True
+    
diff --git a/db/PyMongoDataServer/LogicProcess/UserCtrlDB.py b/db/PyMongoDataServer/LogicProcess/UserCtrlDB.py
new file mode 100644
index 0000000..60709b8
--- /dev/null
+++ b/db/PyMongoDataServer/LogicProcess/UserCtrlDB.py
@@ -0,0 +1,5750 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+#-------------------------------------------------------------------------------
+#
+
+import os
+import zlib
+from time import *
+import datetime
+from binascii import *
+import uuid
+import md5
+import pymongo
+import CtrlDB
+from DBCommon import (CommonDefine, SingletonObject, DataDumper, GlobalFunctions, VersionNoDefine, error, DBController)
+from Common import (CommFunc,CommFuncEx, mylog, RandowPswGenerator)
+from Protocol import (RecvPackProtocol, SendPackProtocol, MergeServerRecvProtocol, MergeServerSendProtocol)
+from Collections import (DataServerPlayerData, DataServerLogData)
+from MangoDBCommon import (getADOExceptionCount, getSIDErrorCnt, addADOExceptionCount, seq, fix_outgoingText, fix_incomingText)
+from ServerClientShareDefine import *
+from Protocol import MMORPGPack
+import ConfigParser
+#import IPY_GameWorld
+#from Config import (DBConfig,)
+DBConfig = __import__('Config.DBConfig')
+from ctypes import string_at
+import traceback
+from EventShell import (EventProcess, EventReport)
+import inspect
+from Collections.CollectionDefine import *
+import binascii
+from Net import (MongoDBServer, )
+from GMToolLogicProcess import  ProjSpecialProcess
+from Common import (FileLog,)
+import MergeProxyClientMgr
+from Config import PyObjConfig
+import PegasusCollectorProxy
+import urllib
+import urllib2
+#-------------------------------------------------------------------------------
+
+MERGE_POS_CONFIG_FILE = 'Config\\PosConfig.txt'
+MergePlayerNameFormat_CONFIG_FILE = 'Config\\MergePlayerNameFormat.txt'
+ATTR_CALL_TIME = ['weekday', 'year', 'month', 'day', 'hour', 'minute']
+Def_Cmp_Lower = -1                #小于
+Def_Cmp_Equ = 0                   #等于
+Def_Cmp_Greater = 1               #大于
+
+IsMergeServer = None
+#g_mergeRegisterDateDict = {} # 跨服玩家完整注册数据日期{newAccid:"日期", ...}
+g_mergeRegisterPlayerDict = {} # 跨服玩家数据缓存 {accID:[pwd, encodedPsw, recvPack, 平台标识, serverID], ...}
+(
+MergeRegPInfoIndex_Pwd, # 跨服玩家上传数据信息列表索引 - 密码
+MergeRegPInfoIndex_EncodedPsw, # 跨服玩家上传数据信息列表索引 - 加密后密码
+MergeRegPInfoIndex_PackData, # 跨服玩家上传数据信息列表索引 - 上传包数据
+MergeRegPInfoIndex_Operator, # 跨服玩家上传数据信息列表索引 - 平台标识
+MergeRegPInfoIndex_ServerID, # 跨服玩家上传数据信息列表索引 - 服务器ID
+) = range(5)
+
+#def fixMergedPlayerName(playerName):
+#    '''去除名字中的合服信息,即去掉名字中'['后面的部分'''
+#    pos = playerName.find('[')
+#    if pos == -1:
+#        return playerName
+#    return playerName[:pos]
+import thread
+lockPlayerID = thread.allocate_lock()
+lockFamilyID = thread.allocate_lock()
+def CallDispatchPlayerID(db,self): 
+    global lockPlayerID
+    lockPlayerID.acquire()#加锁
+    self.isDispatchingPlayerID = True
+    mylog.info("IDDispatch  CallDispatchPlayerID")
+    import socket
+    import time
+    host = DBConfig.IDDispatchServerIP
+    port = DBConfig.IDDispatchServerPort
+    addr = (host, port)
+    BUF_SIZE = 1024
+    try:
+        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        client.connect(addr)
+        data = "PID"
+        client.send(data)
+        dataRecv = client.recv(BUF_SIZE)
+        #print "Dispatch>>>>> recv %s"%dataRecv
+        mylog.info("IDDispatch  recv:%s"%dataRecv)
+        resultDict = eval(dataRecv)
+        if resultDict:
+            if resultDict['result']:
+                minID = resultDict['minID']
+                maxID = resultDict['maxID']
+                recs = []
+                for id in xrange(minID, maxID+1):
+                    recs.append({'PlayerID':id})
+                collection = db[UCN_Dispatch_PlayerID] 
+                collection.insert(recs)
+        client.close()
+    except Exception, e:
+        mylog.error("IDDispatch  CallDispatchPlayerID Connect Exception %s"%e)
+    except:
+        mylog.error("IDDispatch  CallDispatchPlayerID Connect unknown Exception")
+    self.isDispatchingPlayerID = False
+    lockPlayerID.release()#解锁
+    return
+
+def CallDispatchFamilyID(db, fromPack, type, self): 
+    global lockFamilyID
+    lockFamilyID.acquire()#加锁    
+    self.isDispatchingFamilyID = True
+    mylog.info("IDDispatch  CallDispatchFamilyID")
+    import socket
+    import time
+    host = DBConfig.IDDispatchServerIP
+    port = DBConfig.IDDispatchServerPort
+    addr = (host, port)
+    BUF_SIZE = 1024
+    try:
+        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        client.connect(addr)
+        data = "FID"
+        client.send(data)
+        dataRecv = client.recv(BUF_SIZE)
+        #print "Dispatch>>>>> recv %s"%dataRecv
+        mylog.info("IDDispatch  recv:%s"%dataRecv)
+        resultDict = eval(dataRecv)
+        if resultDict:
+            if resultDict['result']:
+                minID = resultDict['minID']
+                maxID = resultDict['maxID']
+                recs = []
+                for id in xrange(minID, maxID+1):
+                    recs.append({'FamilyID':id})
+                collection = db[UCN_Dispatch_FamilyID] 
+                collection.insert(recs)
+                #新分配,通知GameServer
+                self.CallBackToSendFamilyIDPack(fromPack, type, minID, maxID)
+        client.close()
+    except Exception, e:
+        mylog.error("IDDispatch  CallDispatchFamilyID Connect Exception %s"%e)
+    except:
+        mylog.error("IDDispatch  CallDispatchFamilyID Connect unknown Exception")
+    
+    self.isDispatchingFamilyID = False
+    lockFamilyID.release()#解锁
+    return
+
+## 当前时间与指定时间比较
+#  @param curTime 当前服务器时间 
+#  @param timeInfo 指定时间 [[3,4(星期几)], 年,月,日,时,分] 
+#  @return 大于返回1,小于返回-1,相同返回0
+#  @remarks 函数详细说明.异常和不成比较条件(星期几不对)返回None
+def CompareActTime(curTime, timeInfo):
+    for index, callObj in enumerate(ATTR_CALL_TIME):
+        #去除不比较的元素
+        if timeInfo[index] == '-':
+            continue
+        
+        if hasattr(curTime, callObj) != True:
+            return
+        
+        curCallObj = getattr(curTime, callObj)
+
+        #优先星期几特殊验证
+        if type(curCallObj) != int:
+            wday = curCallObj() + 1
+            if wday not in timeInfo[index]:
+                return
+            
+            continue
+        
+        if curCallObj == timeInfo[index]:
+            continue
+        
+        #当前时间大于指定时间
+        if curCallObj > timeInfo[index]:
+            return Def_Cmp_Greater
+        #小于
+        return Def_Cmp_Lower
+    #等于
+    return Def_Cmp_Equ
+
+class UserCtrlDB(CtrlDB.CtrlDB):
+    def __init__(self, ctrlDBMgr):
+        CtrlDB.CtrlDB.__init__(self, 'UserCtrlDB', 3, ctrlDBMgr)
+        self.priorityQueueList[1][0] = (CommonDefine.gstUpdate,
+                                        CommonDefine.gstSaveMapServerCrashData
+                                        )
+        self.priorityQueueList[2][0] = (CommonDefine.gstSaveGameServerData,
+                                                  CommonDefine.gstSavePlayerGMOPer)
+        self.priorityQueueList[0][0] = (CommonDefine.gstPlayerLogin,
+                                          CommonDefine.gstPlayerDetail,
+                                          CommonDefine.gstCreatePlayer,
+                                          CommonDefine.gstCheckPlayerExist,
+                                          CommonDefine.gstQueryCanSendMail,
+                                          CommonDefine.gstGetPlayerMail,
+                                          CommonDefine.gstGetMailDetail,
+                                          CommonDefine.gstUpdateMail,
+                                          CommonDefine.gstDeleteMail,
+                                          CommonDefine.gstOnDay,
+                                          CommonDefine.gstFamilyVS,
+                                          CommonDefine.gstGetPlayerMailState,
+                                          CommonDefine.gstGetCoin,
+                                          CommonDefine.gstCoinChange,
+                                          CommonDefine.gstPlayerBillboardLV,
+                                          CommonDefine.gstAccIDSendPrize,
+                                          CommonDefine.gstInsertAcc,
+                                          CommonDefine.gstGMCommandListReq,
+                                          CommonDefine.gstAddAccItem,
+                                          CommonDefine.gstCheckItemPrize,
+                                          CommonDefine.gstCheckLoadAcc,
+                                          CommonDefine.gstUpdatePswLV2,
+                                          CommonDefine.gstGetExpiationCount,
+                                          CommonDefine.gstGetExpiation,
+                                          CommonDefine.gstAddExpiation,
+                                          CommonDefine.gstAddPlayerMailByAccID,
+                                          CommonDefine.gstServerMergeDeleteRole,
+                                          CommonDefine.gstServerMergeChangeName,
+                                          CommonDefine.gstServerMergeUpdatePlayer,
+                                          CommonDefine.gstQueryIsFamilyLeader,
+                                          CommonDefine.gstServerMergeUpdateAccState,
+                                          CommonDefine.gstMapServerInfo,
+#                                          CommonDefine.gstServerVersion,
+                                          CommonDefine.gstCreatePet,
+                                          CommonDefine.gstSaveRunGataInfo,
+                                          CommonDefine.gstPlayerIDMarkDeleted,
+                                          CommonDefine.gstGetMapServerPlayerData,
+                                          CommonDefine.gstGetGameServerPlayerData,
+                                          CommonDefine.gstSaveGameServerPlayerSaveData,
+                                          CommonDefine.gstSaveGameServerCrashData,
+                                          CommonDefine.gstGetBillboardInfo,
+                                          CommonDefine.gstGetGameServerPlayerLoginData,
+                                          CommonDefine.gstUpdateServerDataVersionNO,
+#                                          CommonDefine.gstGetServerLanguageVersion,
+#                                          CommonDefine.gstGetServerVersions,
+                                          CommonDefine.gstUpdateTelLockState,
+                                          CommonDefine.gstGetPetExpiation,
+                                          CommonDefine.gstGetPetExpiationCount,
+                                          CommonDefine.gstAddPetExpiation,
+                                          CommonDefine.gstUpdateTotalSavePoint,
+                                          CommonDefine.gstSavePlayerInfo,
+                                          CommonDefine.gstUpdateAccAdult,
+                                          CommonDefine.gstCreateRoleServerRequestCreateRole,
+                                          CommonDefine.gstCreateRoleServerCheckPlayerExist,
+                                          CommonDefine.gstCreateRoleServerCheckIsHaveRole,
+                                          CommonDefine.gstQueryNewGuyCardState,
+                                          CommonDefine.gstUpdateNewGuyCardState,
+#                                          CommonDefine.gstGMToolCommand,               #GM工具接口命令 
+#                                          CommonDefine.gstGMToolCommandResult, 
+                                          CommonDefine.gstGMToolCmdUserDBRequest,       #GM工具处理请求
+                                          CommonDefine.gstMergeRegisterPlayer,          #报名跨服战
+                                          CommonDefine.gstMergeQueryRegisterResult,     #查询报名结果
+                                          CommonDefine.gstGeneralDBOper,                #通用数据库操作包
+                                          CommonDefine.gstDiapatchFamilyID,              #分配家族ID
+                                          CommonDefine.gstMergerChildToCenter,           #跨服子服发送自定义消息
+                                          CommonDefine.gstPrepareCreateRole,
+                                          CommonDefine.gstQueryRecharge,            # 查询是否有新的充值订单
+                                          CommonDefine.gstFinishRecharge,
+                                          )
+#        self.__processRequestType = self.__userDBGameServerSaveRequestType + self.__userDBNormalRequestType
+#        + self.__userDBSaveRequestType
+        
+        self.setServer(DBConfig.USER_DB_IP, DBConfig.USER_DB_PORT)
+        self.setDataBase(DBConfig.USER_DB_NAME, DBConfig.userdb_user, DBConfig.userdb_pwd)
+        self.loadMultiServerWarCfg()
+        #self.__LoadIntactUpLoadTimeCfg()
+        if DBConfig.base64:
+            self.translator = DBController.Base64StringManipulator()
+        else:
+            self.translator = DBController.EncodeStringManipulator(DBConfig.encoding)
+        #是否正在请求分配新PlayerID池
+        self.isDispatchingPlayerID = False
+        #是否正在请求分配新PlayerID池
+        self.isDispatchingFamilyID = False
+        self.loginHeap = 0
+        self.loginStartTime = time()
+        
+    def loadMultiServerWarCfg(self):
+        fileName = os.path.join(GlobalFunctions.getAppPath(), MERGE_POS_CONFIG_FILE)
+        if os.path.isfile(fileName):
+            self.__PosConfig = PyObjConfig.PyObjConfig(fileName)
+            
+        self.__MergePlayerNameFormatConfig = None
+        fileName = os.path.join(GlobalFunctions.getAppPath(), MergePlayerNameFormat_CONFIG_FILE)
+        if os.path.isfile(fileName):
+            self.__MergePlayerNameFormatConfig = PyObjConfig.PyObjConfig(fileName)
+            
+#    def __LoadIntactUpLoadTimeCfg(self):
+#        self.__IntactUpLoadTimeCfg = None
+#        fileName = os.path.join(GlobalFunctions.getAppPath(), "Config\\IntactUploadTime.txt")
+#        if os.path.isfile(fileName):
+#            self.__IntactUpLoadTimeCfg = PyObjConfig.PyObjConfig(fileName)
+#        mylog.info('__LoadIntactUpLoadTimeCfg OK')
+#        return
+            
+    def IsMergeServer(self):
+        global IsMergeServer
+        
+        if IsMergeServer != None:
+            return IsMergeServer
+        
+        appPath = GlobalFunctions.getAppPath()
+        mylog.debug("appPath = %s" % (appPath))
+        rootPath = appPath.replace("db\PyMongoDataServer", "")
+        mylog.debug("rootPath=%s" % (rootPath))
+        fileName = os.path.join(rootPath, 'CoreServerGroup\\GameServer\\Config.ini')
+        
+        if not os.path.isfile(fileName):
+            mylog.debug("can not find file %s" % fileName)
+            return False
+        
+        mergeServerIni = ConfigParser.ConfigParser()
+        mergeServerIni.read(fileName)
+        
+        section, option = "config", "IsMergeWarServe"
+        if not mergeServerIni.has_option(section, option):
+            mylog.info("%s 找不到配置: section=%s,option=%s" % (fileName, section, option))
+            return False
+
+        try:
+            IsMergeServer = int(mergeServerIni.get(section, option))
+            return IsMergeServer
+        except ValueError:
+            return False
+    
+    def requestLogicProcess(self, db, pack):
+        pos = 0
+        requestType, pos = CommFunc.ReadBYTE(pack.getBuffer(), pos)
+        
+        mylog.debug("begin process request type = %d"%requestType)
+        
+        if requestType == CommonDefine.gstDiapatchFamilyID:
+            oFuncGrade = self.GetFuncGrade('gstDiapatchFamilyID')
+            oFuncGrade.Start()
+            self.OnDiapatchFamilyID(db, pack)
+            oFuncGrade.End()
+        
+        if requestType == CommonDefine.gstGeneralDBOper:
+            oFuncGrade = self.GetFuncGrade('gstMergeGeneralReturn')
+            oFuncGrade.Start()
+            self.OnGeneralDBOper(db, pack)
+            oFuncGrade.End()
+            return True
+        
+        if requestType == CommonDefine.gstMergeQueryRegisterResult:
+            oFuncGrade = self.GetFuncGrade('gstMergeQueryRegisterResult')
+            oFuncGrade.Start()
+            self.OnMergeQueryRegisterResult(db, pack)
+            oFuncGrade.End()
+            return True
+        
+        if requestType == CommonDefine.gstMergeRegisterPlayer:
+            oFuncGrade = self.GetFuncGrade('gstMergeRegisterPlayer')
+            oFuncGrade.Start()
+            self.OnMergeRegisterPlayerByCache(db, pack)
+            oFuncGrade.End()
+            return True
+        
+        if requestType == CommonDefine.gstQueryNewGuyCardState:
+            oFuncGrade = self.GetFuncGrade("gstQueryNewGuyCardState")
+            oFuncGrade.Start()
+            self.OnQueryNewGuyCardState(db, pack)
+            oFuncGrade.End()
+            return True
+        
+        if requestType == CommonDefine.gstQueryRecharge:
+            oFuncGrade = self.GetFuncGrade("gstQueryRecharge")
+            oFuncGrade.Start()
+            self.OnQueryRecharge(db, pack)
+            oFuncGrade.End()
+            return True
+        
+        if requestType == CommonDefine.gstFinishRecharge:
+            oFuncGrade = self.GetFuncGrade("gstFinishRecharge")
+            oFuncGrade.Start()
+            self.OnFinishRecharge(db, pack)
+            oFuncGrade.End()
+            return True
+        
+        if requestType == CommonDefine.gstUpdateNewGuyCardState:
+            oFuncGrade = self.GetFuncGrade("gstUpdateNewGuyCardState")
+            oFuncGrade.Start()
+            self.onCheckUpdateNewGuyCardState(db, pack)
+            oFuncGrade.End()
+            return True
+        
+        #地图服务器保存崩溃数据
+        if requestType == CommonDefine.gstSaveMapServerCrashData:
+            #保存崩溃数据,之后可能不需要
+            mylog.info("recv map server crash data!")
+            oFuncGrade = self.GetFuncGrade("gstSaveMapServerCrashData")
+            oFuncGrade.Start()  
+            self.onSaveMapServerCrashData(db, pack)
+            oFuncGrade.End()
+            return True
+        #GameServer保存数据
+        if requestType == CommonDefine.gstSaveGameServerData:
+            oFuncGrade = self.GetFuncGrade("gstSaveGameServerData")
+            oFuncGrade.Start()  
+            self.onSaveGameServerData(db, pack)
+            oFuncGrade.End()
+            return True
+        #GameServer读取玩家数据
+        if requestType == CommonDefine.gstGetGameServerPlayerData:
+            oFuncGrade = self.GetFuncGrade("gstGetGameServerPlayerData")
+            oFuncGrade.Start()  
+            self.onGetGameServerPlayerData(db, pack)
+            oFuncGrade.End()
+            return True
+        #GameServer读取GM命令列表
+        if requestType == CommonDefine.gstGMCommandListReq:
+            oFuncGrade = self.GetFuncGrade("gstGMCommandListReq")
+            oFuncGrade.Start()  
+            self.onGMCmdListReq(db, pack)
+            oFuncGrade.End()
+            return True
+        if requestType == CommonDefine.gstPlayerLogin:
+            oFuncGrade = self.GetFuncGrade("gstPlayerLogin")
+            oFuncGrade.Start()  
+            self.onAuthentication(db, pack)
+            oFuncGrade.End()
+            return True
+        if requestType == CommonDefine.gstPlayerDetail:
+            oFuncGrade = self.GetFuncGrade("gstPlayerDetail")
+            oFuncGrade.Start()  
+            if self.IsMergeServer():
+                self.onGetMergePlayerDetail(db, pack)
+            else:
+                self.onGetPlayerDetail(db, pack)
+            oFuncGrade.End()
+            return True
+        if requestType == CommonDefine.gstCreatePlayer:
+            oFuncGrade = self.GetFuncGrade("gstCreatePlayer")
+            oFuncGrade.Start()  
+            self.onCreatePlayer(db, pack)
+            oFuncGrade.End()
+            return True
+        if requestType == CommonDefine.gstCreateRoleServerCheckIsHaveRole:
+            oFuncGrade = self.GetFuncGrade("gstCreateRoleServerCheckIsHaveRole")
+            oFuncGrade.Start()  
+            self.onCreateRoleServerCheckIsHaveRole(db, pack)
+            oFuncGrade.End()
+            return True
+        if requestType == CommonDefine.gstCreateRoleServerCheckPlayerExist:
+            oFuncGrade = self.GetFuncGrade("gstCreateRoleServerCheckPlayerExist")
+            oFuncGrade.Start()  
+            self.onCreateRoleServerCheckPlayerExist(db, pack)
+            oFuncGrade.End()
+            return True
+        if requestType == CommonDefine.gstCreateRoleServerRequestCreateRole:
+            oFuncGrade = self.GetFuncGrade("gstCreateRoleServerRequestCreateRole")
+            oFuncGrade.Start()  
+            self.onCreateRoleServerRequestCreateRole(db, pack)
+            oFuncGrade.End()
+            return True
+                   
+        if requestType == CommonDefine.gstGetGameServerPlayerLoginData:
+            #===================================================================
+            # oFuncGrade = self.GetFuncGrade("gstGetGameServerPlayerLoginData")
+            # oFuncGrade.Start()  
+            # self.onGetGameServerPlayerLoginData(db, pack)
+            # oFuncGrade.End()
+            #===================================================================
+            return True
+        if requestType == CommonDefine.gstSaveGameServerPlayerSaveData:
+            oFuncGrade = self.GetFuncGrade("gstSaveGameServerPlayerSaveData")
+            oFuncGrade.Start()  
+            self.onSaveGameServerPlayerSaveData(db, pack)
+            oFuncGrade.End()
+            return True
+        if requestType == CommonDefine.gstUpdate:
+            if DBConfig.IsOpenDbSaveServer:
+                msg = error.formatMsg('DeployError', error.ERROR_NO_56, "DbSaveServer is  open, type = %d request should be send to PyMongoDBSaveServer"%CommonDefine.gstUpdate)
+                mylog.DeployError(msg, True)
+                return False
+            
+            oFuncGrade = self.GetFuncGrade("gstUpdate")
+            oFuncGrade.Start()  
+            if self.IsMergeServer():
+                if not self.onSaveMapServerPlayerDataMergeServer(db, pack):
+                    mylog.error("onSaveMapServerPlayerDataMergeServer failed!sessionID = 0x%X", pack.getPackHead().sessionID)
+            else:
+                if not self.onSaveMapServerPlayerData(db, pack):
+                    mylog.error("onSaveMapServerPlayerData failed!sessionID = 0x%X", pack.getPackHead().sessionID)
+            oFuncGrade.End()
+            return True
+        if requestType == CommonDefine.gstSavePlayerInfo:
+            oFuncGrade = self.GetFuncGrade("gstSavePlayerInfo")
+            oFuncGrade.Start()  
+            self.OnSavePlayerInfo(db, pack)
+            oFuncGrade.End()
+            return True
+        if requestType == CommonDefine.gstInsertAcc:
+            oFuncGrade = self.GetFuncGrade("gstInsertAcc")
+            oFuncGrade.Start()             
+            self.OnInsertAcc(db, pack)
+            oFuncGrade.End()  
+            return True
+        if requestType == CommonDefine.gstPlayerIDMarkDeleted:
+            oFuncGrade = self.GetFuncGrade("gstPlayerIDMarkDeleted")
+            oFuncGrade.Start()              
+            self.OnPlayerIDMarkDeleted(db, pack)
+            oFuncGrade.End()             
+            return True 
+        if requestType == CommonDefine.gstGetCoin:
+            oFuncGrade = self.GetFuncGrade("gstGetCoin")
+            oFuncGrade.Start()      
+            self.OnGetCoin(db, pack) 
+            oFuncGrade.End()              
+            return True           
+        if requestType == CommonDefine.gstCoinChange:        
+            oFuncGrade = self.GetFuncGrade("gstCoinChange")
+            oFuncGrade.Start()      
+            self.OnCoinChange(db, pack) 
+            oFuncGrade.End() 
+            return True 
+        
+        if requestType == CommonDefine.gstCheckPlayerExist:        
+            oFuncGrade = self.GetFuncGrade("gstCheckPlayerExist")
+            oFuncGrade.Start()      
+            self.OnCheckPlayerExist(db, pack) 
+            oFuncGrade.End()  
+            return True 
+                   
+        if requestType == CommonDefine.gstOnDay:        
+            oFuncGrade = self.GetFuncGrade("gstOnDay")
+            oFuncGrade.Start()      
+            self.OnDay(db, pack) 
+            oFuncGrade.End()   
+            return True 
+           
+        if requestType == CommonDefine.gstSavePlayerGMOPer:        
+            oFuncGrade = self.GetFuncGrade("gstSavePlayerGMOPer")
+            oFuncGrade.Start()      
+            self.OnSavePlayerGMOPer(db, pack) 
+            oFuncGrade.End()  
+            return True 
+        
+        if requestType == CommonDefine.gstGetExpiationCount:        
+            oFuncGrade = self.GetFuncGrade("gstGetExpiationCount")
+            oFuncGrade.Start()      
+            self.OnGetExpiationCount(db, pack) 
+            oFuncGrade.End()   
+            return True 
+                   
+        if requestType == CommonDefine.gstGetPetExpiationCount:        
+            oFuncGrade = self.GetFuncGrade("gstGetPetExpiationCount")
+            oFuncGrade.Start()      
+            self.OnGetPetExpiationCount(db, pack) 
+            oFuncGrade.End()
+            return True 
+           
+        if requestType == CommonDefine.gstGetExpiation:        
+            oFuncGrade = self.GetFuncGrade("gstGetExpiation")
+            oFuncGrade.Start()      
+            self.OnGetExpiation(db, pack) 
+            oFuncGrade.End() 
+            return True 
+        
+        if requestType == CommonDefine.gstGetPetExpiation:        
+            oFuncGrade = self.GetFuncGrade("gstGetPetExpiation")
+            oFuncGrade.Start()      
+            self.OnGetPetExpiation(db, pack) 
+            oFuncGrade.End()  
+            return True 
+        
+        if requestType == CommonDefine.gstUpdateServerDataVersionNO:        
+            oFuncGrade = self.GetFuncGrade("gstUpdateServerDataVersionNO")
+            oFuncGrade.Start()      
+            self.OnUpdateServerDataVersionNO(db, pack) 
+            oFuncGrade.End()   
+            return True 
+                   
+        if requestType == CommonDefine.gstMapServerInfo:        
+            oFuncGrade = self.GetFuncGrade("gstMapServerInfo")
+            oFuncGrade.Start()      
+            self.OnMapServerInfo(db, pack) 
+            oFuncGrade.End()  
+            return True 
+            
+        if requestType == CommonDefine.gstUpdateTotalSavePoint:        
+            oFuncGrade = self.GetFuncGrade("gstUpdateTotalSavePoint")
+            oFuncGrade.Start()      
+            self.OnUpdateTotalSavePoint(db, pack) 
+            oFuncGrade.End()  
+            return True 
+         
+        if requestType == CommonDefine.gstGetPlayerMailState:        
+            oFuncGrade = self.GetFuncGrade("gstGetPlayerMailState")
+            oFuncGrade.Start()      
+            self.OnGetPlayerMailState(db, pack) 
+            oFuncGrade.End()     
+            return True 
+        
+        if requestType == CommonDefine.gstGetMailDetail:        
+            oFuncGrade = self.GetFuncGrade("gstGetMailDetail")
+            oFuncGrade.Start()      
+            self.OnGetMailDetail(db, pack) 
+            oFuncGrade.End()
+            return True          
+            
+        if requestType == CommonDefine.gstGetPlayerMail:        
+            oFuncGrade = self.GetFuncGrade("gstGetPlayerMail")
+            oFuncGrade.Start()      
+            self.OnGetPlayerMail(db, pack) 
+            oFuncGrade.End()   
+            return True   
+                      
+        if requestType == CommonDefine.gstAddPlayerMailByAccID:        
+            oFuncGrade = self.GetFuncGrade("gstAddPlayerMailByAccID")
+            oFuncGrade.Start()      
+            self.OnAddPlayerMailByAccID(db, pack) 
+            oFuncGrade.End()    
+            return True  
+                                                     
+        if requestType == CommonDefine.gstDeleteMail:        
+            oFuncGrade = self.GetFuncGrade("gstDeleteMail")
+            oFuncGrade.Start()      
+            self.OnDeleteMail(db, pack) 
+            oFuncGrade.End()    
+            return True 
+        
+        if requestType == CommonDefine.gstUpdateMail:        
+            oFuncGrade = self.GetFuncGrade("gstUpdateMail")
+            oFuncGrade.Start()      
+            self.OnUpdateMail(db, pack) 
+            oFuncGrade.End()    
+            return True       
+
+        if requestType == CommonDefine.gstQueryCanSendMail:        
+            oFuncGrade = self.GetFuncGrade("gstQueryCanSendMail")
+            oFuncGrade.Start()      
+            self.OnQueryCanSendMail(db, pack) 
+            oFuncGrade.End()    
+            return True    
+        
+        if requestType == CommonDefine.gstAccIDSendPrize:        
+            oFuncGrade = self.GetFuncGrade("gstAccIDSendPrize")
+            oFuncGrade.Start()      
+            self.OnAccIDSendPrize(db, pack) 
+            oFuncGrade.End()    
+            return True                    
+ 
+        if requestType == CommonDefine.gstCheckItemPrize:        
+            oFuncGrade = self.GetFuncGrade("gstCheckItemPrize")
+            oFuncGrade.Start()      
+            self.OnCheckItemPrize(db, pack) 
+            oFuncGrade.End()    
+            return True                           
+                          
+        if requestType == CommonDefine.gstCheckLoadAcc:        
+            oFuncGrade = self.GetFuncGrade("gstCheckLoadAcc")
+            oFuncGrade.Start()      
+            self.OnCheckLoadAcc(db, pack) 
+            oFuncGrade.End()    
+            return True                              
+                            
+        if requestType == CommonDefine.gstAddAccItem:        
+            oFuncGrade = self.GetFuncGrade("gstAddAccItem")
+            oFuncGrade.Start()      
+            self.OnAddAccItem(db, pack) 
+            oFuncGrade.End()    
+            return True      
+                           
+        if requestType == CommonDefine.gstUpdateTelLockState:        
+            oFuncGrade = self.GetFuncGrade("gstUpdateTelLockState")
+            oFuncGrade.Start()      
+            self.OnUpdateTelLockState(db, pack) 
+            oFuncGrade.End()    
+            return True  
+        
+        if requestType == CommonDefine.gstUpdateAccAdult:        
+            oFuncGrade = self.GetFuncGrade("gstUpdateAccAdult")
+            oFuncGrade.Start()      
+            self.OnUpdateAccAdult(db, pack) 
+            oFuncGrade.End()    
+            return True
+        
+        if requestType == CommonDefine.gstAddExpiation:        
+            oFuncGrade = self.GetFuncGrade("gstAddExpiation")
+            oFuncGrade.Start()      
+            self.OnAddExpiation(db, pack) 
+            oFuncGrade.End()    
+            return True                                  
+                        
+        if requestType == CommonDefine.gstAddPetExpiation:        
+            oFuncGrade = self.GetFuncGrade("gstAddPetExpiation")
+            oFuncGrade.Start()      
+            self.OnAddPetExpiation(db, pack) 
+            oFuncGrade.End()    
+            return True                             
+                        
+        if requestType == CommonDefine.gstServerMergeDeleteRole:        
+            oFuncGrade = self.GetFuncGrade("gstServerMergeDeleteRole")
+            oFuncGrade.Start()      
+            self.OnServerMergeDeleteRole(db, pack) 
+            oFuncGrade.End()    
+            return True                            
+
+        if requestType == CommonDefine.gstServerMergeUpdateAccState:        
+            oFuncGrade = self.GetFuncGrade("gstServerMergeUpdateAccState")
+            oFuncGrade.Start()      
+            self.OnServerMergeUpdateAccState(db, pack) 
+            oFuncGrade.End()    
+            return True                              
+
+        if requestType == CommonDefine.gstServerMergeChangeName:        
+            oFuncGrade = self.GetFuncGrade("gstServerMergeChangeName")
+            oFuncGrade.Start()      
+            self.OnServerMergeChangeName(db, pack) 
+            oFuncGrade.End()    
+            return True                              
+ 
+        if requestType == CommonDefine.gstInsertImpeach:        
+            oFuncGrade = self.GetFuncGrade("gstInsertImpeach")
+            oFuncGrade.Start()      
+            self.OnInsertImpeach(db, pack) 
+            oFuncGrade.End()    
+            return True                                                        
+        
+        if requestType ==  CommonDefine.gstGMToolCmdUserDBRequest:
+            oFuncGrade = self.GetFuncGrade("gstGMToolCmdUserDBRequest")
+            oFuncGrade.Start()      
+            self.OnGMToolCmdUserDBRequest(db, pack) 
+            oFuncGrade.End()  
+            return True
+        if requestType == CommonDefine.gstMergerChildToCenter:
+            oFuncGrade = self.GetFuncGrade("gstMergerChildToCenter")
+            oFuncGrade.Start()      
+            self.OnMergerChildToCenter(db, pack) 
+            oFuncGrade.End() 
+            return True
+        
+        if requestType == CommonDefine.gstPrepareCreateRole:
+            oFuncGrade = self.GetFuncGrade("gstPrepareCreateRole")
+            oFuncGrade.Start()      
+            self.OnPrepareCreateRole(db, pack) 
+            oFuncGrade.End() 
+            return True
+        
+        mylog.warning('%s not processed!'%pack.outputString())
+        return True
+    
+    #发送通知GameServer可用的家族ID列表#tagDGCanUseFamilyIDList封包
+    def CallBackToSendFamilyIDPack(self, fromPack, UpdateType, minID, maxID):
+        sendPack = SendPackProtocol.tagDGCanUseFamilyIDList()
+        sendPack.Type = CommonDefine.dgDiapatchFamilyID
+        sendPack.UpdateType = UpdateType
+        for id in range(minID, maxID + 1):
+            sendPack.FamilyIDList.append(id)
+        sendPack.Count = len(sendPack.FamilyIDList)
+        self.sendString(fromPack, sendPack.GetBuffer())
+        return
+    
+    def OnDiapatchFamilyID(self,db, pack):
+        buf = pack.getBuffer()
+        recvPack = RecvPackProtocol.tagGDRequestCanUseFamilyIDList()
+        pos = 0
+        recvPack.ReadData(buf, pos)
+        mylog.debug('OnDiapatchFamilyID pack = %s'%(recvPack.OutputString()))
+        if recvPack.CallType == 0:
+            #初始化请求获取已分配的家族ID列表
+            collection = db[UCN_Dispatch_FamilyID] 
+            result = collection.find()
+            mylog.debug('OnDiapatchFamilyID  db[UCN_Dispatch_FamilyID]  result = %s'%result)
+            if not result or result.count() == 0:
+                #未分配过  需要立即分配
+                if self.isDispatchingFamilyID:
+                    return
+                import threading
+                t = threading.Thread(target = CallDispatchFamilyID, args =(db, pack, recvPack.CallType, self))
+                t.start()
+                mylog.debug('CallType 0 need dispatch')
+            else:
+                sendPack = SendPackProtocol.tagDGCanUseFamilyIDList()
+                sendPack.Type = CommonDefine.dgDiapatchFamilyID
+                sendPack.UpdateType = recvPack.CallType
+                for rec in result:
+                    sendPack.FamilyIDList.append(rec['FamilyID'])
+                sendPack.Count = len(sendPack.FamilyIDList)
+                self.sendString(pack, sendPack.GetBuffer())
+                mylog.debug('CallType 0 sendPack.FamilyIDList %s'%sendPack.OutputString())
+        else:
+            #请求添加新的家族ID
+            if self.isDispatchingFamilyID:
+                return
+            import threading
+            t = threading.Thread(target = CallDispatchFamilyID, args =(db, pack, recvPack.CallType, self))
+            t.start()
+            mylog.debug('CallType 1 need dispatch')
+        return
+    
+    
+    def sendGameServerDBOperResult(self, sessionID, result, resultSet, errMsg):
+        sendPack = SendPackProtocol.tagDGGeneralDBOperResult()
+        sendPack.Type = CommonDefine.dgDBOperResult
+        sendPack.Result = result
+        sendPack.ResultSet = resultSet
+        sendPack.ResultSetLen = len(sendPack.ResultSet)
+        sendPack.ErrMsg = errMsg
+        sendPack.ErrMsgLen = len(sendPack.ErrMsg)
+        self.packSend(sessionID, 0, 0, CommonDefine.atMergeLogic, MMORPGPack.stGame,
+                      MMORPGPack.stData, sendPack.GetBuffer())
+    
+    def OnGeneralDBOper(self, db, pack):
+        buf = pack.getBuffer()
+        recvPack = RecvPackProtocol.tagGDGameServerGeneralDBOper()
+        pos = 0
+        recvPack.ReadData(buf, pos)
+        mylog.debug('pack = %s'%(recvPack.OutputString()))
+        
+        operDict = None
+        try:
+            operDict = eval(recvPack.OperDict)
+        except Exception, e:
+            mylog.warning('eval(\'%s\') failed!'%(recvPack.OperDict))
+            if recvPack.NeedReturn:
+                self.sendGameServerDBOperResult(pack.getSessionID(), 0, '', 'OperDict parse failed!')
+            return
+        if not isinstance(operDict, dict):
+            if recvPack.NeedReturn:
+                mylog.warning('%s is not a dict!'%(recvPack.OperDict))
+                self.sendGameServerDBOperResult(pack.getSessionID(), 0, '', 'OperDict parse failed!')
+            return
+        colName = operDict.get('collection')
+        if not colName:
+            mylog.warning('collection not specified!')
+            if recvPack.NeedReturn:
+                self.sendGameServerDBOperResult(pack.getSessionID(), 0, '', 'collection not specified!')
+            return
+        if not isinstance(colName, basestring):
+            mylog.warning('collection name:%s not valid!'%(colName))
+            if recvPack.NeedReturn:
+                self.sendGameServerDBOperResult(pack.getSessionID(), 0, '', 'collection name not valid!')
+            return
+        col = db[colName]
+        oper = operDict.get('oper')
+        if not oper:
+            mylog.warning('oper not specified!')
+            if recvPack.NeedReturn:
+                self.sendGameServerDBOperResult(pack.getSessionID(), 0, '', 'oper not specified!')
+            return
+        if not isinstance(oper, basestring):
+            mylog.warning('oper:%s not valid!'%(oper))
+            if recvPack.NeedReturn:
+                self.sendGameServerDBOperResult(pack.getSessionID(), 0, '', 'oper not valid!')
+            return
+        oper = oper.lower()
+        
+        if oper == 'drop':
+            result = 1
+            errorMsg = ''
+            try:
+                col.drop()
+            except Exception, e:
+                mylog.warning('drop %s failed!error = %s'%(colName, e))
+                result = 0
+                errorMsg = str(e)
+            except:
+                mylog.warning('drop %s failed!unknown error!'%(colName))
+                result = 0
+                errorMsg = 'unknown exception!'
+            if recvPack.NeedReturn:
+                self.sendGameServerDBOperResult(pack.getSessionID(), result, '', errorMsg)
+            return
+        
+        if oper == 'insert':
+            doc_or_docs = operDict.get('docs')
+            errorMsg = ''
+            result = 1
+            try:
+                col.insert(doc_or_docs, False, True)
+            except Exception, e:
+                mylog.warning('insert %s into %s failed!error = %s'%(doc_or_docs, colName, e))
+                result = 0
+                errorMsg = str(e)
+            except:
+                mylog.warning('insert %s into %s failed!unknown exception!'%(doc_or_docs, colName))
+                result = 0
+                errorMsg = 'unknown exception!'
+            if recvPack.NeedReturn:
+                self.sendGameServerDBOperResult(pack.getSessionID(), result, '', errorMsg)
+            return
+        
+        if oper == 'update':
+            doc = operDict.get('docs')
+            spec = operDict.get('spec')
+            result = 1
+            errorMsg = ''
+            try:
+                col.update(spec, doc, False, False, True, True)
+            except Exception, e:
+                mylog.warning('update %s failed!spec = %s, doc = %s, error = %s'%(colName, spec, doc, e))
+                result = 0
+                errorMsg = str(e)
+            except:
+                mylog.warning('update %s failed!spec = %s, doc = %s,unknown exception occur!'%(colName, spec,
+                                                                                               doc))
+                result = 0
+                errorMsg = 'unknown exception!'
+            if recvPack.NeedReturn:
+                self.sendGameServerDBOperResult(pack.getSessionID(), result, '', errorMsg)
+            return
+        
+        if oper == 'remove':
+            spec_or_id = operDict.get('spec')
+            result = 1
+            errorMsg = ''
+            try:
+                col.remove(spec_or_id, True)
+            except Exception, e:
+                mylog.warning('remove from %s failed!spec = %s, error = %s'%(colName, spec_or_id, e))
+                result = 0
+                errorMsg = str(e)
+            except:
+                mylog.warning('remove from %s failed!spec = %s, unknown exception!'%(colName, spec_or_id))
+                result = 0
+                errorMsg = 'unknown exception!'
+            if recvPack.NeedReturn:
+                self.sendGameServerDBOperResult(pack.getSessionID(), result, '', errorMsg)
+            return
+        
+        if oper == 'find':
+            spec = operDict.get('spec')
+            fields = operDict.get('fields', {})#指定的返回值
+            result = 1
+            errorMsg = ''
+            resultSet = None
+            try:
+                if fields == {}:
+                    resultSet = col.find(spec)
+                else:
+                    resultSet = col.find(spec, fields)
+            except Exception, e:
+                mylog.warning('%s.find(%s) failed!'%(colName, spec))
+                result = 0
+                errorMsg = str(e)
+            except:
+                mylog.warning('%s.find(%s) failed!'%(colName, spec))
+                result = 0
+                errorMsg = 'unknown exception!'
+            
+            if recvPack.NeedReturn:
+                if resultSet:
+                    resultSet = str(list(resultSet))
+                self.sendGameServerDBOperResult(pack.getSessionID(), result, resultSet, errorMsg)
+            return
+        mylog.warning('oper %s not support!'%oper)
+        
+    def OnMergeQueryRegisterResult(self, db, pack):    
+        buf = pack.getBuffer()
+        #len = pack.getLength()
+        recvPack = MergeServerRecvProtocol.tagLPQueryRegisterResult()
+        pos = 0
+        recvPack.ReadData(buf, pos)
+        mylog.debug('pack = %s'%(binascii.b2a_hex(buf)))
+        
+        clientSessionID = pack.getSessionID()
+        client = MergeProxyClientMgr.getMergeProxyClientMgr().findClientBySessionID(clientSessionID)
+        if not client:
+            mylog.warning('client not found!sessionID = %s'%(clientSessionID))
+            return
+        operator = client.operator
+        serverID = client.serverID
+        
+        registerMap = DataServerPlayerData.tagMergeRegisterPlayerMap()
+        registerMap.SetOperator(operator)
+        registerMap.ServerID = serverID
+        registerMap.SetOrgAccID(recvPack.AccID)
+        col = db[UCN_MergeRegisterPlayerMap]
+        sendPack = MergeServerSendProtocol.tagMPQueryRegisterResult()
+        sendPack.Type = CommonDefine.dgMergeQueryNewAccount
+        if not registerMap.adoLoad(col):
+            sendPack.Result = 0
+            self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, 0, CommonDefine.atMergeLogic, MMORPGPack.stNoSense,
+                          MMORPGPack.stNoSense, sendPack.GetBuffer())
+            mylog.warning('query failed!spec = [%s-%s].%s'%(registerMap.Operator, registerMap.ServerID,
+                                                            registerMap.OrgAccID))
+            return
+        sendPack.Result = 1
+        sendPack.Account = registerMap.NewAccID
+        sendPack.AccountLen = len(sendPack.Account)
+        sendPack.Pwd = registerMap.NewPsw
+        sendPack.PwdLen = len(sendPack.Pwd)
+        self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, 0, CommonDefine.atMergeLogic, MMORPGPack.stNoSense,
+                          MMORPGPack.stNoSense, sendPack.GetBuffer())
+        mylog.info('query [%s-%s].%s ok!'%(operator, serverID, recvPack.AccID))
+        
+    def OnMergeRegisterPlayerByCache(self, db, pack):
+        ''' 缓存跨服玩家上传数据信息 
+            目前账号、玩家ID、角色名均已确保唯一,故无需再重新生成新的账号及角色信息
+            直接接收更新缓存即可,玩家登陆跨服服务器时直接从缓存数据中解析角色数据,从而节省db存取步骤
+        '''
+        global g_mergeRegisterPlayerDict
+        try:
+            buf = pack.getBuffer()
+            recvPack = MergeServerRecvProtocol.tagLPRegisterPlayer()
+            pos = 0
+            recvPack.ReadData(buf, pos)
+            #mylog.debug('pack = %s'%(binascii.b2a_hex(buf)))
+            
+            loginResultPack = MergeServerSendProtocol.tagMPRegisterPlayerResult()
+            loginResultPack.Type = CommonDefine.dgMergeRegisterResult
+            
+            #玩家地图数据,和下线保存包 SavePlayerMapServerDataEx 一致          
+            playerData = recvPack.Data
+            playerRec = DataServerPlayerData.tagDBPlayer()
+            pos = 0
+            dbPlayerReadLen = playerRec.readData(playerData, pos, len(playerData))
+            if -1 == dbPlayerReadLen:
+                #数据异常,长度不足
+                #回复失败
+                loginResultPack.Result = 0
+                loginResultPack.ErrorMsg = 'Player data length not enough!'
+                loginResultPack.ErrorMsgLen = len(loginResultPack.ErrorMsg)
+                self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, 0, CommonDefine.atMergeLogic, MMORPGPack.stNoSense,
+                              MMORPGPack.stNoSense, loginResultPack.GetBuffer())
+                mylog.warning('player data too short!')
+                return
+            
+            if playerRec.PlayerID == 0:
+                loginResultPack.Result = 0
+                loginResultPack.ErrorMsg = 'Player data error!'
+                loginResultPack.ErrorMsgLen = len(loginResultPack.ErrorMsg)
+                self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, 0, CommonDefine.atMergeLogic, MMORPGPack.stNoSense,
+                              MMORPGPack.stNoSense, loginResultPack.GetBuffer())
+                mylog.warning('player data error!')
+                return
+            
+            clientSessionID = pack.getSessionID()
+            client = MergeProxyClientMgr.getMergeProxyClientMgr().findClientBySessionID(clientSessionID)
+            if not client:
+                mylog.warning('client not found!sessionID = %s'%(clientSessionID))
+                return
+            operator = client.operator
+            serverID = client.serverID
+            
+            playerID = playerRec.PlayerID
+            accID = playerRec.AccID.lower().strip(chr(0))
+            
+            if accID in g_mergeRegisterPlayerDict:
+                regPlayerInfo = g_mergeRegisterPlayerDict[accID]
+                pwd = regPlayerInfo[MergeRegPInfoIndex_Pwd]
+                encodedPsw = regPlayerInfo[MergeRegPInfoIndex_EncodedPsw]
+            else:
+                pwd = RandowPswGenerator.GeneratePsw(DBConfig.randPswLen, DBConfig.randPswHasDigit, DBConfig.randPswHasLowLetter,
+                                 DBConfig.randPswHasUpperLetter, DBConfig.randPswHasSpecialChar)
+                #加密密码
+                encoder = md5.new()
+                encoder.update(pwd)
+                encodedPsw = encoder.hexdigest()
+                encoder = md5.new()
+                encoder.update(encodedPsw)
+                encodedPsw = encoder.hexdigest()
+            mylog.debug('new pwd = %s,encodedPsw = %s' % (pwd, encodedPsw))
+                
+            playerName = playerRec.PlayerName.strip()
+            
+            #成功,返回新帐号密码
+            loginResultPack.Result = 1
+            loginResultPack.Account = accID
+            loginResultPack.AccountLen = len(loginResultPack.Account)
+            loginResultPack.Pwd = pwd
+            loginResultPack.PwdLen = len(loginResultPack.Pwd)
+            self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, 0, CommonDefine.atMergeLogic, MMORPGPack.stNoSense,
+                              MMORPGPack.stNoSense, loginResultPack.GetBuffer())
+            
+            mylog.info('player [%s-%s]accID=%s, playerID=%s, %s register PK ok!'%(operator.strip(chr(0)), serverID, accID, playerID, playerName))
+            g_mergeRegisterPlayerDict[accID] = [pwd, encodedPsw, recvPack, operator, serverID] # 更新跨服玩家数据缓存
+        except Exception, e:
+            msg = error.formatMsg('error', error.ERROR_NO_175, "OnMergeRegisterPlayer error %s!traceback = %s, pack = %s"%(e, traceback.format_exc(), binascii.b2a_hex(buf)))
+            mylog.error(msg)
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_176, "OnMergeRegisterPlayer error!traceback = %s, pack = %s"%(traceback.format_exc(), binascii.b2a_hex(buf)))
+            mylog.error(msg)
+        return
+    
+#    def OnMergeRegisterPlayer(self, db, pack):
+#        global g_mergeRegisterDateDict
+#        try:
+#            buf = pack.getBuffer()
+##            length = pack.getLength()
+#            recvPack = MergeServerRecvProtocol.tagLPRegisterPlayer()
+#            pos = 0
+#            recvPack.ReadData(buf, pos)
+#            mylog.debug('pack = %s'%(binascii.b2a_hex(buf)))
+#            
+#            loginResultPack = MergeServerSendProtocol.tagMPRegisterPlayerResult()
+#            loginResultPack.Type = CommonDefine.dgMergeRegisterResult
+#            
+#            #玩家地图数据,和下线保存包 SavePlayerMapServerDataEx 一致          
+#            playerData = recvPack.Data
+#            playerRec = DataServerPlayerData.tagDBPlayer()
+#            pos = 0
+#            dbPlayerReadLen = playerRec.readData(playerData, pos, len(playerData))
+#            if -1 == dbPlayerReadLen:
+#                #数据异常,长度不足
+#                #回复失败
+#                loginResultPack.Result = 0
+#                loginResultPack.ErrorMsg = 'Player data length not enough!'
+#                loginResultPack.ErrorMsgLen = len(loginResultPack.ErrorMsg)
+#                self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, 0, CommonDefine.atMergeLogic, MMORPGPack.stNoSense,
+#                              MMORPGPack.stNoSense, loginResultPack.GetBuffer())
+#                mylog.warning('player data too short!')
+#                return
+#            pos += dbPlayerReadLen
+#            if playerRec.PlayerID == 0:
+#                loginResultPack.Result = 0
+#                loginResultPack.ErrorMsg = 'Player data error!'
+#                loginResultPack.ErrorMsgLen = len(loginResultPack.ErrorMsg)
+#                self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, 0, CommonDefine.atMergeLogic, MMORPGPack.stNoSense,
+#                              MMORPGPack.stNoSense, loginResultPack.GetBuffer())
+#                mylog.warning('player data error!')
+#                return
+#            
+#            clientSessionID = pack.getSessionID()
+#            client = MergeProxyClientMgr.getMergeProxyClientMgr().findClientBySessionID(clientSessionID)
+#            if not client:
+#                mylog.warning('client not found!sessionID = %s'%(clientSessionID))
+#                return
+#            operator = client.operator
+#            serverID = client.serverID
+#            accid = playerRec.AccID.lower()    
+#            #校验通过,以下开始合服
+#            #先根据operator.serverID.accid确定是否已报名过
+#            registerMap = DataServerPlayerData.tagMergeRegisterPlayerMap()
+#            registerMap.SetOperator(operator)
+#            registerMap.ServerID = serverID
+#            registerMap.SetOrgAccID(accid)
+#            col = db[UCN_MergeRegisterPlayerMap]
+#            newPlayerID = 0
+#            newAccID = ''
+#            newPsw = ''
+#            firstRegister = False
+#            if registerMap.adoLoad(col):
+#                #已报名过,读取
+#                newPlayerID = registerMap.NewPlayerID
+#                newAccID = registerMap.NewAccID
+#                newPsw = registerMap.NewPsw
+#                mylog.info('already register before!')  
+#            else:
+#                firstRegister = True
+#                #未报名过,生成
+#                #同一运营商的相同帐号,返回失败/视为2个帐号[暂不处理]
+#                newPlayerID = seq(db, UCN_DBPlayer, 'PlayerID', DBConfig.PLAYERID_FEED, DBConfig.PLAYERID_STEP)
+#                newAccID = '%s'%newPlayerID    #以PlayerID的字符串形式作为新帐号
+#                newPsw = RandowPswGenerator.GeneratePsw(DBConfig.randPswLen, DBConfig.randPswHasDigit, DBConfig.randPswHasLowLetter,
+#                                 DBConfig.randPswHasUpperLetter, DBConfig.randPswHasSpecialChar)
+#                mylog.info('make new playerID = %s'%newPlayerID)
+#            #加密密码
+#            encoder = md5.new()
+#            encoder.update(newPsw)
+#            encodedPsw = encoder.hexdigest()
+#            encoder = md5.new()
+#            encoder.update(encodedPsw)
+#            encodedPsw = encoder.hexdigest()
+#            mylog.debug('new psw = %s,encodedPsw = %s'%(newPsw, encodedPsw))
+#            
+#            newAccid = newAccID.lower()    #帐号不区分大小写
+#            #添加到帐号表
+#            if firstRegister:
+#                newAccount = DataServerPlayerData.tagDSAccount()
+#                newAccount.SetACCID(newAccid)    
+#                newAccount.SetPsw(encodedPsw)
+#                newAccount.Adult = 1                   #强制已成年
+#                newAccount.SetOperator(operator)
+#                newAccount.AreaID = serverID           #服务器编号
+#                newAccount.ApplyingAdult = 0
+#                newAccount.SetRegisterTime(datetime.datetime.now().isoformat())
+#                colAccout = db[UCN_DSAccount]
+#                if not newAccount.adoInsertC(colAccout):
+#                    loginResultPack.Result = 0
+#                    loginResultPack.ErrorMsg = 'Insert account failed!!'
+#                    loginResultPack.ErrorMsgLen = len(loginResultPack.ErrorMsg)
+#                    self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, 0, CommonDefine.atMergeLogic, MMORPGPack.stNoSense,
+#                              MMORPGPack.stNoSense, loginResultPack.GetBuffer())
+#                    mylog.warning('Insert account %s failed!'%(newAccid))
+#                    return
+#                mylog.info('Insert account = %s ok!'%newAccount.ACCID)  
+#            
+#            #更新tagDBPlayer表的帐号字段
+#            playerRec.SetAccID(newAccid)
+#            playerRec.PlayerID = newPlayerID
+#            #记录子服平台、区服信息到tagDBPlayer
+#            playerRec.SetOperate(operator)
+#            playerRec.ServerID = serverID
+#            #改名
+##            orgPlayerName = fixMergedPlayerName(playerRec.PlayerName.strip(chr(0)))
+#            orgPlayerName = playerRec.PlayerName.strip()
+#            #playerRec.SetPlayerName('%s[%s-%s]'%(orgPlayerName, operator.strip(chr(0)), serverID))
+#            
+#            #取帐号后缀作为区服标识
+#            parserList = accid.split('@')
+#            serverSign = ""
+#            if len(parserList) >= 2:
+#                serverSign = parserList[-1]               
+#            
+#            parserList2 = orgPlayerName.split('-')
+#            orgNameServerSign = ""
+#            if len(parserList2) >= 2:
+#                orgNameServerSign = parserList2[-1]
+#            if orgNameServerSign and orgNameServerSign == serverSign:
+#                #名称后缀已经和帐号后缀一致,无须改名
+#                pass
+#            else:
+#                if serverSign:
+#                    newName = "%s-%s"%(orgPlayerName, serverSign)
+#                    playerRec.SetPlayerName(newName)
+#                else:
+#                    playerRec.SetPlayerName('%s[%s-%s]'%(orgPlayerName, operator.strip(chr(0)), serverID))
+#        
+#            mylog.debug('new player name = %s ok!'%playerRec.PlayerName)
+##            #设定所在地图和坐标
+##            posConfigKey = '%s-%s'%(operator.strip(chr(0)), serverID)
+##            resetPos = self.__PosConfig.config.get(posConfigKey)
+##            if not resetPos:
+##                #尝试重读
+##                self.loadMultiServerWarCfg()
+##                resetPos = self.__PosConfig.config.get(posConfigKey)
+##                if not resetPos:
+##                    mylog.error('MultiServerWarConfig error!key = %s not found!'%(posConfigKey))
+##                    return
+##            mapid, posX, posY = resetPos
+##            
+##            playerRec.MapID = mapid
+##            playerRec.DataMapID = mapid
+##            playerRec.CopyMapID = mapid
+##            playerRec.PosX = posX
+##            playerRec.PosY = posY
+##            
+##            playerRec.FromDataMapID = mapid
+##            playerRec.FromMapID = mapid
+##            playerRec.FromCopyMapID = mapid
+##            playerRec.FromPosX = posX
+##            playerRec.FromPosY = posY
+##            
+##            playerRec.RebornMapID = mapid
+##            playerRec.RebornPosX = posX
+##            playerRec.RebornPosY = posY
+#            
+#            playerRec.MapID = recvPack.SelectMapID
+#            playerRec.DataMapID = recvPack.SelectDataMapID
+#            playerRec.CopyMapID = recvPack.SelectCopyMapID
+#            playerRec.PosX = recvPack.SelectPosX
+#            playerRec.PosY = recvPack.SelectPosY
+#            
+#            playerRec.FromDataMapID = recvPack.SelectDataMapID
+#            playerRec.FromMapID = recvPack.SelectMapID
+#            playerRec.FromCopyMapID = recvPack.SelectCopyMapID
+#            playerRec.FromPosX = recvPack.SelectPosX
+#            playerRec.FromPosY = recvPack.SelectPosY
+#            
+#            playerRec.RebornMapID = recvPack.SelectMapID
+#            playerRec.RebornPosX = recvPack.SelectPosX
+#            playerRec.RebornPosY = recvPack.SelectPosY
+#            
+#            
+#            #更新tagDBPlayer
+#            col = db[UCN_DBPlayer]
+#            if not playerRec.adoCheckUpdateC(col):
+#                loginResultPack.Result = 0
+#                loginResultPack.ErrorMsg = 'CheckUpdate role failed!'
+#                loginResultPack.ErrorMsgLen = len(loginResultPack.ErrorMsg)
+#                self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, 0, CommonDefine.atMergeLogic, MMORPGPack.stNoSense,
+#                              MMORPGPack.stNoSense, loginResultPack.GetBuffer())
+#                mylog.warning('CheckUpdate player %s.%s failed!'%(playerRec.AccID, playerRec.PlayerID))                
+#                return
+#            mylog.info('CheckUpdate player %s %s %s ok!'%(playerRec.AccID, playerRec.PlayerID, playerRec.PlayerName))
+#            
+#            isIntactUpload = self.__GetIsIntactUpLoad()
+#
+#            # 每天只完整更新一次
+#            saveDateStr = g_mergeRegisterDateDict.get(newAccid, "")
+#            curDateStr = strftime("%Y-%m-%d", localtime())
+#            mylog.info('Check updatePlayerIDAndSavePlayerMapServerDataEx saveDateStr=%s,curDateStr=%s,isIntactUpload=%s' 
+#                       % (saveDateStr, curDateStr, isIntactUpload))
+#            
+#            # 首次上传 或 非首次上传且非同一天
+#            if saveDateStr != curDateStr or isIntactUpload:
+#                #同步PlayerID、PetID、OwnerID、TruckID
+#                self.updatePlayerIDAndSavePlayerMapServerDataEx(db, playerData[pos:], newPlayerID)
+#                mylog.info('    updatePlayerIDAndSavePlayerMapServerDataEx OK! firstRegister=%s' % firstRegister)
+#            g_mergeRegisterDateDict[newAccid] = curDateStr
+#            
+#            #记录到映射表
+#            if firstRegister:
+#                registerMap.SetNewAccID(newAccid)
+#                registerMap.SetNewPsw(newPsw)
+#                registerMap.NewPlayerID = newPlayerID
+#                col = db[UCN_MergeRegisterPlayerMap]
+#                if not registerMap.adoCheckUpdate(col):
+#                    loginResultPack.Result = 0
+#                    loginResultPack.ErrorMsg = 'update map table failed!'
+#                    loginResultPack.ErrorMsgLen = len(loginResultPack.ErrorMsg)
+#                    self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, 0, CommonDefine.atMergeLogic, MMORPGPack.stNoSense,
+#                              MMORPGPack.stNoSense, loginResultPack.GetBuffer())
+#                    mylog.warning('update map table failed!%s-%s-%s'%(registerMap.Operator, registerMap.ServerID,
+#                                                                  registerMap.OrgAccID))
+#                    return
+#            
+#            #成功,返回新帐号密码
+#            loginResultPack.Result = 1
+#            loginResultPack.Account = newAccid
+#            loginResultPack.AccountLen = len(loginResultPack.Account)
+#            loginResultPack.Pwd = newPsw
+#            loginResultPack.PwdLen = len(loginResultPack.Pwd)
+#            self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, 0, CommonDefine.atMergeLogic, MMORPGPack.stNoSense,
+#                              MMORPGPack.stNoSense, loginResultPack.GetBuffer())
+#            mylog.info('player [%s-%s].%s->%s.%s register PK ok!'%(registerMap.Operator, registerMap.ServerID,
+#                                                                   registerMap.OrgAccID, registerMap.NewAccID,
+#                                                                   registerMap.NewPlayerID))
+#        except Exception, e:
+#            msg = error.formatMsg('error', error.ERROR_NO_175, "OnMergeRegisterPlayer error %s!traceback = %s, pack = %s"%(e, traceback.format_exc(), binascii.b2a_hex(buf)))
+#            mylog.error(msg)
+#        except:
+#            msg = error.formatMsg('error', error.ERROR_NO_176, "OnMergeRegisterPlayer error!traceback = %s, pack = %s"%(traceback.format_exc(), binascii.b2a_hex(buf)))
+#            mylog.error(msg)
+#    
+#    ## 获取是否完整上传数据
+#    def __GetIsIntactUpLoad(self):
+#        
+#        #mylog.info('__GetIsIntactUpLoad...')
+#        
+#        if self.__IntactUpLoadTimeCfg == None:
+#            mylog.info('    没有完整上传数据时间配置,重新加载!')
+#            self.__LoadIntactUpLoadTimeCfg()
+#            return False
+#        
+#        timeList = self.__IntactUpLoadTimeCfg.config
+#        
+#        curTime = datetime.datetime.today()
+#        curTimeStr = str(curTime)
+#        curTimeStr = curTimeStr.split(".")[0]
+#        
+#        #mylog.info('    curTimeStr=%s,timeList=%s' % (curTimeStr, str(timeList)))
+#        
+#        for timeInfo in timeList:
+#            
+#            #mylog.info('        check timeInfo=%s' % (str(timeInfo)))
+#            # 判断日期
+#            dateTimeInfo = timeInfo[0]
+#            startTime = dateTimeInfo[0]
+#            endTime = dateTimeInfo[1]
+#            if curTimeStr < startTime or curTimeStr > endTime:
+#                #mylog.info('            非完整上传时间段!')
+#                continue
+#            
+#            beginTime = timeInfo[1]
+#            endTime = timeInfo[2]
+#            
+#            if CompareActTime(curTime, beginTime) in [Def_Cmp_Greater, Def_Cmp_Equ] \
+#                and CompareActTime(curTime, endTime) in [Def_Cmp_Lower, Def_Cmp_Equ]:
+#                #mylog.info('            当前是完整上传时间!')
+#                return True
+#        
+#            #mylog.info('            非完整上传时间!')
+#            
+#        #mylog.info('    所有时间检查完毕,当前非完整上传时间!')
+#        return False
+    
+#    #  @param  saveData: 物品数据开头
+#    #  @param  newPlayerID: 新PlayerID  
+#    def updatePlayerIDAndSavePlayerMapServerDataEx(self, db, saveData, newPlayerID):
+#        pos = 0      
+#        #保存物品等其他数据
+#        #不再支持单表模式
+#        #不再支持文件模式
+#        #保存物品
+#        oFuncGrade = self.GetFuncGrade("UpdatePlayerIDAndSavePlayerMapServerDataEx_1_tagRoleItem")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_RoleItem, DataServerPlayerData.tagRoleItem, saveData[pos:], True)
+#        oFuncGrade.End()
+#        
+#        oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerMapServerDataEx_1_tagRoleMission")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_RoleMission, DataServerPlayerData.tagRoleMission, saveData[pos:])
+#        oFuncGrade.End()
+#        
+#        oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerMapServerDataEx_1_tagRoleMissionDict")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_RoleMissionDict, DataServerPlayerData.tagRoleMissionDict, saveData[pos:])
+#        oFuncGrade.End()
+#        
+#        oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerMapServerDataEx_1_tagRoleSkill")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_RoleSkill, DataServerPlayerData.tagRoleSkill, saveData[pos:])
+#        oFuncGrade.End()
+#        
+#        oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerMapServerDataEx_1_tagRoleBuff")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_RoleBuff, DataServerPlayerData.tagRoleBuff, saveData[pos:])
+#        oFuncGrade.End()
+#        
+#        oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerMapServerDataEx_1_tagRoleRepeatTime")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_RoleRepeatTime, DataServerPlayerData.tagRoleRepeatTime, saveData[pos:])
+#        oFuncGrade.End()
+#        
+#        oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerMapServerDataEx_1_tagPlayerHorseTable")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_PlayerHorseTable, DataServerPlayerData.tagPlayerHorseTable, saveData[pos:])
+#        oFuncGrade.End()
+#        
+#        #跳过gmOperCheck数据      
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_GMOper, DataServerPlayerData.tagGMOper, saveData[pos:])
+#        #跳过GM IP表
+#        gmIPCnt, pos = CommFunc.ReadDWORD(saveData, pos)
+#        gmIPRec = DataServerPlayerData.tagDBGMIP()
+#        for i in xrange(gmIPCnt):
+#            pos += gmIPRec.readData(saveData, pos, len(saveData))
+#            
+#        oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerMapServerDataEx_1_tagRolePet")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_RolePet, DataServerPlayerData.tagRolePet, saveData[pos:])
+#        oFuncGrade.End()
+#        
+#        oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerMapServerDataEx_1_tagPetSkill")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_PetSkill, DataServerPlayerData.tagPetSkill, saveData[pos:])
+#        oFuncGrade.End()
+#        
+#        oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerMapServerDataEx_1_tagRoleNomalDict")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_RoleNomalDict, DataServerPlayerData.tagRoleNomalDict, saveData[pos:])
+#        oFuncGrade.End()
+#        
+#        oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerMapServerDataEx_1_tagPlayerDienstgrad")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_PlayerDienstgrad, DataServerPlayerData.tagPlayerDienstgrad, saveData[pos:])
+#        oFuncGrade.End()
+#        
+#        
+#        oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerMapServerDataEx_1_tagBattleFormation")
+#        oFuncGrade.Start()
+#        pos += self.updatePlayerIDAndSavePlayerDataEx(newPlayerID, db, UCN_BattleFormation, DataServerPlayerData.tagBattleFormation, saveData[pos:])
+#        oFuncGrade.End()
+#        
+#        assert pos == len(saveData)
+#        return (True, newPlayerID)
+#
+#    def updatePlayerIDAndSavePlayerDataEx(self, newPlayerID, db, collectionName, structName, data, checkSID = False):
+#        '''保存玩家物品等数据,优化版'''
+#        oAllFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerDataEx_%s_All"%structName)
+#        oAllFuncGrade.Start()
+#        collection = db[collectionName]
+#        
+#        collection.remove({'PlayerID':newPlayerID})
+#        
+#        #插入新数据
+#        pos = 0
+#        cnt, pos = CommFunc.ReadDWORD(data, pos)
+#        mylog.debug('updatePlayerIDAndSavePlayerDataEx %s data, playerID = %s, cnt = %s'%(structName, newPlayerID, cnt))
+#        rec = structName()
+#        length = len(data)
+#        #这里将数据打成一个字典,即数据库的一条记录存储,这样会比下面那种方式快
+#        doc = {}
+#        if cnt:
+#            doc['PlayerID'] = newPlayerID
+#            doc['Count'] = cnt
+#            doc['__PackSave'] = 1
+#            
+#        for i in xrange(cnt):
+#            oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerDataEx_%s_clear"%structName)
+#            oFuncGrade.Start()
+#            rec.clear()
+#            oFuncGrade.End()
+#            
+#            oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerDataEx_%s_readData"%structName)
+#            oFuncGrade.Start()
+#            readLen = rec.readData(data, pos, length)
+#            oFuncGrade.End()
+#            if readLen == -1:
+#                mylog.warning('%s'%b2a_hex(data))
+#                return 0
+#            pos += readLen
+#            
+#            #更新PlayerID
+#            orgPlayerID = 0
+#            if CommFuncEx.hasField(rec, 'PlayerID'):
+#                orgPlayerID = rec.PlayerID
+#                rec.PlayerID = newPlayerID
+#                #mylog.info('update %s.PlayerID %s->%s'%(rec.__class__.__name__, orgPlayerID, newPlayerID))
+#            #更新PetID字段
+#            if CommFuncEx.hasField(rec, 'PetID'):
+#                if orgPlayerID:
+#                    oldPetID = rec.PetID
+#                    petIndex = rec.PetID % orgPlayerID - 1
+#                    rec.PetID = CommonDefine.makePetID(newPlayerID, petIndex)
+#                    #mylog.info('update %s.PetID %s[%s]->%s[%s]'%(rec.__class__.__name__, oldPetID, orgPlayerID,
+#                    #                                             rec.PetID, newPlayerID))
+#            #更新TruckID字段
+#            if CommFuncEx.hasField(rec, 'TruckID'):
+#                rec.TructID = CommonDefine.makeTruckID(newPlayerID)
+#                #mylog.info('update %s.TructID %s[%s]'%(rec.__class__.__name__, rec.TructID, newPlayerID))
+#                
+#            #更新OwnerID字段
+#            if CommFuncEx.hasField(rec, 'OwnerID'):
+#                if orgPlayerID:
+#                    oldOwnerID = rec.OwnerID
+#                    if orgPlayerID != rec.OwnerID:
+#                        #是宠物ID,重新计算
+#                        petIndex = rec.OwnerID % orgPlayerID - 1
+#                        rec.OwnerID = CommonDefine.makePetID(newPlayerID, petIndex)
+#                    else:
+#                        rec.OwnerID = newPlayerID
+#                    #mylog.info('update %s.OwnerID %s[%s]->%s[%s]'%(rec.__class__.__name__, oldOwnerID, orgPlayerID, rec.OwnerID, newPlayerID))
+#                
+#            if checkSID:
+#                oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerDataEx_%s_makeSID"%structName)
+#                oFuncGrade.Start()
+#                rec.makeSID()
+#                oFuncGrade.End()
+#            #序号做KEY
+#            doc['%s'%(i+1)] = rec.getRecord()
+#            
+#        if doc:
+#            trycnt = 0
+#            while True:
+#                try:
+#                    oFuncGrade = self.GetFuncGrade("updatePlayerIDAndSavePlayerDataEx_%s_insert"%structName)
+#                    oFuncGrade.Start()
+#                    collection.insert(doc, False, True)
+#                    oFuncGrade.End()
+#                    break
+#                except pymongo.errors.OperationFailure, err:
+#                    if(DBConfig.TryCntOnWriteFail > trycnt):
+#                        trycnt += 1
+#                        continue
+#                    addADOExceptionCount()
+#                    mylog.info("docs = %s"%(doc))
+#                    mylog.error('Insert failed!docs = %s, error = %s, trycnt = %d'%(doc, err, trycnt))
+#                    break
+#        oAllFuncGrade.End()
+#        return pos
+    
+    def OnFinishRecharge(self, db, pack):
+        # map完成兑换,假设此处没有回复,则此单变成丢单,暂由人工维护
+        # 若真频繁发生则改为上线恢复
+        try:
+            buf = pack.getBuffer()
+            packLen = pack.getLength()
+            recvPack = RecvPackProtocol.tagMDFinishRecharge()
+            pos = 0
+            recvPack.ReadData(buf, pos)
+            orderID = recvPack.OrderID.strip(chr(0))
+            mylog.debug('OnFinishRecharge ...%s'%orderID)
+        
+            col = db[UCN_PayInfo]
+            result = col.find({"OrderID":orderID})
+            
+            if not result or result.count() == 0:
+                # 没有充值订单
+                return
+            
+            curTime = datetime.datetime.today()
+            curTimeStr = str(curTime)
+            curTimeStr = curTimeStr.split(".")[0]
+            col.update({"OrderID":orderID}, {"$set":{"IsProcess":1, 'EndOrderTime':curTimeStr}})
+            
+            mylog.debug('OnFinishRecharge OrderID = %s'%(orderID))
+
+            return
+        except Exception, e:
+            msg = error.formatMsg('error', error.ERROR_NO_170, "OnFinishRecharge error %s!pack = %s"%(e, binascii.b2a_hex(buf)))
+            mylog.error(msg)
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_170, "OnFinishRecharge error!pack = %s"%(binascii.b2a_hex(buf)))
+            mylog.error(msg)
+        return
+    
+    
+    def OnQueryRecharge(self, db, pack):
+        # map查询新的充值订单, 查询充值表
+        try:
+            buf = pack.getBuffer()
+            packLen = pack.getLength()
+            recvPack = RecvPackProtocol.tagMDQueryRecharge()
+            pos = 0
+            recvPack.ReadData(buf, pos)
+            account = recvPack.Account.strip(chr(0))
+            mylog.debug('OnQueryRecharge ...%s'%account)
+        
+            col = db[UCN_PayInfo]
+            result = col.find({'AccID':account, 'IsProcess':0, 'EndOrderTime':0})
+            
+            if not result or result.count() == 0:
+                # 没有充值订单
+                return
+            
+            # 一单一单发
+            # 先设置IsProcess为1兑换中,等回复结果在真正完成订单
+            billInfo = result[0]
+            
+            sendPack = SendPackProtocol.tagDMRechargePush()
+            sendPack.Type = CommonDefine.dgDBToMapServer
+            sendPack.SubType = CommonDefine.gmReChargePush
+            sendPack.OrderID = fix_outgoingText(billInfo['OrderID'])
+            sendPack.OrderIDLen = len(sendPack.OrderID)
+            sendPack.OrderInfo = fix_outgoingText(billInfo['OrderInfo'])
+            sendPack.OrderInfoLen = len(sendPack.OrderInfo)
+            sendPack.Money = int(billInfo['OrderAmount'])
+            
+            col.update({"OrderID":sendPack.OrderID}, {"$set":{"IsProcess":1}})
+            
+            self.sendString(pack, sendPack.GetBuffer())
+            mylog.debug('OnQueryRecharge OrderID = %s'%(sendPack.OrderID))
+            #mylog.debug('send %s'%sendPack.OutputString())
+            return
+        except Exception, e:
+            msg = error.formatMsg('error', error.ERROR_NO_170, "OnQueryRecharge error %s!pack = %s"%(e, binascii.b2a_hex(buf)))
+            mylog.error(msg)
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_170, "OnQueryRecharge error!pack = %s"%(binascii.b2a_hex(buf)))
+            mylog.error(msg)
+        
+        return
+    
+    def OnQueryNewGuyCardState(self, db, pack):
+        try:
+            buf = pack.getBuffer()
+            packLen = pack.getLength()
+            recvPack = RecvPackProtocol.tagMDIsMediaCardUsed()
+            pos = 0
+            recvPack.ReadData(buf, pos)
+            mylog.debug('OnQueryNewGuyCardState cardID = %s...'%recvPack.CardID)
+        
+            sendPack = SendPackProtocol.tagDMIsMediaCardUsed()
+            sendPack.Type = CommonDefine.dgDBToMapServer
+            sendPack.SubType = CommonDefine.gmQueryNewGuyCardState
+            sendPack.CardIDLen = recvPack.CardIDLen
+            sendPack.CardID = recvPack.CardID
+        
+            obj = DataServerPlayerData.tagDBNewGuyCardState()
+            obj.CardIDLen = recvPack.CardIDLen
+            obj.CardID = recvPack.CardID
+            col = db[UCN_DBNewGuyCardState]
+            lastExceptionCnt = getADOExceptionCount()
+            if not obj.adoLoad(col):
+                if lastExceptionCnt == getADOExceptionCount():
+                    #没有这张卡的记录
+                    sendPack.IsUsed = 0
+                    sendPack.UserDataLen = 0
+                    sendPack.UserData = ''
+                    self.sendString(pack, sendPack.GetBuffer())
+                    mylog.debug('OnQueryNewGuyCardState cardID = %s not found!'%recvPack.CardID)
+                    return
+                #出错了,当成使用过,防刷
+                sendPack.IsUsed = 1
+                sendPack.UserDataLen = 0
+                sendPack.UserData = ''
+                self.sendString(pack, sendPack.GetBuffer())
+                mylog.warning('OnQueryNewGuyCardState query error!cardID = %s'%recvPack.CardID)
+                return
+            #已有这张卡,查看具体状态
+            sendPack.IsUsed = obj.IsUsed
+            sendPack.UserDataLen = obj.UserDataLen
+            sendPack.UserData = obj.UserData
+            sendPack.CardType = obj.CardType
+            sendPack.ValidTime = obj.ValidTime
+            self.sendString(pack, sendPack.GetBuffer())
+            mylog.debug('OnQueryNewGuyCardState cardID = %s state:%s'%(recvPack.CardID, obj.outputString()))
+            #mylog.debug('send %s'%sendPack.OutputString())
+            return
+        except Exception, e:
+            msg = error.formatMsg('error', error.ERROR_NO_170, "OnQueryNewGuyCardState error %s!pack = %s"%(e, binascii.b2a_hex(buf)))
+            mylog.error(msg)
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_170, "OnQueryNewGuyCardState error!pack = %s"%(binascii.b2a_hex(buf)))
+            mylog.error(msg)
+        #异常了,当成使用过,防刷
+        sendPack.IsUsed = 1
+        sendPack.UserDataLen = 0
+        sendPack.UserData = ''
+        self.sendString(pack, sendPack.GetBuffer())      
+    
+    def onCheckUpdateNewGuyCardState(self, db, pack):
+        try:
+            buf = pack.getBuffer()
+            packLen = pack.getLength()
+            recvPack = RecvPackProtocol.tagMDCheckUpdateMediaCardState()
+            pos = 0
+            recvPack.ReadData(buf, pos)
+            
+            sendPack = SendPackProtocol.tagDMCheckUpdateMediaCardResult()
+            sendPack.Type = CommonDefine.dgDBToMapServer
+            sendPack.SubType = CommonDefine.gmUpdateNewGuyCardState
+            sendPack.CardIDLen = recvPack.CardIDLen
+            sendPack.CardID = recvPack.CardID
+            
+            mylog.debug('onCheckUpdateNewGuyCardState %s'%recvPack.OutputString())
+            obj = DataServerPlayerData.tagDBNewGuyCardState()
+            obj.CardIDLen = recvPack.CardIDLen
+            obj.CardID = recvPack.CardID
+            obj.IsUsed = recvPack.IsUsed
+            obj.UserDataLen = recvPack.UserDataLen
+            obj.UserData = recvPack.UserData
+            obj.CardType = recvPack.CardType
+            obj.ValidTime = recvPack.ValidTime
+            
+            col = db[UCN_DBNewGuyCardState]
+            if not obj.adoCheckUpdate(col):
+                sendPack.Result = 0
+                self.sendString(pack, sendPack.GetBuffer())
+                mylog.debug('onCheckUpdateNewGuyCardState failed!cardID = %s'%recvPack.CardID)
+                return
+            sendPack.Result = 1
+            self.sendString(pack, sendPack.GetBuffer())
+            mylog.debug('onCheckUpdateNewGuyCardState success!cardID = %s'%recvPack.CardID)  
+        except Exception, e:
+            msg = error.formatMsg('error', error.ERROR_NO_171, "onCheckUpdateNewGuyCardState error %s!pack = %s"%(e, binascii.b2a_hex(buf)))
+            mylog.error(msg)
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_171, "onCheckUpdateNewGuyCardState error!pack = %s"%(binascii.b2a_hex(buf)))
+            mylog.error(msg)
+        #异常
+        sendPack.Result = 0
+        self.sendString(pack, sendPack.GetBuffer())
+    
+    def OnSavePlayerInfo(self, db, pack):
+        '''保存玩家信息'''
+        pos = 0
+  
+        PlayerInfo = RecvPackProtocol.tagGDSavePlayerInfo()
+        pos = PlayerInfo.ReadData( pack.getBuffer(), pos)
+
+        if not PlayerInfo.GeTuiClientID:
+            # 没有个推ID正常是脱机挂发包,不处理
+            return
+        
+        col = db[UCN_DSAccount]
+        PlayerAcc = DataServerPlayerData.tagDSAccount()
+        PlayerAcc.ACCID = PlayerInfo.AccID.lower()
+        if not PlayerAcc.adoLoadC(col):
+            msg = error.formatMsg('error', error.ERROR_NO_57, "load account failed, accid = %s"%PlayerAcc.ACCID)
+            mylog.error(msg)
+            return
+             
+        PlayerAcc.GeTuiClientID = PlayerInfo.GeTuiClientID
+
+        PlayerAcc.adoUpdateC(col)
+
+    def OnPrepareCreateRole(self, db, pack):
+        '''进入创角埋点'''
+        pos = 0
+
+        PlayerInfo = RecvPackProtocol.tagLDPrepareCreateRole()
+        pos = PlayerInfo.ReadData( pack.getBuffer(), pos)
+        
+        PegasusCollectorProxy.EventReport(9001, "OperatorID=%s&Step=%s&AccountID=%s&Flag=1000"%(
+                        CommFunc.GetPlayerPlatform(PlayerInfo.AccID), 2, CommFunc.GetPlatformAccID(PlayerInfo.AccID)))
+        
+    def __ReadPlayerID(self, db, saveData):
+        playerRec = DataServerPlayerData.tagDBPlayer()
+        pos = 0
+        dbPlayerReadLen = playerRec.readData(saveData, pos, len(saveData))
+        if -1 == dbPlayerReadLen:
+            return (False, 0)
+        pos += dbPlayerReadLen
+        playerID = playerRec.PlayerID
+        if playerID == 0:
+            return (False, 0)
+        mylog.info("__ReadPlayerID playerID = %s"%(playerID))
+        return (True, playerID)
+    
+    def onSaveMapServerPlayerDataMergeServer(self, db, pack):
+        '''玩家下线,跨服服务器下线不保存'''
+        pos = 1    #跳过gstUpdate
+        buf = pack.getBuffer()
+        length = pack.getLength()
+        type, pos = CommFunc.ReadBYTE(buf, pos)
+        if type == CommonDefine.gstPlayerDetail:
+            needReturn, pos = CommFunc.ReadBYTE(buf, pos)
+            packCrcPos = pos
+            packCrc, pos = CommFunc.ReadDWORD(buf, pos)
+            serverTypePos = pos
+            serverType, pos = CommFunc.ReadBYTE(buf, pos)
+            if serverType == MMORPGPack.stMin:
+                #其他服务器未发现异常,检查CRC
+                saveData, pos = CommFunc.ReadString(buf, pos, length - pos)
+                calcCrc = CommFunc.ToDWORD(crc32(saveData))
+                if not packCrc == calcCrc:
+                    #CRC校验错误
+                    serverTypeData = chr(MMORPGPack.stData)
+                    buf = buf[:serverTypePos] + serverTypeData+ buf[(serverTypePos + 1):]
+                    self.onSavePlayerDataCRCError(db, pack, buf[packCrcPos:])
+                    return (False, 0)
+                else:
+                    pass    #正常情况
+            else:
+                self.onSavePlayerDataCRCError(db, pack, buf[packCrcPos:])
+                return (False,0)
+            #正常情况跨服服务器下线不保存数据,直接返回成功
+            result, playerID = self.__ReadPlayerID(db, saveData)
+            mylog.info("onSaveMapServerPlayerDataMergeServer result = %s, playerID = %s, sessionID = 0x%X" 
+                       % (result, playerID, pack.getPackHead().sessionID))
+            #回报
+            if needReturn:
+                updateReturn = SendPackProtocol.tagDBUpdateReturn()
+                updateReturn.CallType = CommonDefine.dgUpDate
+                updateReturn.UpdateType = CommonDefine.gstPlayerDetail
+                updateReturn.Result = result
+                updateReturn.PlayerID = playerID
+                self.sendString(pack, updateReturn.GetBuffer())
+            return (result, playerID)
+    
+    def onSaveMapServerPlayerData(self, db, pack):
+        '''玩家下线,保存玩家在MapServer的数据'''
+        pos = 1    #跳过gstUpdate
+        buf = pack.getBuffer()
+        length = pack.getLength()
+        type, pos = CommFunc.ReadBYTE(buf, pos)
+        if type == CommonDefine.gstPlayerDetail:
+            needReturn, pos = CommFunc.ReadBYTE(buf, pos)
+            packCrcPos = pos
+            packCrc, pos = CommFunc.ReadDWORD(buf, pos)
+            serverTypePos = pos
+            serverType, pos = CommFunc.ReadBYTE(buf, pos)
+            if serverType == MMORPGPack.stMin:
+                #其他服务器未发现异常,检查CRC
+                saveData, pos = CommFunc.ReadString(buf, pos, length - pos)
+                calcCrc = CommFunc.ToDWORD(crc32(saveData))
+                if not packCrc == calcCrc:
+                    #CRC校验错误
+                    serverTypeData = chr(MMORPGPack.stData)
+                    buf = buf[:serverTypePos] + serverTypeData+ buf[(serverTypePos + 1):]
+                    self.onSavePlayerDataCRCError(db, pack, buf[packCrcPos:])
+                    return (False, 0)
+                else:
+                    pass    #正常情况
+            else:
+                self.onSavePlayerDataCRCError(db, pack, buf[packCrcPos:])
+                return (False,0)
+            #正常情况
+            #保存数据
+            result = False
+            playerID = 0
+            if DBConfig.PackSave:
+                result, playerID, accID = self.SavePlayerMapServerDataEx(db, saveData)
+            else:
+                result, playerID, accID = self.SavePlayerMapServerData(db, saveData)
+            if not result:
+                #保存失败
+                sessionID = pack.getPackHead().sessionID
+                msg = error.formatMsg('error', error.ERROR_NO_59, 'Player save data failed!sessionID = %s'%sessionID)
+                mylog.error(msg)
+                
+                DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\SaveFailDump', '%s.mdat'%sessionID, buf[pos:])      
+#                self.sendString(pack, updateReturn.GetBuffer())
+#                return
+            mylog.info("onSaveMapServerPlayerData result = %s, playerID = %s, sessionID = 0x%X"%(result, playerID, pack.getPackHead().sessionID))
+            #回报
+            if needReturn:
+                updateReturn = SendPackProtocol.tagDBUpdateReturn()
+                updateReturn.CallType = CommonDefine.dgUpDate
+                updateReturn.UpdateType = CommonDefine.gstPlayerDetail
+                updateReturn.Result = result
+                updateReturn.PlayerID = playerID
+                self.sendString(pack, updateReturn.GetBuffer())
+                
+            # 玩家下线恢复充值兑换中的订单,IsProcee为1,但endtime为空的情况
+            self.RevoverBillProcess(db, accID)
+            return (result, playerID)
+    
+    # 玩家下线恢复充值兑换中的订单,IsProcee为1,但endtime为空的情况
+    def RevoverBillProcess(self, db, accID):
+        try:
+            if not accID:
+                return
+            account = accID.strip(chr(0))
+            col = db[UCN_PayInfo]
+            result = col.find({'AccID':account, 'IsProcess':1, 'EndOrderTime':0})
+            
+            if not result or result.count() == 0:
+                # 没有充值订单
+                return
+            
+            # 一单一单 恢复
+            billInfo = result[0]
+            orderID = billInfo['OrderID']
+            col.update({"OrderID":orderID}, {"$set":{"IsProcess":0}})
+
+            mylog.debug('RevoverBillProcess success...%s'%orderID)
+        except:
+            maylog.error("RevoverBillProcess error %s"%orderID)
+    
+    def SavePlayerMapServerData(self, db, saveData):
+        playerRec = DataServerPlayerData.tagDBPlayer()
+        pos = 0
+        dbPlayerReadLen = playerRec.readData(saveData, pos, len(saveData))
+        if -1 == dbPlayerReadLen:
+            #数据异常,长度不足
+#            mylog.error('Player save data error:len = %s sessionID = %s'%len(saveData, sessionID))
+#            DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\Player_save', '%s.mdat'%sessionID, saveData)
+            return (False, 0, '')
+        pos += dbPlayerReadLen 
+        mylog.info('Saving player data,playerID = %s....'%playerRec.PlayerID)
+        if playerRec.PlayerID == 0:
+#            mylog.error('playerID = %s'%playerRec.PlayerID)
+            return (False, 0, '')
+        #AccID转小写
+        playerRec.AccID = playerRec.AccID.lower()
+        collection = db[UCN_DBPlayer]
+        
+        oFuncGrade = self.GetFuncGrade("gstSaveMapServerCrashData_1_tagDBPlayer")
+        oFuncGrade.Start()
+        if not playerRec.adoUpdateC(collection):
+#            DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\Player_save', '%s.mdat'%sessionID, saveData)
+#            mylog.error('player save error:playerID = %s'%playerRec.PlayerID)
+            return (False, playerRec.PlayerID, '')
+        oFuncGrade.End()
+        #记录下线日志流向
+        self.recPlayerLogoff(playerRec)
+        #保存物品等其他数据
+        #不再支持单表模式
+        #不再支持文件模式
+        #保存物品
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagRoleItem")
+        oFuncGrade.Start()
+        #对比测试用
+#        if DBConfig.PackSave:
+#            pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleItem, DataServerPlayerData.tagRoleItem, saveData[pos:], True)
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_RoleItem, DataServerPlayerData.tagRoleItem, saveData[pos:], True)
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagRoleMission")
+        oFuncGrade.Start()
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_RoleMission, DataServerPlayerData.tagRoleMission, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagRoleMissionDict")
+        oFuncGrade.Start()
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_RoleMissionDict, DataServerPlayerData.tagRoleMissionDict, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagRoleSkill")
+        oFuncGrade.Start()
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_RoleSkill, DataServerPlayerData.tagRoleSkill, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagRoleBuff")
+        oFuncGrade.Start()
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_RoleBuff, DataServerPlayerData.tagRoleBuff, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagRoleRepeatTime")
+        oFuncGrade.Start()
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_RoleRepeatTime, DataServerPlayerData.tagRoleRepeatTime, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagPlayerHorseTable")
+        oFuncGrade.Start()
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_PlayerHorseTable, DataServerPlayerData.tagPlayerHorseTable, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_gmOperCheck")
+        oFuncGrade.Start()
+        #封号检查
+        self.gmOperCheck(playerRec.AccID, playerRec.PlayerID, saveData[pos:])
+        oFuncGrade.End()
+        
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_GMOper, DataServerPlayerData.tagGMOper, saveData[pos:])
+        #跳过GM IP表
+        gmIPCnt, pos = CommFunc.ReadDWORD(saveData, pos)
+        gmIPRec = DataServerPlayerData.tagDBGMIP()
+        for i in xrange(gmIPCnt):
+            #gmIPRec.clear()
+            pos += gmIPRec.readData(saveData, pos, len(saveData))
+            
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagRolePet")
+        oFuncGrade.Start()
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_RolePet, DataServerPlayerData.tagRolePet, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagPetSkill")
+        oFuncGrade.Start()
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_PetSkill, DataServerPlayerData.tagPetSkill, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagRoleNomalDict")
+        oFuncGrade.Start()
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_RoleNomalDict, DataServerPlayerData.tagRoleNomalDict, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagPlayerDienstgrad")
+        oFuncGrade.Start()
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_PlayerDienstgrad, DataServerPlayerData.tagPlayerDienstgrad, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerData_1_tagBattleFormation")
+        oFuncGrade.Start()
+        pos += self.savePlayerData(playerRec.PlayerID, db, UCN_BattleFormation, DataServerPlayerData.tagBattleFormation, saveData[pos:])
+        oFuncGrade.End()
+        
+        assert pos == len(saveData)
+        return (True, playerRec.PlayerID, playerRec.AccID)
+                
+    def SavePlayerMapServerDataEx(self, db, saveData):
+        playerRec = DataServerPlayerData.tagDBPlayer()
+        pos = 0
+        dbPlayerReadLen = playerRec.readData(saveData, pos, len(saveData))
+        if -1 == dbPlayerReadLen:
+            #数据异常,长度不足
+#            mylog.error('Player save data error:len = %s sessionID = %s'%len(saveData, sessionID))
+#            DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\Player_save', '%s.mdat'%sessionID, saveData)
+            return (False, 0, '')
+        pos += dbPlayerReadLen 
+        mylog.info('Saving player data,playerID = %s....'%playerRec.PlayerID)
+        if playerRec.PlayerID == 0:
+#            mylog.error('playerID = %s'%playerRec.PlayerID)
+            return (False, 0, '')
+        #AccID转小写
+        playerRec.AccID = playerRec.AccID.lower()
+        collection = db[UCN_DBPlayer]
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagDBPlayer")
+        oFuncGrade.Start()
+        if not playerRec.adoUpdateC(collection):
+#            DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\Player_save', '%s.mdat'%sessionID, saveData)
+#            mylog.error('player save error:playerID = %s'%playerRec.PlayerID)
+            return (False, playerRec.PlayerID, '')
+        oFuncGrade.End()
+        #记录下线日志流向
+        if playerRec.FacePic == 0:  # 约定为下线标识
+            self.recPlayerLogoff(playerRec)
+        #保存物品等其他数据
+        #不再支持单表模式
+        #不再支持文件模式
+        #保存物品
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagRoleItem")
+        oFuncGrade.Start()
+        #对比测试用
+#        if DBConfig.PackSave:
+#            pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleItem, DataServerPlayerData.tagRoleItem, saveData[pos:], True)
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleItem, DataServerPlayerData.tagRoleItem, saveData[pos:], True)
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagRoleMission")
+        oFuncGrade.Start()
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleMission, DataServerPlayerData.tagRoleMission, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagRoleMissionDict")
+        oFuncGrade.Start()
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleMissionDict, DataServerPlayerData.tagRoleMissionDict, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagRoleSkill")
+        oFuncGrade.Start()
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleSkill, DataServerPlayerData.tagRoleSkill, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagRoleBuff")
+        oFuncGrade.Start()
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleBuff, DataServerPlayerData.tagRoleBuff, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagRoleRepeatTime")
+        oFuncGrade.Start()
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleRepeatTime, DataServerPlayerData.tagRoleRepeatTime, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagPlayerHorseTable")
+        oFuncGrade.Start()
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_PlayerHorseTable, DataServerPlayerData.tagPlayerHorseTable, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_gmOperCheck")
+        oFuncGrade.Start()
+        #封号检查
+        self.gmOperCheck(playerRec.AccID, playerRec.PlayerID, saveData[pos:])
+        oFuncGrade.End()
+        
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_GMOper, DataServerPlayerData.tagGMOper, saveData[pos:])
+        #跳过GM IP表
+        gmIPCnt, pos = CommFunc.ReadDWORD(saveData, pos)
+        gmIPRec = DataServerPlayerData.tagDBGMIP()
+        for i in xrange(gmIPCnt):
+            #gmIPRec.clear()
+            pos += gmIPRec.readData(saveData, pos, len(saveData))
+            
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagRolePet")
+        oFuncGrade.Start()
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RolePet, DataServerPlayerData.tagRolePet, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagPetSkill")
+        oFuncGrade.Start()
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_PetSkill, DataServerPlayerData.tagPetSkill, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagRoleNomalDict")
+        oFuncGrade.Start()
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleNomalDict, DataServerPlayerData.tagRoleNomalDict, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagPlayerDienstgrad")
+        oFuncGrade.Start()
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_PlayerDienstgrad, DataServerPlayerData.tagPlayerDienstgrad, saveData[pos:])
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("SavePlayerMapServerDataEx_1_tagBattleFormation")
+        oFuncGrade.Start()
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_BattleFormation, DataServerPlayerData.tagBattleFormation, saveData[pos:])
+        oFuncGrade.End()
+        
+        assert pos == len(saveData)
+        return (True, playerRec.PlayerID, playerRec.AccID)
+    
+    def gmOperCheck(self, accID, playerID, data):
+        pos = 0
+        length = len(data)
+        cnt, pos = CommFunc.ReadDWORD(data, pos)
+        length -= pos
+        gmOperRec = DataServerPlayerData.tagGMOper()
+        for i in xrange(cnt):
+            gmOperRec.clear()
+            readLen = gmOperRec.readData(data, pos, length)
+            pos += readLen
+            length -= readLen
+            
+            if gmOperRec.Oper == CommonDefine.gmForbidAcc:
+                #记录封号日志
+                self.onForbiddenUpdate(accID, playerID, True, CommFuncEx.TDateTime_Now(), (int)(gmOperRec.EndTime - CommFuncEx.TDateTime_Now()), gmOperRec.GMAccID,
+                                       'EndTime = %s.Reason = %s'%(CommFuncEx.TDateTimeToString(gmOperRec.EndTime), gmOperRec.Msg))
+        
+    def savePlayerDataEx(self, playerID, db, collectionName, structName, data, checkSID = False):
+        '''保存玩家物品等数据,优化版'''
+        oAllFuncGrade = self.GetFuncGrade("savePlayerDataEx_%s_All"%structName)
+        oAllFuncGrade.Start()
+        collection = db[collectionName]
+        #删除旧数据
+        oFuncGrade = self.GetFuncGrade("savePlayerDataEx_%s_remove"%structName)
+        oFuncGrade.Start()
+        collection.remove({'PlayerID':playerID})    #这里虽然没有做索引,但是速度很快,忽略
+        oFuncGrade.End()
+        
+        #插入新数据
+        pos = 0
+        cnt, pos = CommFunc.ReadDWORD(data, pos)
+        mylog.debug('saving %s data, playerID = %s, cnt = %s'%(structName, playerID, cnt))
+        rec = structName()
+        length = len(data)
+        #这里将数据打成一个字典,即数据库的一条记录存储,这样会比下面那种方式快
+        doc = {}
+        if cnt:
+            doc['PlayerID'] = playerID
+            doc['Count'] = cnt
+            doc['__PackSave'] = 1
+            
+        for i in xrange(cnt):
+            oFuncGrade = self.GetFuncGrade("savePlayerDataEx_%s_clear"%structName)
+            oFuncGrade.Start()
+            rec.clear()
+            oFuncGrade.End()
+            
+            oFuncGrade = self.GetFuncGrade("savePlayerDataEx_%s_readData"%structName)
+            oFuncGrade.Start()
+            readLen = rec.readData(data, pos, length)
+            oFuncGrade.End()
+            if readLen == -1:
+                mylog.info('%s'%b2a_hex(data))
+                return
+            pos += readLen
+            
+            if checkSID:
+                oFuncGrade = self.GetFuncGrade("savePlayerDataEx_%s_makeSID"%structName)
+                oFuncGrade.Start()
+                rec.makeSID()
+                oFuncGrade.End()
+            #序号做KEY
+            doc['%s'%(i+1)] = rec.getRecord()
+            
+        if doc:
+            trycnt = 0
+            while True:
+                try:
+                    oFuncGrade = self.GetFuncGrade("savePlayerDataEx_%s_insert"%structName)
+                    oFuncGrade.Start()
+                    collection.insert(doc, False, True)
+                    oFuncGrade.End()
+                    break
+                except pymongo.errors.OperationFailure, err:
+                    if(DBConfig.TryCntOnWriteFail > trycnt):
+                        trycnt += 1
+                        continue
+                    addADOExceptionCount()
+                    mylog.info("%s.%s:docs = %s"%(self.__class__.__name__, inspect.stack()[0][3], doc))
+                    mylog.error('Insert failed!docs = %s, error = %s, trycnt = %d'%(doc, err, trycnt))
+                    break
+        oAllFuncGrade.End()
+        return pos 
+            
+    
+    def savePlayerData(self, playerID, db, collectionName, structName, data, checkSID = False):
+        '''保存玩家物品数据'''
+        oAllFuncGrade = self.GetFuncGrade("savePlayerData_%s_All"%structName)
+        oAllFuncGrade.Start()
+        
+        #删除旧数据
+        collection = db[collectionName]
+        oFuncGrade = self.GetFuncGrade("savePlayerData_%s_remove"%structName)
+        oFuncGrade.Start()
+        collection.remove({'PlayerID':playerID})
+        oFuncGrade.End()
+        
+        #插入新数据
+        pos = 0
+        cnt, pos = CommFunc.ReadDWORD(data, pos)
+        mylog.debug('saving %s data for player playerID = %s cnt = %s, data = %s'%(structName, playerID, cnt, data))
+        rec = structName()
+        length = len(data)
+        docs = []
+        for i in xrange(cnt):
+            oFuncGrade = self.GetFuncGrade("savePlayerData_%s_clear"%structName)
+            oFuncGrade.Start()
+            rec.clear()
+            oFuncGrade.End()
+            
+            oFuncGrade = self.GetFuncGrade("savePlayerData_%s_readData"%structName)
+            oFuncGrade.Start()
+            readLen = rec.readData(data, pos, length)
+            oFuncGrade.End()
+            if readLen == -1:
+                mylog.info('%s'%(b2a_hex(data)))
+                return
+            pos += readLen
+#            length -= readLen
+            
+            if checkSID:
+                oFuncGrade = self.GetFuncGrade("savePlayerData_%s_makeSID"%structName)
+                oFuncGrade.Start()
+                rec.makeSID()
+                oFuncGrade.End()
+#                rec.adoInsertC(collection)
+#            else:
+#                rec.adoInsert(collection)
+            oFuncGrade = self.GetFuncGrade("savePlayerData_%s_getRecord"%structName)
+            oFuncGrade.Start()
+            doc = rec.getRecord()
+            oFuncGrade.End()
+            
+            docs.append(doc)
+        if len(docs):
+            trycnt = 0
+            while True:
+                try:
+                    oFuncGrade = self.GetFuncGrade("savePlayerData_%s_insert"%structName)
+                    oFuncGrade.Start()
+                    collection.insert(docs, False, True)
+                    oFuncGrade.End()
+                    break
+                except pymongo.errors.OperationFailure, err:
+                    if(DBConfig.TryCntOnWriteFail > trycnt):
+                        trycnt += 1
+                        continue
+                    addADOExceptionCount()
+                    mylog.info("%s.%s:docs = %s"%(self.__class__.__name__, inspect.stack()[0][3], docs))
+                    mylog.error('Insert failed!docs = %s, error = %s, trycnt = %d'%(docs, err, trycnt))
+                    break
+        oAllFuncGrade.End()
+        return pos
+    
+    def recPlayerLogoff(self, dbPlayer):
+        req = DataServerLogData.tagDBPlayerLogInfoOnLogOff()
+        req.AccID = dbPlayer.AccID
+        req.PlayerName = dbPlayer.PlayerName
+        req.AccState = dbPlayer.AccState
+        req.LV = dbPlayer.LV
+        req.Gold = dbPlayer.Gold
+        req.GoldPaper = dbPlayer.GoldPaper
+        req.Silver = dbPlayer.Silver
+        req.SilverPaper = dbPlayer.SilverPaper
+        req.GMLevel = dbPlayer.GMLevel
+        req.Job = dbPlayer.Job
+        req.TJGTime = dbPlayer.HappyPoint   # 脱机挂时间
+        req.TJGState = dbPlayer.State       # 0正常登录,1脱机登录,2脱机登录死亡
+        req.LastLogoffTime = time()
+        req.PlayerID = dbPlayer.PlayerID
+        req.IsOnline = 0    #默认0因关服时没收到loginserver全部下线包
+        sendBuf = ''
+        sendBuf = CommFunc.WriteBYTE(sendBuf, CommonDefine.gstSavePlayerInfoLogOnLogOff)
+        sendBuf = CommFunc.WriteString(sendBuf, req.getLength(), req.getBuffer())
+        self.sendDBRequest(sendBuf)
+        
+    
+    def onSavePlayerDataCRCError(self, db, pack, saveDataWithCRC):
+        #dump 数据
+        dumpFileName = str(uuid.uuid4())    #random uuid
+        msg = error.formatMsg('error', error.ERROR_NO_60, 'sessionID = 0x%x dump to file %s'%(pack.getPackHead().sessionID, dumpFileName))
+        mylog.error(msg)
+        DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs', dumpFileName, saveDataWithCRC)
+        
+        playerRec = DataServerPlayerData.tagDBPlayer()
+        pos = 5    #跳过CRC,ServerType
+        length = len(saveDataWithCRC)
+        if -1 == playerRec.readData(saveDataWithCRC, pos, length):
+            #数据长度不足,无法处理
+            pass
+        else:
+            #封号
+            if self.updatePlayerAccState(db, playerRec.PlayerID, CommonDefine.pysForbidden):
+                #封号成功,记录封号日志
+                self.sendAccForbiddenLogReq(playerRec.AccID, 1)
+        #回报保存失败
+        updateReturn = SendPackProtocol.tagDBUpdateReturn()
+        updateReturn.CallType = CommonDefine.dgUpDate
+        updateReturn.UpdateType = CommonDefine.gstPlayerDetail
+        updateReturn.Result = 0
+        self.sendString(pack, updateReturn.GetBuffer())
+    
+    def sendAccForbiddenLogReq(self, accid, isForbidden):
+        accForbiddenLogReq = DataServerLogData.tagDBPlayerInfoLogForbidden()
+        accForbiddenLogReq.AccID = accid
+        accForbiddenLogReq.IsForbidden = isForbidden
+        accForbiddenLogReq.ForbiddenTime = time()
+        accForbiddenLogReqPackBuf = ''
+        accForbiddenLogReqPackBuf = CommFunc.WriteBYTE(accForbiddenLogReqPackBuf, CommonDefine.gstSavePlayerInfoLogOnForbidden)
+        accForbiddenLogReqPackBuf = CommFunc.WriteString(accForbiddenLogReqPackBuf, accForbiddenLogReq.getLength(), accForbiddenLogReq.getBuffer())
+        self.sendDBRequest(accForbiddenLogReqPackBuf)
+    
+    def updatePlayerAccState(self, db, playerID, newState):
+        '''封号'''
+        collection = db[UCN_DBPlayer]
+        
+        doc = DataServerPlayerData.tagDBPlayer()
+        doc.PlayerID = playerID
+        lastSIDErrorCnt = getSIDErrorCnt()
+        ret = doc.adoLoadC(collection)
+        if not ret:
+            if not (lastSIDErrorCnt == getSIDErrorCnt()):
+                #SID错误
+                mylog.warning('%s.%s SID error found on reading data of playerID = %s!'%(self.__class__.__name__, inspect.stack()[0][3], playerID))
+                return False
+            #无此角色
+            mylog.debug('%s.%s playerID = %s not found!'%(self.__class__.__name__, inspect.stack()[0][3], playerID))
+            return False
+        doc.AccState = newState
+        if not doc.adoUpdateC(collection):
+            return False
+        return True
+    
+    def onSaveGameServerPlayerSaveData(self, db, pack):
+        '''玩家下线,保存玩家在GameServer的数据'''
+        saveGameServerPlayerDataReq = RecvPackProtocol.tagGameServerToBalanceServerPlayerSaveData()
+        saveGameServerPlayerDataReq.ReadData(pack.getBuffer(), 0, pack.getLength())
+        
+        #mylog.debug(saveGameServerPlayerDataReq.OutputString())
+        
+        #playerDataReadPos = 0
+        #playerDataReadPos = self.saveGameServerPlayerData(saveGameServerPlayerDataReq.PlayerID, saveGameServerPlayerDataReq.Data, playerDataReadPos, 'tagPlayerEnemy', DataServerPlayerData.tagPlayerEnemy, db)
+        #playerDataReadPos = self.saveGameServerPlayerData(saveGameServerPlayerDataReq.PlayerID, saveGameServerPlayerDataReq.Data, playerDataReadPos, 'tagPlayerFriend', DataServerPlayerData.tagPlayerFriend, db)       
+        if saveGameServerPlayerDataReq.NeedReturn == 2:
+            #下线触发
+            #伪装成LoginServer发送过来的,这样会回包给LoginServer
+            pack.setSrcSvrType(MMORPGPack.stLogin)
+            self.sendOKString(CommonDefine.dgPlayerSaveGameServerData, pack, '')
+            return
+    
+    def onGetGameServerPlayerLoginData(self, db, pack):
+        # 改成PY处理
+        return
+       #========================================================================
+       # '''GameServer读取玩家登录数据'''
+       # getGameServerPlayerLoginDataPack = RecvPackProtocol.tagGBGetGameServerPlayerLoginData()
+       # getGameServerPlayerLoginDataPack.ReadData(pack.getBuffer(), 0, pack.getLength())
+       # 
+       # playerEnemyRec = DataServerPlayerData.tagPlayerEnemy()
+       # playerEnemyRec.PlayerID = getGameServerPlayerLoginDataPack.PlayerID
+       # collection = db[UCN_PlayerEnemy]
+       # playerEnemyData = playerEnemyRec.adoQueryIndex(collection)
+       # 
+       # playerFriendRec = DataServerPlayerData.tagPlayerFriend()
+       # playerFriendRec.PlayerID = getGameServerPlayerLoginDataPack.PlayerID
+       # collection = db[UCN_PlayerFriend]
+       # playerFriendData = playerFriendRec.adoQueryIndex(collection)
+       # 
+       # allData = playerEnemyData + playerFriendData
+       # self.sendGameServerString(pack, CommonDefine.dgPlayerGameServerLoginData, allData)
+       # mylog.debug('send game server player login data ok!')
+       # 
+       #========================================================================
+        
+    def onCreateRoleServerCheckIsHaveRole(self, db, pack):
+        try:   
+            recvPack = RecvPackProtocol.tagCSIsHaveRole()
+            recvPack.ReadData(pack.getBuffer())   
+            
+            sendPack = SendPackProtocol.tagDRequestResult()
+            sendPack.Type = CommonDefine.gstCreateRoleServerCheckIsHaveRole 
+            sendPack.AccID = recvPack.AccID         
+            
+            Player = DataServerPlayerData.tagDBPlayer()
+            Player.AccID = recvPack.AccID.lower() #帐号统一转小写
+            Player.IsDeleted = 0
+            collection = db[UCN_DBPlayer] 
+            
+            lastExceptionCnt = getADOExceptionCount()
+            lastSIDErrorCnt = getSIDErrorCnt()
+            
+            #检查该帐号是否已有有效角色
+            if Player.adoLoadCEx(collection, {'AccID':fix_incomingText(Player.AccID), 'IsDeleted':Player.IsDeleted}):
+                mylog.info('player of accid = %s exists!'%Player.AccID)
+                sendPack.Result = 1
+                sendPack.ExAttr = 1 
+            else: #disCreatePlayerError_PlayerExist
+                if not lastExceptionCnt == getADOExceptionCount():
+                    #数据库读取出错,但不一定是User库读取出错
+                    sendPack.Result = 0
+                    sendPack.ExAttr = disDataBaseError 
+                elif not lastSIDErrorCnt == getSIDErrorCnt():
+                    if DBConfig.checkSID:  
+                        sendPack.Result = 0
+                        sendPack.ExAttr = disAccStateError
+                    else:
+                        sendPack.Result = 1
+                        sendPack.ExAttr = 1
+                else:
+                    sendPack.Result = 1 
+                    sendPack.ExAttr = 0
+                                            
+            self.sendString(pack, sendPack.GetBuffer())
+            mylog.debug('onCreateRoleServerCheckIsHaveRole ok, Accid = %s!'%recvPack.AccID)  
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_62, "Catch a unexpetcted exception, error = %s"%traceback.format_exc())
+            mylog.error(msg)             
+
+    def onCreateRoleServerCheckPlayerExist(self, db, pack):
+        try:   
+            recvPack = RecvPackProtocol.tagCSCheckPlayerNameExist()
+            recvPack.ReadData(pack.getBuffer())   
+            
+            sendPack = SendPackProtocol.tagDRequestResult()
+            sendPack.Type = CommonDefine.gstCreateRoleServerCheckPlayerExist 
+            sendPack.AccID = recvPack.AccID         
+            sendPack.Result = 1
+            
+            if self.hasPlayerByPlayerName(db, recvPack.PlayerName):
+                sendPack.ExAttr = 1 
+            else:
+                sendPack.ExAttr = 0
+                                            
+            self.sendString(pack, sendPack.GetBuffer())
+            mylog.debug('onCreateRoleServerCheckPlayerExist ok, Accid = %s!'%recvPack.AccID)  
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_63, "Catch a unexpetcted exception, error = %s"%traceback.format_exc())
+            mylog.error(msg)          
+        
+        
+    def onCreatePlayer(self, db, pack):
+        #伪装成LoginServer发送过来的
+        pack.setSrcSvrType(MMORPGPack.stLogin)       
+        
+        Suc, disCode, AccId, data = self.CreateRole(db, pack)
+        if Suc:
+            self.sendOKString(CommonDefine.dgCreatePlayer, pack, data)
+            mylog.debug('send created player info for accid = %s'%AccId)  
+            
+        else:
+            self.sendFailString(CommonDefine.dgCreatePlayer, pack, disCode)
+              
+    def onCreateRoleServerRequestCreateRole(self, db, pack):
+        try:      
+            Suc, disCode, AccId, data = self.CreateRole(db, pack)
+            sendPack = SendPackProtocol.tagDRequestResult()
+            sendPack.Type = CommonDefine.gstCreateRoleServerRequestCreateRole
+            sendPack.Result = Suc
+            sendPack.AccID = AccId
+            if Suc:
+                sendPack.ExAttr = 0  
+            else:
+                sendPack.ExAttr = disCode  
+            mylog.debug('send created player info for accid = %s'%AccId) 
+            self.sendString(pack, sendPack.GetBuffer()) 
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_64, "Catch a unexpetcted exception, error = %s"%traceback.format_exc())
+            mylog.error(msg)              
+     
+    
+    
+    
+    #检查已分配ID表中剩余ID数量
+    def CheckEmptyPlayerIDCount(self, db):
+        mylog.debug("CheckEmptyPlayerIDCount start")
+        collection = db[UCN_Dispatch_PlayerID] 
+        result = collection.find()
+        print result
+        if not result:
+            if self.isDispatchingPlayerID:
+                try_count = 0
+                #此处等待必要性不高,主(单)线程只有当缓存区用完,并且新线程请求过
+                while try_count < 3 and self.isDispatchingPlayerID:
+                    if not self.isDispatchingPlayerID:
+                        return True
+                    sleep(1)
+                    try_count+=1
+                return False
+            
+            CallDispatchPlayerID(db, self)
+            return True
+        emptyCnt = result.count()
+        
+        #数量足够无需分配
+        if emptyCnt > DBConfig.IDDispatchPlayeIDLimit:
+            return True
+        
+        if emptyCnt <= 0:
+            if self.isDispatchingPlayerID:
+                try_count = 0
+                #等待3秒
+                while try_count < 3 and self.isDispatchingPlayerID:
+                    if not self.isDispatchingPlayerID:
+                        return True
+                    sleep(1)
+                    try_count+=1
+                return False
+            CallDispatchPlayerID(db, self)
+            return True
+        
+        #开始使用缓冲数据开一个新线程请求分配新ID池
+        if self.isDispatchingPlayerID:
+            return True
+        
+        import threading
+        t = threading.Thread(target = CallDispatchPlayerID, args =(db, self))
+        t.start()
+        
+        return True
+    
+    #从已分配ID表中取出一个空ID给玩家
+    def PopEmptyPlayerID(self, db):
+        collection = db[UCN_Dispatch_PlayerID] 
+        rec = collection.find_one()
+        if rec:
+            newID = rec['PlayerID']
+            collection.remove(rec)
+            return newID
+        return -1
+    
+    #生成playerID
+    def DispatchNewPlayerID(self, db):
+        
+        UseIDDispatchServer = DBConfig.UseIDDispatchServer
+        if not UseIDDispatchServer:
+            #旧ID生成规则,PLAYERID_FEED表自增
+            return seq(db, UCN_DBPlayer, 'PlayerID', DBConfig.PLAYERID_FEED, DBConfig.PLAYERID_STEP) 
+        #新生成规则 从专门的ID分配服务器获取
+        import thread
+        self.CheckEmptyPlayerIDCount(db)
+        print "CheckEmptyPlayerIDCount OK"
+        return self.PopEmptyPlayerID(db)
+        
+    def CreateRole(self, db, pack):
+        createPlayer = DataServerPlayerData.tagDBPlayer()
+        createPlayer.readData(pack.getBuffer(), 1, pack.getLength() - 1)    #跳过requestType
+        createPlayer.IsDeleted = 0
+        #帐号统一转小写
+        createPlayer.AccID = createPlayer.AccID.lower()
+        collection = db[UCN_DBPlayer] 
+        #检查该帐号是否已有有效角色
+        if createPlayer.adoLoadCEx(collection, {'AccID':fix_incomingText(createPlayer.AccID), 'IsDeleted':createPlayer.IsDeleted}):
+            mylog.warning('player of accid = %s exists!'%createPlayer.AccID)
+            return 0, disCreatePlayerError_PlayerExist, createPlayer.AccID, '' 
+
+        #检查角色名是否重复
+        if self.hasPlayerByPlayerName(db, createPlayer.PlayerName):
+            mylog.warning('player of playerName = %s exists!'%createPlayer.PlayerName)
+            return 0, disCreatePlayerError_PlayerNameConflict, createPlayer.AccID, '' 
+        #记录创建时间
+        createPlayer.CreateRoleTime = CommFuncEx.TDateTimeToString(CommFuncEx.TDateTime_Now()) 
+        #生成自增长的playerID
+        #createPlayer.PlayerID = seq(db, UCN_DBPlayer, 'PlayerID', DBConfig.PLAYERID_FEED, DBConfig.PLAYERID_STEP)
+        newPlayerID = self.DispatchNewPlayerID(db)
+        if newPlayerID == -1:
+            #ID分配失败
+            msg = error.formatMsg('error', error.ERROR_NO_65, 'PlayerID Dispatch failed!accid = %s'%createPlayer.AccID)
+            mylog.error(msg)
+            return 0, disDataBaseError, createPlayer.AccID, '' 
+        createPlayer.PlayerID = newPlayerID
+        #校验通过,往数据库中插入角色
+        mylog.debug('Before insert role!accid = %s, PlayerName = %s'%(createPlayer.AccID, createPlayer.PlayerName))       
+        if not createPlayer.adoInsertC(collection):
+            msg = error.formatMsg('error', error.ERROR_NO_65, 'insert player failed!accid = %s'%createPlayer.AccID)
+            mylog.error(msg)
+            return 0, disDataBaseError, createPlayer.AccID, '' 
+
+        #插入角色成功
+        #读取角色ID
+        if not createPlayer.adoLoad(collection):
+            msg = error.formatMsg('error', error.ERROR_NO_66, 'insert player failed!accid = %s'%createPlayer.AccID)
+            mylog.error(msg)
+            return 0, disDataBaseError, createPlayer.AccID, '' 
+
+        mylog.debug('insert role ok!accid = %s, PlayerName = %s'%(createPlayer.AccID, createPlayer.PlayerName))
+        #构造其他角色初始数据
+        itemData = ''
+        itemData = CommFunc.WriteDWORD(itemData, 0)
+        missionData = itemData
+        missionDictData = itemData
+        skillData = itemData
+        bufData = itemData
+        repeatTimeData = itemData
+        horseData = itemData
+        gmOperData = itemData
+        gmPermitData = itemData
+        petData = itemData
+        petSkillData = itemData
+        normalDictData = itemData
+        dienstgradData = itemData
+        battleFormationData = itemData
+        allData = createPlayer.getBuffer() + itemData + missionData + missionDictData + skillData + bufData + repeatTimeData + horseData\
+                  + gmOperData + gmPermitData + petData + petSkillData + normalDictData + dienstgradData+battleFormationData
+        #计算CRC
+        crc = crc32(allData)
+        dataCrc = ''
+        dataCrc = CommFunc.WriteDWORD(dataCrc, crc)
+        dataCrc = CommFunc.WriteBYTE(dataCrc, 0)    #ServerType
+        dataWithCrc = dataCrc + allData
+        mylog.debug('send created player info for accid = %s'%createPlayer.AccID)
+        result = 1, 0, createPlayer.AccID, dataWithCrc
+        
+        #创角流向
+        dbServerLogRec = RecvPackProtocol.tagDBServerLogRec()
+        dbServerLogRec.Type = CommonDefine.gstSavePlayerLog
+        dbServerLogRec.Oper = 80        #创角流向
+        dbServerLogRec.Time = time()
+        dbServerLogRec.MapID = 1
+        dbServerLogRec.PlayerID = createPlayer.PlayerID
+        dbServerLogRec.Msg = "AccID=%s&Name=%s&Sex=%s&Job=%s"%(createPlayer.AccID, 
+                                                               createPlayer.PlayerName, 
+                                                               createPlayer.Sex, 
+                                                               createPlayer.Job)
+        dbServerLogRec.MsgLen = len(dbServerLogRec.Msg)
+        self.sendDBRequest(dbServerLogRec.GetBuffer())
+        #日志玩家_创建角色更新#tagDBPlayerInfoLogCreateRole
+        createRoleLog = DataServerLogData.tagDBPlayerInfoLogCreateRole()
+        createRoleLog.AccID = createPlayer.AccID
+        createRoleLog.PlayerName = createPlayer.PlayerName
+        createRoleLog.Sex = createPlayer.Sex
+        createRoleLog.Face = createPlayer.Face
+        createRoleLog.PlayerRegisterTime = time()
+        createRoleLog.PlayerID = createPlayer.PlayerID
+        sendBuf = ''
+        sendBuf = CommFunc.WriteBYTE(sendBuf, CommonDefine.gstSavePlayerInfoLogOnCreate)
+        sendBuf = CommFunc.WriteString(sendBuf, createRoleLog.getLength(), createRoleLog.getBuffer())
+        self.sendDBRequest(sendBuf)
+
+        #新玩家导入 - 创角成功步骤事件
+        PegasusCollectorProxy.EventReport(9001, "OperatorID=%s&Step=%s&AccountID=%s&Flag=1000"%(
+                            CommFunc.GetPlayerPlatform(createPlayer.AccID), 3, CommFunc.GetPlatformAccID(createPlayer.AccID)))
+        
+        #UTF8 需要转成url编码才可用
+        playerInfo = urllib.urlencode({"OperatorID": CommFunc.GetPlayerPlatform(createPlayer.AccID),
+                                       "RoleID": createPlayer.PlayerName,
+                                       "AccountID": CommFunc.GetPlatformAccID(createPlayer.AccID),
+                                       "Job": createPlayer.Job}) 
+        
+        PegasusCollectorProxy.EventReport(1103, playerInfo)
+        #=======================================================================
+        # entryEvent = EventReport.entry()
+        # entryEvent.SetEventAgentInfo(CommFunc.GetPlayerPlatform(createPlayer.AccID))
+        # entryEvent.account_id = CommFunc.GetPlatformAccID(createPlayer.AccID)
+        # entryEvent.step = entryEvent.Def_EntryStep_CreatRole
+        # entryEvent.ip = createPlayer.LoginIP
+        # entryEvent.account_name = entryEvent.account_id
+        # EventReport.WriteEvent(entryEvent)
+        #=======================================================================
+        return result        
+                
+    def hasPlayerByPlayerName(self, db, playerName):
+        collection = db[UCN_DBPlayer]
+        #开启BASE64编码后,无法进行大小写不敏感匹配,即大小写不一致的角色名是允许的了
+        resultCollection = collection.find({'PlayerName':fix_incomingText(playerName), 'IsDeleted':0})
+        return (resultCollection.count() != 0)
+
+    def readPlayerPackSaveData(self, col, query, structName, checkSID = False):
+        buf = ''
+        docs = col.find(query).limit(1)
+        if not docs.count():
+            buf = CommFunc.WriteDWORD(buf, docs.count())
+            return buf
+        obj = structName()
+        doc = list(docs)[0]
+        #有数据
+        if doc.has_key('__PackSave'):
+            #以打包方式存储的
+            docCnt = doc['Count']
+            result = ''
+            result = CommFunc.WriteDWORD(result, docCnt)
+            mylog.debug('####reading %s of player %s,cnt = %s'%(structName, query, docCnt))
+            for i in xrange(docCnt):
+                obj.readRecord(doc['%s'%(i+1)])
+                result += obj.getBuffer()
+            return result
+        else:
+            #以非打包方式存储的
+            if checkSID:
+                return obj.adoQueryCustomC(col, query)
+            else:
+                return obj.adoQueryCustom(col, query)
+
+    def getMergePlayerDataBuffer(self, newPlayerID, structName, data, checkSID = False):
+        ''' 获取跨服玩家同步数据缓存buffer '''
+        oAllFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_%s_All"%structName)
+        oAllFuncGrade.Start()
+        
+        pos = 0
+        cnt, pos = CommFunc.ReadDWORD(data, pos)
+        mylog.debug('getMergePlayerDataBuffer %s data, playerID = %s, cnt = %s'%(structName, newPlayerID, cnt))
+        rec = structName()
+        length = len(data)
+
+        result = ''
+        result = CommFunc.WriteDWORD(result, cnt)
+        
+        for i in xrange(cnt):
+            oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_%s_clear"%structName)
+            oFuncGrade.Start()
+            rec.clear()
+            oFuncGrade.End()
+            
+            oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_%s_readData"%structName)
+            oFuncGrade.Start()
+            readLen = rec.readData(data, pos, length)
+            oFuncGrade.End()
+            if readLen == -1:
+                mylog.warning('%s'%b2a_hex(data))
+                return 0, ""
+            pos += readLen
+            
+            #更新PlayerID
+            orgPlayerID = 0
+            if CommFuncEx.hasField(rec, 'PlayerID'):
+                orgPlayerID = rec.PlayerID
+                rec.PlayerID = newPlayerID
+                
+            #更新PetID字段
+            if CommFuncEx.hasField(rec, 'PetID'):
+                if orgPlayerID:
+                    oldPetID = rec.PetID
+                    petIndex = rec.PetID % orgPlayerID - 1
+                    rec.PetID = CommonDefine.makePetID(newPlayerID, petIndex)
+                    
+            #更新TruckID字段
+            if CommFuncEx.hasField(rec, 'TruckID'):
+                rec.TructID = CommonDefine.makeTruckID(newPlayerID)
+                
+            #更新OwnerID字段
+            if CommFuncEx.hasField(rec, 'OwnerID'):
+                if orgPlayerID:
+                    oldOwnerID = rec.OwnerID
+                    if orgPlayerID != rec.OwnerID:
+                        #是宠物ID,重新计算
+                        petIndex = rec.OwnerID % orgPlayerID - 1
+                        rec.OwnerID = CommonDefine.makePetID(newPlayerID, petIndex)
+                    else:
+                        rec.OwnerID = newPlayerID
+                
+            if checkSID:
+                oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_%s_makeSID"%structName)
+                oFuncGrade.Start()
+                rec.makeSID()
+                oFuncGrade.End()
+
+            result += rec.getBuffer()
+            
+        oAllFuncGrade.End()
+        return pos, result
+    
+    def onGetMergePlayerDetail(self, db, pack):
+        ''' 获取跨服玩家详细信息 '''
+        global g_mergeRegisterPlayerDict
+        getPlayerDetailReq = RecvPackProtocol.tagPlayerDetailReq()
+        getPlayerDetailReq.ReadData(pack.getBuffer(), 0, pack.getLength())
+        mylog.debug('getting mergePlayer detail for accid = %s'%getPlayerDetailReq.AccID)
+        queryAccid = getPlayerDetailReq.AccID.lower().strip(chr(0))
+        if queryAccid not in g_mergeRegisterPlayerDict:
+            # 不在跨服缓存中的从库中取
+            return self.onGetPlayerDetail(db, pack)
+        
+        #recvPack = MergeServerRecvProtocol.tagLPRegisterPlayer()
+        regPlayerInfo = g_mergeRegisterPlayerDict[queryAccid]
+        recvPack = regPlayerInfo[MergeRegPInfoIndex_PackData]
+        #operator = regPlayerInfo[MergeRegPInfoIndex_Operator].strip(chr(0)) # 平台改为直接去从账号中取,支持混服
+        #serverID = regPlayerInfo[MergeRegPInfoIndex_ServerID]
+        playerData = recvPack.Data
+        dbPlayer = DataServerPlayerData.tagDBPlayer()
+        pos = 0
+        dbPlayerReadLen = dbPlayer.readData(playerData, pos, len(playerData))
+        playerID = dbPlayer.PlayerID
+        pos += dbPlayerReadLen
+        dbPlayer.MapID = recvPack.SelectMapID
+        dbPlayer.DataMapID = recvPack.SelectDataMapID
+        dbPlayer.CopyMapID = recvPack.SelectCopyMapID
+        dbPlayer.PosX = recvPack.SelectPosX
+        dbPlayer.PosY = recvPack.SelectPosY
+        
+        dbPlayer.FromDataMapID = recvPack.SelectDataMapID
+        dbPlayer.FromMapID = recvPack.SelectMapID
+        dbPlayer.FromCopyMapID = recvPack.SelectCopyMapID
+        dbPlayer.FromPosX = recvPack.SelectPosX
+        dbPlayer.FromPosY = recvPack.SelectPosY
+        
+        dbPlayer.RebornMapID = recvPack.SelectMapID
+        dbPlayer.RebornPosX = recvPack.SelectPosX
+        dbPlayer.RebornPosY = recvPack.SelectPosY
+        
+        playerName = dbPlayer.PlayerName.strip()
+        accID = dbPlayer.AccID.lower().strip(chr(0))
+        operator = CommFunc.GetPlayerPlatform(accID)
+        serverID = CommFunc.GetPlayerServerID(accID)
+        newPlayerName = self.__GetMergePlayerName(operator, serverID, playerName)
+        if playerName != newPlayerName:
+            dbPlayer.SetPlayerName(newPlayerName)
+            
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagRoleItem")
+        oFuncGrade.Start()
+        p, itemData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagRoleItem, playerData[pos:], True)
+        pos += p
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagRoleMission")
+        oFuncGrade.Start()
+        p, missionData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagRoleMission, playerData[pos:])
+        pos += p
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagRoleMissionDict")
+        oFuncGrade.Start()
+        p, roleMissionDictData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagRoleMissionDict, playerData[pos:])
+        pos += p
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagRoleSkill")
+        oFuncGrade.Start()
+        p, roleSkillData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagRoleSkill, playerData[pos:])
+        pos += p
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagRoleBuff")
+        oFuncGrade.Start()
+        p, roleBuffData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagRoleBuff, playerData[pos:])
+        pos += p
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagRoleRepeatTime")
+        oFuncGrade.Start()
+        p, roleRepeatTimeData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagRoleRepeatTime, playerData[pos:])
+        pos += p
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagPlayerHorseTable")
+        oFuncGrade.Start()
+        p, roleHorseData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagPlayerHorseTable, playerData[pos:])
+        pos += p
+        oFuncGrade.End()
+        
+        #跳过gmOperCheck数据      
+        p, gmOperData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagGMOper, playerData[pos:])
+        pos += p
+        #跳过GM IP表
+        p, gmIPData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagDBGMIP, playerData[pos:])
+        pos += p
+        
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagRolePet")
+        oFuncGrade.Start()
+        p, rolePetData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagRolePet, playerData[pos:])
+        pos += p
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagPetSkill")
+        oFuncGrade.Start()
+        p, petSkillData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagPetSkill, playerData[pos:])
+        pos += p
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagRoleNomalDict")
+        oFuncGrade.Start()
+        p, roleNormalDictData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagRoleNomalDict, playerData[pos:])
+        pos += p
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagPlayerDienstgrad")
+        oFuncGrade.Start()
+        p, roleDienstgradData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagPlayerDienstgrad, playerData[pos:])
+        pos += p
+        oFuncGrade.End()
+        
+        oFuncGrade = self.GetFuncGrade("getMergePlayerDataBuffer_1_tagBattleFormation")
+        oFuncGrade.Start()
+        p, battleFormationData = self.getMergePlayerDataBuffer(playerID, DataServerPlayerData.tagBattleFormation, playerData[pos:])
+        pos += p
+        oFuncGrade.End()
+         
+        allData = dbPlayer.getBuffer() + itemData + missionData + roleMissionDictData + roleSkillData + roleBuffData + roleRepeatTimeData + roleHorseData + gmOperData\
+                     + gmIPData + rolePetData + petSkillData + roleNormalDictData + roleDienstgradData + battleFormationData
+        #加上CRC
+        crc = crc32(allData)
+        dataCrc = ''
+        dataCrc = CommFunc.WriteDWORD(dataCrc, crc)
+        dataCrc = CommFunc.WriteBYTE(dataCrc, 0)    #ServerType
+        dataWithCrc = dataCrc + allData
+        self.sendOKString(CommonDefine.dgPlayerInit, pack, dataWithCrc)
+        mylog.debug('gstPlayerDetail Send operator=%s,serverID=%s, accid = %s playerID = %s playerName = %s newPlayerName=%s'
+                    %(operator, serverID, queryAccid, dbPlayer.PlayerID, playerName, newPlayerName))
+        return
+    
+    def __GetMergePlayerName(self, operator, serverID, playerName):
+        # 获取玩家跨服服务器上的名字
+        if not self.__MergePlayerNameFormatConfig:
+            return playerName
+        try:
+            splitSign, withServerFormat, withoutServerFormat = self.__MergePlayerNameFormatConfig.config
+            curFormat, curParam = withServerFormat if splitSign in playerName else withoutServerFormat
+            curParam = eval(str(curParam).replace("operator", operator).replace("serverID", str(serverID)).replace("playerName", playerName))
+            return curFormat % curParam
+        except:
+            mylog.error("__GetMergePlayerName error! operator=%s, serverID=%s, playerName=%s" % (operator, serverID, playerName))
+            return playerName
+        
+    def onGetPlayerDetail(self, db, pack):
+        getPlayerDetailReq = RecvPackProtocol.tagPlayerDetailReq()
+        getPlayerDetailReq.ReadData(pack.getBuffer(), 0, pack.getLength())
+        mylog.debug('getting player detail for accid = %s'%getPlayerDetailReq.AccID)
+        queryAccid = getPlayerDetailReq.AccID.lower().strip(chr(0))
+        #判定是否在合服之中
+        try:
+            playerList = self.queryMergePlayerList(db, queryAccid)
+        except:
+            #出了异常,回复数据库繁忙
+            self.sendFailString(CommonDefine.dgPlayerInit, pack, disDataBaseError)
+            msg = error.formatMsg('error', error.ERROR_NO_67, 'kick accid = %s reason = %s, error :\n %s'%(queryAccid, disDataBaseError, traceback.format_exc()))
+            mylog.error(msg)
+            return
+        if len(playerList) > 0:
+            #合服处理
+            sendPack = SendPackProtocol.tagServerMergeInfo()
+            sendPack.PlayerCount = len(playerList)
+            for playerDict in playerList:
+                try:
+                    singlePlayer = SendPackProtocol.tagServerMergePlayer()
+                    leaderFamilyInfo = []
+                    try:
+                        #查询玩家是否家族长
+                        leaderFamilyInfo = self.getFamilyLeaderFamilyID(db, playerDict['PlayerID'])
+                    except:
+                        self.sendFailString(CommonDefine.dgPlayerInit, pack, disDataBaseError)
+                        msg = error.formatMsg('error', error.ERROR_NO_68, 'kick accid = %s reason = %s'%(queryAccid, disDataBaseError))
+                        mylog.error(msg)
+                        return
+                    if len(leaderFamilyInfo) > 0:
+                        #家族长
+                        if len(leaderFamilyInfo) > 1:
+                            #此人至少是两个家族的家族长,这逻辑上不可能
+                            self.sendFailString(CommonDefine.dgPlayerInit, pack, disDataBaseError)
+                            msg = error.formatMsg('error', error.ERROR_NO_69, 'kick accid = %s reason = %s'%(queryAccid, disDataBaseError))
+                            mylog.error(msg)
+                            return
+                        singlePlayer.LeaderFamilyID = leaderFamilyInfo[0]['ID']
+                    else:
+                        #非家族长
+                        singlePlayer.LeaderFamilyID = 0
+                    singlePlayer.PlayerID = playerDict['PlayerID']
+                    singlePlayer.Name = playerDict['PlayerName']
+                    singlePlayer.Job = playerDict['Job']
+                    singlePlayer.Sex = playerDict['Sex']
+                    singlePlayer.LV = playerDict['LV']
+                    singlePlayer.TotalSTR = playerDict['STR']
+                    singlePlayer.TotalPNE = playerDict['PNE']
+                    singlePlayer.TotalPHY = playerDict['PHY']
+                    singlePlayer.TotalCON = playerDict['CON']
+                    singlePlayer.Gold = playerDict['Gold']
+                    singlePlayer.GoldPaper = playerDict['GoldPaper']
+                    singlePlayer.Silver = playerDict['Silver']
+                    singlePlayer.SilverPaper = playerDict['SilverPaper']
+                    singlePlayer.WarehouseGold = playerDict['WarehouseGold']
+                    singlePlayer.WarehouseSilver = playerDict['WarehouseSilver']
+                    singlePlayer.FightPower = playerDict['FightPower']
+                    
+                    sendPack.Players.append(singlePlayer)
+                except KeyError, why:
+                    self.sendFailString(CommonDefine.dgPlayerInit, pack, disDataBaseError)
+                    msg = error.formatMsg('error', error.ERROR_NO_70, 'exception = %s:kick accid = %s reason = %s'%(why, queryAccid, disDataBaseError))
+                    mylog.error(msg)
+                    return
+            self.sendOKString(CommonDefine.dgServerMerge, pack, sendPack.GetBuffer())
+            return
+        else:
+            #非合服
+            #读取角色基本信息
+            dbPlayer = DataServerPlayerData.tagDBPlayer()
+            dbPlayer.AccID = getPlayerDetailReq.AccID
+            dbPlayer.IsDeleted = 0
+            collection = db[UCN_DBPlayer]
+            lastExceptionCnt = getADOExceptionCount()
+            lastSIDErrorCnt = getSIDErrorCnt()
+            loadOK = dbPlayer.adoLoadCEx(collection, {'AccID':fix_incomingText(dbPlayer.AccID), 'IsDeleted':dbPlayer.IsDeleted})
+            if not lastExceptionCnt == getADOExceptionCount():
+                #数据库读取出错,但不一定是User库读取出错
+                self.sendFailString(CommonDefine.dgPlayerInit, pack, disDataBaseError)
+                return
+            mylog.info('accid = %s,playerID = %s'%(queryAccid, dbPlayer.PlayerID))
+            
+            #UTF8 需要转成url编码才可用
+            #===================================================================
+            # playerInfo = urllib.urlencode({"RoleID": fix_outgoingText(dbPlayer.PlayerName),
+            #                               "AccountID": CommFunc.GetPlatformAccID(dbPlayer.AccID),
+            #                               "IP":getPlayerDetailReq.IP.strip(chr(0)),
+            #                               "SessionID":PegasusCollectorProxy.GetSessionID(db, dbPlayer.AccID),
+            #                               "Level":dbPlayer.LV,
+            #                               "Job":dbPlayer.Job
+            #                               }) 
+            # 
+            # #登录事件
+            # PegasusCollectorProxy.EventReport(1100, playerInfo)
+            #===================================================================
+            if not lastSIDErrorCnt == getSIDErrorCnt():
+                #SID校验出错,封号
+                if not CommonDefine.isAccStateForbidden(dbPlayer.AccState):
+                    if DBConfig.checkSID:
+                        #封号
+                        dbPlayer.AccState = CommonDefine.pysSIDCheckErrorForbidden
+                        dbPlayer.adoUpdateC(collection)
+                        mylog.debug('AccID = %s check SID failed!'%queryAccid)
+                        #记录流向
+                        #===========================================================================
+                        # dbServerLogRec = RecvPackProtocol.tagDBServerLogRec()
+                        # dbServerLogRec.Type = CommonDefine.gstSavePlayerLog
+                        # dbServerLogRec.Oper = 119    #封号流向
+                        # dbServerLogRec.Time = time()
+                        # dbServerLogRec.MapID = 0
+                        # dbServerLogRec.PlayerID = dbPlayer.PlayerID
+                        # dbServerLogRec.Msg = 'ADO SID Check Error !'
+                        # dbServerLogRec.MsgLen = len(dbServerLogRec.Msg)
+                        # self.sendDBRequest(dbServerLogRec.GetBuffer())
+                        #===========================================================================
+                        #另外,独立记录玩家封号日志
+#                        dbPlayerInfoLogForbidden = RecvPackProtocol.tagDBPlayerInfoLogForbidden()
+#                        dbPlayerInfoLogForbidden.AccID = dbPlayer.AccID
+#                        dbPlayerInfoLogForbidden.IsForbidden = True
+#                        dbPlayerInfoLogForbidden.ForbiddenTime = time()
+#                        sendPackBuf = ''
+#                        sendPackBuf = CommFunc.WriteBYTE(sendPackBuf, CommonDefine.gstSavePlayerInfoLogOnForbidden)
+#                        sendPackBuf = CommFunc.WriteString(sendPackBuf, dbPlayerInfoLogForbidden.GetLength(), dbPlayerInfoLogForbidden.GetBuffer())
+#                        self.ctrlDBManager.sendDBRequest(sendPackBuf)
+                        self.sendAccForbiddenLogReq(dbPlayer.AccID, 1)
+                #修改来C++原来的逻辑
+                #回复LoginServer
+                if DBConfig.checkSID:
+                    self.sendFailString(CommonDefine.dgPlayerInit, pack, disAccStateError)
+                    return
+            
+            #读取物品等其他数据
+            #如果没有必要,就不支持单表模式了
+            #读取物品
+            queryDict = {'PlayerID':dbPlayer.PlayerID}
+            collection = db[UCN_RoleItem]
+            itemData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleItem, True)
+
+            itemCnt = CommFunc.ReadDWORD(itemData, 0)
+            mylog.debug('roleItem cnt = %s'%itemCnt[0])
+            #读取和存储时将数据DUMP出来,方便查证窜号问题
+
+            collection = db[UCN_RoleMission]
+            missionData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleMission)
+             
+            missionCnt = CommFunc.ReadDWORD(missionData, 0)
+            mylog.debug('roleMission cnt = %s'%missionCnt[0])
+            #读取和存储时将数据DUMP出来,方便查证窜号问题
+
+            collection = db[UCN_RoleMissionDict]
+            roleMissionDictData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleMissionDict)
+            
+            missonDictCnt = CommFunc.ReadDWORD(roleMissionDictData, 0)
+            mylog.debug('roleMissionDict cnt = %s'%missonDictCnt[0])
+
+            collection = db[UCN_RoleSkill]
+            roleSkillData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleSkill)
+                
+            skillCnt = CommFunc.ReadDWORD(roleSkillData, 0)
+            mylog.debug('roleSkill cnt = %s'%skillCnt[0])
+
+            collection = db[UCN_RoleBuff]
+            roleBuffData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleBuff)
+               
+            bufCnt = CommFunc.ReadDWORD(roleBuffData, 0)
+            mylog.debug('roleBuff cnt = %s'%bufCnt[0])
+
+            collection = db[UCN_RoleRepeatTime]
+            roleRepeatTimeData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleRepeatTime)
+             
+            repeatTimeCnt = CommFunc.ReadDWORD(roleRepeatTimeData, 0)
+            mylog.debug('roleRepeatTime cnt = %s'%repeatTimeCnt[0])
+
+            collection = db[UCN_PlayerHorseTable]
+            roleHorseData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagPlayerHorseTable)
+                
+            horseCnt = CommFunc.ReadDWORD(roleHorseData, 0)
+            mylog.debug('roleHorse cnt = %s'%horseCnt[0])
+
+            collection = db[UCN_GMOper]
+            gmOperData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagGMOper)
+             
+            gmOperCnt = CommFunc.ReadDWORD(gmOperData, 0)
+            mylog.debug('gmOper cnt = %s'%gmOperCnt[0])
+
+            collection = db[UCN_RolePet]
+            rolePetData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRolePet)
+                
+            petCnt = CommFunc.ReadDWORD(rolePetData, 0)
+            mylog.debug('rolePet cnt = %s'%petCnt[0])
+
+            collection = db[UCN_PetSkill]
+            petSkillData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagPetSkill)
+                
+            petSkillCnt = CommFunc.ReadDWORD(petSkillData, 0)
+            mylog.debug('petSkill cnt = %s'%petSkillCnt[0])
+
+            collection = db[UCN_RoleNomalDict]
+            roleNormalDictData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleNomalDict)
+              
+            dictCnt = CommFunc.ReadDWORD(roleNormalDictData, 0)
+            mylog.debug('roleNormalDict cnt = %s'%dictCnt[0])
+
+            collection = db[UCN_PlayerDienstgrad]
+            roleDienstgradData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagPlayerDienstgrad)
+            
+            roleDienstgradCnt = CommFunc.ReadDWORD(roleDienstgradData, 0)
+            mylog.debug('roleDienstgrad cnt = %s'%roleDienstgradCnt[0])
+            
+            
+            
+            collection = db[UCN_BattleFormation]
+            battleFormationData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagBattleFormation)
+            
+            battleFormationCnt = CommFunc.ReadDWORD(battleFormationData, 0)
+            mylog.debug('battleFormationcnt = %s'%battleFormationCnt[0])
+            
+
+            #封停检查
+            if dbPlayer.AccState == CommonDefine.pysForbidden:
+                #GM封号
+                gmOperRec = self.extractGMOper(queryAccid, CommonDefine.gmForbidAcc, gmOperData)
+                if gmOperRec:
+                    #找到封号操作
+                    if gmOperRec.EndTime > CommFuncEx.TDateTime_Now():
+                        #封号尚未结束,踢掉
+                        self.sendFailString(CommonDefine.dgPlayerInit, pack, disAccStateError)
+                        return
+                    else:
+                        #封号时间已到,解封
+                        msg = 'Time past.EndTime = %s.Reason = %s'%(CommFuncEx.TDateTimeToString(gmOperRec.EndTime), gmOperRec.Msg)
+                        self.unFobbidenAcc(db, dbPlayer, gmOperRec.GMAccID, msg)
+                        mylog.info('auto unforbidden accid = %s msg = %s'%(queryAccid, msg))
+                else:
+                    #未找到了封号记录,解封                
+                    msg = 'No forbidden oper found!'
+                    self.unFobbidenAcc(db, dbPlayer, '', msg)
+                    mylog.info('auto unforbidden accid = %s msg = %s'%(queryAccid, msg))
+            elif dbPlayer.AccState == CommonDefine.pysSIDCheckErrorForbidden:
+                #数据异常封停
+                self.sendFailString(CommonDefine.dgPlayerInit, pack, disAccStateError)
+                return
+            
+            #读取禁止IP数据
+            gmIP = DataServerPlayerData.tagDBGMIP()
+            gmIP.AccID = queryAccid.lower()
+            collection = db[UCN_DBGMIP]
+            gmIPData = gmIP.adoQueryIndex(collection)
+            
+            gmIPCnt = CommFunc.ReadDWORD(gmIPData, 0)
+            mylog.debug('gmIP cnt = %s'%gmIPCnt[0])
+             
+            allData = dbPlayer.getBuffer() + itemData + missionData + roleMissionDictData + roleSkillData + roleBuffData + roleRepeatTimeData + roleHorseData + gmOperData\
+                         + gmIPData + rolePetData + petSkillData + roleNormalDictData + roleDienstgradData+battleFormationData
+            #加上CRC
+            crc = crc32(allData)
+            dataCrc = ''
+            dataCrc = CommFunc.WriteDWORD(dataCrc, crc)
+            dataCrc = CommFunc.WriteBYTE(dataCrc, 0)    #ServerType
+            dataWithCrc = dataCrc + allData
+            self.sendOKString(CommonDefine.dgPlayerInit, pack, dataWithCrc)
+            mylog.debug('gstPlayerDetail Send accid = %s playerID = %s'%(queryAccid, dbPlayer.PlayerID))
+    
+    def unFobbidenAcc(self, db, dbPlayer, gmAccid, msg):
+#        dbPlayer = DataServerPlayerData.tagDBPlayer()
+#        dbPlayer.AccID = accid.lower()
+        dbPlayer.AccState = CommonDefine.pysNormal
+        collection = db[UCN_DBPlayer]
+        dbPlayer.adoUpdateExC(collection, {"AccID":fix_incomingText(dbPlayer.AccID), "IsDeleted":dbPlayer.IsDeleted})
+        #写解封日志
+        self.onForbiddenUpdate(dbPlayer.AccID, dbPlayer.PlayerID, False, CommFuncEx.TDateTime_Now(), 0, gmAccid, msg)
+    
+    def onForbiddenUpdate(self, accid, playerID, isForbidden, operTime, timeLimit, operGMAccid, msg):
+        mylog.info('accid = %s playerID = %s isForbidden = %s operTime = %s timeLimit = %s operGMAccid = %s msg = %s'%
+                   (accid, playerID, isForbidden, ctime(operTime), timeLimit, operGMAccid, msg))
+        
+#        dbPlayerFobiddenLogReq = ''
+#        dbPlayerFobiddenLogReq = CommFunc.WriteBYTE(dbPlayerFobiddenLogReq, CommonDefine.gstSavePlayerInfoLogOnForbidden)
+#        dbPlayerFobiddenLog = DataServerLogData.tagDBPlayerInfoLogForbidden()
+#        dbPlayerFobiddenLog.AccID = accid.lower()
+#        dbPlayerFobiddenLog.IsForbidden = isForbidden
+#        dbPlayerFobiddenLog.ForbiddenTime = operTime
+#        dbPlayerFobiddenLogReq = CommFunc.WriteString(dbPlayerFobiddenLogReq, dbPlayerFobiddenLog.getLength(), dbPlayerFobiddenLog.getBuffer())
+#        self.sendDBRequest(dbPlayerFobiddenLogReq)
+        self.sendAccForbiddenLogReq(accid.lower(), isForbidden)
+        
+        accForbiddenLogReq = ''
+        accForbiddenLogReq = CommFunc.WriteBYTE(accForbiddenLogReq, CommonDefine.gstAccForbiddenLog)
+        accForbiddenLog = DataServerLogData.tagAccForbiddenLog()
+        accForbiddenLog.AccID = accid.lower()
+        accForbiddenLog.PlayerID = playerID
+        accForbiddenLog.Oper = isForbidden
+        accForbiddenLog.OperTime = operTime
+        accForbiddenLog.TimeLimit = timeLimit
+        accForbiddenLog.GMAccID = operGMAccid
+        accForbiddenLog.Msg = msg
+        accForbiddenLogReq = CommFunc.WriteString(accForbiddenLogReq, accForbiddenLog.getLength(), accForbiddenLog.getBuffer())
+        self.sendDBRequest(accForbiddenLogReq)
+        
+    def extractGMOper(self, accid, gmOper, gmOperData):
+        pos = 0
+        operCnt, pos = CommFunc.ReadDWORD(gmOperData, pos)
+        mylog.info('accid = %s gmOperCnt = %s'%(accid, operCnt))
+        gmOperRec = DataServerPlayerData.tagGMOper()
+        for i in xrange(operCnt):
+            pos += gmOperRec.readData(gmOperData, pos)
+            if gmOperRec.Oper == gmOper:
+                return gmOperRec
+        return None
+    
+#    def isGMOperOverdue(self, accid, gmOper, gmOperData):
+#        pass
+    
+    def getFamilyLeaderFamilyID(self, db, leaderID):
+        collection = db[UCN_FamilyInfo]
+        familyInfoSnap = list(collection.find({'LeaderID':leaderID}, ['ID']))
+        return familyInfoSnap
+    
+    def queryMergePlayerList(self, db, accid):
+        '''查询处于合服状态的角色列表'''
+        collection = db[UCN_DBPlayer]
+        playerList = list(collection.find({'AccID':fix_incomingText(accid), 'IsDeleted':0, 'AccState':CommonDefine.pysServerMerge}))
+        if self.translator:
+            playerList = self.translator.transform_outgoing(playerList, None)
+        return playerList
+    
+    def onAuthentication(self, db, pack):
+        '''帐号认证'''
+        global g_mergeRegisterPlayerDict
+        
+        authPack = RecvPackProtocol.tagDataServerPlayerLogin()
+        authPack.ReadData(pack.getBuffer(), 0, pack.getLength())
+        accountRec = DataServerPlayerData.tagDSAccount()
+        authAccID = authPack.AccID.lower().strip(chr(0))
+        accountRec.ACCID = authAccID
+        
+        # 跨服缓存中的
+        if authAccID in g_mergeRegisterPlayerDict:
+            mylog.debug('auth mergeServer Player accid = %s...'%authAccID)
+            mergePlayerInfo = g_mergeRegisterPlayerDict[authAccID]
+            psw = mergePlayerInfo[MergeRegPInfoIndex_Pwd]
+            encodedpsw = mergePlayerInfo[MergeRegPInfoIndex_EncodedPsw]
+            # 匹配密码
+            if encodedpsw != authPack.Psw.strip(chr(0)): #去掉字符串末尾的0
+                #密码不匹配
+                mylog.debug('input psw = %s is incorrect, encodedpsw=%s, psw = %s'%(authPack.Psw.strip(), encodedpsw, psw))
+                self.sendFailString(CommonDefine.dgPlayerLogin, pack, disPswCheckError)
+                return True
+            self.sendOKString(CommonDefine.dgPlayerLogin, pack, accountRec.getBuffer())
+            return True
+        mylog.debug('auth accid = %s-%s...'%(authPack.AccID, authPack.IDType))
+        
+        #在数据库查找此帐号
+        collection = db[UCN_DSAccount]
+        
+        if int(authPack.IDType) == CommonDefine.gitFreeSDK:
+            #读取旧数据
+            accountRec.adoLoadC(collection)
+
+            accountRec.AppID = authPack.AppID.strip(chr(0))
+            accountRec.AccountID = authPack.AccountID
+            accountRec.TokenExpire = authPack.TokenExpire.strip(chr(0))
+            accountRec.Phone = authPack.Phone
+            accountRec.Psw = authPack.Psw.strip(chr(0))
+            accountRec.Adult = authPack.Adult
+            accountRec.RegIP = authPack.IP.strip(chr(0))    # RegIP 当做登录IP用 2018-03-03
+            
+            #===================================================================
+            # if not CommonDefine.IsDebug() and DBConfig.PlatformName != accountRec.AppID:
+            #    mylog.debug('appid fail:%s'%(accountRec.AppID))
+            #    #此处如有必要可以加上 区服验证,要考虑合服、跨服、混服
+            #    self.sendFailString(CommonDefine.dgPlayerLogin, pack, disPswCheckError)
+            #    return True
+            #===================================================================
+            
+            #if "@test@" in accountRec.ACCID or "@yun@" in accountRec.ACCID or accountRec.RegIP == "127.0.0.1":
+            if CommonDefine.IsDebug() or accountRec.RegIP == "127.0.0.1":
+                #debug内部服务器不验证token, 脱机挂玩家不验证
+                mylog.debug('iner no check')
+                pass
+            else:
+                # url的访问没有多线程 有可能导致登录堆积卡顿的现象
+                if self.loginHeap < 7:
+                    # 10秒内前X个玩家验证,后面不验证
+                    values = {'token' : accountRec.Psw, 
+                              'account' : CommFunc.GetPlatformAccID(accountRec.ACCID), 
+                              'appid' : accountRec.AppID } 
+                    try:
+                        data = urllib.urlencode(values) 
+                        req = urllib2.Request(DBConfig.CheckTokenUrl, data) 
+                        response = urllib2.urlopen(req, timeout=1) 
+                        the_page = response.read()
+                        if '"0"' in the_page:
+                            mylog.debug('checktoken fail:%s'%(accountRec.Psw))
+                            self.sendFailString(CommonDefine.dgPlayerLogin, pack, disPswCheckError)
+                            return True
+                    except:
+                        pass
+                    
+                nowTime = time()
+                if nowTime - self.loginStartTime < 10:
+                    self.loginHeap += 1
+                else:
+                    self.loginStartTime = nowTime
+                    self.loginHeap = 0
+                
+        elif int(authPack.IDType) == CommonDefine.gitMRGame:
+            #读取旧数据
+            accountRec.adoLoadC(collection)
+
+            accountRec.AppID = authPack.AppID.strip(chr(0))
+            accountRec.AccountID = authPack.AccountID
+            accountRec.TokenExpire = authPack.TokenExpire.strip(chr(0))
+            accountRec.Phone = authPack.Phone
+            accountRec.Psw = authPack.Psw.strip(chr(0))
+            accountRec.Adult = authPack.Adult
+            accountRec.RegIP = authPack.IP.strip(chr(0))    # RegIP 当做登录IP用 2018-03-03
+
+            # 此处有风险没有验证token
+
+        elif int(authPack.IDType) == CommonDefine.gitSPGame:
+            # 思璞游戏 用充值key验证
+            accountRec.adoLoadC(collection)
+
+            accountRec.AppID = authPack.AppID.strip(chr(0))
+            accountRec.AccountID = authPack.AccountID
+            accountRec.TokenExpire = authPack.TokenExpire.strip(chr(0))
+            accountRec.Phone = authPack.Phone
+            accountRec.Psw = authPack.Psw.strip(chr(0))
+            accountRec.Adult = authPack.Adult
+            accountRec.RegIP = authPack.IP.strip(chr(0))    # RegIP 当做登录IP用 2018-03-03
+            extra = authPack.Extra
+            if accountRec.RegIP == "127.0.0.1":
+                #debug内部服务器不验证token, 脱机挂玩家不验证
+                mylog.debug('iner no check')
+            else:
+                if CommFunc.GetPlatformAccID(authAccID) not in authPack.Extra:
+                    #session_id 中存有帐号名,位置在以|分隔的第二个参数里
+                    self.sendFailString(CommonDefine.dgPlayerLogin, pack, disPswCheckError)
+                    mylog.debug('spgame session error')
+                    return True
+                if md5.md5(authPack.Extra + accountRec.TokenExpire + CommFunc.GetLoginKey(authAccID)).hexdigest().lower() != accountRec.Psw.lower():
+                    self.sendFailString(CommonDefine.dgPlayerLogin, pack, disPswCheckError)
+                    mylog.debug('spgame token error--%s-%s'%([authPack.Extra, accountRec.TokenExpire, authAccID], CommFunc.GetLoginKey(authAccID)))
+                    return True
+            
+        else:
+            #需要添加异常计数后继续
+            lastExceptionCnt = getADOExceptionCount()
+            lastSIDErrorCnt = getSIDErrorCnt()
+            if not accountRec.adoLoadC(collection):
+                if lastExceptionCnt != getADOExceptionCount():
+                    #数据库访问异常
+                    mylog.warning('DB access excption!')
+                    self.sendFailString(CommonDefine.dgPlayerLogin, pack, disDataBaseError)
+                    return True
+                if lastSIDErrorCnt == getSIDErrorCnt():
+                    #用户确实不存在
+                    mylog.warning('accid = %s not found!'%authPack.AccID)
+                    self.sendFailString(CommonDefine.dgPlayerLogin, pack, disUserNameNotExist)
+                    return True
+                elif DBConfig.checkSID:
+                    #Sid不对 踢人
+                    mylog.debug("authPack.AccID = %s, sid error"%authPack.AccID)
+                    self.sendFailString(CommonDefine.dgPlayerLogin, pack, disGMKick)
+                    return True
+                                
+            #用户名匹配,下面匹配密码
+            if not (accountRec.Psw == authPack.Psw.strip(chr(0))):    #去掉字符串末尾的0
+                #密码不匹配
+                mylog.debug('input psw = %s while stored psw = %s'%(authPack.Psw.strip(), accountRec.Psw.strip()))
+                self.sendFailString(CommonDefine.dgPlayerLogin, pack, disPswCheckError)
+                return True
+        
+        PegasusCollectorProxy.EventReport(9001, "OperatorID=%s&Step=%s&AccountID=%s&Flag=1000"%(
+                              CommFunc.GetPlayerPlatform(authAccID), 1, CommFunc.GetPlatformAccID(authAccID)))
+        #帐号密码验证通过,更新累计登录次数
+        accountRec.LogNum += 1
+        accountRec.LastLoginTime= CommFuncEx.TDateTimeToString(CommFuncEx.TDateTime_Now()) 
+        if not accountRec.adoCheckUpdateC(collection):
+            #更新失败
+            mylog.warning('%s update LogNum error'%authPack.AccID)
+            self.sendFailString(CommonDefine.dgPlayerLogin, pack, disDataBaseError)
+            return True
+        #更新累计登录次数成功,认证完成
+        self.sendOKString(CommonDefine.dgPlayerLogin, pack, accountRec.getBuffer())
+        return True
+    
+    def sendOKString(self, type, fromPacket, buf):
+        #等价于ChinDataServer AODThread.SendOKString
+        packBuf = ''
+        packBuf = CommFunc.WriteBYTE(packBuf, type)
+        packBuf = CommFunc.WriteBYTE(packBuf, 1)    #失败
+        packBuf = CommFunc.WriteString(packBuf, len(buf), buf)
+        self.sendString(fromPacket, packBuf)
+    
+    def sendFailString(self, type, fromPacket, disconnectReason = 0):
+        #等价于ChinDataServer AODThread.SendFailString
+        packBuf = ''
+        packBuf = CommFunc.WriteBYTE(packBuf, type)
+        packBuf = CommFunc.WriteBYTE(packBuf, 0)    #失败
+        packBuf = CommFunc.WriteBYTE(packBuf, disconnectReason)
+        self.sendString(fromPacket, packBuf)
+    
+    def sendString(self, fromPacket, packBuf):
+        self.packSend(fromPacket.getSessionID(), fromPacket.getPackHead().sessionID, fromPacket.getPackHead().poolIndex, fromPacket.getPackHead().type,
+                      fromPacket.getPackHead().srcSvrType, fromPacket.getPackHead().dstSvrType, packBuf)
+    
+    def onSaveMapServerCrashData(self, db, pack):
+        crashData = RecvPackProtocol.tagMDSaveMapServerCrashData()
+        buf = pack.getBuffer()
+        pos = 0
+        length = len(buf)
+        crashData.readData(buf, pos, length)
+ 
+        if crashData.SaveStream.StreamData.Count:
+            FileLog.getLogger('MapServerRestoreLog').info('保存MapServer崩溃数据,玩家数量是: %s'%(crashData.SaveStream.StreamData.Count))
+            mylog.info("Saving MapServer Crash Data, count = %d, poolIndex = %d"%(crashData.SaveStream.StreamData.Count, pack.getPackHead().poolIndex));
+            if crashData.VersionNO != VersionNoDefine.SERVER_DATA_VERSION_NO:
+                msg = error.formatMsg('fatal', error.ERROR_NO_71, "Saving MapServer Crash Data Error! count = %d version(%d)!=currentVersion(%d)"%(crashData.SaveStream.StreamData.Count, crashData.VersionNO, VersionNoDefine.SERVER_DATA_VERSION_NO))
+                mylog.fatal(msg)
+                FileLog.getLogger('MapServerRestoreLog').fatal('崩溃数据版本校验失败!如果是版本升级,请先用旧版本进行崩溃数据导入!')
+                DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\SaveFailDump', 'tagMDSaveMapServerCrashData_%d.mdat'%crashData.MapID, buf)                
+                return;
+            
+            if crashData.SaveStream.CRCCheckErrorServerType == MMORPGPack.stMin:
+                if CommonDefine.DUMPPACKET:
+                    debugdata = crashData.SaveStream.StreamData.getBuffer()
+                    mylog.debug("crashData.SaveStream.StreamData.getBuffer() = %s, len = %d"%(b2a_hex(debugdata), len(debugdata)))
+                mylog.debug("CommonDefine.DATASAVE_MARK = %d"%CommonDefine.DATASAVE_MARK)
+                # 检查CRC
+                CalcCRC = CommFunc.ToDWORD(crc32(crashData.SaveStream.StreamData.getBuffer(), CommonDefine.DATASAVE_MARK))
+                if CalcCRC != crashData.SaveStream.CRC:
+                    msg = error.formatMsg('error', error.ERROR_NO_72, "Saving MapServer Crash Data CRC Error! CalcCRC = %0x, PackCRC = %0x"%(CalcCRC, crashData.SaveStream.CRC))
+                    mylog.error(msg)
+                    FileLog.getLogger('MapServerRestoreLog').fatal('崩溃数据CRC校验失败!')
+                    DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\SaveFailDump', 'tagMDSaveMapServerCrashData_%d.mdat'%crashData.MapID, buf)                
+                    # 不回应,地图无法准备就绪,所有玩家无法登陆
+                    return
+            else:
+
+                #在其他服务器已经查出CRC错误
+                msg = error.formatMsg('error', error.ERROR_NO_73, "Saving MapServer Crash Data CRC Error! PackCRC = %0x"%crashData.SaveStream.CRC)
+                mylog.error(msg);
+                FileLog.getLogger('MapServerRestoreLog').fatal('崩溃数据CRC在其他服务已校验失败!具体可查看主日志')
+                DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\SaveFailDump', 'tagMDSaveMapServerCrashData_%d.mdat'%crashData.MapID, buf)
+                return;
+        else:
+            FileLog.getLogger('MapServerRestoreLog').info('无崩溃数据!')
+            mylog.info("hvae processed mapserver empty crash data")
+
+        for i in xrange(crashData.SaveStream.StreamData.Count):
+            PlayerData = crashData.SaveStream.StreamData.AllPlayerStream[i]
+            pack.setBuffer(string_at(PlayerData.Data, PlayerData.Len))
+            result, playerID = self.onSaveMapServerPlayerData(db, pack)
+            if result:
+                FileLog.getLogger('MapServerRestoreLog').info('第%s个玩家,PlayerID = %s'%(i+1, playerID))
+            
+        if crashData.SaveStream.StreamData.Count:
+            FileLog.getLogger('MapServerRestoreLog').info('崩溃数据保存成功!')
+            mylog.info("Saving MapServer Crash Data OK! count = %d, poolIndex = %d"%(crashData.SaveStream.StreamData.Count, pack.getPackHead().poolIndex));      
+        
+        sendPack = SendPackProtocol.tagDBUpdateReturn()
+        sendPack.CallType = CommonDefine.dgUpdateMapServerCrashData
+        sendPack.Result = 1
+        sendPack.MapID = crashData.MapID
+        self.packSend(pack.getSessionID(), pack.getPackHead().sessionID, pack.getPackHead().poolIndex, pack.getPackHead().type,
+                      pack.getPackHead().srcSvrType, pack.getPackHead().dstSvrType, sendPack.GetBuffer())
+        
+    def onGMCmdListReq(self, db, pack):
+        #已废除
+        pass
+    
+    def onGetGameServerPlayerData(self, db, pack):
+        collection = db[UCN_DBPyXMZZ]
+        XMZZ = DataServerPlayerData.tagDBPyXMZZ()
+        data = XMZZ.adoQueryAll(collection)
+        mylog.debug("tagDBPyXMZZ ok")
+        
+        collection = db[UCN_DBPySealDemonRecord]
+        sealDemonRecord = DataServerPlayerData.tagDBPySealDemonRecord()
+        data += sealDemonRecord.adoQueryAll(collection)
+        mylog.debug("tagDBPySealDemonRecord ok")
+        
+        collection = db[UCN_DBPyBossAttention]
+        bossAttention = DataServerPlayerData.tagDBPyBossAttention()
+        data += bossAttention.adoQueryAll(collection)
+        mylog.debug("tagDBPyBossAttention ok")
+        
+        collection = db[UCN_DBPyBourseItemLastPrice]
+        bourseItemLastPrice = DataServerPlayerData.tagDBPyBourseItemLastPrice()
+        data += bourseItemLastPrice.adoQueryAll(collection)
+        mylog.debug("tagDBPyBourseItemLastPrice ok")
+        
+        collection = db[UCN_DBPyBourseRecord]
+        bourseRecord = DataServerPlayerData.tagDBPyBourseRecord()
+        data += bourseRecord.adoQueryAll(collection)
+        mylog.debug("tagDBPyBourseRecord ok")
+        
+        collection = db[UCN_DBPyFamilyStoreItem]
+        familyStoreItem = DataServerPlayerData.tagDBPyFamilyStoreItem()
+        data += familyStoreItem.adoQueryAll(collection)
+        mylog.debug("tagDBPyFamilyStoreItem ok")
+
+        collection = db[UCN_DBPyPlayerFriend]
+        playerFriend = DataServerPlayerData.tagDBPyPlayerFriend()
+        data += playerFriend.adoQueryAll(collection)
+        mylog.debug("tagDBPyPlayerFriend ok")
+        
+        collection = db[UCN_PlayerEnemy]
+        playerEnemy = DataServerPlayerData.tagPlayerEnemy()
+        data += playerEnemy.adoQueryAll(collection)
+        mylog.debug("tagPlayerEnemy ok")
+        
+        collection = db[UCN_DBPyPlayerContacts]
+        playerContacts = DataServerPlayerData.tagDBPyPlayerContacts()
+        data += playerContacts.adoQueryAll(collection)
+        mylog.debug("tagDBPyPlayerContacts ok")
+        
+        collection = db[UCN_DBPyPlayerBlack]
+        playerBlacklist = DataServerPlayerData.tagDBPyPlayerBlack()
+        data += playerBlacklist.adoQueryAll(collection)
+        mylog.debug("tagDBPyPlayerBlack ok")
+        
+        collection = db[UCN_PersonalSocial]
+        playerSocial = DataServerPlayerData.tagPersonalSocial()
+        data += playerSocial.adoQueryAll(collection)
+        mylog.debug("tagPersonalSocial ok")
+        
+        collection = db[UCN_PlayerTeamTable]
+        playerTeam = DataServerPlayerData.tagPlayerTeamTable()
+        data += playerTeam.adoQueryAll(collection)
+        mylog.debug("tagPlayerTeamTable ok")
+        collection = db[UCN_TeamMemberTable]
+        teamMember = DataServerPlayerData.tagTeamMemberTable()
+        data += teamMember.adoQueryAll(collection)
+        mylog.debug("tagTeamMemberTable ok")        
+        collection = db[UCN_FamilyInfo]
+        familyInfo = DataServerPlayerData.tagFamilyInfo()
+        data += familyInfo.adoQueryAll(collection)
+        mylog.debug("tagFamilyInfo ok")        
+        collection = db[UCN_PlayerFamily]
+        playerFamily = DataServerPlayerData.tagPlayerFamily()
+        data += playerFamily.adoQueryAll(collection)
+        mylog.debug("tagPlayerFamily ok")           
+        collection = db[UCN_DBFamilyVS]
+        familyVS = DataServerPlayerData.tagDBFamilyVS()
+        data += familyVS.adoQueryAll(collection)
+        mylog.debug("tagDBFamilyVS ok")          
+        collection = db[UCN_GameWorldEvent]
+        gameWorldEvent = DataServerPlayerData.tagGameWorldEvent()
+        data += gameWorldEvent.adoQueryAll(collection)
+        mylog.debug("tagGameWorldEvent ok")          
+        collection = db[UCN_DBMissionPub]
+        missionPub = DataServerPlayerData.tagDBMissionPub()
+        data += missionPub.adoQueryAll(collection)
+        mylog.debug("tagDBMissionPub ok")           
+        collection = db[UCN_DBIPManage]
+        ipManage = DataServerPlayerData.tagDBIPManage()
+        data += ipManage.adoQueryAll(collection)
+        mylog.debug("tagDBIPManage ok")          
+        collection = db[UCN_DBGameServerEventTrig]
+        gameServerEventTrig = DataServerPlayerData.tagDBGameServerEventTrig()
+        data += gameServerEventTrig.adoQueryAll(collection)
+        mylog.debug("tagDBGameServerEventTrig ok")          
+        collection = db[UCN_DBCountryInfo]
+        countryInfo = DataServerPlayerData.tagDBCountryInfo()
+        data += countryInfo.adoQueryAll(collection)
+        mylog.debug("tagDBCountryInfo ok")             
+        collection = db[UCN_DBCountryFamilyWarResult]
+        countryFamilyWarResult = DataServerPlayerData.tagDBCountryFamilyWarResult()
+        data += countryFamilyWarResult.adoQueryAll(collection)
+        mylog.debug("tagDBCountryFamilyWarResult ok")                
+        collection = db[UCN_DBCountryFamilyWarRace]
+        countryFamilyWarRace = DataServerPlayerData.tagDBCountryFamilyWarRace()
+        data += countryFamilyWarRace.adoQueryAll(collection)
+        mylog.debug("tagDBCountryFamilyWarRace ok")           
+        collection = db[UCN_DBCountryFamilyWarRequest]
+        countryFamilyWarReq = DataServerPlayerData.tagDBCountryFamilyWarRequest()
+        data += countryFamilyWarReq.adoQueryAll(collection)
+        mylog.debug("tagDBCountryFamilyWarRequest ok")            
+        collection = db[UCN_DBBillboard]
+        billboard = DataServerPlayerData.tagDBBillboard()
+        data += billboard.adoQueryAll(collection)
+        mylog.debug("tagDBBillboard ok")          
+        collection = db[UCN_DBGoldOrderForm]
+        goldOrderForm = DataServerPlayerData.tagDBGoldOrderForm()
+        data += goldOrderForm.adoQueryAll(collection)
+        mylog.debug("tagDBGoldOrderForm ok")          
+        collection = db[UCN_DBOverdueGoldOrderForm]
+        overdueGoldOrderForm = DataServerPlayerData.tagDBOverdueGoldOrderForm()
+        data += overdueGoldOrderForm.adoQueryAll(collection)
+        mylog.debug("tagDBOverdueGoldOrderForm ok")       
+        collection = db[UCN_DBUnclaimedGoldForm]
+        unclaimeGoldForm = DataServerPlayerData.tagDBUnclaimedGoldForm()
+        data += unclaimeGoldForm.adoQueryAll(collection)
+        
+        collection = db[UCN_DBFamilyTech]
+        familyTech = DataServerPlayerData.tagDBFamilyTech()
+        data += familyTech.adoQueryAll(collection)
+        mylog.debug("tagDBFamilyTech ok")          
+        collection = db[UCN_DBPlayerLabel]
+        playrLabel = DataServerPlayerData.tagDBPlayerLabel()
+        data += playrLabel.adoQueryAll(collection)
+        mylog.debug("tagDBPlayerLabel ok")               
+        collection = db[UCN_DBPlayerRecall]
+        playerRecall = DataServerPlayerData.tagDBPlayerRecall()
+        data += playerRecall.adoQueryAll(collection)
+        mylog.debug("tagDBPlayerRecall ok")           
+        collection = db[UCN_DBVsReward]
+        dbVSReward = DataServerPlayerData.tagDBVsReward()
+        data += dbVSReward.adoQueryAll(collection)
+        mylog.debug("tagDBVsReward ok") 
+        collection = db[UCN_DBFamilyReward]
+        dbFamilyReward = DataServerPlayerData.tagDBFamilyReward()
+        data += dbFamilyReward.adoQueryAll(collection)
+        mylog.debug("tagDBFamilyReward ok")
+        collection = db[UCN_DBFamilyRewardRec]
+        dbFamilyRewardRec = DataServerPlayerData.tagDBFamilyRewardRec()
+        data += dbFamilyRewardRec.adoQueryAll(collection)
+        mylog.debug("tagDBFamilyRewardRec ok")  
+        collection = db[UCN_DBFamilyAction]
+        dbFamilyAction = DataServerPlayerData.tagDBFamilyAction()
+        data += dbFamilyAction.adoQueryAll(collection)
+        mylog.debug("tagDBFamilyAction ok")
+        collection = db[UCN_GameFBPassRec]
+        dbGameFBPassRec = DataServerPlayerData.tagGameFBPassRec()
+        data += dbGameFBPassRec.adoQueryAll(collection)
+        mylog.debug("tagGameFBPassRec ok")
+        collection = db[UCN_UniversalGameRec]
+        dbUniversalGameRec = DataServerPlayerData.tagUniversalGameRec()
+        data += dbUniversalGameRec.adoQueryAll(collection)
+        mylog.debug("tagUniversalGameRec ok") 
+        collection = db[UCN_GameGroup]
+        dbGameGroup = DataServerPlayerData.tagGameGroup()
+        data += dbGameGroup.adoQueryAll(collection)
+        mylog.debug("tagGameGroup ok") 
+        collection = db[UCN_GameGroupMember]
+        dbGameGroupMember = DataServerPlayerData.tagGameGroupMember()
+        data += dbGameGroupMember.adoQueryAll(collection)
+        mylog.debug("tagGameGroupMember ok")
+        collection = db[UCN_GameGroupMutualInfo]
+        dbGameGroupMutualInfo = DataServerPlayerData.tagGameGroupMutualInfo()
+        data += dbGameGroupMutualInfo.adoQueryAll(collection)
+        mylog.debug("tagGameGroupMutualInfo ok")
+        collection = db[UCN_GameBourseItem]
+        dbGameBourseItem = DataServerPlayerData.tagGameBourseItem()
+        data += dbGameBourseItem.adoQueryAll(collection)
+        mylog.debug("tagGameBourseItem ok")
+        collection = db[UCN_HighLadderPlayer]
+        dbHighLadderPlayer = DataServerPlayerData.tagHighLadderPlayer()
+        data += dbHighLadderPlayer.adoQueryAll(collection)
+        mylog.debug("tagHighLadderPlayer ok")
+        collection = db[UCN_DBHighLadderItem]
+        dbDBHighLadderItem = DataServerPlayerData.tagDBHighLadderItem()
+        data += dbDBHighLadderItem.adoQueryAll(collection)
+        mylog.debug("tagDBHighLadderItem ok")
+        collection = db[UCN_HighLadderVSRec]
+        dbHighLadderVSRec = DataServerPlayerData.tagHighLadderVSRec()
+        data += dbHighLadderVSRec.adoQueryAll(collection)
+        mylog.debug("tagHighLadderVSRec ok")  
+        
+        collection = db[UCN_DBCompensationItem]
+        dbDBCompensationItem = DataServerPlayerData.tagDBCompensationItem()
+        data += dbDBCompensationItem.adoQueryAll(collection)
+        mylog.debug("tagDBCompensationItem ok") 
+        
+        collection = db[UCN_DBPersonalCompensation]
+        dbDBPersonalCompensation = DataServerPlayerData.tagDBPersonalCompensation()
+        data += dbDBPersonalCompensation.adoQueryAll(collection)
+        mylog.debug("tagDBPersonalCompensation ok") 
+        
+        collection = db[UCN_DBEntireCompensationRequire]
+        dbDBEntireCompensationRequire = DataServerPlayerData.tagDBEntireCompensationRequire()
+        data += dbDBEntireCompensationRequire.adoQueryAll(collection)
+        mylog.debug("tagDBEntireCompensationRequire ok")
+         
+        collection = db[UCN_CompensationPlayerRec]
+        dbCompensationPlayerRec = DataServerPlayerData.tagCompensationPlayerRec()
+        data += dbCompensationPlayerRec.adoQueryAll(collection)
+        mylog.debug("tagCompensationPlayerRec ok") 
+        
+        collection = db[UCN_PlayerViewCache]
+        dbPlayerViewCache = DataServerPlayerData.tagPlayerViewCache()
+        data += dbPlayerViewCache.adoQueryAll(collection)
+        mylog.debug("tagPlayerViewCache ok") 
+        
+        
+                
+        #压缩
+        try:
+            #mylog.debug("unzip data = %s, len = %d"%(binascii.b2a_hex(data), len(data)))
+            compressData = zlib.compress(data, 9)    #最大压缩
+        except:
+            msg = error.formatMsg('fatal', error.ERROR_NO_75, 'Compress game server player data failed!error =\n%s'%traceback.format_exc())
+            mylog.fatal(msg)
+            return
+        #发送前打上版本号
+        SendData =''
+        SendData = CommFunc.WriteDWORD(SendData,VersionNoDefine.GAMESERVER_GAMEWORLD_DATA_VERSION_NO)
+        
+        SendData+=compressData
+        self.sendGameServerString(pack, CommonDefine.dgGameServerData, SendData)
+        mylog.info('Game server player data send ok! len = %d'%(len(data)))
+    
+    def onSaveGameServerData(self, db, pack):
+#//数据库保存gamedata#tagGDGameServerGameData
+#
+#struct    tagGDPlayerGameData
+#{
+#    DWORD        PlayerID;
+#    DWORD        DataLen;
+#    char        Data[DataLen];        //size = DataLen
+#};
+#
+#struct    tagGBGameServerBackUpData
+#{
+#    DWORD        GameDataLen;
+#    char        GameData[GameDataLen];        //size = GameDataLen
+#    WORD        PlayerGameDataCount;
+#    tagGDPlayerGameData        PlayerGameData[PlayerGameDataCount];        //size = PlayerGameDataCount
+#};
+#
+#struct    tagGDGameServerGameData
+#{
+#    WORD        Mark;
+#    WORD        VersionNO;        //版本号
+#    DWORD        CRC;
+#    tagGBGameServerBackUpData        GameServerBackUpData;
+#};
+#        //GameServer保存数据#tagGameServerToBalanceServerSaveData
+#struct      tagGameServerToBalanceServerSaveData
+#{
+#    BYTE    PackDir;
+#    BYTE    PackType;
+#    BYTE    NeedReturn;
+#    BYTE    Type;
+#    String  Data;
+#};
+        #这个封包特殊,无法自动生成代码
+        pos = 1    #跳过gstSaveGameServerData
+        #tagGameServerToBalanceServerSaveData
+        needReturn, pos = CommFunc.ReadBYTE(pack.getBuffer(), pos)
+        type, pos = CommFunc.ReadBYTE(pack.getBuffer(), pos)
+        self.saveGameServerGameData(db, pack, pack.getBuffer(), pos, type, needReturn)
+            
+    def saveGameServerGameData(self, db, pack, data, pos, saveType, needReturn):
+        if saveType == CommonDefine.dgGameServerCrashData:
+            #FileLog.getLogger('GameServerDataRestoreLog').info('解析崩溃数据中。。。')
+            #tagGDGameServerGameData
+            mark, pos = CommFunc.ReadWORD(data, pos)
+            versionNO, pos = CommFunc.ReadWORD(data, pos)
+            crc, pos = CommFunc.ReadDWORD(data, pos)
+            #tagGBGameServerBackUpData
+            gameDataLen, pos = CommFunc.ReadDWORD(data, pos)
+            gameData, pos = CommFunc.ReadString(data, pos, gameDataLen)
+            
+            #===================================================================
+            # #暂无GameServer个人信息
+            # playerGameDataCount, pos = CommFunc.ReadWORD(data, pos)
+            # playerSaveDataList = []
+            # for recIndex in xrange(playerGameDataCount):
+            #    #tagGDPlayerGameData
+            #    playerID, pos = CommFunc.ReadDWORD(data, pos)
+            #    playerDataLen, pos = CommFunc.ReadDWORD(data, pos)
+            #    playerData, pos = CommFunc.ReadString(data, pos, playerDataLen)
+            # 
+            #    SinglePlayerSaveData = (playerID, playerData)
+            #    playerSaveDataList.append(SinglePlayerSaveData)
+            #===================================================================
+            #数据版本校验
+            if gameDataLen:
+                if not versionNO == VersionNoDefine.GAMESERVER_GAMEWORLD_DATA_VERSION_NO:
+                    msg = error.formatMsg('fatal', error.ERROR_NO_76, 'Save game server crash data error:data version conflict!versionNO = %s, db version = %s'%(versionNO, VersionNoDefine.GAMESERVER_GAMEWORLD_DATA_VERSION_NO))
+                    mylog.fatal(msg)
+                    FileLog.getLogger('GameServerDataRestoreLog').fatal('崩溃数据版本号校验失败(如果是更新版本,请启动旧版本服务器导入崩溃数据试试)')
+                    #数据是压缩数据
+                    DataDumper.DumpData(os.path.join(GlobalFunctions.getAppPath(), CommonDefine.DUMP_PATH), 'tagGDGameServerGameData', '0.mdat', data)
+                    return True
+                #校验通过,存到数据库
+                #存储世界数据
+                try:
+                    mylog.debug("Compress GameData = %s"%b2a_hex(gameData))
+                    decompressGameData = zlib.decompress(gameData)
+                    pyDataLen, pyDataHex = decompressGameData.split('|', 1)
+                    pyDataLen = int(pyDataLen)
+                    mylog.debug("disCompresspydata len %s, GameData = %s"%(pyDataLen, pyDataHex[:pyDataLen]))
+                    decompressGameData = binascii.a2b_hex(pyDataHex[:pyDataLen]) + pyDataHex[pyDataLen:]
+                except:
+                    msg = error.formatMsg('error', error.ERROR_NO_77, 'Decompress game server world data failed!error = \n%s'%traceback.format_exc())
+                    mylog.error(msg)
+                    FileLog.getLogger('GameServerDataRestoreLog').fatal('崩溃数据解压失败,可能是数据损坏.')
+                else:
+                    #成功解压,存到数据库
+                    #FileLog.getLogger('GameServerDataRestoreLog').info('崩溃数据解压成功!开始保存。。。')
+                    mylog.info('Decompress game server world data success, len = %d!saving...'%len(decompressGameData))
+                    mylog.debug("GameData = %s"%b2a_hex(decompressGameData))
+                    gameDataReadPos = 0
+                    try:
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyXMZZ, DataServerPlayerData.tagDBPyXMZZ, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPySealDemonRecord, DataServerPlayerData.tagDBPySealDemonRecord, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyBossAttention, DataServerPlayerData.tagDBPyBossAttention, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyBourseItemLastPrice, DataServerPlayerData.tagDBPyBourseItemLastPrice, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyBourseRecord, DataServerPlayerData.tagDBPyBourseRecord, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyFamilyStoreItem, DataServerPlayerData.tagDBPyFamilyStoreItem, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyPlayerFriend, DataServerPlayerData.tagDBPyPlayerFriend, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_PlayerEnemy, DataServerPlayerData.tagPlayerEnemy, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyPlayerContacts, DataServerPlayerData.tagDBPyPlayerContacts, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyPlayerBlack, DataServerPlayerData.tagDBPyPlayerBlack, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_PersonalSocial, DataServerPlayerData.tagPersonalSocial, db)
+                        
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_PlayerTeamTable, DataServerPlayerData.tagPlayerTeamTable, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_TeamMemberTable, DataServerPlayerData.tagTeamMemberTable, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_FamilyInfo, DataServerPlayerData.tagFamilyInfo, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_PlayerFamily, DataServerPlayerData.tagPlayerFamily, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBFamilyVS, DataServerPlayerData.tagDBFamilyVS, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameWorldEvent, DataServerPlayerData.tagGameWorldEvent, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBMissionPub, DataServerPlayerData.tagDBMissionPub, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBIPManage, DataServerPlayerData.tagDBIPManage, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBGameServerEventTrig, DataServerPlayerData.tagDBGameServerEventTrig, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBCountryInfo, DataServerPlayerData.tagDBCountryInfo, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBCountryFamilyWarResult, DataServerPlayerData.tagDBCountryFamilyWarResult, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBCountryFamilyWarRace, DataServerPlayerData.tagDBCountryFamilyWarRace, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBCountryFamilyWarRequest, DataServerPlayerData.tagDBCountryFamilyWarRequest, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBBillboard, DataServerPlayerData.tagDBBillboard, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBGoldOrderForm, DataServerPlayerData.tagDBGoldOrderForm, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBOverdueGoldOrderForm, DataServerPlayerData.tagDBOverdueGoldOrderForm, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBUnclaimedGoldForm, DataServerPlayerData.tagDBUnclaimedGoldForm, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBFamilyTech, DataServerPlayerData.tagDBFamilyTech, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPlayerLabel, DataServerPlayerData.tagDBPlayerLabel, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPlayerRecall, DataServerPlayerData.tagDBPlayerRecall, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBVsReward, DataServerPlayerData.tagDBVsReward, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBFamilyReward, DataServerPlayerData.tagDBFamilyReward, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBFamilyRewardRec, DataServerPlayerData.tagDBFamilyRewardRec, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBFamilyAction, DataServerPlayerData.tagDBFamilyAction, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameFBPassRec, DataServerPlayerData.tagGameFBPassRec, db)                        
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_UniversalGameRec, DataServerPlayerData.tagUniversalGameRec, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameGroup, DataServerPlayerData.tagGameGroup, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameGroupMember, DataServerPlayerData.tagGameGroupMember, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameGroupMutualInfo, DataServerPlayerData.tagGameGroupMutualInfo, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameBourseItem, DataServerPlayerData.tagGameBourseItem, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_HighLadderPlayer, DataServerPlayerData.tagHighLadderPlayer, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBHighLadderItem, DataServerPlayerData.tagDBHighLadderItem, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_HighLadderVSRec, DataServerPlayerData.tagHighLadderVSRec, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBCompensationItem, DataServerPlayerData.tagDBCompensationItem, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPersonalCompensation, DataServerPlayerData.tagDBPersonalCompensation, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBEntireCompensationRequire, DataServerPlayerData.tagDBEntireCompensationRequire, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_CompensationPlayerRec, DataServerPlayerData.tagCompensationPlayerRec, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_PlayerViewCache, DataServerPlayerData.tagPlayerViewCache, db)
+                        
+                        
+                        #gameDataReadPos = self.savePlayerDeleteFriendData(decompressGameData, gameDataReadPos, RecvPackProtocol.tagDeleteFriendKey, UCN_PlayerFriend, db) 
+                        mylog.info('Save game server world data ok!')
+                        FileLog.getLogger('GameServerDataRestoreLog').info('系统崩溃数据保存成功!')
+                    except CommonDefine.ShortBuf:
+                        msg = error.formatMsg('error', error.ERROR_NO_78, 'Short data buf, ignore...')
+                        mylog.error(msg)
+                        FileLog.getLogger('GameServerDataRestoreLog').fatal('崩溃数据可能不完整')
+                    #===========================================================
+                    # FileLog.getLogger('GameServerDataRestoreLog').info('本次GameServer崩溃数据包含以下%s个玩家数据'%len(playerSaveDataList))
+                    # mylog.info('Saving game server player data,playerCnt = %s'%len(playerSaveDataList))
+                    # #存储玩家数据
+                    # for rec in playerSaveDataList:
+                    #    playerID, playerSaveData = rec
+                    #    playerDataReadPos = 0
+                    #    try:
+                    #        playerDataReadPos = self.saveGameServerPlayerData(playerID, playerSaveData, playerDataReadPos, 'tagPlayerEnemy', DataServerPlayerData.tagPlayerEnemy, db)
+                    #        playerDataReadPos = self.saveGameServerPlayerData(playerID, playerSaveData, playerDataReadPos, 'tagPlayerFriend', DataServerPlayerData.tagPlayerFriend, db)
+                    #    except CommonDefine.ShortBuf:
+                    #        msg = error.formatMsg('error', error.ERROR_NO_79, 'Not completed player data found!PlayerID = %s data = %s'%(playerID, playerSaveData))
+                    #        mylog.error(msg)
+                    #        FileLog.getLogger('GameServerDataRestoreLog').fatal('本次GameServer崩溃数据的玩家好友和仇人数据可能不完整!')
+                    #        continue
+                    #    FileLog.getLogger('GameServerDataRestoreLog').info('PlayerID = %s'%(playerID))
+                    #===========================================================
+                    FileLog.getLogger('GameServerDataRestoreLog').info('本次GameServer崩溃数据保存成功!')
+                    mylog.info('Save game server player data ok!')
+            else:
+                #mylog.info('Empty crash data,ignore...')
+                FileLog.getLogger('GameServerDataRestoreLog').info('无崩溃数据...')
+            #回报
+            sendPack = SendPackProtocol.tagDBUpdateReturn()
+            sendPack.CallType = CommonDefine.dgUpDate
+            sendPack.UpdateType = CommonDefine.gstSaveGameServerCrashData
+            sendPack.Result = 1
+            self.packSend(pack.getSessionID(), pack.getPackHead().sessionID,
+                      pack.getPackHead().poolIndex, pack.getPackHead().type,
+                      pack.getPackHead().srcSvrType, pack.getPackHead().dstSvrType,
+                      sendPack.GetBuffer())
+        elif saveType == 0:
+            #tagGameServerToBalanceServerSaveData
+            gameData = data[pos:]
+            decompressGameDataLen = 0
+            if gameData:
+                #存储世界数据
+                try:
+                    mylog.debug("Compress len %s, GameData = %s"%(len(gameData), b2a_hex(gameData)))
+                    decompressGameData = zlib.decompress(gameData)
+                    pyDataLen, pyDataHex = decompressGameData.split('|', 1)
+                    pyDataLen = int(pyDataLen)
+                    mylog.debug("disCompresspydata len %s, GameData = %s"%(pyDataLen, pyDataHex[:pyDataLen]))
+                    decompressGameData = binascii.a2b_hex(pyDataHex[:pyDataLen]) + pyDataHex[pyDataLen:]
+                    
+                except:
+                    msg = error.formatMsg('error', error.ERROR_NO_80, 'Decompress game server world data failed! error = \n%s'%traceback.format_exc())
+                    mylog.error(msg)
+                else:
+                    #成功解压,存到数据库
+                    decompressGameDataLen = len(decompressGameData)
+                    mylog.info('Decompress game server world data success, len = %s!saving...'%decompressGameDataLen)
+                    mylog.debug("GameData = %s"%b2a_hex(decompressGameData))
+                    gameDataReadPos = 0
+                    try:
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyXMZZ, DataServerPlayerData.tagDBPyXMZZ, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPySealDemonRecord, DataServerPlayerData.tagDBPySealDemonRecord, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyBossAttention, DataServerPlayerData.tagDBPyBossAttention, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyBourseItemLastPrice, DataServerPlayerData.tagDBPyBourseItemLastPrice, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyBourseRecord, DataServerPlayerData.tagDBPyBourseRecord, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyFamilyStoreItem, DataServerPlayerData.tagDBPyFamilyStoreItem, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyPlayerFriend, DataServerPlayerData.tagDBPyPlayerFriend, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_PlayerEnemy, DataServerPlayerData.tagPlayerEnemy, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyPlayerContacts, DataServerPlayerData.tagDBPyPlayerContacts, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPyPlayerBlack, DataServerPlayerData.tagDBPyPlayerBlack, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_PersonalSocial, DataServerPlayerData.tagPersonalSocial, db)
+                        
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_PlayerTeamTable, DataServerPlayerData.tagPlayerTeamTable, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_TeamMemberTable, DataServerPlayerData.tagTeamMemberTable, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_FamilyInfo, DataServerPlayerData.tagFamilyInfo, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_PlayerFamily, DataServerPlayerData.tagPlayerFamily, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBFamilyVS, DataServerPlayerData.tagDBFamilyVS, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameWorldEvent, DataServerPlayerData.tagGameWorldEvent, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBMissionPub, DataServerPlayerData.tagDBMissionPub, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBIPManage, DataServerPlayerData.tagDBIPManage, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBGameServerEventTrig, DataServerPlayerData.tagDBGameServerEventTrig, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBCountryInfo, DataServerPlayerData.tagDBCountryInfo, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBCountryFamilyWarResult, DataServerPlayerData.tagDBCountryFamilyWarResult, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBCountryFamilyWarRace, DataServerPlayerData.tagDBCountryFamilyWarRace, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBCountryFamilyWarRequest, DataServerPlayerData.tagDBCountryFamilyWarRequest, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBBillboard, DataServerPlayerData.tagDBBillboard, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBGoldOrderForm, DataServerPlayerData.tagDBGoldOrderForm, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBOverdueGoldOrderForm, DataServerPlayerData.tagDBOverdueGoldOrderForm, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBUnclaimedGoldForm, DataServerPlayerData.tagDBUnclaimedGoldForm, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBFamilyTech, DataServerPlayerData.tagDBFamilyTech, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPlayerLabel, DataServerPlayerData.tagDBPlayerLabel, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPlayerRecall, DataServerPlayerData.tagDBPlayerRecall, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBVsReward, DataServerPlayerData.tagDBVsReward, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBFamilyReward, DataServerPlayerData.tagDBFamilyReward, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBFamilyRewardRec, DataServerPlayerData.tagDBFamilyRewardRec, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBFamilyAction, DataServerPlayerData.tagDBFamilyAction, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameFBPassRec, DataServerPlayerData.tagGameFBPassRec, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_UniversalGameRec, DataServerPlayerData.tagUniversalGameRec, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameGroup, DataServerPlayerData.tagGameGroup, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameGroupMember, DataServerPlayerData.tagGameGroupMember, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameGroupMutualInfo, DataServerPlayerData.tagGameGroupMutualInfo, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_GameBourseItem, DataServerPlayerData.tagGameBourseItem, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_HighLadderPlayer, DataServerPlayerData.tagHighLadderPlayer, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBHighLadderItem, DataServerPlayerData.tagDBHighLadderItem, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_HighLadderVSRec, DataServerPlayerData.tagHighLadderVSRec, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBCompensationItem, DataServerPlayerData.tagDBCompensationItem, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBPersonalCompensation, DataServerPlayerData.tagDBPersonalCompensation, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_DBEntireCompensationRequire, DataServerPlayerData.tagDBEntireCompensationRequire, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_CompensationPlayerRec, DataServerPlayerData.tagCompensationPlayerRec, db)
+                        gameDataReadPos = self.savegameServerWorldData(decompressGameData, gameDataReadPos, UCN_PlayerViewCache, DataServerPlayerData.tagPlayerViewCache, db)
+                        
+                                  
+                        #gameDataReadPos = self.savePlayerDeleteFriendData(decompressGameData, gameDataReadPos, RecvPackProtocol.tagDeleteFriendKey, UCN_PlayerFriend, db)
+                        mylog.info('Save game server world data ok!')
+                    except CommonDefine.ShortBuf:
+                        msg = error.formatMsg('error', error.ERROR_NO_81, 'Short data buf, ignore...')
+                        mylog.error(msg)
+  
+            else:
+                mylog.info('Empty crash data,ignore...')
+            #回报
+            if needReturn == 1:
+                sendPack = SendPackProtocol.tagDBUpdateReturn()
+                sendPack.CallType = CommonDefine.dgUpDate
+                sendPack.UpdateType = CommonDefine.gstSaveGameServerData
+                sendPack.Result = 1
+                self.packSend(pack.getSessionID(), pack.getPackHead().sessionID,
+                          pack.getPackHead().poolIndex, pack.getPackHead().type,
+                          pack.getPackHead().srcSvrType, pack.getPackHead().dstSvrType,
+                          sendPack.GetBuffer())
+                mylog.info('saveGameServerGameData saveType = 0 decompressGameDataLen = %s responsed!'%decompressGameDataLen)
+            
+        elif saveType == CommonDefine.dgPlayerMailList:
+            self.savePlayerMailData(data[pos:], "tagDBMailList", DataServerPlayerData.tagDBMailList, db)
+        elif saveType == CommonDefine.dgPlayerMailItemList:
+            self.savePlayerMailData(data[pos:], "tagDBMailItemList", DataServerPlayerData.tagDBMailItemList, db)
+        else:
+            mylog.warning('saveType = %s not processed!'%saveType)
+    
+    def saveGameServerPlayerData(self, playerID, data, pos, collectionName, structName, db):
+        if pos >= len(data):
+            raise CommonDefine.ShortBuf(collectionName)
+        recCnt, pos = CommFunc.ReadDWORD(data, pos)
+        mylog.info('Saving %s cnt = %s playerID = %s'%(collectionName, recCnt, playerID))
+        #删除旧数据
+        collection = db[collectionName]
+        rec = structName()
+        rec.PlayerID = playerID
+        rec.adoDeleteByIndex(collection)
+        #插入新数据
+        docs = []
+        for i in xrange(0, recCnt):
+            rec.clear()
+            readLen = rec.readData(data, pos, len(data))
+            if readLen == -1:
+                raise CommonDefine.ShortBuf(collectionName)
+            pos += readLen
+            docs.append(rec.getRecord())
+        
+        if not docs:
+            return pos
+        
+        trycnt = 0
+        while(True):
+            try:
+                collection.insert(docs, False, True)
+                break
+            except pymongo.errors.PyMongoError, err:
+
+                if(DBConfig.TryCntOnWriteFail > trycnt):
+                    trycnt += 1
+                    continue
+                    
+                addADOExceptionCount()
+                mylog.info("%s.%s:rec = %s"%(self.__class__.__name__, inspect.stack()[0][3], rec))
+                msg = error.formatMsg('error', error.ERROR_NO_152, 'Insert failed!PlayerID = %s, error = %s, trycnt = %d'%(playerID, err, trycnt))
+                mylog.error(msg)
+
+                return pos
+            
+        return pos
+        
+    def savegameServerWorldData(self, data, pos, collectionName, structName, db):
+        if pos >= len(data):
+            mylog.info('!!!Saving Error %s cnt = %s'%(collectionName, pos)) 
+            raise CommonDefine.ShortBuf(collectionName)
+        recCnt, pos = CommFunc.ReadDWORD(data, pos)
+        mylog.info('Saving %s cnt = %s'%(collectionName, recCnt)) 
+        
+#        structNameParts = structName.split('.')
+#        collectionnName = structNameParts[len(structNameParts) - 1]
+        collection = db[collectionName]
+        db.drop_collection(collection)
+        
+        docs = []
+        rec = structName()
+        for i in xrange(0, recCnt):
+            rec.clear()
+            readLen = rec.readData(data, pos, len(data))
+            rec.dumpString()
+            if -1 == readLen:
+                mylog.error('%s.%s readData failed, index = %s'%(self.__class__.__name_, inspect.stack()[0][3], i) )
+                raise CommonDefine.ShortBuf(collectionName)    #如果读取出错,后面全错了
+            pos += readLen
+#            rec.adoInsert(collection)
+            #优化,改成批插入
+            docs.append(rec.getRecord())
+        
+        if not docs:
+            return pos
+        
+        trycnt = 0
+        while True:
+            try:
+                collection.insert(docs, False, True)
+                break
+            except pymongo.errors.OperationFailure, err:
+                if(DBConfig.TryCntOnWriteFail > trycnt):
+                    trycnt += 1
+                    continue
+                addADOExceptionCount()
+                mylog.info("%s.%s save %s failed!"%(self.__class__.__name__, inspect.stack()[0][3], docs))
+                mylog.error('%s.%s, error = %s, trycnt = %s'%(self.__class__.__name__, inspect.stack()[0][3], err, trycnt))
+                return pos
+            
+        return pos      
+    
+    def savePlayerDeleteFriendData(self, data, pos, packStruct, collectionName, db):
+        if pos >= len(data):
+            raise CommonDefine.ShortBuf(collectionName)
+        recCnt, pos = CommFunc.ReadDWORD(data, pos)
+        mylog.info('Saving PlayerDeleteFriend data Cnt = %s'%recCnt)
+        
+        collection = db[collectionName]
+        rec = packStruct()
+        #playerFriend = structName()
+        for i in xrange(0, recCnt):
+            readLen = rec.ReadData(data, pos, len(data))
+            if -1 == readLen:
+                raise CommonDefine.ShortBuf(collectionName)
+            pos += readLen
+            #删除好友
+            #playerFriend.PlayerID = rec.PlayerID
+            #playerFriend.FriendID = rec.FriendID
+            trycnt = 0
+            while True:
+                try:
+                    collection.remove({'PlayerID':rec.PlayerID, 'FriendID':rec.FriendID})
+                    collection.remove({'PlayerID':rec.FriendID, 'FriendID':rec.PlayerID})
+                    break
+                except pymongo.errors.OperationFailure, err:
+                    if(DBConfig.TryCntOnWriteFail > trycnt):
+                        trycnt += 1
+                    continue
+                    addADOExceptionCount()
+                    mylog.info("%s.%s:PlayerID = %s"%(self.__class__.__name__, inspect.stack()[0][3], rec.PlayerID))
+                    mylog.error('delete failure!PlayerID = %s, error = %s, trycnt = %d'%(rec.PlayerID, err, trycnt))
+                    return pos         
+        return pos
+    
+    def savePlayerMailData(self, data, collectionName, structName, db):
+        if data:
+            if len(data) < 4:
+                msg = error.formatMsg('error', error.ERROR_NO_82, "invalid player mail data, collectionName = %s", collectionName)
+                mylog.error(msg)
+                return
+            
+            pos = 0
+            recCnt, pos = CommFunc.ReadDWORD(data, pos)
+            mylog.info('Saving %s cnt = %s'%(collectionName, recCnt)) 
+            
+    #        structNameParts = structName.split('.')
+    #        collectionnName = structNameParts[len(structNameParts) - 1]
+            collection = db[collectionName]
+#            db.drop_collection(collection)
+            
+            rec = structName()
+            datalen = len(data)
+            for i in xrange(recCnt):
+                rec.clear()
+                readLen = rec.readData(data, pos, datalen)
+                if -1 == readLen:
+                    raise CommonDefine.ShortBuf(collectionName)    #如果读取出错,后面全错了
+                pos += readLen
+                rec.adoInsert(collection)             
+        else:
+            mylog.info("empty player mail list data, collectionName = %s", collectionName)   
+        
+    # loginserver发来的 帐号最开始只在运营商那边
+    def OnInsertAcc(self, db, pack):
+        data = pack.getBuffer()
+        pos = 0
+        datalen = len(data)
+        try:
+            oTypeSend = RecvPackProtocol.tagBDStringTypeSend()
+            pos = oTypeSend.ReadData(data, pos, datalen)
+            
+            Acc = DataServerPlayerData.tagDSAccount()
+            Acc.readData(oTypeSend.Data, 0, oTypeSend.DataLen)
+            Acc.RegisterTime= CommFuncEx.TDateTimeToString(CommFuncEx.TDateTime_Now()) 
+            collection = db[UCN_DSAccount]
+            if not Acc.adoInsertC(collection):
+                self.sendFailString(CommonDefine.dgInsertAcc, pack, 0)
+                return False
+
+            self.sendOKString(CommonDefine.dgInsertAcc, pack, "")     
+            return True
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_83, "Insert Acc failed, accid = %s, error = \n%s"%(Acc.ACCID, traceback.format_exc()))
+            mylog.error(msg)
+        return False
+    
+    def OnPlayerIDMarkDeleted(self, db, pack):
+        data = pack.getBuffer()
+        datalen = len(data)
+        pos = 0
+        try:
+            oMarkPlayerDeleted = RecvPackProtocol.tagMarkPlayerDeleted()
+            pos = oMarkPlayerDeleted.ReadData(data, pos, datalen)
+            
+            col = db[UCN_DBPlayer]
+            oPlayer = DataServerPlayerData.tagDBPlayer()
+            oPlayer.PlayerID = oMarkPlayerDeleted.PlayerID 
+            SidErrorCnt = getSIDErrorCnt()
+            if not oPlayer.adoLoadC(col):
+                if SidErrorCnt == getSIDErrorCnt():
+                    return False
+                if DBConfig.checkSID:
+                    return False
+            
+            oPlayer.IsDeleted = 1
+            if not oPlayer.adoUpdateExC(col, {'AccID':fix_incomingText(oPlayer.AccID), 'PlayerID':oPlayer.PlayerID}):
+                return False
+            
+            #=======================================================================================
+            # oDBServerLogRec = RecvPackProtocol.tagDBServerLogRec()
+            # oDBServerLogRec.Type = CommonDefine.gstSavePlayerLog
+            # oDBServerLogRec.Oper = 81
+            # oDBServerLogRec.Time = time()
+            # oDBServerLogRec.MapID = 1
+            # oDBServerLogRec.PlayerID = oMarkPlayerDeleted.PlayerID
+            # 
+            # self.sendDBRequest(oDBServerLogRec.GetBuffer())
+            #=======================================================================================
+            return True            
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_84, "OnPlayerIDMarkDeleted failed! Playerid = %d, exception = %s"%(oMarkPlayerDeleted.PlayerID, traceback.format_exc()))
+            mylog.error(msg)
+        
+        return False
+    
+    def OnGetCoin(self, db, pack):
+        try:
+            oDGetValueByAcc = RecvPackProtocol.tagDGetValueByAcc()
+            oDGetValueByAcc.ReadData(pack.getBuffer())
+            
+            col = db[UCN_AccCoins]
+            oAccCoins = DataServerPlayerData.tagAccCoins()
+            oAccCoins.AccID = oDGetValueByAcc.Acc
+            if not oAccCoins.adoLoad(col):
+                mylog.info("gstGetCoin, not found match record")
+                return False
+            
+            mylog.info("Type = %d, AccId = %s, GoldCoins = %d"%(CommonDefine.gstGetCoin, oDGetValueByAcc.Acc, oAccCoins.GoldCoins))
+            
+            #返回点券数目
+            oSvrValue = SendPackProtocol.tagDServerValueType()
+            oSvrValue.Type = CommonDefine.dgCoin
+            oSvrValue.Value = oAccCoins.GoldCoins
+            
+            self.sendString(pack, oSvrValue.GetBuffer())
+            mylog.info("process gstGetCoin ok")
+            return True
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_85, "OnGetCoin catch excepption, error = \n%s"%traceback.format_exc())
+            mylog.error(msg)
+        
+        return False
+    
+    def OnCoinChange(self, db, pack):
+        try:
+            oCoinChangeReq = RecvPackProtocol.tagMDCoinChangeReq()
+            oCoinChangeReq.ReadData(pack.getBuffer())
+            mylog.info("gstCoinChange, AccId = %s, PlayerID = %d, coin = %d"%(oCoinChangeReq.Acc, oCoinChangeReq.PlayerID, oCoinChangeReq.Coin))
+            
+            col = db[UCN_AccCoins]
+            oAccCoins = DataServerPlayerData.tagAccCoins()
+            oAccCoins.AccID = oCoinChangeReq.Acc
+            
+            retPack = SendPackProtocol.tagDServerValueType()
+            retPack.Type = CommonDefine.dgCoinChangeResult
+            if not oAccCoins.adoLoad(col):
+                mylog.info("gstGetCoin, not found match record")
+                self.sendString(pack, retPack.GetBuffer())
+                return False
+            
+            mylog.info("Type = %d, AccId = %s, PlayerID = %d,  Before exchange GoldCoins = %d"%(CommonDefine.gstCoinChange, oCoinChangeReq.Acc, oCoinChangeReq.PlayerID, oAccCoins.GoldCoins))
+                      
+            if oCoinChangeReq.Coin > oAccCoins.GoldCoins:
+                mylog.info("not enough coin to exchange")
+                self.sendString(pack, retPack.GetBuffer())
+                return False
+                
+            oAccCoins.GoldCoins -= oCoinChangeReq.Coin
+            oAccCoins.UseGoldCoins += oCoinChangeReq.Coin
+            
+            if not oAccCoins.adoUpdate(col):
+                self.sendString(pack, retPack.GetBuffer())
+                msg = error.formatMsg('error', error.ERROR_NO_87, "Type = %d, AccId = %s, PlayerID = %d,  update exchange GoldCoins fail"%(CommonDefine.gstCoinChange, oCoinChangeReq.Acc, oCoinChangeReq.PlayerID))
+                mylog.error(msg)
+                return False            
+            
+            #兑换成功
+            retPack.Value = oCoinChangeReq.Coin
+            self.sendString(pack, retPack.GetBuffer())
+            
+            #刷新点券
+            retPack.Type = CommonDefine.dgCoin
+            retPack.Value = oAccCoins.GoldCoins
+            self.sendString(pack, retPack.GetBuffer())  
+             
+            #记录玩家操作日志
+            #=======================================================================================
+            # oDBServerLogRec = RecvPackProtocol.tagDBServerLogRec()
+            # oDBServerLogRec.Type = CommonDefine.gstSavePlayerLog
+            # oDBServerLogRec.Oper = 135 #135       从商城兑换的点券
+            # oDBServerLogRec.Time = time()
+            # oDBServerLogRec.MapID = 1
+            # oDBServerLogRec.PlayerID = oCoinChangeReq.PlayerID
+            # oDBServerLogRec.Msg = "AccID = %s, coin = %d"%(oCoinChangeReq.Acc, oCoinChangeReq.Coin)            
+            # oDBServerLogRec.MsgLen = len(oDBServerLogRec.Msg)   
+            # self.sendDBRequest(oDBServerLogRec.GetBuffer())
+            #=======================================================================================
+            
+            # 记录玩家点券变化日志
+            oDBPlayerLogInfoOnCoinChange = DataServerLogData.tagDBPlayerLogInfoOnCoinChange()             
+            oDBPlayerLogInfoOnCoinChange.AccID = oCoinChangeReq.Acc
+            oDBPlayerLogInfoOnCoinChange.Coin = oCoinChangeReq.Coin
+            self.sendDBRequest(chr(CommonDefine.gstSavePlayerInfoLogOnOnCoinChange) + oDBPlayerLogInfoOnCoinChange.getBuffer())
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_88, "OnCoinChange throw exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False
+        return True
+    
+    def OnCheckPlayerExist(self, db, pack):
+        try:
+            curPack = RecvPackProtocol.tagBDCheckNameExist()
+            curPack.ReadData(pack.getBuffer())
+            
+            retPack = SendPackProtocol.tagDBPlayerNameIsExist()
+            
+            oPlayer = DataServerPlayerData.tagDBPlayer()
+            oPlayer.PlayerName = curPack.Name
+            oPlayer.IsDeleted = 0
+            col = db[UCN_DBPlayer]
+            
+            retPack.CallType = CommonDefine.dgCheckPlayerExist
+            retPack.Name = curPack.Name
+            retPack.NameLen = len(retPack.Name)
+            retPack.Result = oPlayer.adoLoadCEx(col, {'PlayerName':fix_incomingText(oPlayer.PlayerName), 'IsDeleted':oPlayer.IsDeleted})
+            retPack.PlayerID = oPlayer.PlayerID   
+            self.sendString(pack, retPack.GetBuffer())
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_89, "OnCheckPlayerExist catch exception\n%s"%traceback.format_exc())
+            mylog.error(msg)            
+            return False
+        return True
+    
+    def OnDay(self, db, pack):
+        mylog.warning("process gstOnDay in the future!")
+        
+        #触发调用EventShell事件
+        if DBConfig.EventShellEnable:
+            try:
+                EventProcess.OnDayProcess(db)
+            except:
+                msg = error.formatMsg('error', error.ERROR_NO_161, "OnDay EventProcess.OnDayProcess catch exception\n%s"%traceback.format_exc())
+                mylog.error(msg)    
+            return
+        
+    def OnSavePlayerGMOPer(self, db, pack):
+        data = pack.getBuffer()
+        pos = 1
+        PlayerId, pos = CommFunc.ReadDWORD(data, pos)
+        if -1 == self.savePlayerData(PlayerId, db, "tagGMOper", DataServerPlayerData.tagGMOper, data[pos:]):
+            msg = error.formatMsg('error', error.ERROR_NO_90, "Save Player GM Oper failed, playerid = %d"%PlayerId)
+            mylog.error(msg)
+            return False
+        return True
+    
+    def OnGetExpiationCount(self, db, pack):
+        curPack = RecvPackProtocol.tagDGetValueByAcc()
+        curPack.ReadData(pack.getBuffer())
+        
+        col = db[UCN_Expiation]
+#        col.ensure_index('AccID')
+        recCount = col.find({'AccID':fix_incomingText(curPack.Acc)}).count()
+
+        retPack = SendPackProtocol.tagDServerValueType()
+        retPack.Type = CommonDefine.dgGetExpiationCount
+        retPack.Value = recCount
+        self.sendString(pack, retPack.GetBuffer())
+        return True
+    
+    def OnGetPetExpiationCount(self, db, pack):
+        curPack = RecvPackProtocol.tagDGetValueByAcc()
+        curPack.ReadData(pack.getBuffer())
+        
+        col = db[UCN_PetExpiation]
+#        col.ensure_index('AccID')
+        recCount = col.find({'AccID':fix_incomingText(curPack.Acc)}).count()
+
+        retPack = SendPackProtocol.tagDServerValueType()
+        retPack.Type = CommonDefine.dgGetPetExpiationCount
+        retPack.Value = recCount
+        self.sendString(pack, retPack.GetBuffer())
+        return True
+    
+    def OnGetExpiation(self, db, pack):
+        
+        curPack = RecvPackProtocol.tagMDGetExpiationEx()
+        curPack.ReadData(pack.getBuffer())
+        needCount = curPack.Count #一次希望获取的补偿个数
+        
+        #创建回包
+        sendPack = SendPackProtocol.tagDMGetExpiationExResult()
+        sendPack.Type = CommonDefine.dgGetExpiation
+        sendPack.Count = 0
+        #查询用
+        collection = db[UCN_Expiation]
+#        collection.ensure_index('AccID')
+        expiations = collection.find({"AccID":fix_incomingText(curPack.Acc)})
+        #删除用
+        colDel = db[UCN_Expiation]
+        
+        for curData in expiations:
+            if sendPack.Count >= needCount:
+                break
+            expiation = SendPackProtocol.tagExpiation()
+            expiation.ExpiationIndex = curData["ExpiationIndex"]
+            expiation.AccID = fix_outgoingText(curData["AccID"])
+            expiation.ExpiationTime = curData["ExpiationTime"]
+            expiation.Gold = curData["Gold"]
+            expiation.GoldPaper = curData["GoldPaper"]
+            expiation.Silver = curData["Silver"]
+            expiation.SilverPaper = curData["SilverPaper"]
+            expiation.ItemTypeID = curData["ItemTypeID"]
+            expiation.Count = curData["Count"]
+            expiation.IsLocked = curData["IsLocked"]
+            expiation.ItemPlaceType = curData["ItemPlaceType"]
+            expiation.ItemPlaceIndex = curData["ItemPlaceIndex"]
+            expiation.IsBind = curData["IsBind"]
+            expiation.ItemStarLV = curData["ItemStarLV"]
+            expiation.IdentifyPar = curData["IdentifyPar"]
+            expiation.CurDurg = curData["CurDurg"]
+            expiation.MaxDurg = curData["MaxDurg"]
+            expiation.CanPlaceStoneCount = curData["CanPlaceStoneCount"]
+            expiation.ItemProperty = curData["ItemProperty"]
+            expiation.SoulProperty = curData["SoulProperty"]
+            expiation.Maker = curData["Maker"]
+            expiation.MakerName = fix_outgoingText(curData["MakerName"])
+            expiation.Stone1 = curData["Stone1"]
+            expiation.Stone2 = curData["Stone2"]
+            expiation.Stone3 = curData["Stone3"]
+            expiation.Stone4 = curData["Stone4"]
+            expiation.Stone5 = curData["Stone5"]
+            expiation.Stone6 = curData["Stone6"]
+            expiation.Stone7 = curData["Stone7"]
+            expiation.Stone8 = curData["Stone8"]
+            expiation.Stone9 = curData["Stone9"]
+            expiation.RemainHour = curData["RemainHour"]
+            expiation.CreateTime = fix_outgoingText(curData["CreateTime"])
+            expiation.ElementEffect = curData["ElementEffect"]
+            expiation.IsSuite = curData["IsSuite"]
+            expiation.FitLV = curData["FitLV"]
+            expiation.EquipAddSkillCnt = curData["EquipAddSkillCnt"]
+            expiation.ExpireTime = curData["ExpireTime"]
+            expiation.BaseAtkPlus = curData["BaseAtkPlus"]
+            expiation.BaseDefPlus = curData["BaseDefPlus"]
+            expiation.AddSkillData = fix_outgoingText(curData["AddSkillData"])
+            expiation.BaseHP = curData["BaseHP"]
+            expiation.BaseMagicDef = curData["BaseMagicDef"]
+            expiation.EquipMinAtkValue = curData["EquipMinAtkValue"]
+            expiation.Proficiency = curData["Proficiency"]
+            expiation.RelMaxAddSkillCnt = curData["RelMaxAddSkillCnt"]
+            expiation.FamilyActiveValue = curData["FamilyActiveValue"]
+            expiation.UserDataLen = curData["UserDataLen"]
+            expiation.UserData = fix_outgoingText(curData["UserData"])
+            sendPack.Datas.append(expiation)#所有属性赋值后压入列表
+            #ExpiationIndex是自增长的,唯一的
+            colDel.remove({'ExpiationIndex':expiation.ExpiationIndex})
+            sendPack.Count+=1
+       
+        if  sendPack.Count == 0:
+            return False 
+        self.sendString(pack, sendPack.GetBuffer())
+        
+        #通知写补偿日志
+        for i in xrange(sendPack.Count):
+            dbData = sendPack.Datas[i]
+            saveLog = DataServerLogData.tagExpiationLog()
+            saveLog.ReceiveDate = time()
+            saveLog.ExpiationIndex = dbData.ExpiationIndex;
+            saveLog.AccID =  dbData.AccID
+            saveLog.MakerName = dbData.MakerName
+            saveLog.CreateTime = dbData.CreateTime
+            saveLog.ExpiationTime = dbData.ExpiationTime;
+            saveLog.Gold = dbData.Gold;
+            saveLog.GoldPaper = dbData.GoldPaper;
+            saveLog.Silver = dbData.Silver;
+            saveLog.SilverPaper = dbData.SilverPaper;
+            saveLog.ItemTypeID = dbData.ItemTypeID;
+            saveLog.Count = dbData.Count;
+            saveLog.IsLocked = dbData.IsLocked;
+            saveLog.ItemPlaceType = dbData.ItemPlaceType;
+            saveLog.ItemPlaceIndex = dbData.ItemPlaceIndex;
+            saveLog.IsBind = dbData.IsBind;
+            saveLog.ItemStarLV = dbData.ItemStarLV;
+            saveLog.IdentifyPar = dbData.IdentifyPar;
+            saveLog.CurDurg = dbData.CurDurg;
+            saveLog.MaxDurg = dbData.MaxDurg;
+            saveLog.CanPlaceStoneCount = dbData.CanPlaceStoneCount;
+            saveLog.ItemProperty = dbData.ItemProperty;
+            saveLog.SoulProperty = dbData.SoulProperty;
+            saveLog.Maker = dbData.Maker;
+            saveLog.Stone1 = dbData.Stone1;
+            saveLog.Stone2 = dbData.Stone2;
+            saveLog.Stone3 = dbData.Stone3;
+            saveLog.Stone4 = dbData.Stone4;
+            saveLog.Stone5 = dbData.Stone5;
+            saveLog.Stone6 = dbData.Stone6;
+            saveLog.Stone7 = dbData.Stone7;
+            saveLog.Stone8 = dbData.Stone8;
+            saveLog.Stone9 = dbData.Stone9;
+            saveLog.RemainHour = dbData.RemainHour;
+            saveLog.ElementEffect = dbData.ElementEffect;
+            saveLog.IsSuite = dbData.IsSuite;
+            saveLog.FitLV = dbData.FitLV;
+            saveLog.EquipAddSkillCnt = dbData.EquipAddSkillCnt;
+            saveLog.ExpireTime = dbData.ExpireTime;
+            saveLog.BaseAtkPlus = dbData.BaseAtkPlus;
+            saveLog.BaseDefPlus = dbData.BaseDefPlus;
+            saveLog.AddSkillData = dbData.AddSkillData
+            saveLog.BaseHP = dbData.BaseHP;
+            saveLog.BaseMagicDef = dbData.BaseMagicDef;
+            saveLog.EquipMinAtkValue = dbData.EquipMinAtkValue;
+            saveLog.Proficiency = dbData.Proficiency;
+            saveLog.RelMaxAddSkillCnt = dbData.RelMaxAddSkillCnt;
+            saveLog.FamilyActiveValue = dbData.FamilyActiveValue;   
+            self.sendDBRequest(chr(CommonDefine.gstGetExpiationLog) + saveLog.getBuffer())
+        return True
+#        curPack = RecvPackProtocol.tagDGetValueByAcc()
+#        curPack.ReadData(pack.getBuffer())
+#        
+#        col = db.tagExpiation
+#        dbData = DataServerPlayerData.tagExpiation()
+#        dbData.AccID = curPack.Acc
+#        result = dbData.adoLoad(col)
+#        
+#        #回报客户端
+#        sendPack = RecvPackProtocol.tagBDStringTypeSend()
+#        sendPack.Type = CommonDefine.dgGetExpiation
+#        sendPack.Data = dbData.getBuffer()
+#        sendPack.DataLen = sendPack.data
+#        self.sendString(pack, sendPack.GetBuffer())
+#        
+#        #没有领取到数据, 返回失败
+#        if not result:
+#            return False
+#        colDel = db.tagExpiation
+#        colDel.remove({'ExpiationIndex':dbData.ExpiationIndex,"AccID":dbData.AccID})
+#        #保存日志
+#        saveLog = DataServerLogData.tagExpiationLog()
+#        saveLog.ReceiveDate = time()
+#        saveLog.ExpiationIndex = dbData.ExpiationIndex;
+#        saveLog.AccID =  dbData.AccID
+#        saveLog.MakerName = dbData.MakerName
+#        saveLog.CreateTime = dbData.CreateTime
+#        saveLog.ExpiationTime = dbData.ExpiationTime;
+#        saveLog.Gold = dbData.Gold;
+#        saveLog.GoldPaper = dbData.GoldPaper;
+#        saveLog.Silver = dbData.Silver;
+#        saveLog.SilverPaper = dbData.SilverPaper;
+#        saveLog.ItemTypeID = dbData.ItemTypeID;
+#        saveLog.Count = dbData.Count;
+#        saveLog.IsLocked = dbData.IsLocked;
+#        saveLog.ItemPlaceType = dbData.ItemPlaceType;
+#        saveLog.ItemPlaceIndex = dbData.ItemPlaceIndex;
+#        saveLog.IsBind = dbData.IsBind;
+#        saveLog.ItemStarLV = dbData.ItemStarLV;
+#        saveLog.IdentifyPar = dbData.IdentifyPar;
+#        saveLog.CurDurg = dbData.CurDurg;
+#        saveLog.MaxDurg = dbData.MaxDurg;
+#        saveLog.CanPlaceStoneCount = dbData.CanPlaceStoneCount;
+#        saveLog.ItemProperty = dbData.ItemProperty;
+#        saveLog.SoulProperty = dbData.SoulProperty;
+#        saveLog.Maker = dbData.Maker;
+#        saveLog.Stone1 = dbData.Stone1;
+#        saveLog.Stone2 = dbData.Stone2;
+#        saveLog.Stone3 = dbData.Stone3;
+#        saveLog.Stone4 = dbData.Stone4;
+#        saveLog.Stone5 = dbData.Stone5;
+#        saveLog.Stone6 = dbData.Stone6;
+#        saveLog.Stone7 = dbData.Stone7;
+#        saveLog.Stone8 = dbData.Stone8;
+#        saveLog.Stone9 = dbData.Stone9;
+#        saveLog.RemainHour = dbData.RemainHour;
+#        saveLog.ElementEffect = dbData.ElementEffect;
+#        saveLog.IsSuite = dbData.IsSuite;
+#        saveLog.FitLV = dbData.FitLV;
+#        saveLog.EquipAddSkillCnt = dbData.EquipAddSkillCnt;
+#        saveLog.ExpireTime = dbData.ExpireTime;
+#        saveLog.BaseAtkPlus = dbData.BaseAtkPlus;
+#        saveLog.BaseDefPlus = dbData.BaseDefPlus;
+#        saveLog.AddSkillData = dbData.AddSkillData
+#        saveLog.BaseHP = dbData.BaseHP;
+#        saveLog.BaseMagicDef = dbData.BaseMagicDef;
+#        saveLog.EquipMinAtkValue = dbData.EquipMinAtkValue;
+#        saveLog.Proficiency = dbData.Proficiency;
+#        saveLog.RelMaxAddSkillCnt = dbData.RelMaxAddSkillCnt;
+#        saveLog.FamilyActiveValue = dbData.FamilyActiveValue;
+#            
+#        self.sendDBRequest(chr(CommonDefine.gstGetExpiationLog) + saveLog.getBuffer())
+#        return True
+    
+    def OnGetPetExpiation(self, db, pack):
+        curPack = RecvPackProtocol.tagDGetValueByAcc()
+        curPack.ReadData(pack.getBuffer())
+        
+        col = db[UCN_PetExpiation]
+        dbData = DataServerPlayerData.tagPetExpiation()
+        dbData.AccID = curPack.Acc
+        result = dbData.adoLoad(col)
+        
+        #回报客户端
+        sendPack = RecvPackProtocol.tagBDStringTypeSend()
+        sendPack.Type = CommonDefine.dgGetPetExpiation
+        sendPack.Data = dbData.getBuffer()
+        sendPack.DataLen = dbData.getLength()
+        self.sendString(pack, sendPack.GetBuffer())
+        
+        #没有领取到数据, 返回失败
+        if not result:
+            return False        
+        
+        #存日志
+        saveLog = DataServerLogData.tagPetExpiationLog()
+        saveLog.ReceiveDate = time();
+
+        saveLog.ExpiationIndex = dbData.ExpiationIndex;
+        saveLog.AccID = dbData.AccID
+        saveLog.ExpiationTime = dbData.ExpiationTime;
+        saveLog.NPCID = dbData.NPCID;
+        saveLog.Lv = dbData.Lv;
+        saveLog.Exp = dbData.Exp;
+        saveLog.BindType = dbData.BindType;
+        saveLog.UseCreatorDrugCnt = dbData.UseCreatorDrugCnt;
+        saveLog.Friendliness = dbData.Friendliness;
+        saveLog.SkillIDList = dbData.SkillIDList
+        saveLog.HPTalent = dbData.HPTalent;
+        saveLog.PhysicAtkTalent = dbData.PhysicAtkTalent;
+        saveLog.MagicAtkTalent = dbData.MagicAtkTalent;
+        saveLog.PhysicDefTalent = dbData.PhysicDefTalent;
+        saveLog.MagicDefTalent = dbData.MagicDefTalent;
+        
+        self.sendDBRequest(chr(CommonDefine.gstGetPetExpiationLog) + saveLog.getBuffer(), pack)
+        return True
+    
+    def gstUpdateServerDataVersionNO(self, db, pack):
+        '''服务器数据库版本刷新'''
+        dbRecv = DataServerPlayerData.tagServerDataVersionNO()
+        if -1 == dbRecv.readData(pack.getBuffer()):
+            msg = error.formatMsg('error', error.ERROR_NO_91, "tagServerDataVersionNO:%S"%"lack of pack data")
+            mylog.error(msg)
+            return False
+        
+        #删除原来的数据
+        col = db[UCN_ServerDataVersionNO]
+        col.drop()
+        
+        #插入新版本
+        if not dbRecv.adoInsert(col):
+            msg = error.formatMsg('error', error.ERROR_NO_92, "insert tagServerDataVersionNO data failed!")
+            mylog.error(msg)           
+            return False
+        
+        return True 
+    
+    def OnMapServerInfo(self, db, pack):
+        recvPack = RecvPackProtocol.tagBDStringTypeSend()
+        recvPack.ReadData(pack.getBuffer())
+        
+        dbData = DataServerPlayerData.tagDBMapServerInfo()
+        if -1 == dbData.readData(recvPack.Data):
+            msg = error.formatMsg('error', error.ERROR_NO_93, "tagDBMapServerInfo:lack of pack data")
+            mylog.error(msg)              
+            return False    
+        
+        dbData.Time = time()
+        
+        dbData.LogIndex = seq(db, 'tagDBMapServerInfo', 'LogIndex', DBConfig.LOGINDEX_FEED, DBConfig.LOGINDEX_STEP)
+                
+        col = db[UCN_DBMapServerInfo]
+        if not dbData.adoCheckUpdateEx(col, {"LogID":dbData.LogID, "Msg":fix_incomingText(dbData.Msg)}): 
+            msg = error.formatMsg('error', error.ERROR_NO_94, 'OnMapServerInfo failed:LogID = %s, LogIndex = %s, Msg = %s'%(self.LogID, self.LogIndex, self.Msg))
+            mylog.error(msg)              
+            return False
+        
+        return True
+    
+    def OnUpdateTotalSavePoint(self, db, pack):
+        try:
+            mylog.info("begin process gstUpdateTotalSavePoint")
+            recvPack = RecvPackProtocol.tagBDStringTypeSend()
+            recvPack.ReadData(pack.getBuffer())
+            
+            dbData = DataServerLogData.tagDBPlayerSaveCoinLog()
+            if -1 == dbData.readData(recvPack.Data):
+                msg = error.formatMsg('error', error.ERROR_NO_95, "tagDBPlayerSaveCoinLog:lack of pack data:data = %s,datalen = %d"%(b2a_hex(recvPack.Data), len(recvPack.Data)))
+                mylog.error(msg)                
+                return False    
+            
+            col = db[UCN_DSAccount]
+            dbDoc = DataServerPlayerData.tagDSAccount()
+            dbDoc.AccID = recvPack.AccID
+            ret = dbDoc.adoLoadC(col)
+            if ret:
+                dbDoc.TotalSavePoint += dbData.Coin
+            else:
+                dbDoc.TotalSavePoint = 0
+                
+            if not dbDoc.adoCheckUpdateC(col):
+                msg = error.formatMsg('error', error.ERROR_NO_86, "UpdateTotalSavePoint failed,data = %s,datalen = %d"%(b2a_hex(recvPack.Data), len(recvPack.Data)))
+                mylog.error(msg)
+                return False            
+        
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_96, "OnUpdateTotalSavePoint throw a exception, packdata = %s, packdata len = %d\n%s"(b2a_hex(pack.getBuffer()), len(pack.getBuffer()), traceback.format_exc()))
+            mylog.error(msg)
+            return False
+        
+        mylog.info("end process gstUpdateTotalSavePoint")
+        return True
+    
+    def OnGetPlayerMailState(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagDBGetMailListReq()
+            recvPack.ReadData(pack.getBuffer())
+            
+            col = db[UCN_DBMailList]
+            docCount = col.find({"ReceverID":recvPack.PlayerID, "$ne":{"MailType":CommonDefine.wmtSave}}).count()
+            if  docCount >= CommonDefine.MAX_PLAYER_MAIL_COUNT:
+                state = CommonDefine.pmiFull
+            else:
+                docCount = col.find({"ReceverID":recvPack.PlayerID, "MailType":CommonDefine.wmtUnReaded}).count()
+                if docCount > 0 :
+                    state = CommonDefine.pmiNewLetter
+                else:
+                    state = CommonDefine.pmiNull
+                    
+            sendPack = SendPackProtocol.tagPlayerMailInfo()
+            sendPack.InfoType = state
+            #RouteServer和GameServer都会发此查询包,但所有回包都经RouteServer转发给客户端
+            #如果封包来自GameServer,就伪装成来自RouteServer
+            if pack.getPackHead().srcSvrType == MMORPGPack.stGame:
+                pack.getPackHead().srcSvrType = MMORPGPack.stRoute
+                pack.getPackHead().poolIndex = recvPack.RouteServerIndex
+                
+            self.sendGameServerString(pack, CommonDefine.dgPlayerMailState, sendPack.GetBuffer())
+            
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_97, "OnGetPlayerMailState throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False
+        
+        return True
+    
+    def OnGetMailDetail(self, db, pack):
+        '''取得玩家邮件详情'''
+        try:
+            recvPack = RecvPackProtocol.tagDBGetMailDetailReq()
+            recvPack.ReadData(pack.getBuffer())
+            
+            col = db[UCN_DBMailItemList]
+            
+            dbMailItemList = DataServerPlayerData.tagDBMailItemList()
+            dbMailItemList.MailID = recvPack.MailID
+            itemData = dbMailItemList.adoQueryIndex(col)
+            
+            col = db[UCN_DBMailList]
+            dbMailList = DataServerPlayerData.tagDBMailList()
+            dbMailList.MailID = recvPack.MailID    
+            if not dbMailList.adoLoad(col):
+                mylog.warning("mail list not exist! mailid = %s"%recvPack.MailID)
+                return False       
+            
+            sendPack = SendPackProtocol.tagDBMailDetailView()
+            sendPack.Type = CommonDefine.dgMailDetail
+            sendPack.MailDetailData = dbMailList.getBuffer()
+            sendPack.MailDetailDataLen = len(sendPack.MailDetailData)
+            sendPack.MailItemData = itemData
+            sendPack.MailItemDataLen = len(itemData)
+            
+            self.sendString(pack, sendPack.GetBuffer())
+            
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_98, "OnGetMailDetail throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False
+        return True    
+    
+    def OnGetPlayerMail(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagDBGetMailListReq()
+            recvPack.ReadData(pack.getBuffer())
+            
+            sendPack = SendPackProtocol.tagDBGetPlayerMail()
+            sendPack.Type = CommonDefine.dgMailList
+                            
+            col = db[UCN_DBMailList]
+            docs = col.find({"ReceverID":recvPack.PlayerID, "ExistTime":{"$lt":CommonDefine.MailExistTime}})
+            for doc in docs:
+                mainInfo = SendPackProtocol.tagDBMailInfo()
+                mainInfo.MailID = fix_outgoingText(doc['MailID'])
+                mainInfo.MailType = doc['MailType']
+                mainInfo.SenderName = fix_outgoingText(doc['SenderName'])
+                mainInfo.Title = fix_outgoingText(doc['Title'])
+                mainInfo.LetterType = doc['LetterType']
+                mainInfo.ExistTime = doc['ExistTime']
+                mainInfo.TitleUseSysMessage = doc['TitleUseSysMessage']
+                sendPack.Mail.append(mainInfo)
+                
+            sendPack.MailCount = len(sendPack.Mail)
+            self.sendString(pack, sendPack.GetBuffer())
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_99, "OnGetPlayerMail throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False
+        return True
+    
+    def OnAddPlayerMailByAccID(self, db, pack):
+        result = False
+        sendPack = RecvPackProtocol.tagBDStringTypeSend()
+        try:
+            recvPack = RecvPackProtocol.tagBDStringTypeSend()
+            recvPack.ReadData(pack.getBuffer())
+            
+            #这里实际希望将ADOResult返回回去,实际上GetBuffer不会打包ADOResult
+            sendPack.Data = recvPack.Data
+            sendPack.DataLen = recvPack.DataLen 
+                        
+            while(True):
+                curMail = DataServerPlayerData.tagDBMailList_SaveSysMail()
+                if -1 == curMail.readData(recvPack.Data):
+                    msg = error.formatMsg('error', error.ERROR_NO_100, "tagDBMailList_SaveSysMail lack of pack data")
+                    mylog.error(msg)
+                    break
+                
+                col = db[UCN_DBPlayer]
+                docs = col.find({"AccID":fix_incomingText(recvPack.AccID), "IsDeleted":0})
+                if docs.count() <= 0:
+                    mylog.info("not exist player role , accid = %s"%recvPack.AccID)
+                    break
+                
+                col = db[UCN_DBMailList]
+                if col.find({"MailID":curMail.MailID}).count() > 0:
+                    msg = error.formatMsg('error', error.ERROR_NO_101, "OnAddPlayerMailByAccID: exist a same mailid")
+                    mylog.error(msg)
+                    break
+                    
+                doc = DataServerPlayerData.tagDBMailList()
+                doc.SenderID = curMail.SenderID
+                doc.ReceverID = docs[0]["PlayerID"]
+                doc.MailID = curMail.MailID
+                doc.MailType = curMail.MailType
+                doc.SenderName = curMail.SenderName
+                doc.Title = curMail.Title
+                doc.Money = curMail.Money
+                doc.LetterType = curMail.LetterType
+                doc.ExistTime = curMail.ExistTime
+                doc.Content = curMail.Content
+                doc.ContentLen = len(doc.Content)
+                doc.TitleUseSysMessage = curMail.TitleUseSysMessage
+                doc.ContentUseSysMessage = curMail.ContentUseSysMessage
+                if doc.adoInsert(col):
+                    result = True
+                    
+                break       
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_102, "OnAddPlayerMailByAccID throw a exception\n\s"%traceback.format_exc())
+            mylog.error(msg)
+            
+        sendPack.Type = CommonDefine.dgAddPlayerMailByAccID
+        self.sendString(pack, sendPack.GetBuffer())
+        return result
+    
+    def OnDeleteMail(self, db, pack):
+        try:
+            recvPack  = RecvPackProtocol.tagDBDeleteMail()
+            recvPack.ReadData(pack.getBuffer())
+            
+#            删除邮件
+            col = db[UCN_DBMailList]
+            doc = DataServerPlayerData.tagDBMailList()
+            doc.MailID = recvPack.MailID
+            if not doc.adoDeleteByIndex(col):
+                msg = error.formatMsg('error', error.ERROR_NO_103, "DeleteMail fail:data = %s"%b2a_hex(pack.getBuffer()))
+                mylog.error(msg)
+                return False
+            
+#            删除物品
+            col = db[UCN_DBMailItemList] 
+            doc = DataServerPlayerData.tagDBMailItemList()
+            doc.MailID = recvPack.MailID
+            if not doc.adoDeleteByIndex(col):
+                msg = error.formatMsg('error', error.ERROR_NO_104, "DeleteMail fail:data = %s"%b2a_hex(pack.getBuffer()))
+                mylog.error(msg)
+                return False                
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_105, "OnDeleteMail throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False
+        return True
+        
+    #更新邮件(gstUpdateMail)
+    def OnUpdateMail(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagDBUpdateMail()
+            recvPack.ReadData(pack.getBuffer())
+            
+            col = db[UCN_DBMailList]
+            doc = DataServerPlayerData.tagDBMailList()
+            doc.MailID = recvPack.MailID
+            
+            if not doc.adoLoad(col):
+                DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\UpdateMailFailDump', '%d_%s.mdat'%(pack.getPackHead().sessionID, recvPack.MailID), pack.getBuffer())      
+                msg = error.formatMsg('error', error.ERROR_NO_106, "update mail fail, load tagDBMailList fail, session = %d, mailid = %s"%(pack.getPackHead().sessionID, recvPack.MailID))
+                mylog.error(msg)
+                return False
+            
+            if recvPack.UpdateMailType:
+                doc.MailType = recvPack.MailType
+                
+            if recvPack.UpdateLetterType:
+                doc.LetterType = recvPack.LetterType
+                
+            if recvPack.GetAllMoney:
+                doc.Money = 0
+                
+            if recvPack.ReturnMail:
+                doc.ReceverID = doc.SenderID
+                doc.SenderID = 0
+                doc.LetterType = 0
+                doc.ExistTime = 0
+                doc.Money = 0
+                
+            if not doc.adoUpdate(col):
+                DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\UpdateMailFailDump', '%d_%s.mdat'%(pack.getPackHead().sessionID, recvPack.MailID), b2a_hex(pack.getBuffer()))      
+                msg = error.formatMsg('error', error.ERROR_NO_107, "update mail fail, maiid = %s, sessionid = %d"%(recvPack.MailID, pack.getPackHead().sessionID))
+                mylog.error(msg)
+                return False    
+                
+            if recvPack.GetAllItem:
+                col = db[UCN_DBMailItemList]     
+                doc.MailID = recvPack.MailID
+                
+                if not doc.adoDeleteByIndex(col):
+                    DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\UpdateMailFailDump', '%d_%s.mdat'%(pack.getPackHead().sessionID, recvPack.MailID), b2a_hex(pack.getBuffer()))      
+                    msg = error.formatMsg('error', error.ERROR_NO_108, "update mail fail, maiid = %s, sessionid = %d"%(recvPack.MailID, pack.getPackHead().sessionID))
+                    mylog.error(msg)
+                    return False                        
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_109, "OnUpdateMail throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False
+        return True
+    
+    #检查玩家是否能够发送邮件给对方(gstQueryCanSendMail) 
+    def OnQueryCanSendMail(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagBDCheckNameExist()
+            recvPack.ReadData(pack.getBuffer())
+            
+            sendPack = SendPackProtocol.tagDBPlayerNameIsExist()
+            sendPack.CallType = CommonDefine.dgQueryCanSendMail
+            sendPack.Name = recvPack.Name
+            sendPack.NameLen = len(sendPack.Name)
+            
+            col = db[UCN_DBPlayer]
+#            name = "^%s$"%recvPack.Name
+#            docs = col.find({"AccID":{"$regex":name, "$options":"i"}, "IsDeleted":0})
+            docs = col.find({"AccID":fix_incomingText(recvPack.Name), "IsDeleted":0})            
+            if not docs.count():
+                sendPack.PlayerID = 0
+                sendPack.Result = 0
+            else:
+                sendPack.PlayerID = docs[0]["PlayerID"]
+                col = db[UCN_DBMailList]
+                count = col.find({"ReceverID":sendPack.PlayerID, "MailType":{"$ne":CommonDefine.wmtSave}}).count()
+                if count > CommonDefine.MAX_PLAYER_MAIL_COUNT:
+                    sendPack.Result = 0
+                else:
+                    sendPack.Result = 1
+                           
+            self.sendString(pack, sendPack.GetBuffer())
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_110, "OnQueryCanSendMail throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False            
+        return True      
+    
+    def OnAccIDSendPrize(self, db, pack):
+        sendPack = SendPackProtocol.tagDPlayerGetItem()
+        sendPack.Type = CommonDefine.dgAccIDSendPrize
+        ret = True
+        while(True):
+            try:
+                recvPack = RecvPackProtocol.tagDGetValueByAcc()
+                recvPack.ReadData(pack.getBuffer())
+                
+                col = db[UCN_AccIDSendPrize]
+                trycnt = 0
+                while(True):
+                    try:
+                        col.update({"ExpiredTime":{"$lt":time()}, "AccID":fix_incomingText(recvPack.Acc), "IsAccept":0}, {'$set':{"IsAccept":2}}, False, False, True, True)
+                        break
+                    except pymongo.errors.OperationFailure:
+                        if(DBConfig.TryCntOnWriteFail > trycnt):
+                            trycnt += 1
+                            continue
+                        ret = False 
+                        addADOExceptionCount() 
+                        msg = error.formatMsg('error', error.ERROR_NO_111, 'OnAccIDSendPrize!Update failed!AccID = %s, trycnt = %d'%(recvPack.Acc, trycnt))
+                        mylog.error(msg)
+                        break
+                  
+                if not ret:
+                    break  
+                
+                docs = col.find({"AccID":fix_incomingText(recvPack.Acc), "IsAccept":0}).limit(1) #top 1
+                if docs.count():
+                    doc = docs[0]
+                    CheckValue = doc['CheckValue']
+                    sendPack.ItemID = doc['PrizeID']
+                    sendPack.Count = doc['PrizeNum']
+                    sendPack.IsBind = doc['IsBind']
+                
+                    
+                    trycnt = 0
+                    while(True):
+                        try:
+                            col.update({"CheckValue":CheckValue}, {'$set':{"IsAccept":1}}, False, False, True, True)
+                            break
+                        except pymongo.errors.OperationFailure:
+                            if(DBConfig.TryCntOnWriteFail > trycnt):
+                                trycnt += 1
+                                continue
+                            ret = False 
+                            addADOExceptionCount()
+                            msg = error.formatMsg('error', error.ERROR_NO_112, 'OnAccIDSendPrize!Update failed!AccID = %s, trycnt = %d'%(recvPack.Acc, trycnt))
+                            mylog.error(msg)
+                            break   
+                
+                    if not ret:
+                        break                 
+                
+                sendPack.RemainItemCount = col.find({"AccID":fix_incomingText(recvPack.Acc), "IsAccept":0}).count()
+            except:
+                msg = error.formatMsg('error', error.ERROR_NO_113, "OnAccIDSendPrize throw a exception\n%s"%traceback.format_exc())
+                mylog.error(msg)
+                ret = False  
+            break   
+        self.sendString(pack, sendPack.GetBuffer())
+        return ret    
+         
+    def OnCheckItemPrize(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagDGetValueByAcc()
+            recvPack.ReadData(pack.getBuffer())
+            #临时代码,这个请求的处理很慢,怀疑是数据库慢,证实下
+            import timeit
+            startTick = timeit.default_timer()
+            
+            col = db[UCN_AccIDSendPrize]
+            PrizeCnt = col.find({"AccID":fix_incomingText(recvPack.Acc), "IsAccept":0}).count()
+            
+            processTime = timeit.default_timer() - startTick
+            if processTime > DBConfig.ProfileThreshold / 1000.0:
+                mylog.warning('OnCheckItemPrize db process time = %s, PrizeCnt = %s'%(processTime, PrizeCnt))
+            
+            startTick = timeit.default_timer()
+            
+            sendPack = SendPackProtocol.tagDServerValueType();
+            sendPack.Type = CommonDefine.dgCheckItemPrizeResult   
+            sendPack.Value =  PrizeCnt
+            self.sendString(pack, sendPack.GetBuffer())
+            
+            processTime = timeit.default_timer() - startTick
+            if processTime > DBConfig.ProfileThreshold / 1000.0:
+                mylog.warning('sendString process time = %s'%(processTime))
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_114, "OnCheckItemPrize throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False            
+        return True    
+    
+    def OnCheckLoadAcc(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagDGetValueByAcc()
+            recvPack.ReadData(pack.getBuffer())
+                      
+            col = db[UCN_DSAccount]
+            doc = DataServerPlayerData.tagDSAccount()
+            doc.ACCID = recvPack.Acc
+#            LastSIDErrorCnt = getSIDErrorCnt()
+            strNow = CommFuncEx.TDateTimeToString(CommFuncEx.TDateTime_Now()) 
+            if not doc.adoLoadC(col):
+#                if LastSIDErrorCnt != getSIDErrorCnt():
+#                    if DBConfig.checkSID:
+#                        self.sendFailString(CommonDefine.dgPlayerLogin, pack)
+#                        mylog.info("%s Update Error !doc.LogNum = %d"%recvPack.Acc, doc.LogNum)
+#                        return
+                doc.LogNum = 0
+                doc.RegisterTime = strNow
+                if not doc.adoInsertC(col):
+                    self.sendFailString(CommonDefine.dgPlayerLogin, pack)
+                    mylog.info("%s Update Error !doc.LogNum = %d"%(recvPack.Acc, doc.LogNum))
+                    return False
+                
+            doc.LogNum += 1
+            doc.LastLoginTime = strNow
+            if not doc.adoUpdateC(col):
+                self.sendFailString(CommonDefine.dgPlayerLogin, pack)
+                mylog.info("%s Update Error !doc.LogNum = %d"%(recvPack.Acc, doc.LogNum))
+                return False
+            
+            self.sendOKString(CommonDefine.dgPlayerAccLoad, pack, doc.getBuffer())  
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_115, "OnCheckLoadAcc throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False            
+        return True        
+    
+    def OnAddAccItem(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagBDStringTypeSend()
+            recvPack.ReadData(pack.getBuffer())
+            
+            recvData = RecvPackProtocol.tagIRAddItem()
+            recvData.ReadData(recvPack.Data)
+    
+            mylog.warning("Type == gstAddAccItem, accid = %s, itemID = %d, itemCnt = %d"%(recvData.Acc, recvData.ItemID, recvData.ItemCnt));
+    
+            col = db[UCN_AccIDSendPrize]
+            doc = DataServerPlayerData.tagAccIDSendPrize()
+            doc.CheckValue = GlobalFunctions.GetTransactionIDStr(32)
+            doc.AccID = recvData.Acc
+            doc.PrizeID = recvData.ItemID;
+            doc.PrizeNum = recvData.ItemCnt
+            doc.ExpiredTime = time() + 365*18*24*60*60      #过期时间为现在之后的18年
+            doc.PrizeReason = "gstAddAccItem"
+            doc.IsAccept = 0
+            doc.SendPrizeTime = time()
+            doc.IsBind = recvData.IsBind
+            
+            sendPack = SendPackProtocol.tagIAddItemResult();
+            
+            if not doc.adoInsert(col):
+                mylog.warning("Type == gstAddAccItem, transactionIDStr = %s, accid = %s, itemID = %d, itemCnt = %d, Insert Error!"%(doc.CheckValue, recvData.Acc, recvData.ItemID, recvData.ItemCnt));
+    
+#                回报BalanceServer插入成功
+#                dgAddAccItemOK
+                sendPack.Acc = recvData.Acc;
+                sendPack.AccLen = sendPack.Acc.Length();
+                sendPack.ItemID = recvData.ItemID;
+                sendPack.Count = recvData.ItemCnt;
+                sendPack.Result = 0;
+                self.sendString(pack, chr(CommonDefine.dgAddAccItemOK) + sendPack.GetBuffer);
+                return False;
+            
+            #插入ChinLog表记录
+            curLog = DataServerLogData.tagAccTransactionLog()
+            curLog.TransactionID = doc.CheckValue
+            curLog.AccID = recvData.Acc
+            curLog.OperReason = "gstAddAccItem"
+            curLog.ProcessTime = time();
+            curLog.ItemID = recvData.ItemID;
+            curLog.ItemCount = recvData.ItemCnt;
+            self.sendDBRequest(chr(CommonDefine.gstItemTransactionLog) + curLog.getBuffer())       
+            
+            #回报BalanceServer插入成功
+            #dgAddAccItemOK
+            sendPack.Acc = recvData.Acc;
+            sendPack.AccLen = sendPack.Acc.Length();
+            sendPack.ItemID = recvData.ItemID;
+            sendPack.Count = recvData.ItemCnt;
+            sendPack.Result = 1;
+            self.sendString(pack, chr(CommonDefine.dgAddAccItemOK) + sendPack.GetBuffer);
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_116, "OnAddAccItem throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False            
+        return True      
+    
+    def OnUpdateTelLockState(self, db, pack): 
+        try:
+            recvPack = RecvPackProtocol.tagBDStringTypeSend()
+            recvPack.ReadData(pack.getBuffer())
+            
+            recvData = DataServerPlayerData.tagDSAccount_UpdateTelLockState()
+            recvData.readData(recvPack.Data)
+            
+            col = db[UCN_DSAccount]
+            doc = DataServerPlayerData.tagDSAccount()
+            doc.ACCID = recvData.AccID
+            ret = doc.adoLoadC(col)
+            doc.TelLockState = recvData.TelLockState
+            if not doc.adoCheckUpdateC(col):
+                msg = error.formatMsg('error', error.ERROR_NO_117, 'OnUpdateTelLockState!Update failed!ACCID = %s,TelLockState = %s'%(recvData.AccID,recvData.TelLockState))
+                mylog.error(msg)
+                return False
+            
+#            trycnt = 0
+#            while(True):
+#                try:
+#                    col.update({"ACCID":fix_incomingText(recvData.AccID)}, {"$set":{"TelLockState":recvData.TelLockState}}, False, False, True)
+#                   
+#                    break
+#                except pymongo.errors.OperationFailure:
+#                    if(DBConfig.TryCntOnWriteFail > trycnt):
+#                        trycnt += 1
+#                        continue
+#                    msg = error.formatMsg('error', error.ERROR_NO_117, 'OnUpdateTelLockState!Update failed!ACCID = %s, trycnt = %d\n%s'%(recvData.AccID, trycnt, traceback.format_exc()))
+#                    mylog.error(msg)
+#                    return False           
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_118, "OnUpdateTelLockState ACCID = %s, TelLockState = %s, throw a exception\n%s"%(recvData.AccID,recvData.TelLockState,traceback.format_exc()))
+            mylog.error(msg)
+            return False            
+        return True    
+    
+
+    def OnUpdateAccAdult(self, db, pack): 
+        try:
+            recvPack = RecvPackProtocol.tagBDStringTypeSend()
+            recvPack.ReadData(pack.getBuffer())
+            
+            recvData = DataServerPlayerData.tagDSAccount_UpdateAdult()
+            recvData.readData(recvPack.Data)
+            
+            col = db[UCN_DSAccount]
+            doc = DataServerPlayerData.tagDSAccount()
+            doc.ACCID = recvData.AccID
+            ret = doc.adoLoadC(col)
+            doc.Adult = recvData.Adult
+            if not doc.adoCheckUpdateC(col):
+                msg = error.formatMsg('error', error.ERROR_NO_121, 'OnUpdateAccAdult!Update failed!ACCID = %s,Adult = %s'%(recvData.AccID,recvData.Adult))
+                mylog.error(msg)
+                return False
+            
+#            trycnt = 0
+#            while(True):
+#                try:
+#                    col.update({"ACCID":fix_incomingText(recvData.AccID)}, {"$set":{"Adult":recvData.Adult}}, False, False, True)
+#                    break
+#                except pymongo.errors.OperationFailure:
+#                    if(DBConfig.TryCntOnWriteFail > trycnt):
+#                        trycnt += 1
+#                        continue
+#                    msg = error.formatMsg('error', error.ERROR_NO_121, 'OnUpdateAccAdult!Update failed!ACCID = %s, trycnt = %d'%(recvData.AccID, trycnt))
+#                    mylog.error(msg)
+#                    return False               
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_122, "OnUpdateAccAdult throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False            
+        return True 
+    def OnAddExpiation(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagBDStringTypeSend()
+            recvPack.ReadData(pack.getBuffer())
+    
+            col = db[UCN_Expiation]
+            doc = DataServerPlayerData.tagExpiation()
+            doc.readData(recvPack.Data);
+            doc.ExpiationIndex = seq(db, 'tagExpiation', 'ExpiationIndex',
+                                      DBConfig.tagExpiation_ExpiationIndex_FEED, 
+                                      DBConfig.tagExpiation_ExpiationIndex_STEP)
+    
+            if doc.adoInsert(col):
+                #成功
+                doc.ADOResult = 1
+            else:
+                #失败
+                doc.ADOResult = 0
+    
+    
+            sendPack = RecvPackProtocol.tagBDStringTypeSend();
+            sendPack.Type = CommonDefine.dgAddExpiationOK;
+            sendPack.Data = doc.getBuffer()
+            sendPack.DataLen = len(sendPack.Data)
+    
+            self.sendString(pack, sendPack.GetBuffer())            
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_123, "OnAddExpiation throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False            
+        return True            
+         
+    def OnAddPetExpiation(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagBDStringTypeSend()
+            recvPack.ReadData(pack.getBuffer())
+    
+            col = db[UCN_PetExpiation]
+            doc = DataServerPlayerData.tagPetExpiation()
+            doc.readData(recvPack.Data);
+            doc.ExpiationIndex = seq(db, 'tagPetExpiation', 'ExpiationIndex',
+                                      DBConfig.tagPetExpiation_ExpiationIndex_FEED, 
+                                      DBConfig.tagPetExpiation_ExpiationIndex_STEP)
+            if doc.adoInsert(col):
+                #成功
+                doc.ADOResult = 1
+            else:
+                #失败
+                doc.ADOResult = 0
+    
+    
+            sendPack = RecvPackProtocol.tagBDStringTypeSend();
+            sendPack.Type = CommonDefine.dgAddPetExpiationOK;
+            sendPack.Data = doc.getBuffer()
+            sendPack.DataLen = len(sendPack.Data)
+    
+            self.sendString(pack, sendPack.GetBuffer())            
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_124, "OnAddPetExpiation throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False            
+        return True     
+    
+    def OnServerMergeDeleteRole(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagBDStringTypeSend()
+            recvPack.ReadData(pack.getBuffer())
+            
+            recvData = DataServerPlayerData.tagDBPlayer_DeleteRoleUpdateRole()
+            if -1 == recvData.readData(recvPack.Data):
+                self.sendFailString(CommonDefine.dgServerMergeDeleteRole, pack)
+                msg = error.formatMsg('error', error.ERROR_NO_125, "tagDBPlayer_DeleteRoleUpdateRole:lack of pack data")
+                mylog.error(msg)
+                return False
+            
+            trycnt = 0
+            while(True):
+                try:
+                    col = db[UCN_DBPlayer]
+#                    col.update({'PlayerID':recvData.DeletePlayerID}, {'$set':{"IsDeleted":1}}, False, False, True, True)
+#                    rec = {"Gold":recvData.Gold, "GoldPaper":recvData.GoldPaper, "Silver":recvData.Silver, "SilverPaper":recvData.SilverPaper, "WarehouseGold":recvData.WarehouseGold, "WarehouseSilver":recvData.WarehouseSilver}
+#                    col.update({'PlayerID':recvData.UpdatePlayerID}, {'$set':rec}, False, False, True, True) 
+                    
+                    doc = DataServerPlayerData.tagDBPlayer()
+                    #删除的角色改变状态
+                    doc.PlayerID = recvData.DeletePlayerID
+                    Ret = doc.adoLoadC(col)
+                    doc.IsDeleted = 1
+                    doc.adoUpdateC(col)
+
+                    #保留的角色信息更新
+                    updatedoc = DataServerPlayerData.tagDBPlayer()
+                    updatedoc.PlayerID = recvData.UpdatePlayerID
+                    Ret = updatedoc.adoLoadC(col)
+                    updatedoc.Gold = recvData.Gold
+                    updatedoc.GoldPaper = recvData.GoldPaper
+                    updatedoc.Silver = recvData.Silver
+                    updatedoc.SilverPaper = recvData.SilverPaper
+                    updatedoc.WarehouseGold = recvData.WarehouseGold
+                    updatedoc.WarehouseSilver = recvData.WarehouseSilver
+                    updatedoc.adoUpdateC(col) 
+      
+                    break
+                except pymongo.errors.OperationFailure:
+                    if(DBConfig.TryCntOnWriteFail > trycnt):
+                        trycnt += 1
+                        continue 
+                    msg = error.formatMsg('error', error.ERROR_NO_126, 'OnServerMergeDeleteRole!Update failed!DeletePlayerID = %s, UpdatePlayerID = %s, trycnt = %d'%(recvData.DeletePlayerID, recvData.UpdatePlayerID, trycnt)) 
+                    mylog.error(msg)                  
+                    self.sendFailString(CommonDefine.dgServerMergeDeleteRole, pack)
+                    return False  
+            
+            #155 . 因合服而删除角色
+            #=======================================================================================
+            # sendPack = RecvPackProtocol.tagDBServerLogRec()
+            # sendPack.Type = CommonDefine.gstSavePlayerLog
+            # sendPack.Oper = 155
+            # sendPack.Time = time()
+            # sendPack.MapID = 0
+            # sendPack.PlayerID = recvData.DeletePlayerID
+            # self.sendDBRequest(sendPack.GetBuffer())
+            #=======================================================================================
+            
+            self.sendOKString(CommonDefine.dgServerMergeDeleteRole, pack, "")
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_127, "OnServerMergeDeleteRole throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False            
+        return True   
+                
+    def OnServerMergeUpdateAccState(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagBDStringTypeSend()
+            recvPack.ReadData(pack.getBuffer())
+                        
+            recvData = DataServerPlayerData.tagDBPlayer_ChangeAccState()
+            recvData.readData(recvPack.Data)
+            
+            trycnt = 0
+            while(True):
+                try:
+                    col = db[UCN_DBPlayer]
+                    doc = DataServerPlayerData.tagDBPlayer()
+                    doc.PlayerID = recvData.PlayerID
+                    Ret = doc.adoLoadC(col)
+                    doc.AccState = recvData.AccState
+                    doc.adoUpdateC(col)
+                    
+#                    col.update({'PlayerID':recvData.PlayerID}, {'$set':{"AccState":recvData.AccState}}, False, False, True, True)         
+                    break
+                except pymongo.errors.OperationFailure:
+                    if(DBConfig.TryCntOnWriteFail > trycnt):
+                        trycnt += 1
+                        continue
+                      
+                    msg = error.formatMsg('error', error.ERROR_NO_128, 'OnServerMergeUpdateAccState!Update failed!PlayerID = %s, trycnt = %d'%(recvData.PlayerID, trycnt))
+                    mylog.error(msg) 
+                    self.sendFailString(CommonDefine.dgServerMergeUpdateAccState, pack)
+                    return False              
+            
+            self.sendOKString(CommonDefine.dgServerMergeUpdateAccState, pack, "")
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_129, "OnServerMergeUpdateAccState throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False            
+        return True      
+    
+    def OnServerMergeChangeName(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagBDStringTypeSend()
+            recvPack.ReadData(pack.getBuffer())
+                        
+            recvData = DataServerPlayerData.tagDBPlayer_ChangeName()
+            recvData.readData(recvPack.Data)
+            mylog.info('OnServerMergeChangeName playerID = %s, newName = %s...'%(recvData.PlayerID, recvData.PlayerName))
+            trycnt = 0
+            while(True):
+                try:
+                    col = db[UCN_DBPlayer]
+                    if col.find({"PlayerName":fix_incomingText(recvData.PlayerName)}).count():
+                        recvData.ADOResult = 0
+                    else:
+                        # 纯记录 暂时关闭
+                        #=======================================================
+                        # col = db[UCN_DBPlayerChangeNameLog]
+                        # if not col.find({"PlayerID":recvData.PlayerID}).count():
+                        #    trycnt1 = 0
+                        #    while(True):
+                        #        try:
+                        #            col.insert({"PlayerID":recvData.PlayerID, "SrcPlayerID":recvData.PlayerID, "OldPlayerName":fix_incomingText(recvData.PlayerName)}, False, True)
+                        #            break
+                        #        except pymongo.errors.OperationFailure:
+                        #            if(DBConfig.TryCntOnWriteFail > trycnt1):
+                        #                trycnt1 += 1
+                        #                continue 
+                        #            msg = error.formatMsg('error', error.ERROR_NO_130, 'OnServerMergeUpdateAccState!insert tagDBPlayerChangeNameLog failed!PlayerID = %s, trycnt = %d'%(recvData.PlayerID, trycnt1))
+                        #            mylog.error(msg)  
+                        #            break                                    
+                        #=======================================================
+                            
+                        # 下线保存 此处修改无意义,外部改名通知GameServer       
+                        #=======================================================
+                        # col = db[UCN_DBMailList]
+                        # col.update({'SenderID':recvData.PlayerID}, {'$set':{"SenderName":fix_incomingText(recvData.PlayerName)}}, False, False, True, True)  
+                        # mylog.info("OnServerMergeChangeName!update tagDBMailList ok.")
+                        # 
+                        # col = db[UCN_DBPlayer]
+                        # doc = DataServerPlayerData.tagDBPlayer()
+                        # doc.PlayerID = recvData.PlayerID
+                        # Ret = doc.adoLoadC(col)
+                        # doc.AccState = 1
+                        # doc.PlayerName = recvData.PlayerName
+                        # doc.adoUpdateC(col)
+                        # #col.update({'PlayerID':recvData.PlayerID}, {'$set':{"AccState":1, "PlayerName":fix_incomingText(recvData.PlayerName)}}, False, False, True, True) 
+                        # mylog.info("OnServerMergeChangeName!update tagDBPlayer ok.")
+                        # 
+                        # col = db[UCN_PlayerEnemy]
+                        # col.update({'EnemyID':recvData.PlayerID}, {'$set':{"EnemyName":fix_incomingText(recvData.PlayerName)}}, False, False, True, True)  
+                        # mylog.info("OnServerMergeChangeName!update tagPlayerEnemy ok.")                  
+                        # 
+                        # col = db[UCN_PlayerFriend]
+                        # col.update({'FriendID':recvData.PlayerID}, {'$set':{"FriendName":fix_incomingText(recvData.PlayerName)}}, False, False, True, True)  
+                        # mylog.info("OnServerMergeChangeName!update tagPlayerFriend ok.")  
+                        #=======================================================
+                        
+                        recvData.ADOResult = 1  
+                          
+                    sendPack = RecvPackProtocol.tagBDStringTypeSend()
+                    sendPack.Type = CommonDefine.dgServerMergeChangeName;
+                    sendPack.Data = recvData.getBuffer()
+                    sendPack.DataLen = len(sendPack.Data) 
+                    self.sendString(pack, sendPack.GetBuffer())
+                    break                   
+                except pymongo.errors.OperationFailure:
+                    if(DBConfig.TryCntOnWriteFail > trycnt):
+                        trycnt += 1
+                        continue 
+                    
+                    msg = error.formatMsg('error', error.ERROR_NO_131, 'OnServerMergeChangeName!Update failed!PlayerID = %s, trycnt = %d'%(recvData.PlayerID, trycnt))
+                    mylog.error(msg)  
+                    return False              
+            
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_132, "OnServerMergeChangeName throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False
+        mylog.info('OnServerMergeChangeName playerID = %s, newName = %s ok!'%(recvData.PlayerID, recvData.PlayerName))            
+        return True       
+         
+    def OnInsertImpeach(self, db, pack):
+        try:
+            recvPack = RecvPackProtocol.tagBDStringTypeSend()
+            recvPack.ReadData(pack.getBuffer())
+                        
+            doc = DataServerPlayerData.tagDBImpeach()
+            doc.ReadData(recvPack.Data)
+            doc.ImpeachIndex = seq(db, 'tagDBImpeach', 'ImpeachIndex',
+                                      DBConfig.tagDBImpeach_ImpeachIndex_FEED, 
+                                      DBConfig.tagDBImpeach_ImpeachIndex_STEP)
+            col = db[UCN_DBImpeach]
+            if not doc.adoInsert(col):
+                msg = error.formatMsg('error', error.ERROR_NO_133, "OnInsertImpeach!insert tagDBImpeach failed!")
+                mylog.error(msg)    
+                return False 
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_134, "OnServerMergeChangeName throw a exception\n%s"%traceback.format_exc())
+            mylog.error(msg)
+            return False            
+        return True   
+    def OnGMToolCmdUserDBRequest(self,db, pack):
+        try:
+            ProjSpecialProcess.OnGMToolCmdUserDBRequest(db,pack)
+        except:
+            msg = error.formatMsg('error', error.ERROR_NO_172, "OnGMToolCmdUserDBRequest Catch a unexpetcted exception, error = %s"%traceback.format_exc())
+            mylog.error(msg)
+            return False
+        return True
+    def OnMergerChildToCenter(self,db, pack):
+        mylog.info('OnMergerChildToCenter in')
+#        #伪装来源,便于回包
+#        pack.getPackHead().srcSvrType = MMORPGPack.stGame  
+#        pack.getPackHead().type = CommonDefine.dgMergerChildToCenter 
+        #获取发包参数
+        ServerMgr = MongoDBServer.getServerMgr()
+        sendViaSessionID = ServerMgr.getClientSessionIDByName("CenterGate",0)
+        SessionID = 0
+        PoolIndex = -1
+
+        #读取数据
+        buf = pack.getBuffer()           
+        recvPack = MergeServerRecvProtocol.tagLPStringData()
+        pos = 0
+        recvPack.ReadData(buf, pos)
+        #转发数据到GameServer    
+        sendPack = SendPackProtocol.tagDGMergerChildToGameStringData()
+        sendPack.Type = CommonDefine.dgMergerChildToCenter
+        sendPack.DataLen = recvPack.DataLen
+        sendPack.Data = recvPack.Data
+        
+        ServerMgr.packSendBySessionID(sendViaSessionID, SessionID, PoolIndex,
+                  CommonDefine.atInner,
+                  MMORPGPack.stGame, MMORPGPack.stData, 
+                  sendPack.GetBuffer())
+        mylog.info('OnMergerChildToCenter sendString toGameServer %s'%recvPack.Data)
+        return True
+    #导出单玩家数据
+    def DumpSinglePlayerDataByAcc(self,db,account):
+        
+        mylog.info('DumpSinglePlayerDataByAcc accid = %s'%account)
+        #非合服
+        #读取角色基本信息
+        dbPlayer = DataServerPlayerData.tagDBPlayer()
+        dbPlayer.AccID = account
+        dbPlayer.IsDeleted = 0
+        collection = db[UCN_DBPlayer]
+        lastExceptionCnt = getADOExceptionCount()
+        lastSIDErrorCnt = getSIDErrorCnt()
+        loadOK = dbPlayer.adoLoadCEx(collection, {'AccID':fix_incomingText(dbPlayer.AccID), 'IsDeleted':dbPlayer.IsDeleted})
+        if not lastExceptionCnt == getADOExceptionCount():
+            #数据库读取出错,但不一定是User库读取出错
+            mylog.info('DumpSinglePlayerDataByAcc  Exception accid = %s,playerID = %s'%(queryAccid, dbPlayer.PlayerID))
+            return
+        
+        
+        #读取物品等其他数据
+        #如果没有必要,就不支持单表模式了
+        #读取物品
+        queryDict = {'PlayerID':dbPlayer.PlayerID}
+        collection = db[UCN_RoleItem]
+        itemData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleItem, True)
+
+        itemCnt = CommFunc.ReadDWORD(itemData, 0)
+   
+        collection = db[UCN_RoleMission]
+        missionData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleMission)
+         
+        missionCnt = CommFunc.ReadDWORD(missionData, 0)
+
+        collection = db[UCN_RoleMissionDict]
+        roleMissionDictData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleMissionDict)
+        
+        missonDictCnt = CommFunc.ReadDWORD(roleMissionDictData, 0)
+
+        collection = db[UCN_RoleSkill]
+        roleSkillData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleSkill)
+            
+        skillCnt = CommFunc.ReadDWORD(roleSkillData, 0)
+
+        collection = db[UCN_RoleBuff]
+        roleBuffData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleBuff)
+           
+        bufCnt = CommFunc.ReadDWORD(roleBuffData, 0)
+
+        collection = db[UCN_RoleRepeatTime]
+        roleRepeatTimeData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleRepeatTime)
+         
+        repeatTimeCnt = CommFunc.ReadDWORD(roleRepeatTimeData, 0)
+
+        collection = db[UCN_PlayerHorseTable]
+        roleHorseData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagPlayerHorseTable)
+            
+        horseCnt = CommFunc.ReadDWORD(roleHorseData, 0)
+
+        collection = db[UCN_GMOper]
+        gmOperData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagGMOper)
+         
+        gmOperCnt = CommFunc.ReadDWORD(gmOperData, 0)
+
+        collection = db[UCN_RolePet]
+        rolePetData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRolePet)
+            
+        petCnt = CommFunc.ReadDWORD(rolePetData, 0)
+
+        collection = db[UCN_PetSkill]
+        petSkillData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagPetSkill)
+            
+        petSkillCnt = CommFunc.ReadDWORD(petSkillData, 0)
+
+        collection = db[UCN_RoleNomalDict]
+        roleNormalDictData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagRoleNomalDict)
+          
+        dictCnt = CommFunc.ReadDWORD(roleNormalDictData, 0)
+
+        collection = db[UCN_PlayerDienstgrad]
+        roleDienstgradData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagPlayerDienstgrad)
+        
+        roleDienstgradCnt = CommFunc.ReadDWORD(roleDienstgradData, 0)
+
+        collection = db[UCN_BattleFormation]
+        battleFormationData = self.readPlayerPackSaveData(collection, queryDict, DataServerPlayerData.tagBattleFormation)
+        
+        battleFormationCnt = CommFunc.ReadDWORD(battleFormationData, 0)
+
+        #读取禁止IP数据
+        gmIP = DataServerPlayerData.tagDBGMIP()
+        gmIP.AccID = account.lower()
+        collection = db[UCN_DBGMIP]
+        gmIPData = gmIP.adoQueryIndex(collection)
+        
+        gmIPCnt = CommFunc.ReadDWORD(gmIPData, 0)
+        mylog.debug('gmIP cnt = %s'%gmIPCnt[0])
+         
+        allData = dbPlayer.getBuffer() + itemData + missionData + roleMissionDictData + roleSkillData + roleBuffData + roleRepeatTimeData + roleHorseData + gmOperData\
+                     + gmIPData + rolePetData + petSkillData + roleNormalDictData + roleDienstgradData+battleFormationData
+        #
+        DumpDir = os.path.join(GlobalFunctions.getAppPath(),"DumpPlayerData")
+        if not os.path.exists(DumpDir):
+            os.mkdir(DumpDir)
+            
+        fileHandler = open(os.path.join(DumpDir,"%s.pdsave"%account),'wb')
+        import struct
+        fileHandler.write(allData)
+        fileHandler.flush()
+        fileHandler.close()
+        
+    def SaveSinglePlayerDataFromDumpFile(self, db, account):
+        #
+        DumpDir = os.path.join(GlobalFunctions.getAppPath(),"DumpPlayerData")
+        if not os.path.exists(DumpDir):
+            os.mkdir(DumpDir)
+            return (False, 0)
+        FileDir = os.path.join(DumpDir,"%s.pdsave"%account)
+        saveData = ""
+        try:
+            fileHandler = open(FileDir,'rb')
+            saveData = fileHandler.read()
+            fileHandler.close()
+        except:
+            return (False, 0)
+        
+        
+        playerRec = DataServerPlayerData.tagDBPlayer()
+        pos = 0
+        dbPlayerReadLen = playerRec.readData(saveData, pos, len(saveData))
+        if -1 == dbPlayerReadLen:
+            return (False, 0)
+        pos += dbPlayerReadLen 
+        mylog.info('Saving player data,playerID = %s....'%playerRec.PlayerID)
+        if playerRec.PlayerID == 0:
+            return (False, 0)
+        #AccID转小写
+        playerRec.AccID = playerRec.AccID.lower()
+        collection = db[UCN_DBPlayer]
+        
+        if not playerRec.adoCheckUpdateC(collection):
+#            DataDumper.DumpData(GlobalFunctions.getAppPath(), 'UserLogs\\Player_save', '%s.mdat'%sessionID, saveData)
+#            mylog.error('player save error:playerID = %s'%playerRec.PlayerID)
+            return (False, playerRec.PlayerID)
+        #保存物品等其他数据
+        #不再支持单表模式
+        #不再支持文件模式
+        #保存物品
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleItem, DataServerPlayerData.tagRoleItem, saveData[pos:], True)
+        
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleMission, DataServerPlayerData.tagRoleMission, saveData[pos:])
+        
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleMissionDict, DataServerPlayerData.tagRoleMissionDict, saveData[pos:])
+        
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleSkill, DataServerPlayerData.tagRoleSkill, saveData[pos:])
+
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleBuff, DataServerPlayerData.tagRoleBuff, saveData[pos:])
+
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleRepeatTime, DataServerPlayerData.tagRoleRepeatTime, saveData[pos:])
+
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_PlayerHorseTable, DataServerPlayerData.tagPlayerHorseTable, saveData[pos:])
+
+        #封号检查
+        self.gmOperCheck(playerRec.AccID, playerRec.PlayerID, saveData[pos:])
+        
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_GMOper, DataServerPlayerData.tagGMOper, saveData[pos:])
+        #跳过GM IP表
+        gmIPCnt, pos = CommFunc.ReadDWORD(saveData, pos)
+        gmIPRec = DataServerPlayerData.tagDBGMIP()
+        for i in xrange(gmIPCnt):
+            #gmIPRec.clear()
+            pos += gmIPRec.readData(saveData, pos, len(saveData))
+            
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RolePet, DataServerPlayerData.tagRolePet, saveData[pos:])
+
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_PetSkill, DataServerPlayerData.tagPetSkill, saveData[pos:])
+
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_RoleNomalDict, DataServerPlayerData.tagRoleNomalDict, saveData[pos:])
+
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_PlayerDienstgrad, DataServerPlayerData.tagPlayerDienstgrad, saveData[pos:])
+
+        pos += self.savePlayerDataEx(playerRec.PlayerID, db, UCN_BattleFormation, DataServerPlayerData.tagBattleFormation, saveData[pos:])
+
+        assert pos == len(saveData)
+        return (True, playerRec.PlayerID)
+       
+def test():
+    import os
+    os.system('pause')
+    
+if __name__ == '__main__':
+    test()
+        

--
Gitblit v1.8.0