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)