#!/usr/bin/python  
 | 
# -*- coding: GBK -*-  
 | 
#  
 | 
##@package  
 | 
#  
 | 
# @todo: Â¼Èë·µÀû # Êý¾Ý¿â×ֶΠÇþµÀspid Õ˺Åaccid ÏÉÓñgold ¶Ò»»ËùÔÚ·þserverid  
 | 
#  
 | 
# @author: Alee  
 | 
# @date 2019-1-22 ÏÂÎç03:23:30  
 | 
# @version 1.0  
 | 
#  
 | 
# @note:   
 | 
#  
 | 
#---------------------------------------------------------------------  
 | 
  
 | 
import pymongo  
 | 
from pymongo.son_manipulator import SONManipulator  
 | 
import base64  
 | 
from functools import wraps  
 | 
from time import (sleep)  
 | 
  
 | 
from lib import CommFunc  
 | 
  
 | 
  
 | 
class ObjectIdRemover(SONManipulator):  
 | 
    def transform_outgoing(self, son, collection):  
 | 
        if '_id' in son:  
 | 
            del son['_id']  
 | 
        return son  
 | 
  
 | 
class EncodeStringManipulator(SONManipulator):  
 | 
    def __init__(self, encoding):  
 | 
        self.encoding = encoding  
 | 
    def transform_incoming(self, son, collection):  
 | 
          
 | 
        def transform_value(value):  
 | 
            if isinstance(value, dict):  
 | 
                return transform_dict(value)  
 | 
            elif isinstance(value, list):  
 | 
                return [transform_value(v) for v in value]  
 | 
            elif isinstance(value, basestring):  
 | 
                result, value = CommFunc.EncodingToUnicode(self.encoding, value)  
 | 
                return value  
 | 
            return value  
 | 
          
 | 
        def transform_dict(object):  
 | 
            for (key, value) in object.items():  
 | 
                object[key] = transform_value(value)  
 | 
            return object  
 | 
          
 | 
        def transform_list(container):  
 | 
            for item in container:  
 | 
                transform_dict(item)  
 | 
            return container  
 | 
          
 | 
        if isinstance(son, dict):  
 | 
            return transform_dict(son)  
 | 
        elif isinstance(son, list):  
 | 
            return transform_list(son)  
 | 
        return son  
 | 
      
 | 
    def transform_outgoing(self, son, collection):  
 | 
          
 | 
        def transform_value(value):  
 | 
            if isinstance(value, dict):  
 | 
                return transform_dict(value)  
 | 
            elif isinstance(value, list):  
 | 
                return [transform_value(v) for v in value]  
 | 
            elif isinstance(value, basestring):  
 | 
                result, value =CommFunc.UnicodeToEncoding(self.encoding, value)  
 | 
                return value  
 | 
            return value  
 | 
          
 | 
        def transform_dict(object):  
 | 
            for (key, value) in object.items():  
 | 
                object[key] = transform_value(value)  
 | 
            return object  
 | 
          
 | 
        def transform_list(container):  
 | 
            for item in container:  
 | 
                transform_dict(item)  
 | 
            return container  
 | 
          
 | 
        if isinstance(son, dict):  
 | 
            return transform_dict(son)  
 | 
        elif isinstance(son, list):  
 | 
            return transform_list(son)  
 | 
        return son  
 | 
      
 | 
class Base64StringManipulator(SONManipulator):  
 | 
      
 | 
    def transform_incoming(self, son, collection):  
 | 
          
 | 
        def transform_value(value):  
 | 
            if isinstance(value, dict):  
 | 
                return transform_dict(value)  
 | 
            elif isinstance(value, list):  
 | 
                return [transform_value(v) for v in value]  
 | 
            elif isinstance(value, basestring):  
 | 
                return base64.b64encode(value)  
 | 
            return value  
 | 
          
 | 
        def transform_dict(object):  
 | 
            for (key, value) in object.items():  
 | 
                object[key] = transform_value(value)  
 | 
            return object  
 | 
          
 | 
        def transform_list(container):  
 | 
            for item in container:  
 | 
                transform_dict(item)  
 | 
            return container  
 | 
          
 | 
        if isinstance(son, dict):  
 | 
            return transform_dict(son)  
 | 
        elif isinstance(son, list):  
 | 
            return transform_list(son)  
 | 
        return son  
 | 
      
 | 
    def transform_outgoing(self, son, collection):  
 | 
          
 | 
        def transform_value(value):  
 | 
            if isinstance(value, dict):  
 | 
                return transform_dict(value)  
 | 
            elif isinstance(value, list):  
 | 
                return [transform_value(v) for v in value]  
 | 
            elif isinstance(value, basestring):  
 | 
                return base64.b64decode(value)  
 | 
            return value  
 | 
          
 | 
        def transform_dict(object):  
 | 
            for (key, value) in object.items():  
 | 
                object[key] = transform_value(value)  
 | 
            return object  
 | 
          
 | 
        def transform_list(container):  
 | 
            for item in container:  
 | 
                transform_dict(item)  
 | 
            return container  
 | 
          
 | 
        if isinstance(son, dict):  
 | 
            return transform_dict(son)  
 | 
        elif isinstance(son, list):  
 | 
            return transform_list(son)  
 | 
        return son  
 | 
        
 | 
