1 import sqlite3 2 import os 3 from threading import Lock, BoundedSemaphore 4 5 6 class ConnPool: 7 8 def __init__(self, db_name, max_conn): 9 self.__MaxConn = max_conn # 最大連接數 10 self.__CurConn = 0 # 當前連接數 11 self.__FreeConn = 0 # 空閑連接數 12 self.__lock = Lock() # 鎖 13 self.__connList = [] # 連接池 14 15 self.dbName = db_name # 數據庫名稱 16 self.init_conn() # 初始化 17 18 def init_conn(self): 19 for i in range(self.__MaxConn): 20 try: 21 conn = sqlite3.connect(os.path.abspath('.') + '\\' + self.dbName + '.db', check_same_thread=False) 22 if conn is not None: 23 self.__connList.append(conn) # 將獲取到的數據庫連接加入連接池 24 self.__FreeConn += 1 25 except Exception as e: 26 print("Get Sqlite Connection Failed: {0}".format(i) + e) 27 self.__sem = BoundedSemaphore(self.__FreeConn) # 初始化信號量 28 self.__MaxConn = self.__FreeConn 29 30 # 每當有請求時,從數據庫連接池中返回一個可用連接,並更新使用和空閑連接數 31 def get_connection(self): 32 if 0 == len(self.__connList): 33 return None 34 self.__sem.acquire() # 消耗資源使計數器遞減,為0時阻塞調用 35 self.__lock.acquire() # 加鎖 36 conn = self.__connList.pop() # 從連接列表中彈出一個數據庫連接 37 38 self.__FreeConn -= 1 # 空閑連接計數-1 39 self.__CurConn += 1 # 當前連接計數+1 40 41 self.__lock.release() # 釋放鎖 42 return conn 43 44 # 釋放當前使用的連接 45 def release_connection(self, conn): 46 if conn is None: 47 return False 48 49 self.__lock.acquire() # 加鎖 50 51 self.__connList.append(conn) # 歸還數據庫連接 52 self.__FreeConn += 1 53 self.__CurConn -= 1 54 55 self.__lock.release() # 釋放鎖 56 try: 57 self.__sem.release() # 歸還資源使計數器遞增 58 except ValueError: 59 print("超出計數器上限.") 60 return True 61 62 # 銷毀數據庫連接池 63 def destroy_pool(self): 64 self.__lock.acquire() # 加鎖 65 if len(self.__connList) > 0: 66 for it in self.__connList: 67 it.close() 68 self.__CurConn = 0 69 self.__FreeConn = 0 70 self.__connList.clear() 71 self.__lock.release() # 釋放鎖 72 73 # 獲取空閑的連接數 74 def get_free_conn(self): 75 return self.__FreeConn 76 77 # 析構函數 78 def __del__(self): 79 self.destroy_pool() 80 81 82 # 創建一個數據庫資源管理類,傳入一個類型為ConnPool對象,生成一個數據庫連接,析構函數中釋放此連接 83 class ConnPoolRAII: 84 def __init__(self, conn_pool: ConnPool): 85 self.connRAII = conn_pool.get_connection() 86 self.poolRAII = conn_pool 87 self.__lock = Lock() # 數據庫操作鎖 88 self.init_db() # 初始化數據庫 89 90 # 數據庫初始化 91 def init_db(self): 92 # 若用於存儲下位機的表不存在,則進行初始化創建 93 if not self.is_exist('Client'): 94 self.operate('''create table Client( 95 ID integer primary key autoincrement, 96 Client_name text(10) not null, 97 IPAddress text(20) not null, 98 Status numeric default 0 99 )''') 100 101 # 檢查指定表是否存在 102 def is_exist(self, table_name): 103 res = self.query('''select count(*) from sqlite_master where type='table' and name='{0}' 104 '''.format(table_name)) 105 if res.fetchone()[0] == 0: 106 return False 107 return True 108 109 # 為每一個客戶機創建一個用於存儲數據的表格 110 def create_table(self, client_name): 111 return self.operate(''' 112 create table {0}( 113 ID integer primary key autoincrement, 114 Weight real default 0, 115 Temperature real default 0, 116 Date integer not null 117 ); 118 '''.format(client_name)) 119 120 # 新增客戶機函數 121 def add_client(self, ip): 122 client_name = 'Client{0}'.format(ip[ip.rfind('.') + 1:]) # 獲取客戶端名稱,以Clientxxx為格式 123 res = self.query("select * from Client where IPAddress=='{0}'".format(client_name)) # 查詢Client表中是否存在當前客戶端信息 124 sql_insert = "insert into Client (Client_name, IPAddress) values ('{0}','{1}')".format(client_name, ip) 125 if res and (res.fetchone() is None): 126 if self.operate(sql_insert) and self.create_table(client_name): 127 print("創建表成功") # 測試用,后續改為日志 128 return True 129 else: 130 print("創建表失敗,檢查客戶端是否已存在!") 131 return False 132 133 # 用於查詢類操作,要求輸入sql語句 134 def query(self, sql): 135 self.__lock.acquire() # 加鎖 136 c = self.connRAII.cursor() # 獲取cursor 137 try: 138 res = c.execute(sql) # 執行sql 139 self.__lock.release() # 釋放鎖 140 return res # 返回查詢結果 141 except Exception as e: 142 print(e) 143 self.__lock.release() # 釋放鎖 144 return False # 返回False 145 146 # 增刪改等操作,提供sql語句,返回bool值 147 def operate(self, sql): 148 self.__lock.acquire() # 加鎖 149 c = self.connRAII.cursor() # 獲取cursor 150 try: 151 c.execute(sql) # 執行sql 152 self.connRAII.commit() # 提交執行結果 153 self.__lock.release() # 釋放鎖 154 return True # 返回操作成功 155 except Exception as e: 156 print(e) # 打印錯誤信息 157 self.__lock.release() # 釋放鎖 158 return False # 返回False 159 160 # 析構函數 161 def __del__(self): 162 self.poolRAII.release_connection(self.connRAII)