rda-python-common 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rda_python_common/PgCMD.py +603 -0
- rda_python_common/PgDBI.py +2306 -0
- rda_python_common/PgFile.py +3118 -0
- rda_python_common/PgLOG.py +1689 -0
- rda_python_common/PgLock.py +640 -0
- rda_python_common/PgOPT.py +1740 -0
- rda_python_common/PgSIG.py +1164 -0
- rda_python_common/PgSplit.py +299 -0
- rda_python_common/PgUtil.py +1854 -0
- rda_python_common/__init__.py +0 -0
- rda_python_common/pg_cmd.py +493 -0
- rda_python_common/pg_dbi.py +1885 -0
- rda_python_common/pg_file.py +2462 -0
- rda_python_common/pg_lock.py +533 -0
- rda_python_common/pg_log.py +1352 -0
- rda_python_common/pg_opt.py +1447 -0
- rda_python_common/pg_pass.py +92 -0
- rda_python_common/pg_sig.py +879 -0
- rda_python_common/pg_split.py +260 -0
- rda_python_common/pg_util.py +1534 -0
- rda_python_common/pgpassword.py +92 -0
- rda_python_common-2.0.0.dist-info/METADATA +20 -0
- rda_python_common-2.0.0.dist-info/RECORD +27 -0
- rda_python_common-2.0.0.dist-info/WHEEL +5 -0
- rda_python_common-2.0.0.dist-info/entry_points.txt +3 -0
- rda_python_common-2.0.0.dist-info/licenses/LICENSE +21 -0
- rda_python_common-2.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
#
|
|
2
|
+
###############################################################################
|
|
3
|
+
#
|
|
4
|
+
# Title : PgLock.py
|
|
5
|
+
# Author : Zaihua Ji, zji@ucar.edu
|
|
6
|
+
# Date : 08/118/2020
|
|
7
|
+
# 2025-01-10 transferred to package rda_python_common from
|
|
8
|
+
# https://github.com/NCAR/rda-shared-libraries.git
|
|
9
|
+
# Purpose : python library module for functions to lock RDADB records
|
|
10
|
+
#
|
|
11
|
+
# Github : https://github.com/NCAR/rda-python-common.git
|
|
12
|
+
#
|
|
13
|
+
###############################################################################
|
|
14
|
+
#
|
|
15
|
+
import re
|
|
16
|
+
import time
|
|
17
|
+
from . import PgLOG
|
|
18
|
+
from . import PgSIG
|
|
19
|
+
from . import PgUtil
|
|
20
|
+
from . import PgFile
|
|
21
|
+
from . import PgDBI
|
|
22
|
+
|
|
23
|
+
DOLOCKS = {-2 : 'Force Unlock', -1 : 'Unlock', 0 : 'Unlock', 1 : 'Relock', 2 : 'Force Relock'}
|
|
24
|
+
|
|
25
|
+
def end_db_transaction(idx):
|
|
26
|
+
|
|
27
|
+
if idx > 0:
|
|
28
|
+
PgDBI.endtran()
|
|
29
|
+
else:
|
|
30
|
+
PgDBI.aborttran()
|
|
31
|
+
return idx
|
|
32
|
+
|
|
33
|
+
#
|
|
34
|
+
# check and return running process status: 1-running/uncheckable,0-stopped
|
|
35
|
+
#
|
|
36
|
+
def check_process_running_status(host, pid, dolock, lmsg, logact):
|
|
37
|
+
|
|
38
|
+
if not PgFile.local_host_action(host, DOLOCKS[dolock], lmsg, logact): return 1
|
|
39
|
+
stat = PgSIG.check_host_pid(host, pid)
|
|
40
|
+
if stat > 0:
|
|
41
|
+
if logact: PgLOG.pglog("{}: Cannot {}".format(lmsg, DOLOCKS[dolock]), logact)
|
|
42
|
+
return 1
|
|
43
|
+
if stat < 0 and dolock > -2 and dolock < 2:
|
|
44
|
+
if logact: PgLOG.pglog("{}: Fail checking lock info to {}".format(lmsg, DOLOCKS[dolock]), logact)
|
|
45
|
+
return 1
|
|
46
|
+
return 0
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# lock/unlock dscheck record
|
|
50
|
+
#
|
|
51
|
+
# lock if dolock > 0, unlock if <= 0, skip for locked on different host if 0 or 1
|
|
52
|
+
# force unlock if < -1 or force lock if 2
|
|
53
|
+
#
|
|
54
|
+
def lock_dscheck(cidx, dolock, logact = 0):
|
|
55
|
+
|
|
56
|
+
if not cidx: return 0
|
|
57
|
+
if logact:
|
|
58
|
+
logerr = logact|PgLOG.ERRLOG
|
|
59
|
+
logout = logact&(~PgLOG.EXITLG)
|
|
60
|
+
else:
|
|
61
|
+
logerr = PgLOG.LOGERR
|
|
62
|
+
logout = PgLOG.LOGWRN if dolock > 1 or dolock < 0 else 0
|
|
63
|
+
table = "dscheck"
|
|
64
|
+
cnd = "cindex = {}".format(cidx)
|
|
65
|
+
fields = "command, pid, lockhost, lockcmd"
|
|
66
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logerr)
|
|
67
|
+
if not pgrec: return 0 # dscheck is gone or db error
|
|
68
|
+
|
|
69
|
+
pid = pgrec['pid']
|
|
70
|
+
host = pgrec['lockhost']
|
|
71
|
+
lockcmd = pgrec['lockcmd']
|
|
72
|
+
(chost, cpid) = PgLOG.current_process_info()
|
|
73
|
+
clockcmd = PgLOG.get_command()
|
|
74
|
+
|
|
75
|
+
if pid == 0 and dolock <= 0: return cidx # no need unlock
|
|
76
|
+
lckpid = -pid if pid > 0 and pid == cpid and not PgUtil.pgcmp(host, chost, 1) else pid
|
|
77
|
+
if dolock > 0 and lckpid < 0: return cidx # no need lock again
|
|
78
|
+
|
|
79
|
+
cinfo = "{}-{}-Chk{}({})".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime(), cidx, pgrec['command'])
|
|
80
|
+
if lckpid > 0 and (clockcmd == "dscheck" or lockcmd != "dscheck"):
|
|
81
|
+
lmsg = "{} Locked by {}/{}/{}".format(cinfo, pid, host, lockcmd)
|
|
82
|
+
if check_process_running_status(host, pid, dolock, lmsg, logout): return -cidx
|
|
83
|
+
|
|
84
|
+
record = {}
|
|
85
|
+
if dolock > 0:
|
|
86
|
+
if pid != cpid: record['pid'] = cpid
|
|
87
|
+
if host != chost: record['lockhost'] = chost
|
|
88
|
+
if lockcmd != clockcmd: record['lockcmd'] = clockcmd
|
|
89
|
+
else:
|
|
90
|
+
if pid: record['pid'] = 0
|
|
91
|
+
if not record: return cidx
|
|
92
|
+
|
|
93
|
+
lkrec = PgDBI.pgget(table, fields, cnd, logerr|PgLOG.DOLOCK)
|
|
94
|
+
if not lkrec: return end_db_transaction(0) # dscheck is gone or db error
|
|
95
|
+
|
|
96
|
+
if (not lkrec['pid'] or
|
|
97
|
+
lkrec['pid'] == pid and PgUtil.pgcmp(lkrec['lockhost'], host, 1) == 0 or
|
|
98
|
+
lkrec['pid'] == cpid and PgUtil.pgcmp(lkrec['lockhost'], chost, 1) == 0):
|
|
99
|
+
if not PgDBI.pgupdt(table, record, cnd, logerr):
|
|
100
|
+
if logout: PgLOG.pglog(cinfo + ": Error update lock", logout)
|
|
101
|
+
cidx = -cidx
|
|
102
|
+
else:
|
|
103
|
+
if logout: PgLOG.pglog("{}: Relocked {}/{}".format(cinfo, lkrec['pid'], lkrec['lockhost']), logout)
|
|
104
|
+
cidx = -cidx
|
|
105
|
+
|
|
106
|
+
return end_db_transaction(cidx)
|
|
107
|
+
|
|
108
|
+
#
|
|
109
|
+
# lock dscheck record for given cidx, pid and host
|
|
110
|
+
#
|
|
111
|
+
def lock_host_dscheck(cidx, pid, host, logact = 0):
|
|
112
|
+
|
|
113
|
+
if not (cidx and pid): return 0
|
|
114
|
+
if logact:
|
|
115
|
+
logerr = logact|PgLOG.ERRLOG
|
|
116
|
+
logout = logact&(~PgLOG.EXITLG)
|
|
117
|
+
else:
|
|
118
|
+
logerr = PgLOG.LOGERR
|
|
119
|
+
logout = 0
|
|
120
|
+
table = "dscheck"
|
|
121
|
+
cnd = "cindex = {}".format(cidx)
|
|
122
|
+
fields = "command, pid, lockhost, lockcmd"
|
|
123
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logerr)
|
|
124
|
+
if not pgrec: return 0 # dscheck is gone or db error
|
|
125
|
+
(chost, cpid) = PgLOG.current_process_info()
|
|
126
|
+
|
|
127
|
+
cinfo = "{}-{}-Chk{}({})".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime(), cidx, pgrec['command'])
|
|
128
|
+
if pgrec['pid']:
|
|
129
|
+
if pid == pgrec['pid'] and PgUtil.pgcmp(pgrec['lockhost'], host, 1) == 0:
|
|
130
|
+
return -cidx # locked by the real process already
|
|
131
|
+
elif cpid != pgrec['pid'] or PgUtil.pgcmp(pgrec['lockhost'], chost, 1):
|
|
132
|
+
if logout:
|
|
133
|
+
lmsg = "{} Locked by {}/{}/{}".format(cinfo, pid, host, pgrec['lockcmd'])
|
|
134
|
+
PgLOG.pglog(lmsg +": Cannot Lock", logout)
|
|
135
|
+
return -cidx # locked by other process
|
|
136
|
+
|
|
137
|
+
record = {}
|
|
138
|
+
record['pid'] = pid
|
|
139
|
+
record['lockhost'] = host
|
|
140
|
+
record['lockcmd'] = PgLOG.get_command(pgrec['command'])
|
|
141
|
+
|
|
142
|
+
lkrec = PgDBI.pgget(table, fields, cnd, logerr|PgLOG.DOLOCK)
|
|
143
|
+
if not lkrec: return end_db_transaction(0)
|
|
144
|
+
|
|
145
|
+
if (not lkrec['pid'] or
|
|
146
|
+
lkrec['pid'] == pid and PgUtil.pgcmp(lkrec['lockhost'], host, 1) == 0 or
|
|
147
|
+
lkrec['pid'] == cpid and PgUtil.pgcmp(lkrec['lockhost'], chost, 1) == 0):
|
|
148
|
+
if not PgDBI.pgupdt(table, record, cnd, logerr):
|
|
149
|
+
if logout: PgLOG.pglog(cinfo + ": Error update lock", logout)
|
|
150
|
+
cidx = -cidx
|
|
151
|
+
else:
|
|
152
|
+
if logout: PgLOG.pglog("{}: Relocked {}/{}".format(cinfo, lkrec['pid'], lkrec['lockhost']), logout)
|
|
153
|
+
cidx = -cidx
|
|
154
|
+
|
|
155
|
+
return end_db_transaction(cidx)
|
|
156
|
+
|
|
157
|
+
#
|
|
158
|
+
# lock/unlock data request record
|
|
159
|
+
#
|
|
160
|
+
# lock if dolock > 0, unlock if <= 0, skip for locked on different host if 0 or 1
|
|
161
|
+
# force unlock if < -1 or 2
|
|
162
|
+
#
|
|
163
|
+
def lock_request(ridx, dolock, logact = 0):
|
|
164
|
+
|
|
165
|
+
if not ridx: return 0
|
|
166
|
+
if logact:
|
|
167
|
+
logerr = logact|PgLOG.ERRLOG
|
|
168
|
+
logout = logact&(~PgLOG.EXITLG)
|
|
169
|
+
else:
|
|
170
|
+
logerr = PgLOG.LOGERR
|
|
171
|
+
logout = PgLOG.LOGWRN if dolock > 1 or dolock < 0 else 0
|
|
172
|
+
table = "dsrqst"
|
|
173
|
+
cnd = "rindex = {}".format(ridx)
|
|
174
|
+
fields = "pid, lockhost"
|
|
175
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logerr)
|
|
176
|
+
if not pgrec: return 0 # request is gone or db error
|
|
177
|
+
|
|
178
|
+
pid = pgrec['pid']
|
|
179
|
+
host = pgrec['lockhost']
|
|
180
|
+
(chost, cpid) = PgLOG.current_process_info()
|
|
181
|
+
|
|
182
|
+
if pid == 0 and dolock <= 0: return ridx # no need unlock
|
|
183
|
+
lckpid = -pid if pid > 0 and pid == cpid and not PgUtil.pgcmp(host, chost, 1) else pid
|
|
184
|
+
if dolock > 0 and lckpid < 0: return ridx # no need lock again
|
|
185
|
+
|
|
186
|
+
rinfo = "{}-{}-Rqst{}".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime(), ridx)
|
|
187
|
+
if lckpid > 0:
|
|
188
|
+
lmsg = "{} Locked by {}/{}".format(rinfo, pid, host)
|
|
189
|
+
if check_process_running_status(host, pid, dolock, lmsg, logout): return -ridx
|
|
190
|
+
|
|
191
|
+
record = {}
|
|
192
|
+
if dolock > 0:
|
|
193
|
+
if pid != cpid: record['pid'] = cpid
|
|
194
|
+
if host != chost: record['lockhost'] = chost
|
|
195
|
+
if record: record['locktime'] = int(time.time())
|
|
196
|
+
else:
|
|
197
|
+
if pid: record['pid'] = 0
|
|
198
|
+
if host: record['lockhost'] = ""
|
|
199
|
+
if not record: return ridx
|
|
200
|
+
|
|
201
|
+
lkrec = PgDBI.pgget(table, fields, cnd, logerr|PgLOG.DOLOCK)
|
|
202
|
+
if not lkrec: return end_db_transaction(0) # request is gone or db error
|
|
203
|
+
|
|
204
|
+
if (not lkrec['pid'] or
|
|
205
|
+
lkrec['pid'] == pid and PgUtil.pgcmp(lkrec['lockhost'], host, 1) == 0 or
|
|
206
|
+
lkrec['pid'] == cpid and PgUtil.pgcmp(lkrec['lockhost'], chost, 1) == 0):
|
|
207
|
+
if not PgDBI.pgupdt(table, record, cnd, logerr):
|
|
208
|
+
if logout: PgLOG.pglog(rinfo + ": Error update lock", logout)
|
|
209
|
+
ridx = -ridx
|
|
210
|
+
else:
|
|
211
|
+
if logout: PgLOG.pglog("{}: Relocked {}/{}".format(rinfo, lkrec['pid'], lkrec['lockhost']), logout)
|
|
212
|
+
ridx = -ridx
|
|
213
|
+
|
|
214
|
+
return end_db_transaction(ridx)
|
|
215
|
+
|
|
216
|
+
#
|
|
217
|
+
# lock dsrqst record for given cidx, pid and host
|
|
218
|
+
#
|
|
219
|
+
def lock_host_request(ridx, pid, host, logact = 0):
|
|
220
|
+
|
|
221
|
+
if not (ridx and pid): return 0
|
|
222
|
+
if logact:
|
|
223
|
+
logerr = logact|PgLOG.ERRLOG
|
|
224
|
+
logout = logact&(~PgLOG.EXITLG)
|
|
225
|
+
else:
|
|
226
|
+
logerr = PgLOG.LOGERR
|
|
227
|
+
logout = 0
|
|
228
|
+
table = "dsrqst"
|
|
229
|
+
cnd = "rindex = {}".format(ridx)
|
|
230
|
+
fields = "pid, lockhost"
|
|
231
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logerr)
|
|
232
|
+
if not pgrec: return 0 # dscheck is gone or db error
|
|
233
|
+
|
|
234
|
+
rinfo = "{}-{}-Rqst{}".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime(), ridx)
|
|
235
|
+
if pgrec['pid']:
|
|
236
|
+
if pid == pgrec['pid'] and PgUtil.pgcmp(pgrec['lockhost'], host, 1) == 0: return ridx
|
|
237
|
+
if logout:
|
|
238
|
+
lmsg = "{} Locked by {}/{}".format(rinfo, pid, host)
|
|
239
|
+
PgLOG.pglog(lmsg +": Cannot Lock", logout)
|
|
240
|
+
return -ridx
|
|
241
|
+
record = {}
|
|
242
|
+
record['pid'] = pid
|
|
243
|
+
record['lockhost'] = host
|
|
244
|
+
record['locktime'] = int(time.time())
|
|
245
|
+
|
|
246
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logerr|PgLOG.DOLOCK)
|
|
247
|
+
if not pgrec: return end_db_transaction(0)
|
|
248
|
+
|
|
249
|
+
if not pgrec['pid'] or pid == pgrec['pid'] and PgUtil.pgcmp(pgrec['lockhost'], host, 1) == 0:
|
|
250
|
+
if not PgDBI.pgupdt(table, record, cnd, logerr):
|
|
251
|
+
if logout: PgLOG.pglog(rinfo + ": Error update lock", logout)
|
|
252
|
+
ridx = -ridx
|
|
253
|
+
else:
|
|
254
|
+
if logout: PgLOG.pglog("{}: Relocked {}/{}".format(rinfo, pgrec['pid'], pgrec['lockhost']), logout)
|
|
255
|
+
ridx = -ridx
|
|
256
|
+
|
|
257
|
+
return end_db_transaction(ridx)
|
|
258
|
+
|
|
259
|
+
#
|
|
260
|
+
# lock/unlock dataset update record
|
|
261
|
+
#
|
|
262
|
+
# lock if dolock > 0, unlock if <= 0, skip for locked on different host if 0 or 1
|
|
263
|
+
# force unlock if < -1 or 2
|
|
264
|
+
#
|
|
265
|
+
def lock_update(lidx, linfo, dolock, logact = 0):
|
|
266
|
+
|
|
267
|
+
if not lidx: return 0
|
|
268
|
+
if logact:
|
|
269
|
+
logerr = logact|PgLOG.ERRLOG
|
|
270
|
+
logout = logact&(~PgLOG.EXITLG)
|
|
271
|
+
else:
|
|
272
|
+
logerr = PgLOG.LOGERR
|
|
273
|
+
logout = PgLOG.LOGWRN if dolock > 1 or dolock < 0 else 0
|
|
274
|
+
table = "dlupdt"
|
|
275
|
+
cnd = "lindex = {}".format(lidx)
|
|
276
|
+
fields = "pid, hostname"
|
|
277
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logerr)
|
|
278
|
+
if not pgrec: return 0 # update record is deleted
|
|
279
|
+
|
|
280
|
+
pid = pgrec['pid']
|
|
281
|
+
host = pgrec['hostname']
|
|
282
|
+
(chost, cpid) = PgLOG.current_process_info()
|
|
283
|
+
|
|
284
|
+
if pid == 0 and dolock <= 0: return lidx # no need unlock
|
|
285
|
+
lckpid = -pid if pid > 0 and pid == cpid and not PgUtil.pgcmp(host, chost, 1) else pid
|
|
286
|
+
if dolock > 0 and lckpid < 0: return lidx # no need lock again
|
|
287
|
+
|
|
288
|
+
if not linfo: linfo = "{}-{}-Updt{}".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime(), lidx)
|
|
289
|
+
if lckpid > 0:
|
|
290
|
+
lmsg = "{} Locked by {}/{}".format(linfo, pid, host)
|
|
291
|
+
if check_process_running_status(host, pid, dolock, lmsg, logout): return -lidx
|
|
292
|
+
|
|
293
|
+
record = {}
|
|
294
|
+
if dolock > 0:
|
|
295
|
+
if pid != cpid: record['pid'] = cpid
|
|
296
|
+
if host != chost: record['hostname'] = chost
|
|
297
|
+
if record: record['locktime'] = int(time.time())
|
|
298
|
+
else:
|
|
299
|
+
if pid: record['pid'] = 0
|
|
300
|
+
if host: record['hostname'] = ''
|
|
301
|
+
if not record: return lidx
|
|
302
|
+
|
|
303
|
+
lkrec = PgDBI.pgget(table, fields, cnd, logerr|PgLOG.DOLOCK)
|
|
304
|
+
if not lkrec: return end_db_transaction(0) # update record is deleted
|
|
305
|
+
|
|
306
|
+
if not lkrec['pid'] or lkrec['pid'] == pid and PgUtil.pgcmp(lkrec['hostname'], host, 1) == 0:
|
|
307
|
+
if not PgDBI.pgupdt(table, record, cnd, logerr):
|
|
308
|
+
if logout: PgLOG.pglog(linfo + ": Error update lock", logout)
|
|
309
|
+
lidx = -lidx
|
|
310
|
+
else:
|
|
311
|
+
if logout: PgLOG.pglog("{}: Relocked {}/{}".format(linfo, lkrec['pid'], lkrec['hostname']), logout)
|
|
312
|
+
lidx = -lidx
|
|
313
|
+
|
|
314
|
+
return end_db_transaction(lidx)
|
|
315
|
+
|
|
316
|
+
#
|
|
317
|
+
# lock/unlock dataset update control record
|
|
318
|
+
#
|
|
319
|
+
# lock if dolock > 0, unlock if <= 0, skip for locked on different host if 0 or 1,
|
|
320
|
+
# unlock dead process if < -1 or 2, force unlock if -2
|
|
321
|
+
#
|
|
322
|
+
def lock_update_control(cidx, dolock, logact = 0):
|
|
323
|
+
|
|
324
|
+
if not cidx: return 0
|
|
325
|
+
if logact:
|
|
326
|
+
logerr = logact|PgLOG.ERRLOG
|
|
327
|
+
logout = logact&(~PgLOG.EXITLG)
|
|
328
|
+
else:
|
|
329
|
+
logerr = PgLOG.LOGERR
|
|
330
|
+
logout = PgLOG.LOGWRN if dolock > 1 or dolock < 0 else 0
|
|
331
|
+
table = "dcupdt"
|
|
332
|
+
cnd = "cindex = {}".format(cidx)
|
|
333
|
+
fields = "pid, lockhost"
|
|
334
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logerr)
|
|
335
|
+
if not pgrec: return 0 # update control record is deleted
|
|
336
|
+
|
|
337
|
+
pid = pgrec['pid']
|
|
338
|
+
host = pgrec['lockhost']
|
|
339
|
+
(chost, cpid) = PgLOG.current_process_info()
|
|
340
|
+
|
|
341
|
+
if pid == 0 and dolock <= 0: return cidx # no need unlock
|
|
342
|
+
lckpid = -pid if pid > 0 and pid == cpid and not PgUtil.pgcmp(host, chost, 1) else pid
|
|
343
|
+
if dolock > 0 and lckpid < 0: return cidx # no need lock again
|
|
344
|
+
|
|
345
|
+
cinfo = "{}-{}-UC{}".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime(), cidx)
|
|
346
|
+
if lckpid > 0:
|
|
347
|
+
lmsg = "{} Locked by {}/{}".format(cinfo, pid, host)
|
|
348
|
+
if check_process_running_status(host, pid, dolock, lmsg, logout): return -cidx
|
|
349
|
+
|
|
350
|
+
record = {}
|
|
351
|
+
if dolock > 0:
|
|
352
|
+
if pid != cpid: record['pid'] = cpid
|
|
353
|
+
if host != chost: record['lockhost'] = chost
|
|
354
|
+
if record: record['chktime'] = int(time.time())
|
|
355
|
+
else:
|
|
356
|
+
if pid: record['pid'] = 0
|
|
357
|
+
if host: record['lockhost'] = ''
|
|
358
|
+
if not record: return cidx
|
|
359
|
+
|
|
360
|
+
lkrec = PgDBI.pgget(table, fields, cnd, logerr|PgLOG.DOLOCK)
|
|
361
|
+
if not lkrec: return end_db_transaction(0) # update control record is deleted
|
|
362
|
+
|
|
363
|
+
if (not lkrec['pid'] or
|
|
364
|
+
lkrec['pid'] == pid and PgUtil.pgcmp(lkrec['lockhost'], host, 1) == 0 or
|
|
365
|
+
lkrec['pid'] == cpid and PgUtil.pgcmp(lkrec['lockhost'], chost, 1) == 0):
|
|
366
|
+
if not PgDBI.pgupdt(table, record, cnd, logerr):
|
|
367
|
+
if logout: PgLOG.pglog(cinfo + ": Error update lock", logout)
|
|
368
|
+
cidx = -cidx
|
|
369
|
+
else:
|
|
370
|
+
if logout: PgLOG.pglog("{}: Relocked {}/{}".format(cinfo, lkrec['pid'], lkrec['lockhost']), logout)
|
|
371
|
+
cidx = -cidx
|
|
372
|
+
|
|
373
|
+
return end_db_transaction(cidx)
|
|
374
|
+
|
|
375
|
+
#
|
|
376
|
+
# lock dscheck record for given cidx, pid and host
|
|
377
|
+
#
|
|
378
|
+
def lock_host_update_control(cidx, pid, host, logact = 0):
|
|
379
|
+
|
|
380
|
+
if not (cidx and pid): return 0
|
|
381
|
+
if logact:
|
|
382
|
+
logerr = logact|PgLOG.ERRLOG
|
|
383
|
+
logout = logact&(~PgLOG.EXITLG)
|
|
384
|
+
else:
|
|
385
|
+
logerr = PgLOG.LOGERR
|
|
386
|
+
logout = 0
|
|
387
|
+
table = "dcupdt"
|
|
388
|
+
cnd = "cindex = {}".format(cidx)
|
|
389
|
+
fields = "pid, lockhost"
|
|
390
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logerr)
|
|
391
|
+
if not pgrec: return 0 # dscheck is gone or db error
|
|
392
|
+
|
|
393
|
+
cinfo = "{}-{}-UC{}".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime(), cidx)
|
|
394
|
+
if pgrec['pid']:
|
|
395
|
+
if pid == pgrec['pid'] and PgUtil.pgcmp(pgrec['lockhost'], host, 1) == 0: return cidx
|
|
396
|
+
if logout:
|
|
397
|
+
lmsg = "{} Locked by {}/{}".format(cinfo, pid, host)
|
|
398
|
+
PgLOG.pglog(lmsg +": Cannot Lock", logout)
|
|
399
|
+
return -cidx
|
|
400
|
+
|
|
401
|
+
record = {}
|
|
402
|
+
record['pid'] = pid
|
|
403
|
+
record['lockhost'] = host
|
|
404
|
+
record['chktime'] = int(time.time())
|
|
405
|
+
|
|
406
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logerr|PgLOG.DOLOCK)
|
|
407
|
+
if not pgrec: return end_db_transaction(0)
|
|
408
|
+
|
|
409
|
+
if not pgrec['pid'] or pid == pgrec['pid'] and PgUtil.pgcmp(pgrec['lockhost'], host, 1) == 0:
|
|
410
|
+
if not PgDBI.pgupdt(table, record, cnd, logerr):
|
|
411
|
+
if logout: PgLOG.pglog(cinfo + ": Error update lock", logout)
|
|
412
|
+
cidx = -cidx
|
|
413
|
+
else:
|
|
414
|
+
if logout: PgLOG.pglog("{}: Relocked {}/{}".format(cinfo, pgrec['pid'], pgrec['lockhost']), logout)
|
|
415
|
+
cidx = -cidx
|
|
416
|
+
|
|
417
|
+
return end_db_transaction(cidx)
|
|
418
|
+
|
|
419
|
+
#
|
|
420
|
+
# return lock information of a locked process
|
|
421
|
+
#
|
|
422
|
+
def lock_process_info(pid, lockhost, runhost = None, pcnt = 0):
|
|
423
|
+
|
|
424
|
+
retstr = " {}<{}".format(lockhost, pid)
|
|
425
|
+
if pcnt: retstr += "/{}".format(pcnt)
|
|
426
|
+
retstr += ">"
|
|
427
|
+
if runhost and runhost != lockhost: retstr += '/' + runhost
|
|
428
|
+
return retstr
|
|
429
|
+
|
|
430
|
+
#
|
|
431
|
+
# lock/unlock data request partition record
|
|
432
|
+
#
|
|
433
|
+
# lock if dolock > 0, unlock if <= 0, skip for locked on different host if 0 or 1
|
|
434
|
+
# force unlock if < -1 or 2
|
|
435
|
+
#
|
|
436
|
+
def lock_partition(pidx, dolock, logact = 0):
|
|
437
|
+
|
|
438
|
+
if not pidx: return 0
|
|
439
|
+
if logact:
|
|
440
|
+
logerr = logact|PgLOG.ERRLOG
|
|
441
|
+
logout = logact&(~PgLOG.EXITLG)
|
|
442
|
+
else:
|
|
443
|
+
logerr = PgLOG.LOGERR
|
|
444
|
+
logout = PgLOG.LOGWRN if dolock > 1 or dolock < 0 else 0
|
|
445
|
+
table = "ptrqst"
|
|
446
|
+
cnd = "pindex = {}".format(pidx)
|
|
447
|
+
fields = "pid, lockhost"
|
|
448
|
+
pgrec = PgDBI.pgget(table, "rindex, ptorder, " + fields, cnd, logerr)
|
|
449
|
+
if not pgrec: return 0 # request is gone or db error
|
|
450
|
+
|
|
451
|
+
ridx = pgrec['rindex']
|
|
452
|
+
pid = pgrec['pid']
|
|
453
|
+
host = pgrec['lockhost']
|
|
454
|
+
(chost, cpid) = PgLOG.current_process_info()
|
|
455
|
+
|
|
456
|
+
if pid == 0 and dolock <= 0: return pidx # no need unlock
|
|
457
|
+
lckpid = -pid if pid > 0 and pid == cpid and not PgUtil.pgcmp(host, chost, 1) else pid
|
|
458
|
+
if dolock > 0 and lckpid < 0: return pidx # no need lock again
|
|
459
|
+
|
|
460
|
+
pinfo = "{}-{}-RPT{}(Rqst{}/PTO{})".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime(), pidx, ridx, pgrec['ptorder'])
|
|
461
|
+
if lckpid > 0:
|
|
462
|
+
lmsg = "{} Locked by {}/{}".format(pinfo, pid, host)
|
|
463
|
+
if check_process_running_status(host, pid, dolock, lmsg, logout): return -pidx
|
|
464
|
+
|
|
465
|
+
record = {}
|
|
466
|
+
if dolock > 0:
|
|
467
|
+
if pid != cpid: record['pid'] = cpid
|
|
468
|
+
if host != chost: record['lockhost'] = chost
|
|
469
|
+
if record: record['locktime'] = int(time.time())
|
|
470
|
+
else:
|
|
471
|
+
if pid: record['pid'] = 0
|
|
472
|
+
if host: record['lockhost'] = ""
|
|
473
|
+
if not record: return pidx
|
|
474
|
+
|
|
475
|
+
lkrec = PgDBI.pgget(table, fields, cnd, logerr|PgLOG.DOLOCK)
|
|
476
|
+
if not lkrec: return end_db_transaction(0) # request partition is gone or db error
|
|
477
|
+
|
|
478
|
+
if (not lkrec['pid'] or
|
|
479
|
+
lkrec['pid'] == pid and PgUtil.pgcmp(lkrec['lockhost'], host, 1) == 0 or
|
|
480
|
+
lkrec['pid'] == cpid and PgUtil.pgcmp(lkrec['lockhost'], chost, 1) == 0):
|
|
481
|
+
lmsg = update_partition_lock(ridx, record, logout)
|
|
482
|
+
if lmsg:
|
|
483
|
+
if logout: PgLOG.pglog("{}: {}".format(pinfo, lmsg), logout)
|
|
484
|
+
pidx = -pidx
|
|
485
|
+
elif not PgDBI.pgupdt(table, record, cnd, logerr):
|
|
486
|
+
if logout: PgLOG.pglog(pinfo + ": error update lock", logout)
|
|
487
|
+
pidx = -pidx
|
|
488
|
+
else:
|
|
489
|
+
PgLOG.pglog("{}: Relocked {}/{}".format(pinfo, lkrec['pid'], lkrec['lockhost']), logout)
|
|
490
|
+
pidx = -pidx
|
|
491
|
+
|
|
492
|
+
return end_db_transaction(pidx)
|
|
493
|
+
|
|
494
|
+
#
|
|
495
|
+
# lock dsrqst partition record for given cidx, pid and host
|
|
496
|
+
#
|
|
497
|
+
def lock_host_partition(pidx, pid, host, logact = 0):
|
|
498
|
+
|
|
499
|
+
if not (pidx and pid): return 0
|
|
500
|
+
if logact:
|
|
501
|
+
logerr = logact|PgLOG.ERRLOG
|
|
502
|
+
logout = logact&(~PgLOG.EXITLG)
|
|
503
|
+
else:
|
|
504
|
+
logerr = PgLOG.LOGERR
|
|
505
|
+
logout = 0
|
|
506
|
+
table = "ptrqst"
|
|
507
|
+
cnd = "pindex = {}".format(pidx)
|
|
508
|
+
fields = "pid, lockhost"
|
|
509
|
+
pgrec = PgDBI.pgget(table, "rindex, ptorder, " + fields, cnd, logerr)
|
|
510
|
+
if not pgrec: return 0 # dscheck is gone or db error
|
|
511
|
+
|
|
512
|
+
ridx = pgrec['rindex']
|
|
513
|
+
pinfo = "{}-{}-RPT{}(Rqst{}/PTO{})".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime(), pidx, ridx, pgrec['ptorder'])
|
|
514
|
+
if pgrec['pid']:
|
|
515
|
+
if pid == pgrec['pid'] and PgUtil.pgcmp(pgrec['lockhost'], host, 1) == 0: return pidx
|
|
516
|
+
if logout:
|
|
517
|
+
lmsg = "{} Locked by {}/{}".format(pinfo, pid, host)
|
|
518
|
+
PgLOG.pglog(lmsg +": Cannot Lock", logout)
|
|
519
|
+
return -pidx
|
|
520
|
+
|
|
521
|
+
record = {}
|
|
522
|
+
record['pid'] = pid
|
|
523
|
+
record['lockhost'] = host
|
|
524
|
+
record['locktime'] = int(time.time())
|
|
525
|
+
|
|
526
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logerr|PgLOG.DOLOCK)
|
|
527
|
+
if not pgrec: return end_db_transaction(0)
|
|
528
|
+
|
|
529
|
+
if not pgrec['pid'] or pid == pgrec['pid'] and PgUtil.pgcmp(pgrec['lockhost'], host, 1) == 0:
|
|
530
|
+
lmsg = update_partition_lock(ridx, record, logout)
|
|
531
|
+
if lmsg:
|
|
532
|
+
if logout: PgLOG.pglog("{}: {}".format(pinfo, lmsg), logout)
|
|
533
|
+
pidx = -pidx
|
|
534
|
+
elif not PgDBI.pgupdt(table, record, cnd, logerr):
|
|
535
|
+
if logout: PgLOG.pglog(pinfo + ": error update lock", logout)
|
|
536
|
+
pidx = -pidx
|
|
537
|
+
else:
|
|
538
|
+
if logout: PgLOG.pglog("{}: Relocked {}/{}".format(pinfo, pgrec['pid'], pgrec['lockhost']), logout)
|
|
539
|
+
pidx = -pidx
|
|
540
|
+
|
|
541
|
+
return end_db_transaction(pidx)
|
|
542
|
+
|
|
543
|
+
#
|
|
544
|
+
# update dsrqst lock info for given partition lock status
|
|
545
|
+
# Return None if all is fine; error message otherwise
|
|
546
|
+
#
|
|
547
|
+
def update_partition_lock(ridx, ptrec, logact = 0):
|
|
548
|
+
|
|
549
|
+
if not ridx: return 0
|
|
550
|
+
if logact:
|
|
551
|
+
logerr = logact|PgLOG.ERRLOG
|
|
552
|
+
logout = logact&(~PgLOG.EXITLG)
|
|
553
|
+
else:
|
|
554
|
+
logerr = PgLOG.LOGERR
|
|
555
|
+
logout = PgLOG.LOGWRN
|
|
556
|
+
table = "dsrqst"
|
|
557
|
+
lockhost = "partition"
|
|
558
|
+
cnd = "rindex = {}".format(ridx)
|
|
559
|
+
pgrec = PgDBI.pgget(table, "pid, lockhost", cnd, logact|PgLOG.DOLOCK)
|
|
560
|
+
if not pgrec: return "Error get Rqst{} record".format(ridx) # should not happen
|
|
561
|
+
|
|
562
|
+
if pgrec['pid'] > 0 and pgrec['lockhost'] != lockhost:
|
|
563
|
+
return "Rqst{} locked by non-lockhost process ({}/{})".format(ridx, pgrec['pid'], pgrec['lockhost'])
|
|
564
|
+
|
|
565
|
+
record = {}
|
|
566
|
+
if ptrec['pid'] > 0:
|
|
567
|
+
record['pid'] = pgrec['pid'] + 1
|
|
568
|
+
record['lockhost'] = lockhost
|
|
569
|
+
record['locktime'] = ptrec['locktime']
|
|
570
|
+
else:
|
|
571
|
+
if pgrec['pid'] > 1:
|
|
572
|
+
pcnt = PgDBI.pgget('ptrqst', '', cnd + " AND pid > 0")
|
|
573
|
+
if pgrec['pid'] > pcnt: pgrec['pid'] = pcnt
|
|
574
|
+
record['pid'] = pgrec['pid'] - 1
|
|
575
|
+
record['lockhost'] = lockhost
|
|
576
|
+
else:
|
|
577
|
+
record['pid'] = 0
|
|
578
|
+
record['lockhost'] = ''
|
|
579
|
+
if not PgDBI.pgupdt(table, record, cnd, logact):
|
|
580
|
+
return "Error update Rqst{} lock".format(ridx)
|
|
581
|
+
|
|
582
|
+
return None
|
|
583
|
+
|
|
584
|
+
#
|
|
585
|
+
# lock/unlock dataset record for Quasar Backup
|
|
586
|
+
#
|
|
587
|
+
# lock if dolock > 0, unlock if <= 0, skip for locked on different host if 0 or 1,
|
|
588
|
+
# unlock dead process if < -1 or 2, force unlock if -2
|
|
589
|
+
#
|
|
590
|
+
def lock_dataset(dsid, dolock, logact = 0):
|
|
591
|
+
|
|
592
|
+
if not dsid: return 0
|
|
593
|
+
if logact:
|
|
594
|
+
logerr = logact|PgLOG.ERRLOG
|
|
595
|
+
logout = logact&(~PgLOG.EXITLG)
|
|
596
|
+
else:
|
|
597
|
+
logerr = PgLOG.LOGERR
|
|
598
|
+
logout = PgLOG.LOGWRN if dolock > 1 or dolock < 0 else 0
|
|
599
|
+
table = "dataset"
|
|
600
|
+
cnd = "dsid = '{}'".format(dsid)
|
|
601
|
+
fields = "pid, lockhost"
|
|
602
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logerr)
|
|
603
|
+
if not pgrec: return 0 # dataset not exists
|
|
604
|
+
|
|
605
|
+
pid = pgrec['pid']
|
|
606
|
+
host = pgrec['lockhost']
|
|
607
|
+
(chost, cpid) = PgLOG.current_process_info()
|
|
608
|
+
|
|
609
|
+
if pid == 0 and dolock <= 0: return 1 # no need unlock
|
|
610
|
+
lckpid = -pid if pid > 0 and pid == cpid and not PgUtil.pgcmp(host, chost, 1) else pid
|
|
611
|
+
if dolock > 0 and lckpid < 0: return 1 # no need lock again
|
|
612
|
+
|
|
613
|
+
dinfo = "{}-{}-{}".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime(), dsid)
|
|
614
|
+
if lckpid > 0:
|
|
615
|
+
lmsg = "{} Locked by {}/{}".format(dinfo, pid, host)
|
|
616
|
+
if check_process_running_status(host, pid, dolock, lmsg, logout): return -1
|
|
617
|
+
|
|
618
|
+
record = {}
|
|
619
|
+
if dolock > 0:
|
|
620
|
+
if pid != cpid: record['pid'] = cpid
|
|
621
|
+
if host != chost: record['lockhost'] = chost
|
|
622
|
+
else:
|
|
623
|
+
if pid: record['pid'] = 0
|
|
624
|
+
if not record: return 1
|
|
625
|
+
|
|
626
|
+
lkrec = PgDBI.pgget(table, fields, cnd, logerr|PgLOG.DOLOCK)
|
|
627
|
+
if not lkrec: return end_db_transaction(0) # dscheck is gone or db error
|
|
628
|
+
|
|
629
|
+
lstat = 1
|
|
630
|
+
if (not lkrec['pid'] or
|
|
631
|
+
lkrec['pid'] == pid and PgUtil.pgcmp(lkrec['lockhost'], host, 1) == 0 or
|
|
632
|
+
lkrec['pid'] == cpid and PgUtil.pgcmp(lkrec['lockhost'], chost, 1) == 0):
|
|
633
|
+
if not PgDBI.pgupdt(table, record, cnd, logerr):
|
|
634
|
+
if logout: PgLOG.pglog(dinfo + ": Error update lock", logout)
|
|
635
|
+
lstat = -1
|
|
636
|
+
else:
|
|
637
|
+
if logout: PgLOG.pglog("{}: Relocked {}/{}".format(dinfo, lkrec['pid'], lkrec['lockhost']), logout)
|
|
638
|
+
lstat = -1
|
|
639
|
+
|
|
640
|
+
return end_db_transaction(lstat)
|