#ÓÃÓÚÐÞÊÎDBControllerµÄÊý¾Ý¿â²Ù×÷º¯Êý  
 | 
#¶ÏÏß×Ô¶¯ÖØÊÔ  
 | 
def reconnect_decorator(func):  
 | 
    @wraps(func)  
 | 
    def wrapper(*args, **kwds):  
 | 
        MAX_RECONNECT = 10  
 | 
        RECONNECT_INTERVAL = 0.1  
 | 
        failCnt = 0  
 | 
        while True:  
 | 
            try:  
 | 
                #È¥µôself  
 | 
                return func(*args, **kwds)  
 | 
            except pymongo.errors.AutoReconnect, e:  
 | 
                failCnt += 1  
 | 
                sleep(RECONNECT_INTERVAL)  
 | 
                if failCnt > MAX_RECONNECT:  
 | 
                    raise e  
 | 
      
 | 
    return wrapper  
 | 
  
 | 
class DBController:  
 | 
    def __init__(self, host, port, dbName, user, pwd, encoding):  
 | 
        self.host = host  
 | 
        self.port = port  
 | 
        self.dbName = dbName  
 | 
        self.user = user  
 | 
        self.pwd = pwd  
 | 
          
 | 
        self.connected = False  
 | 
        self.con = None  
 | 
        self.db = None  
 | 
        self.lastError = None  
 | 
        self.translator = None  
 | 
        #===========================================================================================  
 | 
        # if encoding == 'base64':  
 | 
        #    self.translator = Base64StringManipulator()  
 | 
        # else:  
 | 
        #    self.translator = EncodeStringManipulator(encoding)  
 | 
        #===========================================================================================  
 | 
        self.initialize()  
 | 
          
 | 
    def initialize(self):  
 | 
        if not self.connected:  
 | 
            if not self.doConnect(self.host, self.port):  
 | 
                return False  
 | 
            authResult = self.doAuthentication(self.dbName, self.user, self.pwd)  
 | 
            if self.db:  
 | 
                self.db.add_son_manipulator(ObjectIdRemover())  
 | 
            return authResult  
 | 
        return True  
 | 
          
 | 
    def doConnect(self, ip, port):  
 | 
        try:  
 | 
            self.con = pymongo.Connection(ip, port)  
 | 
        except TypeError, typeError:  
 | 
            raise  
 | 
        except pymongo.errors.ConnectionFailure, failure:  
 | 
            self.lastError = failure  
 | 
            return False  
 | 
        except Exception, e:  
 | 
            self.lastError = e  
 | 
            return False  
 | 
        except:  
 | 
            self.lastError = 'Unknown exception occur!'  
 | 
            return False  
 | 
        self.connected = True  
 | 
        return True  
 | 
      
 | 
    def doAuthentication(self, dbName, user, pwd):  
 | 
        if not self.connected or not self.con:  
 | 
            self.lastError = 'Not connected yet!'  
 | 
            return False  
 | 
        self.db = self.con[dbName]  
 | 
        authDB = self.con['admin']  
 | 
        try:  
 | 
            return authDB.authenticate(user, pwd)  
 | 
