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.
@@ -0,0 +1,603 @@
1
+ #
2
+ ###############################################################################
3
+ #
4
+ # Title : PgCMD.py
5
+ # Author : Zaihua Ji, zji@ucar.edu
6
+ # Date : 08/25/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 record commands for delayed
10
+ # mode or command recovery
11
+ #
12
+ # Github : https://github.com/NCAR/rda-python-common.git
13
+ #
14
+ ###############################################################################
15
+ #
16
+ import os
17
+ import re
18
+ import sys
19
+ import time
20
+ from . import PgLOG
21
+ from . import PgSIG
22
+ from . import PgUtil
23
+ from . import PgLock
24
+ from . import PgDBI
25
+
26
+ # cached dscheck info
27
+ DSCHK = {}
28
+ BOPTIONS = {"hostname" : None, "qoptions" : None, "modules" : None, "environments" : None}
29
+ BFIELDS = ', '.join(BOPTIONS)
30
+
31
+ TRYLMTS = {
32
+ 'dsquasar' : 3,
33
+ 'dsarch' : 2,
34
+ 'default' : 1
35
+ }
36
+
37
+ DLYPTN = r'(^|\s)-(d|BP|BatchProcess|DelayedMode)(\s|$)'
38
+ DLYOPT = {
39
+ 'dsarch' : ' -d',
40
+ 'dsupdt' : ' -d',
41
+ 'dsrqst' : ' -d'
42
+ }
43
+ #
44
+ # params: dict array holding option values
45
+ # opt: 2 - each value of the dict array is a list; otherwise 1
46
+ # addhost: 1 to add host name too
47
+ # initial set Batch options passed in from command line
48
+ #
49
+ def set_batch_options(params, opt, addhost = 0):
50
+
51
+ if 'QS' in params: BOPTIONS['qoptions'] = (params['QS'][0] if opt == 2 else params['QS'])
52
+ if 'MO' in params: BOPTIONS['modules'] = (params['MO'][0] if opt == 2 else params['MO'])
53
+ if 'EV' in params: BOPTIONS['environments'] = (params['EV'][0] if opt == 2 else params['EV'])
54
+ if addhost and 'HN' in params: BOPTIONS['hostname'] = (params['HN'][0] if opt == 2 else params['HN'])
55
+
56
+ #
57
+ # boptions: dict array holding batch options
58
+ # refresh: 1 to clean the previous cached global batch options
59
+ # checkkey: 1 to check and valid pre-defined fields
60
+ #
61
+ # fill Batch options recorded in RDADB
62
+ #
63
+ def fill_batch_options(boptions, refresh = 0, checkkey = 0):
64
+
65
+ if refresh:
66
+ for bkey in BOPTIONS:
67
+ BOPTIONS[bkey] = None # clean the hash before filling it up
68
+
69
+ if not boptions: return
70
+ for bkey in boptions:
71
+ if not checkkey or bkey in BOPTIONS:
72
+ BOPTIONS[bkey] = boptions[bkey]
73
+
74
+ #
75
+ # bkey: batch option field name
76
+ # bval: batch option value
77
+ # override: 1 to override an existing option
78
+ #
79
+ # fill a single Batch option
80
+ #
81
+ def set_one_boption(bkey, bval, override = 0):
82
+
83
+ if bval:
84
+ if override or not ( bkey in BOPTIONS and BOPTIONS[bkey]): BOPTIONS[bkey] = bval
85
+ elif override and bkey in BOPTIONS and BOPTIONS[bkey]:
86
+ BOPTIONS[bkey] = None
87
+
88
+ #
89
+ # fill the passed in dict record with the pre-saved batch options
90
+ #
91
+ def get_batch_options(pgrec = None):
92
+
93
+ record = {}
94
+ for bkey in BOPTIONS:
95
+ if pgrec and bkey in pgrec and pgrec[bkey]:
96
+ record[bkey] = pgrec[bkey]
97
+ elif BOPTIONS[bkey]:
98
+ record[bkey] = BOPTIONS[bkey]
99
+
100
+ return record
101
+
102
+ #
103
+ # return delay mode option to append to argv string for a specified cmd
104
+ #
105
+ def append_delayed_mode(cmd, argv):
106
+
107
+ if cmd in DLYOPT and not re.search(DLYPTN, argv, re.I):
108
+ return DLYOPT[cmd]
109
+ else:
110
+ return ''
111
+
112
+ #
113
+ # check given doptions and cmd, and return the try limit and specified hosts
114
+ #
115
+ def get_delay_options(doptions, cmd):
116
+
117
+ mcount = 0
118
+ hosts = None
119
+
120
+ if doptions:
121
+ for bval in doptions:
122
+ if re.match(r'^(\d+)$', bval):
123
+ mcount = int(bval)
124
+ if mcount > 99: mcount = 99
125
+ else:
126
+ hosts = bval
127
+
128
+ if mcount == 0: mcount = get_try_limit(cmd)
129
+ if hosts: set_one_boption('hostname', hosts, 1)
130
+
131
+ return (mcount, hosts)
132
+
133
+ #
134
+ # find an existing dscheck record from the cached command argument; create and initialize one if not exist
135
+ #
136
+ def init_dscheck(oindex, otype, cmd, dsid, action, workdir = None, specialist = None, doptions = None, logact = 0):
137
+
138
+ cidx = 0
139
+ argv = PgLOG.argv_to_string(sys.argv[1:], 0, "Process in Delayed Mode")
140
+ argextra = None
141
+
142
+ if not logact: logact = PgLOG.LGEREX
143
+ if not workdir: workdir = os.getcwd()
144
+ if not specialist: specialist = PgLOG.PGLOG['CURUID']
145
+
146
+ (mcount, hosts) = get_delay_options(doptions, cmd)
147
+
148
+ if len(argv) > 100:
149
+ argextra = argv[100:]
150
+ argv = argv[0:100]
151
+
152
+ bck = PgLOG.PGLOG['BCKGRND']
153
+ PgLOG.PGLOG['BCKGRND'] = 0
154
+ cinfo = "{}-{}-Chk".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime())
155
+ pgrec = get_dscheck(cmd, argv, workdir, specialist, argextra, logact)
156
+ if pgrec: # found existing dscheck record
157
+ cidx = pgrec['cindex']
158
+ cmsg = "{}{}: {} batch process ".format(cinfo, cidx, get_command_info(pgrec))
159
+ cidx = PgLock.lock_dscheck(cidx, 1, PgLOG.LOGWRN)
160
+ if cidx < 0:
161
+ PgLOG.pglog(cmsg + "is Running, No restart", PgLOG.LOGWRN)
162
+ sys.exit(0)
163
+ if cidx > 0:
164
+ if not hosts and pgrec['hostname']:
165
+ hosts = pgrec['hostname']
166
+ set_one_boption('hostname', hosts, 0)
167
+ if mcount: pgrec['mcount'] = mcount
168
+ DSCHK['chkcnd'] = "cindex = {}".format(cidx)
169
+ if(pgrec['status'] == 'D' or pgrec['fcount'] and pgrec['dcount'] >= pgrec['fcount'] or
170
+ pgrec['tcount'] > pgrec['mcount'] or not pgrec['pid'] and pgrec['tcount'] == pgrec['mcount']):
171
+ PgLOG.pglog("{}is {}".format(cmsg, ('Done' if pgrec['status'] == 'D' else 'Finished')), PgLOG.LOGWRN)
172
+ PgLock.lock_dscheck(cidx, 0, logact)
173
+ sys.exit(0)
174
+
175
+ if not cidx: # add new dscheck record
176
+ record = {}
177
+ if hosts and re.match(r'^(ds\d|\d)\d\d.\d$', hosts):
178
+ PgLOG.pglog(hosts + ": Cannot pass DSID for hostname to submit batch process", PgLOG.LGEREX)
179
+ if oindex: set_command_control(oindex, otype, cmd, logact)
180
+ record['oindex'] = oindex
181
+ record['dsid'] = dsid
182
+ record['action'] = action
183
+ record['otype'] = otype
184
+ (record['date'], record['time']) = PgUtil.get_date_time()
185
+ record['command'] = cmd
186
+ record['argv'] = argv
187
+ if mcount > 0: record['mcount'] = mcount
188
+ record['specialist'] = specialist
189
+ record['workdir'] = workdir
190
+ if argextra: record['argextra'] = argextra
191
+ record.update(get_batch_options())
192
+ cidx = PgDBI.pgadd("dscheck", record, logact|PgLOG.AUTOID)
193
+ if cidx:
194
+ cmsg = "{}{}: {} Adds a new check".format(cinfo, cidx, get_command_info(record))
195
+ PgLOG.pglog(cmsg, PgLOG.LOGWRN)
196
+ sys.exit(0)
197
+
198
+ (chost, cpid) = PgLOG.current_process_info()
199
+ (rhost, rpid) = PgLOG.current_process_info(1)
200
+
201
+ if not check_command_specialist_host(hosts, chost, specialist, cmd, action, PgLOG.LOGERR):
202
+ PgLock.lock_dscheck(cidx, 0, logact)
203
+ sys.exit(1)
204
+
205
+ record = {}
206
+ record['status'] = "R"
207
+ if mcount > 0: record['mcount'] = mcount
208
+ record['bid'] = (cpid if PgLOG.PGLOG['CURBID'] else 0)
209
+ if pgrec['stttime'] and pgrec['chktime'] > pgrec['stttime']:
210
+ (record['ttltime'], record['quetime']) = get_dscheck_runtime(pgrec)
211
+ record['chktime'] = record['stttime'] = int(time.time())
212
+ if not pgrec['subtime']: record['subtime'] = record['stttime']
213
+ if dsid and not pgrec['dsid']: record['dsid'] = dsid
214
+ if action and not pgrec['action']: record['action'] = action
215
+ if oindex and not pgrec['oindex']: record['oindex'] = oindex
216
+ if otype and not pgrec['otype']: record['otype'] = otype
217
+ if argv and not pgrec['argv']: record['argv'] = argv
218
+ record['runhost'] = rhost
219
+ if pgrec['command'] == "dsrqst" and pgrec['oindex']:
220
+ (record['fcount'], record['dcount'], record['size']) = get_dsrqst_counts(pgrec, logact)
221
+ PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
222
+
223
+ DSCHK['dcount'] = pgrec['dcount']
224
+ DSCHK['fcount'] = pgrec['fcount']
225
+ DSCHK['size'] = pgrec['size']
226
+ DSCHK['cindex'] = cidx
227
+ DSCHK['dflags'] = pgrec['dflags']
228
+ PgLOG.PGLOG['DSCHECK'] = DSCHK # add global access link
229
+ if not PgLOG.PGLOG['BCKGRND']: PgLOG.PGLOG['BCKGRND'] = 1 # turn off screen output if not yet
230
+ tcnt = pgrec['tcount']
231
+ if not pgrec['pid']: tcnt += 1
232
+ tstr = "the {} run".format(PgLOG.int2order(tcnt)) if tcnt > 1 else "running"
233
+ pstr = "{}<{}>".format(chost, cpid)
234
+ if rhost != chost: pstr += "/{}<{}>".format(rhost, rpid)
235
+ PgLOG.pglog("{}Starts {} ({})".format(cmsg, tstr, pstr), PgLOG.LOGWRN)
236
+ PgLOG.PGLOG['BCKGRND'] = bck
237
+
238
+ return cidx
239
+
240
+ #
241
+ # check and validate if the current host is configured for the specialist
242
+ #
243
+ def check_command_specialist_host(hosts, chost, specialist, cmd, act = 0, logact = 0):
244
+
245
+ if cmd == 'dsrqst' and act == 'PR':
246
+ mflag = 'G'
247
+ else:
248
+ cnd = "command = '{}' AND specialist = '{}' AND hostname = '{}'".format(cmd, specialist, chost)
249
+ pgrec = PgDBI.pgget("dsdaemon", 'matchhost', cnd, logact)
250
+ mflag = (pgrec['matchhost'] if pgrec else 'G')
251
+
252
+ return PgLOG.check_process_host(hosts, chost, mflag, "{}-{}".format(specialist, cmd), logact)
253
+
254
+ #
255
+ # set command control info
256
+ #
257
+ def set_command_control(oindex, otype, cmd, logact = 0):
258
+
259
+ if not oindex: return
260
+
261
+ pgctl = None
262
+ if cmd == "dsrqst":
263
+ if otype == 'P':
264
+ pgrec = PgDBI.pgget("ptrqst", "rindex", "pindex = {}".format(oindex), logact)
265
+ if pgrec: pgctl = get_partition_control(pgrec, None, None, logact)
266
+ else:
267
+ pgrec = PgDBI.pgget("dsrqst", "dsid, gindex, cindex, rqsttype", "rindex = {}".format(oindex), logact)
268
+ if pgrec: pgctl = get_dsrqst_control(pgrec, logact)
269
+ elif cmd == "dsupdt":
270
+ if otype == 'L':
271
+ pgrec = PgDBI.pgget("dlupdt", "cindex", "lindex = {}".format(oindex), logact)
272
+ if not (pgrec and pgrec['cindex']): return
273
+ oindex = pgrec['cindex']
274
+ pgctl = PgDBI.pgget("dcupdt", BFIELDS, "cindex = {}".format(oindex), logact)
275
+ if pgctl:
276
+ for bkey in pgctl:
277
+ set_one_boption(bkey, pgctl[bkey], 0)
278
+
279
+ #
280
+ # get dsrqst control info
281
+ #
282
+ def get_dsrqst_control(pgrqst, logact = 0):
283
+
284
+ cflds = BFIELDS
285
+ if 'ptcount' in pgrqst and pgrqst['ptcount'] == 0: cflds += ", ptlimit, ptsize"
286
+ if pgrqst['cindex']:
287
+ pgctl = PgDBI.pgget("rcrqst", cflds, "cindex = {}".format(pgrqst['cindex']), logact)
288
+ else:
289
+ pgctl = None
290
+ if not pgctl:
291
+ gcnd = "dsid = '{}' AND gindex = ".format(pgrqst['dsid'])
292
+ if pgrqst['rqsttype'] in "ST":
293
+ tcnd = " AND (rqsttype = 'T' OR rqsttype = 'S')"
294
+ else:
295
+ tcnd = " AND rqsttype = '{}'".format(pgrqst['rqsttype'])
296
+ gindex = pgrqst['gindex']
297
+ while True:
298
+ pgctl = PgDBI.pgget("rcrqst", cflds, "{}{}{}".format(gcnd, gindex, tcnd), logact)
299
+ if pgctl or not gindex: break
300
+ pgctl = PgDBI.pgget("dsgroup", "pindex", "{}{}".format(gcnd, gindex), logact)
301
+ if not pgctl: break
302
+ gindex = pgctl['pindex']
303
+
304
+ return pgctl
305
+
306
+ #
307
+ # get dsrqst partition control info
308
+ #
309
+ def get_partition_control(pgpart, pgrqst = None, pgctl = None, logact = 0):
310
+
311
+ if not pgctl:
312
+ if not pgrqst and pgpart['rindex']:
313
+ pgrqst = PgDBI.pgget("dsrqst", "dsid, gindex, cindex, rqsttype", "rindex = {}".format(pgpart['rindex']), logact)
314
+ if pgrqst: pgctl = get_dsrqst_control(pgrqst, logact)
315
+
316
+ return pgctl
317
+
318
+ #
319
+ # build the dynamic options
320
+ #
321
+ def get_dynamic_options(cmd, oindex, otype):
322
+
323
+ if oindex: cmd += " {}".format(oindex)
324
+ if otype: cmd += ' ' + otype
325
+ ret = options = ''
326
+ for loop in range(3):
327
+ ret = PgLOG.pgsystem(cmd, PgLOG.LOGWRN, 279) # 1+2+4+16+256
328
+ if loop < 2 and PgLOG.PGLOG['SYSERR'] and 'Connection timed out' in PgLOG.PGLOG['SYSERR']:
329
+ time.sleep(PgSIG.PGSIG['ETIME'])
330
+ else:
331
+ break
332
+ if ret:
333
+ ret = ret.strip()
334
+ ms = re.match(r'^(-.+)/(-.+)$', ret)
335
+ if ms:
336
+ options = ms.group(1) if otype == 'R' else ms.group(2)
337
+ elif re.match(r'^(-.+)$', ret):
338
+ options = ret
339
+ if not options:
340
+ if ret: PgLOG.PGLOG['SYSERR'] += ret
341
+ PgLOG.PGLOG['SYSERR'] += " for {}".format(cmd)
342
+
343
+ return options
344
+
345
+ #
346
+ # retrieve a dscheck record for provided cmd, argv and other conditions
347
+ #
348
+ def get_dscheck(cmd, argv, workdir, specialist, argextra = None, logact = 0):
349
+
350
+ cnd = "command = '{}' AND specialist = '{}' AND argv = '{}'".format(cmd, specialist, argv)
351
+ pgrecs = PgDBI.pgmget("dscheck", "*", cnd, logact)
352
+ cnt = len(pgrecs['cindex']) if pgrecs else 0
353
+ if cnt == 0 and cmd in DLYOPT:
354
+ ms = re.match(r'^(.+){}$'.format(DLYOPT[cmd]), argv)
355
+ if ms:
356
+ argv = ms.group(1)
357
+ cnt = 1
358
+ elif not argextra:
359
+ dopt = append_delayed_mode(cmd, argv)
360
+ if dopt:
361
+ argv += dopt
362
+ cnt = 1
363
+ if cnt:
364
+ cnd = "command = '{}' AND specialist = '{}' AND argv = '{}'".format(cmd, specialist, argv)
365
+ pgrecs = PgDBI.pgmget("dscheck", "*", cnd, logact)
366
+ cnt = len(pgrecs['cindex']) if pgrecs else 0
367
+
368
+ for i in range(cnt):
369
+ pgrec = PgUtil.onerecord(pgrecs, i)
370
+ if pgrec['workdir'] and PgUtil.pgcmp(workdir, pgrec['workdir']): continue
371
+ if PgUtil.pgcmp(argextra, pgrec['argextra']): continue
372
+ return pgrec
373
+
374
+ return None
375
+
376
+ #
377
+ # delete one dsceck record fo given cindex
378
+ #
379
+ def delete_dscheck(pgrec, chkcnd, logact = 0):
380
+
381
+ if not chkcnd:
382
+ if pgrec:
383
+ chkcnd = "cindex = {}".format(pgrec['cindex'])
384
+ elif 'chkcnd' in DSCHK:
385
+ chkcnd = DSCHK['chkcnd']
386
+ else:
387
+ return 0 # nothing to delete
388
+ if not pgrec:
389
+ pgrec = PgDBI.pgget("dscheck", "*", chkcnd, logact)
390
+ if not pgrec: return 0 # dscheck record is gone
391
+
392
+ record = {}
393
+ record['cindex'] = pgrec['cindex']
394
+ record['command'] = pgrec['command']
395
+ record['dsid'] = (pgrec['dsid'] if pgrec['dsid'] else PgLOG.PGLOG['DEFDSID'])
396
+ record['action'] = (pgrec['action'] if pgrec['action'] else "UN")
397
+ record['specialist'] = pgrec['specialist']
398
+ record['hostname'] = pgrec['runhost']
399
+ if pgrec['bid']: record['bid'] = pgrec['bid']
400
+ if pgrec['command'] == "dsrqst" and pgrec['oindex']:
401
+ (record['fcount'], record['dcount'], record['size']) = get_dsrqst_counts(pgrec, logact)
402
+ else:
403
+ record['fcount'] = pgrec['fcount']
404
+ record['dcount'] = pgrec['dcount']
405
+ record['size'] = pgrec['size']
406
+ record['tcount'] = pgrec['tcount']
407
+ record['date'] = pgrec['date']
408
+ record['time'] = pgrec['time']
409
+ record['closetime'] = PgUtil.curtime(1)
410
+ (record['ttltime'], record['quetime']) = get_dscheck_runtime(pgrec)
411
+ record['argv'] = pgrec['argv']
412
+ if pgrec['argextra']:
413
+ record['argv'] += pgrec['argextra']
414
+ if len(record['argv']) > 255: record['argv'] = record['argv'][0:255]
415
+ if pgrec['errmsg']: record['errmsg'] = pgrec['errmsg']
416
+ record['status'] = ('F' if pgrec['status'] == "R" else pgrec['status'])
417
+
418
+ if PgDBI.pgget("dschkhist", "", chkcnd):
419
+ stat = PgDBI.pgupdt("dschkhist", record, chkcnd, logact)
420
+ else:
421
+ stat = PgDBI.pgadd("dschkhist", record, logact)
422
+ if stat:
423
+ cmsg = "{} cleaned as '{}' at {} on {}".format(get_command_info(pgrec), record['status'], PgLOG.current_datetime(), PgLOG.PGLOG['HOSTNAME'])
424
+ PgLOG.pglog("Chk{}: {}".format(pgrec['cindex'], cmsg), PgLOG.LOGWRN|PgLOG.FRCLOG)
425
+ stat = PgDBI.pgdel("dscheck", chkcnd, logact)
426
+ if record['status'] == "E" and 'errmsg' in record:
427
+ PgLOG.pglog("Chk{}: {} Exits with Error\n{}".format(pgrec['cindex'], get_command_info(pgrec), record['errmsg']), logact)
428
+
429
+ return stat
430
+
431
+ #
432
+ # get dsrqst fcount and dcount
433
+ #
434
+ def get_dsrqst_counts(pgchk, logact = 0):
435
+
436
+ fcount = pgchk['fcount']
437
+ dcount = pgchk['dcount']
438
+ size = pgchk['size']
439
+
440
+ if pgchk['otype'] == 'P':
441
+ table = 'ptrqst'
442
+ cnd = "pindex = {}".format(pgchk['oindex'])
443
+ fields = "fcount"
444
+ else:
445
+ table = 'dsrqst'
446
+ cnd = "rindex = {}".format(pgchk['oindex'])
447
+ fields = "fcount, pcount, size_input, size_request"
448
+ pgrec = PgDBI.pgget(table, fields, cnd, logact)
449
+ if pgrec:
450
+ fcnt = pgrec['fcount']
451
+ else:
452
+ fcnt = 0
453
+ pgrec = {'fcount' : 0}
454
+ if not fcnt: fcnt = PgDBI.pgget("wfrqst", "", cnd, logact)
455
+ if fcnt and fcount != fcnt: fcount = fcnt
456
+ if fcount:
457
+ if 'pcount' in pgrec and pgrec['pcount']:
458
+ dcnt = pgrec['pcount']
459
+ else:
460
+ dcnt = PgDBI.pgget("wfrqst", "", cnd + " AND status = 'O'", logact)
461
+ if dcnt and dcnt != dcount: dcount = dcnt
462
+ if not size:
463
+ if 'size_input' in pgrec and pgrec['size_input']:
464
+ if size != pgrec['size_input']: size = pgrec['size_input']
465
+ elif 'size_request' in pgrec and pgrec['size_request']:
466
+ if size != pgrec['size_request']: size = pgrec['size_request']
467
+ elif fcnt: # evaluate total size only if file count is set in request/partition record
468
+ pgrec = PgDBI.pgget("wfrqst", "sum(size) data_size", cnd, logact)
469
+ if pgrec and pgrec['data_size']: size = pgrec['data_size']
470
+
471
+ return (fcount, dcount, size)
472
+
473
+ #
474
+ # set dscheck fcount
475
+ #
476
+ def set_dscheck_fcount(count, logact = 0):
477
+
478
+ record = {'fcount' : count, 'chktime' : int(time.time())}
479
+ PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
480
+ DSCHK['fcount'] = count
481
+
482
+ return DSCHK['dcount'] # return Done count
483
+
484
+ #
485
+ # set dscheck dcount
486
+ #
487
+ def set_dscheck_dcount(count, size, logact = 0):
488
+
489
+ record = {'dcount' : count, 'size' : size, 'chktime' : int(time.time())}
490
+ PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
491
+ DSCHK['dcount'] = count
492
+ DSCHK['size'] = size
493
+
494
+ return DSCHK['dcount'] # return Done count
495
+
496
+ #
497
+ # add dscheck dcount
498
+ #
499
+ def add_dscheck_dcount(count, size, logact = 0):
500
+
501
+ record = {}
502
+ if count:
503
+ DSCHK['dcount'] += count
504
+ record['dcount'] = DSCHK['dcount']
505
+ if size:
506
+ DSCHK['size'] += size
507
+ record['size'] = DSCHK['size']
508
+ record['chktime'] = int(time.time())
509
+ PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
510
+
511
+ return DSCHK['dcount'] # return Done count
512
+
513
+ #
514
+ # set dscheck source information
515
+ #
516
+ def set_dscheck_attribute(fname, value, logact = 0):
517
+
518
+ record = {}
519
+ if value: record[fname] = value
520
+ record['chktime'] = int(time.time())
521
+ PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
522
+
523
+ #
524
+ # update dscheck status
525
+ #
526
+ def record_dscheck_status(stat, logact = 0):
527
+
528
+ pgrec = PgDBI.pgget("dscheck", "lockhost, pid", DSCHK['chkcnd'], logact)
529
+ if not pgrec: return 0
530
+ if not (pgrec['pid'] and pgrec['lockhost']): return 0
531
+ (chost, cpid) = PgLOG.current_process_info()
532
+ if pgrec['pid'] != cpid or pgrec['lockhost'] != chost: return 0
533
+
534
+ # update dscheck status only if it is still locked by the current process
535
+ record = {'status' : stat, 'chktime' : int(time.time()), 'pid' : 0}
536
+ return PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
537
+
538
+ #
539
+ # get the number of tries to execute for a given cmd under dscheck control
540
+ #
541
+ def get_try_limit(cmd):
542
+
543
+ return (TRYLMTS[cmd] if cmd in TRYLMTS else TRYLMTS['default'])
544
+
545
+ #
546
+ # get the execution time for a dscheck command
547
+ #
548
+ def get_dscheck_runtime(pgrec, current = 0):
549
+
550
+ ttime = (0 if current else pgrec['ttltime'])
551
+ qtime = (0 if current else pgrec['quetime'])
552
+
553
+ # if pgrec['bid'] and PgLOG.PGLOG['CURBID']:
554
+ # if PgLOG.PGLOG['PGBATCH'] == PgLOG.PGLOG['SLMNAME']:
555
+ # stat = PgSIG.check_slurm_status(pgrec['bid'], PgLOG.LOGERR)
556
+ # if stat:
557
+ # if stat['PEND']: qtime += stat['PEND']
558
+ # if stat['TOTAL']: ttime += stat['TOTAL']
559
+ # return (ttime, qtime)
560
+
561
+ if pgrec['subtime']:
562
+ ttime += (pgrec['chktime'] - pgrec['subtime'])
563
+ if pgrec['stttime']: qtime += (pgrec['stttime'] - pgrec['subtime'])
564
+
565
+ return (ttime, qtime)
566
+
567
+ #
568
+ # retrieve a command string from a given dscheck record
569
+ #
570
+ def get_command_info(pgrec):
571
+
572
+ if pgrec['oindex']:
573
+ if pgrec['command'] == "dsupdt":
574
+ cinfo = "UC{}".format(pgrec['oindex'])
575
+ elif pgrec['command'] == "dsrqst":
576
+ if pgrec['otype'] == "P":
577
+ cinfo = "RPT{}".format(pgrec['oindex'])
578
+ else:
579
+ cinfo = "Rqst{}".format(pgrec['oindex'])
580
+ else:
581
+ cinfo ="{}-{}".format(pgrec['command'], pgrec['oindex'])
582
+ else:
583
+ cinfo =pgrec['command']
584
+ if pgrec['dsid']: cinfo += " " + pgrec['dsid']
585
+ if pgrec['action']: cinfo += " " + pgrec['action']
586
+ cinfo += " of " + pgrec['specialist']
587
+
588
+ return cinfo
589
+
590
+ #
591
+ # change the dscheck original command information
592
+ #
593
+ def change_dscheck_oinfo(oidx, otype, nidx, ntype):
594
+
595
+ cnd = "oindex = {} AND otype = '{}'".format(oidx, otype)
596
+ pgchk = PgDBI.pgget('dscheck', 'cindex, oindex, otype', cnd, PgLOG.LGEREX)
597
+ if not pgchk: return 0 # miss dscheck record to change
598
+
599
+ record = {}
600
+ DSCHK['oindex'] = record['oindex'] = nidx
601
+ DSCHK['otype'] = record['otype'] = ntype
602
+ cnd = "cindex = {}".format(pgchk['cindex'])
603
+ return PgDBI.pgupdt('dscheck', record, cnd, PgLOG.LGEREX)