| #!/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")  |