#            return self.db.authenticate(user, pwd)  
 | 
        except TypeError, typeError:  
 | 
            self.lastError = typeError  
 | 
            return False  
 | 
        except Exception, e:  
 | 
            self.lastError = e  
 | 
            return False  
 | 
        except:  
 | 
            self.lastError = 'Unknown exception occur!'  
 | 
            return False  
 | 
      
 | 
    def find_one(self, colName, spec, filter = None):  
 | 
        result, recList = self.find(colName, spec, filter, 1)  
 | 
        if not result:  
 | 
            return False, None  
 | 
        for rec in recList:  
 | 
            return True, rec  
 | 
        return True, None  
 | 
      
 | 
    @reconnect_decorator  
 | 
    def find(self, colName, spec = None, filter = None, maxCnt = 0, sortBy = None):  
 | 
        if not self.connected:  
 | 
            if not self.initialize():  
 | 
                return False, []  
 | 
              
 | 
        result = False  
 | 
        resultDictList = []  
 | 
        col = self.db[colName]  
 | 
        if self.translator:  
 | 
            spec = self.translator.transform_incoming(spec, None)  
 | 
        try:  
 | 
            resultCollection = col.find(spec, filter, limit = maxCnt, sort = sortBy)  
 | 
            if self.translator:  
 | 
                resultDictList = self.translator.transform_outgoing(list(resultCollection), None)  
 | 
            else:  
 | 
                resultDictList = list(resultCollection)  
 | 
            return True, resultDictList  
 | 
        except TypeError, typeError:  
 | 
            self.lastError = typeError  
 | 
            return result, resultDictList  
 | 
        except pymongo.errors.OperationFailure, err:  
 | 
            self.lastError = err  
 | 
            return result, resultDictList  
 | 
        except Exception, e:  
 | 
            self.lastError = e  
 | 
            return result, resultDictList  
 | 
        except:  
 | 
            self.lastError = 'Unknown exception occur!'  
 | 
            return result, resultDictList      
 | 
          
 | 
    @reconnect_decorator  
 | 
    def insert(self, colName, doc_or_docs, isSafe = True):  
 | 
        if not self.connected:  
 | 
            if not self.initialize():  
 | 
                return False  
 | 
              
 | 
        col = self.db[colName]  
 | 
        if self.translator:  
 | 
            doc_or_docs = self.translator.transform_incoming(doc_or_docs, None)  
 | 
        try:  
 | 
            col.insert(doc_or_docs, safe = isSafe)  
 | 
        except pymongo.errors.OperationFailure, err:  
 | 
            self.lastError = err  
 | 
            return False  
 | 
        except Exception, e:  
 | 
            self.lastError = e  
 | 
            return False  
 | 
        except:  
 | 
            self.lastError = 'Unknown exception occur!'  
 | 
            return False  
 | 
        return True  
 | 
      
 | 
    @reconnect_decorator  
 | 
    def update(self, colName, spec, doc, isUpsert = False, isSafe = True, isMulti = False):  
 | 
        if not self.connected:  
 | 
            if not self.initialize():  
 | 
                return False  
 | 
              
 | 
        col = self.db[colName]  
 | 
        #ÐèÒªÏȶÔdoc½øÐд¦Àí£¬µ«Óɲ»ÄÜ¿ªÆôcollection.updateµÄmanipulate,ÒòΪÄÇ»áÓ¦ÓÃËùÓд¦Àí  
 | 
        if self.translator:  
 | 
            spec = self.translator.transform_incoming(spec, None)  
 | 
            doc = self.translator.transform_incoming(doc, None)  
 | 
        try:  
 | 
            col.update(spec, doc, upsert = isUpsert, safe = isSafe, multi = isMulti)  
 | 
        except TypeError, typeError:  
 | 
            self.lastError = typeError  
 | 
            return False  
 | 
        except pymongo.errors.OperationFailure, err:  
 | 
            self.lastError = err  
 | 
            return False  
 | 
        except Exception, e:  
 | 
            self.lastError = e  
 | 
            return False  
 | 
        except:  
 | 
            self.lastError = 'Unknown exception occur!'  
 | 
            return False  
 | 
        return True  
 | 
      
 | 
    @reconnect_decorator  
 | 
    def save(self, colName, doc, isSafe = True):  
 | 
        if not self.connected:  
 | 
            if not self.initialize():  
 | 
                return False  
 | 
              
 | 
        col = self.db[colName]  
 | 
        if self.translator:  
 | 
            doc = self.translator.transform_incoming(doc, None)  
 | 
        try:  
 | 
            col.save(doc, safe = isSafe)  
 | 
        except TypeError, typeError:  
 | 
            self.lastError = typeError  
 | 
            return False  
 | 
        except pymongo.errors.OperationFailure, err:  
 | 
            self.lastError = err  
 | 
            return False  
 | 
        except Exception, e:  
 | 
            self.lastError = e  
 | 
            return False  
 | 
        except:  
 | 
            self.lastError = 'Unknown exception occur!'  
 | 
            return False  
 | 
        return True  
 | 
      
 | 
    @reconnect_decorator  
 | 
    def remove(self, colName, spec = None, isSafe = True):  
 | 
        if not self.connected:  
 | 
            if not self.initialize():  
 | 
                return False  
 | 
              
 | 
        col = self.db[colName]  
 | 
        if self.translator:  
 | 
            spec = self.translator.transform_incoming(spec, None)  
 | 
        try:  
 | 
            col.remove(spec, safe = isSafe)  
 | 
        except pymongo.errors.OperationFailure, err:  
 | 
            self.lastError = err  
 | 
            return False  
 | 
        except Exception, e:  
 | 
            self.lastError = e  
 | 
            return False  
 | 
        except:  
 | 
            self.lastError = 'Unknown exception occur!'  
 | 
            return False  
 | 
        return True  
 | 
      
 | 
    @reconnect_decorator  
 | 
    def drop(self, colName):  
 | 
        if not self.connected:  
 | 
            if not self.initialize():  
 | 
                return False  
 | 
     
 | 
        col = self.db[colName]  
 | 
        try:  
 | 
            col.drop()  
 | 
        except TypeError, typeError:  
 | 
            self.lastError = typeError  
 | 
            return False  
 | 
        except Exception, e:  
 | 
            self.lastError = e  
 | 
            return False  
 | 
        except:  
 | 
            self.lastError = 'Unknown exception occur!'  
 | 
            return False  
 | 
        return True  
 | 
      
 | 
    @reconnect_decorator  
 | 
    def count(self, colName):  
 | 
        if not self.connected:  
 | 
            if not self.initialize():  
 | 
                return False, 0  
 | 
              
 | 
        col = self.db[colName]  
 | 
        try:  
 | 
            cnt = col.count()  
 | 
        except pymongo.errors.OperationFailure, err:  
 | 
            self.lastError = err  
 | 
            return False, 0  
 | 
        except Exception, e:  
 | 
            self.lastError = e  
 | 
            return False, 0  
 | 
        except:  
 | 
            self.lastError = 'Unknown exception occur!'  
 | 
            return False, 0  
 | 
        return True, cnt  
 | 
        
 | 
  
 | 
  
 | 
      
 | 
def test_DBController():  
 | 
    fileIO = open("Bill.txt")  
 | 
    # spid accid gold  
 | 
    testColName = 'tagDoubleBill'  
 | 
    dbController = DBController('localhost', 27017, "DoubleBillDB", 'sa', 'sa', None)  
 | 
      
 | 
    print "¿ªÊ¼Â¼ÈëÊý¾Ý"  
 | 
    cnt = 0   
 | 
    spidDict= {}  
 | 
    #ÇþµÀSpID Õ˺ÅAccID ÏÉÓñGold ¶Ò»»ËùÔÚ·þServerID  
 | 
    for line in fileIO.readlines():  
 | 
        try:  
 | 
            spID, accID, gold = line.strip().split()  
 | 
        except:  
 | 
            print "Error:", line  
 | 
            continue  
 | 
        result, recs = dbController.find(testColName, {"SpID":spID, "AccID":accID})  
 | 
        if recs:  
 | 
            print "ÖØ¸´²åÈë", spID, accID, gold   
 | 
            continue  
 | 
          
 | 
        doc = {"SpID":spID, "AccID":accID, "Gold":gold, "ServerID":""}  
 | 
        result = dbController.insert(testColName, doc)  
 | 
        if not result:  
 | 
            print "²åÈëʧ°Ü", spID, accID, gold  
 | 
            continue  
 | 
          
 | 
          
 | 
        spidDict[spID] = 0  
 | 
        cnt += 1  
 | 
          
 | 
    print "¼ÈëÇþµÀ·µÀû½áÊø£¬×ܹ²%sÌõ, º¬Æ½Ì¨%s"%(cnt, spidDict.keys())  
 | 
      
 | 
      
 | 
#¿ªÊ¼Â¼ÈëÊý¾Ý  
 | 
#¼ÈëÇþµÀ·µÀû½áÊø£¬×ܹ²681Ìõ, º¬Æ½Ì¨['kupai', 'uc', 'gionee', 'xiaomi', 'vivo', 'lenovo', 'meizu', 'yyb', 'oppo', 'qh360']  
 | 
      
 | 
      
 | 
def test():  
 | 
  
 | 
    test_DBController()  
 | 
    print 'test ok!'  
 | 
  
 | 
if __name__ == '__main__':  
 | 
    test()  
 | 
    import os  
 | 
    os.system("pause")  
 |