rda-python-dsarch 1.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,837 @@
1
+ #
2
+ ###############################################################################
3
+ #
4
+ # Title : PgMeta.py
5
+ # Author : Zaihua Ji, zji@ucar.edu
6
+ # Date : 09/18/2020
7
+ # 2025-01-22 transferred to package rda_python_dsarch from
8
+ # https://github.com/NCAR/rda-shared-libraries.git
9
+ # Purpose : python library module to handle file counts and metadata gathering
10
+ #
11
+ # Github : https://github.com/NCAR/rda-python-dsarch.git
12
+ #
13
+ ###############################################################################
14
+ #
15
+ import os
16
+ import re
17
+ from os import path as op
18
+ from rda_python_common import PgLOG
19
+ from rda_python_common import PgSIG
20
+ from rda_python_common import PgCMD
21
+ from rda_python_common import PgDBI
22
+ from rda_python_common import PgUtil
23
+ from rda_python_common import PgSplit
24
+
25
+ GCOUNTS = {}
26
+ META = {} # keys: GM, GW, DM, DW, RM, RW, SM, and SW
27
+ TGIDXS = {} # cache value for function get_top_gindex()
28
+ TIDXS = {} # cache all unique top group index
29
+
30
+ CMD = {
31
+ 'GX' : "gatherxml",
32
+ 'DX' : "dcm",
33
+ 'RX' : "rcm",
34
+ 'SX' : "scm",
35
+ 'SL' : "sml"
36
+ }
37
+
38
+ logfile = PgLOG.PGLOG['LOGFILE']
39
+ errfile = PgLOG.PGLOG['ERRFILE']
40
+
41
+ #
42
+ # switch to log file name provided
43
+ #
44
+ def switch_logfile(logname = None):
45
+
46
+ global logfile, errfile
47
+
48
+ if logname:
49
+ logfile = PgLOG.PGLOG['LOGFILE']
50
+ errfile = PgLOG.PGLOG['ERRFILE']
51
+ PgLOG.PGLOG['LOGFILE'] = logname + '.log'
52
+ PgLOG.PGLOG['ERRFILE'] = logname + '.err'
53
+ else:
54
+ PgLOG.PGLOG['LOGFILE'] = logfile
55
+ PgLOG.PGLOG['ERRFILE'] = errfile
56
+
57
+ #
58
+ # get sub group level
59
+ #
60
+ def get_group_levels(dsid, gindex, level):
61
+
62
+ pgrec = PgDBI.pgget("dsgroup", "pindex", "dsid = '{}' AND gindex = {}".format(dsid, gindex), PgLOG.LGEREX)
63
+ if pgrec and pgrec['pindex']:
64
+ level = get_group_levels(dsid, pgrec['pindex'], level + 1)
65
+
66
+ return level
67
+
68
+ #
69
+ # reset datset/group file counts. Set all the way through if index is 0
70
+ # act == 4/8 change web/saved file counts, respectively
71
+ # go up if limit < 0
72
+ #
73
+ def reset_filenumber(dsid, gindex, act, level = 0, gtype = None, limit = 0):
74
+
75
+ wcnd = "gindex = {}".format(gindex)
76
+ dcnd = "dsid = '{}'".format(dsid)
77
+ gcnd = "{} AND {}".format(dcnd, wcnd)
78
+ # 0-pms,1-cpm,2-pm,3-mc,4-cdc,5-dc,6-wc,7-ds,8-nc,9-ns,10-sc,11-ss,12-tu
79
+ counts = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
80
+ pidx = None
81
+ retcnt = 0
82
+
83
+ if not gtype:
84
+ retcnt = 1
85
+ if gindex:
86
+ pgrec = PgDBI.pgget("dsgroup", "pindex, grptype", gcnd, PgLOG.LGEREX)
87
+ if not pgrec or abs(pgrec['pindex']) >= abs(gindex): return 0
88
+ gtype = pgrec['grptype']
89
+ pidx = pgrec['pindex']
90
+ else:
91
+ gtype = 'P'
92
+
93
+ if not level:
94
+ if act == 1: act = 14
95
+ if gindex:
96
+ level += 1
97
+ if pidx: level = get_group_levels(dsid, pidx, level+1)
98
+ if limit > 0: limit += level
99
+
100
+ if not level: PgDBI.pgget("dataset", "dsid", dcnd, PgLOG.LGEREX|PgLOG.DOLOCK)
101
+
102
+ # get file counts at the current group
103
+ if act&4:
104
+ if gtype == 'P':
105
+ pgrec = PgSplit.pgget_wfile(dsid, "SUM(data_size) dsize, COUNT(wid) dcount",
106
+ wcnd + " AND type = 'D' AND status = 'P'", PgLOG.LGEREX)
107
+ if pgrec:
108
+ counts[5] = counts[4] = pgrec['dcount']
109
+ if pgrec['dsize']: counts[7] = pgrec['dsize']
110
+
111
+ pgrec = PgSplit.pgget_wfile(dsid, "SUM(data_size) nsize, COUNT(wid) ncount",
112
+ wcnd + " AND type = 'N' AND status = 'P'", PgLOG.LGEREX)
113
+ if pgrec:
114
+ counts[8] = pgrec['ncount']
115
+ if pgrec['nsize']: counts[9] = pgrec['nsize']
116
+ counts[6] = PgSplit.pgget_wfile(dsid, "", wcnd, PgLOG.LGEREX)
117
+
118
+ if act&8:
119
+ pgrec = PgDBI.pgget("sfile", "SUM(data_size) ssize, COUNT(sid) scount",
120
+ gcnd + " AND status <> 'D'", PgLOG.LGEREX)
121
+ if pgrec:
122
+ counts[10] = pgrec['scount']
123
+ if pgrec['ssize']: counts[11] = pgrec['ssize']
124
+
125
+ pcnd = "{} AND pindex = {}".format(dcnd, gindex)
126
+ if limit < 0:
127
+ flds = "gindex"
128
+ if act&4: flds += ", dwebcnt, webcnt, nwebcnt, dweb_size, nweb_size"
129
+ if act&8: flds += ", savedcnt, saved_size"
130
+
131
+ grecs = PgDBI.pgmget("dsgroup", flds, pcnd, PgLOG.LGEREX)
132
+ gcnt = len(grecs['gindex']) if grecs else 0
133
+ if gcnt:
134
+ for i in range(gcnt):
135
+ if act&4:
136
+ if gtype == 'P':
137
+ counts[5] += grecs['dwebcnt'][i]
138
+ counts[7] += grecs['dweb_size'][i]
139
+ counts[8] += grecs['nwebcnt'][i]
140
+ counts[9] += grecs['nweb_size'][i]
141
+ counts[6] += grecs['webcnt'][i]
142
+ if act&8:
143
+ counts[10] += grecs['savedcnt'][i]
144
+ counts[11] += grecs['saved_size'][i]
145
+ cnt = update_filenumber(dsid, gindex, act, counts, level)
146
+ if cnt:
147
+ if pidx != None: cnt += reset_filenumber(dsid, pidx, act, (level-1), None, -1)
148
+ counts[11] += cnt
149
+ elif limit == 0 or level < limit:
150
+ grecs = PgDBI.pgmget("dsgroup", "gindex, grptype", pcnd, PgLOG.LGEREX)
151
+ gcnt = len(grecs['gindex']) if grecs else 0
152
+ for i in range(gcnt):
153
+ gidx = grecs['gindex'][i]
154
+ if abs(gidx) <= abs(gindex): continue
155
+ subcnts = reset_filenumber(dsid, gidx, act, level+1, grecs['grptype'][i], limit)
156
+ if gtype == 'P':
157
+ counts[0] += subcnts[0]
158
+ counts[2] += subcnts[2]
159
+ counts[5] += subcnts[5]
160
+ counts[7] += subcnts[7]
161
+ counts[8] += subcnts[8]
162
+ counts[9] += subcnts[9]
163
+ counts[3] += subcnts[3]
164
+ counts[6] += subcnts[6]
165
+ counts[10] += subcnts[10]
166
+ counts[11] += subcnts[11]
167
+ counts[12] += subcnts[12]
168
+
169
+ cnt = update_filenumber(dsid, gindex, act, counts, level)
170
+ if cnt:
171
+ if pidx != None: cnt += reset_filenumber(dsid, pidx, act, level-1, None, -1)
172
+ counts[12] += cnt
173
+
174
+ if level == 0: PgDBI.endtran()
175
+ return (counts[12] if retcnt else counts)
176
+
177
+ #
178
+ # update group/dataset file counts
179
+ #
180
+ def update_filenumber(dsid, gindex, act, counts, level = 0):
181
+
182
+ flds = "mfstat, wfstat, dfstat"
183
+ if gindex:
184
+ table = "dsgroup"
185
+ cnd = "dsid = '{}' AND gindex = {}".format(dsid, gindex)
186
+ msg = "{}-G{}".format(dsid, gindex)
187
+ if level: flds += ", level"
188
+ else:
189
+ table = "dataset"
190
+ cnd = "dsid = '{}'".format(dsid)
191
+ msg = dsid +":"
192
+
193
+ if act&4: flds += ", dwebcnt, webcnt, cdwcnt, nwebcnt, dweb_size, nweb_size"
194
+ if act&8: flds += ", saved_size, savedcnt"
195
+
196
+ pgrec = PgDBI.pgget(table, flds, cnd, PgLOG.LGEREX)
197
+ if not pgrec: return PgLOG.pglog("Group Index {} not exists for '{}'".format(gindex, dsid), PgLOG.LOGWRN)
198
+
199
+ record = {}
200
+ if act&4:
201
+ if pgrec['dweb_size'] != counts[7]:
202
+ record['dweb_size'] = counts[7]
203
+ msg += " DS-{}".format(record['dweb_size'])
204
+ if pgrec['nweb_size'] != counts[9]:
205
+ record['nweb_size'] = counts[9]
206
+ msg += " NS-{}".format(record['nweb_size'])
207
+ if pgrec['cdwcnt'] != counts[4]:
208
+ record['cdwcnt'] = counts[4]
209
+ msg += " CDC-{}".format(record['cdwcnt'])
210
+ if pgrec['dwebcnt'] != counts[5]:
211
+ record['dwebcnt'] = counts[5]
212
+ msg += " DC-{}".format(record['dwebcnt'])
213
+ if pgrec['nwebcnt'] != counts[8]:
214
+ record['nwebcnt'] = counts[8]
215
+ msg += " NC-{}".format(record['nwebcnt'])
216
+ if pgrec['webcnt'] != counts[6]:
217
+ record['webcnt'] = counts[6]
218
+ msg += " WC-{}".format(record['webcnt'])
219
+ stat = 'D' if counts[5] else ('N' if counts[8] else ('W' if counts[6] else 'E'))
220
+ if stat != pgrec['wfstat']:
221
+ pgrec['wfstat'] = record['wfstat'] = stat
222
+ msg += " WF-" + stat
223
+ if act&8:
224
+ if pgrec['savedcnt'] != counts[10]:
225
+ record['savedcnt'] = counts[10]
226
+ msg += " SC-{}".format(record['savedcnt'])
227
+ if pgrec['saved_size'] != counts[11]:
228
+ record['saved_size'] = counts[11]
229
+ msg += " SS-{}".format(record['saved_size'])
230
+
231
+ if level:
232
+ if level != pgrec['level']:
233
+ record['level'] = level
234
+ else:
235
+ level = None
236
+
237
+ if record:
238
+ stat = ('P' if (pgrec['wfstat'] == 'D' or pgrec['mfstat'] == 'P') else
239
+ ('N' if (pgrec['wfstat'] == 'W' or pgrec['wfstat'] == 'N' or pgrec['mfstat'] == 'M') else 'E'))
240
+ if stat != pgrec['dfstat']:
241
+ record['dfstat'] = stat
242
+ msg += " DF-" + stat
243
+
244
+ if level:
245
+ msg += " LVL-{}".format(level)
246
+
247
+ if PgDBI.pgupdt(table, record, cnd, PgLOG.LGEREX):
248
+ PgLOG.pglog(msg, PgLOG.LOGWRN)
249
+ return 1
250
+
251
+ return 0
252
+
253
+ #
254
+ # cache changes of the saved files
255
+ #
256
+ def record_savedfile_changes(dsid, gindex, record, pgrec = None):
257
+
258
+ ret = 0
259
+ ostat = pgrec['status'] if pgrec else ""
260
+ otype = pgrec['type'] if pgrec else ""
261
+ stat = record['status'] if 'status' in record and record['status'] else ostat
262
+ type = record['type'] if 'type' in record and record['type'] else otype
263
+ size = record['data_size'] if 'data_size' in record and record['data_size'] else (pgrec['data_size'] if pgrec else 0)
264
+
265
+ if otype == 'P' and ostat != 'P': otype = ''
266
+ if type == 'P' and stat != 'P': type = ''
267
+
268
+ if not pgrec or pgrec['status'] == 'D' or pgrec['dsid'] == PgLOG.PGLOG['DEFDSID']: # new file record
269
+ ret += record_filenumber(dsid, gindex, 8, type, 1, size)
270
+ elif dsid != pgrec['dsid'] or gindex != pgrec['gindex']: # file moved from one dataset/group to another
271
+ ret += record_filenumber(dsid, gindex, 8, type, 1, size)
272
+ ret += record_filenumber(pgrec['dsid'], pgrec['gindex'], 8, otype, -1, -pgrec['data_size'])
273
+ elif type == otype: # same type data
274
+ if size != pgrec['data_size'] and type == "P": # P type data size changed
275
+ ret += record_filenumber(dsid, gindex, 8, "P", 0, (size - pgrec['data_size']))
276
+ elif type == 'P' or otype == 'P': # different types
277
+ ret += record_filenumber(dsid, gindex, 8, type, 1, size)
278
+ ret += record_filenumber(dsid, gindex, 8, otype, -1, -pgrec['data_size'])
279
+
280
+ return ret
281
+
282
+ #
283
+ # cache changes of web files
284
+ #
285
+ def record_webfile_changes(dsid, gindex, record, pgrec = None):
286
+
287
+ ret = 0
288
+ ostat = pgrec['status'] if pgrec else ""
289
+ otype = pgrec['type'] if pgrec else ""
290
+ stat = record['status'] if 'status' in record and record['status'] else ostat
291
+ type = record['type'] if 'type' in record and record['type'] else otype
292
+ size = record['data_size'] if 'data_size' in record and record['data_size'] else (pgrec['data_size'] if pgrec else 0)
293
+
294
+ if ostat != 'P': otype = ''
295
+ if stat != 'P': type = ''
296
+
297
+ if not pgrec or pgrec['status'] == 'D': # new file record
298
+ ret += record_filenumber(dsid, gindex, 4, type, 1, size)
299
+ elif dsid != pgrec['dsid'] or gindex != pgrec['gindex']: # file moved from one dataset/group to another
300
+ ret += record_filenumber(dsid, gindex, 4, type, 1, size)
301
+ ret += record_filenumber(pgrec['dsid'], pgrec['gindex'], 2, otype, -1, -pgrec['data_size'])
302
+ elif type == otype: # same type data
303
+ if size != pgrec['data_size'] and (type == "D" or type == "N"): # D or N type data size changed
304
+ ret += record_filenumber(dsid, gindex, 4, type, 0, (size - pgrec['data_size']))
305
+ elif type == 'D' or type == 'N' or otype == 'D' or otype == 'N': # different types
306
+ ret += record_filenumber(dsid, gindex, 4, type, 1, size)
307
+ ret += record_filenumber(dsid, gindex, 4, otype, -1, -pgrec['data_size'])
308
+
309
+ return ret
310
+
311
+ #
312
+ # record group file counts act&4 for webfile and act&8 for savedfile
313
+ #
314
+ def record_filenumber(dsid, gindex, act, type, cnt, size):
315
+
316
+ if dsid not in GCOUNTS: GCOUNTS[dsid] = {}
317
+ if gindex not in GCOUNTS[dsid]:
318
+ # 0-pms,1-cpm,2-pm,3-mc,4-cdc,5-dc,6-wc,7-ds,8-nc,9-ns,10-sc,11-ss # 12-flag(1-group type is P)
319
+ counts = GCOUNTS[dsid][gindex] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
320
+ gcnd = "dsid = '{}' AND gindex = {} AND grptype = 'P'".format(dsid, gindex)
321
+ if gindex and not PgDBI.pgget("dsgroup", "", gcnd, PgLOG.LGEREX): counts[12] = 0
322
+ else:
323
+ counts = GCOUNTS[dsid][gindex]
324
+ if type and not counts[12]: type = ''
325
+ if act == 1: act = 12 # for all
326
+
327
+ if act&4:
328
+ if type == 'D':
329
+ counts[4] += cnt
330
+ counts[5] += cnt
331
+ if size: counts[7] += size
332
+ if type == 'N':
333
+ counts[8] += cnt
334
+ if size: counts[9] += size
335
+ counts[6] += cnt
336
+ if act&8:
337
+ counts[10] += cnt
338
+ if size: counts[11] += size
339
+
340
+ return 1
341
+
342
+ #
343
+ # save the recorded COUNTS of group files into RDADB for given dsid
344
+ #
345
+ def save_filenumber(dsid, act, reset, dosave = 0):
346
+
347
+ dsids = [dsid] if dsid else list(GCOUNTS)
348
+ ret = 0
349
+ for dsid in dsids:
350
+ if dsid not in GCOUNTS: continue
351
+ if not dosave:
352
+ del GCOUNTS[dsid]
353
+ continue
354
+
355
+ gindexs = sorted(GCOUNTS[dsid])
356
+ if not gindexs: continue
357
+ for gindex in gindexs:
358
+ if not gindex: continue
359
+ gcnts = GCOUNTS[dsid][gindex]
360
+ while gindex:
361
+ # loop to pass the group file counts upto the dataset
362
+ gindex = group_filenumber(dsid, gindex, act, gcnts)
363
+
364
+ # now update the file numbers
365
+ gindexs = sorted(GCOUNTS[dsid])
366
+ gcnt = len(gindexs)
367
+ s = 's' if gcnt > 1 else ''
368
+ PgLOG.pglog("Reset file counts for {} Groups of {} ...".format(gcnt, dsid), PgLOG.WARNLG)
369
+ gcnt = 0
370
+ for gindex in gindexs:
371
+ gcnt += add_filenumber(dsid, gindex, act, GCOUNTS[dsid][gindex])
372
+ del GCOUNTS[dsid]
373
+ s = 's' if gcnt > 1 else ''
374
+ PgLOG.pglog("{} Dataset/Group Record{} set for file counts of {}".format(gcnt, s, dsid), PgLOG.WARNLG)
375
+ if reset and gcnt: PgDBI.reset_rdadb_version(dsid)
376
+ ret += gcnt
377
+
378
+ return ret
379
+
380
+ #
381
+ # add group file counts to parent group
382
+ #
383
+ def group_filenumber(dsid, gindex, act, gcnts):
384
+
385
+ pgrec = PgDBI.pgget("dsgroup", "pindex, grptype", "dsid = '{}' AND gindex = {}".format(dsid, gindex), PgLOG.LGEREX)
386
+ if not pgrec: return 0 # should not happen
387
+
388
+ pidx = pgrec['pindex']
389
+ pflag = (1 if pgrec['grptype'] == 'P' else 0)
390
+ if pidx not in GCOUNTS[dsid]: GCOUNTS[dsid][pidx] = [0]*13
391
+ pcnts = GCOUNTS[dsid][pidx]
392
+ pcnts[12] = pflag
393
+
394
+ if act&4:
395
+ if pflag:
396
+ pcnts[5] += gcnts[5]
397
+ pcnts[7] += gcnts[7]
398
+ pcnts[8] += gcnts[8]
399
+ pcnts[9] += gcnts[9]
400
+ pcnts[6] += gcnts[6]
401
+ if act&8:
402
+ pcnts[10] += gcnts[10]
403
+ pcnts[11] += gcnts[11]
404
+
405
+ return pidx
406
+
407
+ #
408
+ # add group/dataset file counts to RDADB
409
+ def add_filenumber(dsid, gindex, act, counts):
410
+
411
+ fields = ['primary_size', 'cpmcnt', 'pmsscnt', 'msscnt', 'cdwcnt', 'dwebcnt',
412
+ 'webcnt', 'dweb_size', 'nwebcnt', 'nweb_size', 'savedcnt', 'saved_size']
413
+ shorts = ['PS', 'CPC', 'PC', 'MC', 'CDC', 'DC', 'WC', 'DS', 'NC', 'NS', 'SC', 'SS']
414
+ i = 0 if act&2 else (4 if act&4 else 10)
415
+ j = 12 if act&8 else (10 if act&4 else 4)
416
+ if i >= j: return 0 # should not happen
417
+
418
+ if gindex:
419
+ table = "dsgroup"
420
+ cnd = "dsid = '{}' AND gindex = {}".format(dsid, gindex)
421
+ msg = "{}-G{}".format(dsid, gindex)
422
+ flds = "gidx, "
423
+ else:
424
+ table = "dataset"
425
+ cnd = "dsid = '{}'".format(dsid)
426
+ msg = dsid + ":"
427
+ flds = ''
428
+
429
+ flds += ', '.join(fields[i:j]) + ", mfstat, wfstat, dfstat"
430
+ pgrec = PgDBI.pgget(table, flds, cnd, PgLOG.LGEREX)
431
+ if not pgrec: return PgLOG.pglog("Group Index {} not exists for '{}'".format(gindex, dsid), PgLOG.LOGWRN)
432
+
433
+ sqlary = []
434
+ while i < j:
435
+ if counts[i]:
436
+ sqlary.append("{} = {} + {}".format(fields[i], fields[i], counts[i]))
437
+ counts[i] += pgrec[fields[i]]
438
+ msg += " {}-{}".format(shorts[i], counts[i])
439
+ else:
440
+ counts[i] = pgrec[fields[i]]
441
+ i += 1
442
+
443
+ if act&4:
444
+ stat = 'D' if counts[5] else ('W' if counts[6] else 'E')
445
+ if stat != pgrec['wfstat']:
446
+ sqlary.append("wfstat = '{}'".format(stat))
447
+ pgrec['wfstat'] = stat
448
+ msg += " WF-" + stat
449
+
450
+ if not sqlary: return 0 # nothing needs change
451
+
452
+ stat = ('P' if (pgrec['wfstat'] == 'D' or pgrec['mfstat'] == 'P') else
453
+ ('N' if (pgrec['wfstat'] == 'W' or pgrec['wfstat'] == 'N' or pgrec['mfstat'] == 'M') else 'E'))
454
+ if stat != pgrec['dfstat']:
455
+ sqlary.append("dfstat = '{}'".format(stat))
456
+ pgrec['dfstat'] = stat
457
+ msg += " DF-" + stat
458
+
459
+ if gindex: cnd = "gidx = {}".format(pgrec['gidx'])
460
+ if PgDBI.pgexec("UPDATE {} SET {} WHERE {}".format(table, ', '.join(sqlary), cnd), PgLOG.LGEREX):
461
+ PgLOG.pglog(msg, PgLOG.LOGWRN)
462
+ return 1
463
+
464
+ return 0
465
+
466
+ #
467
+ # record actions of gathering xml metadata for mssfile/webfile
468
+ # cate: M or W
469
+ #
470
+ def record_meta_gather(cate, dsid, file, fmt, lfile = None, mfile = None):
471
+
472
+ if cate == 'M': return 0
473
+
474
+ if not fmt: return PgLOG.pglog("{}-{}: Miss Data Format for 'gatherxml'".format(dsid, file), PgLOG.LOGERR)
475
+
476
+ c = "G" + cate
477
+ if c not in META: META[c] = {}
478
+ d = PgUtil.metadata_dataset_id(dsid)
479
+ if d not in META[c]: META[c][d] = []
480
+ f = fmt.lower()
481
+ if f == "netcdf": f = "cf" + f
482
+ if not lfile: lfile = op.basename(file)
483
+ META[c][d].append([file, f, lfile, mfile])
484
+
485
+ return 1
486
+
487
+ #
488
+ # record actions of deleting xml metadata for mssfile/webfile
489
+ # cate: M or W
490
+ #
491
+ def record_meta_delete(cate, dsid, file):
492
+
493
+ if cate == 'M': return 0
494
+ c = "D" + cate
495
+ if c not in META: META[c] = {}
496
+ d = PgUtil.metadata_dataset_id(dsid)
497
+ if d not in META[c]: META[c][d] = {}
498
+ if file not in META[c][d]:
499
+ META[c][d][file] = ''
500
+ return 1
501
+
502
+ return 0
503
+
504
+ #
505
+ # record actions of moving xml metadata for mssfile/webfile
506
+ # cate: M or W
507
+ #
508
+ def record_meta_move(cate, dsid, ndsid, file, nfile):
509
+
510
+ if cate == 'M': return 0
511
+ c = "R" + cate
512
+ if c not in META: META[c] = {}
513
+ d = PgUtil.metadata_dataset_id(dsid)
514
+ if d not in META[c]: META[c][d] = {}
515
+ if file not in META[c][d]:
516
+ n = None if ndsid == dsid else PgUtil.metadata_dataset_id(ndsid)
517
+ META[c][d][file] = [n, nfile]
518
+ return 1
519
+
520
+ return 0
521
+
522
+ #
523
+ # record actions of getting group summary xml metadata for mssfile/webfile
524
+ # cate: M or W
525
+ #
526
+ def record_meta_summary(cate, dsid, gindex, gindex1 = None):
527
+
528
+ if cate == 'M': return 0
529
+ ret = 0
530
+ c = "S" + cate
531
+ if c not in META: META[c] = {}
532
+ d = PgUtil.metadata_dataset_id(dsid)
533
+ if d not in META[c]: META[c][d] = {}
534
+ if gindex not in META[c][d]:
535
+ META[c][d][gindex] = 1
536
+ ret += 1
537
+ if not (gindex1 is None or gindex1 in META[c][d]):
538
+ META[c][d][gindex1] = 1
539
+ ret += 1
540
+
541
+ return ret
542
+
543
+ #
544
+ # process all cached metadata actions cat == M or W
545
+ #
546
+ def process_metadata(cate, metacnt, logact = PgLOG.LOGWRN):
547
+
548
+ if cate == 'M': return 0
549
+ cnt = 0
550
+ cnt += process_meta_delete(cate, logact)
551
+ cnt += process_meta_move(cate, logact)
552
+ cnt += process_meta_summary(cate, logact)
553
+ cnt += process_meta_gather(cate, logact)
554
+
555
+ return cnt
556
+
557
+ #
558
+ # process cached metadata gathering actions cate: M or W
559
+ #
560
+ def process_meta_gather(cate, logact = PgLOG.LOGWRN):
561
+
562
+ global TIDXS
563
+
564
+ if cate == 'M': return 0
565
+ c = 'G' + cate
566
+ if c not in META: return 0
567
+ opt = 5
568
+ act = logact
569
+ if act&PgLOG.EXITLG:
570
+ act &= ~PgLOG.EXITLG
571
+ if PgLOG.PGLOG['DSCHECK']: opt |= 256
572
+
573
+ PgLOG.PGLOG['ERR2STD'] = ["Warning: ", "already up-to-date", "process currently running",
574
+ "rsync", "No route to host", "''*'"]
575
+ switch_logfile("gatherxml")
576
+ dary = list(META[c])
577
+ dcnt = len(dary)
578
+ cnt = 0
579
+ sx = ''
580
+ rs = PgLOG.PGLOG['RSOptions']
581
+ if not rs and dcnt == 1:
582
+ if len(META[c][dary[0]]) > 2:
583
+ sx = "{} -d {} -r{} ".format(CMD['SX'], dary[0], ('m' if cate == 'M' else 'w'))
584
+ rs = " -S -R"
585
+
586
+ for d in dary:
587
+ for ary in META[c][d]:
588
+ cmd = "{} -d {} -f {}{} ".format(CMD['GX'], d, ary[1], rs)
589
+ if cate == 'M':
590
+ if ary[2] and op.exists(ary[2]): cmd += "-l {} ".format(ary[2])
591
+ if ary[3]: cmd += "-m {} ".format(ary[3])
592
+ cmd += ary[0]
593
+ if PgSIG.start_background(cmd, act, opt, 1):
594
+ cnt += 1
595
+ if PgLOG.PGLOG['DSCHECK'] and cnt > 0 and (cnt%20) == 0:
596
+ PgCMD.add_dscheck_dcount(10, 0, logact)
597
+ elif PgLOG.PGLOG['SYSERR']:
598
+ PgDBI.record_dscheck_error(PgLOG.PGLOG['SYSERR'])
599
+ PgLOG.PGLOG['ERR2STD'] = []
600
+
601
+ if cnt > 0:
602
+ if PgSIG.PGSIG['BPROC'] > 1: PgSIG.check_background(None, 0, logact, 1)
603
+ if cnt > 1: PgLOG.pglog("Metadata gathered for {} files".format(cnt), PgLOG.WARNLG)
604
+ if sx:
605
+ if 'all' in TIDXS:
606
+ PgLOG.pgsystem(sx + 'all', act, opt)
607
+ else:
608
+ for tidx in TIDXS:
609
+ PgLOG.pgsystem("{}{}".format(sx, tidx), act, opt)
610
+
611
+ if PgLOG.PGLOG['DSCHECK'] and (cnt%20) > 0:
612
+ PgCMD.add_dscheck_dcount(int((cnt%20)/2), 0, logact)
613
+
614
+ del META[c]
615
+ TIDXS = {}
616
+ switch_logfile()
617
+
618
+ return cnt
619
+
620
+ #
621
+ # process cached metadata deleting actions cate: M or W
622
+ #
623
+ def process_meta_delete(cate, logact = PgLOG.LOGWRN):
624
+
625
+ if cate == 'M': return 0
626
+ c = 'D' + cate
627
+ if c not in META: return 0
628
+ cnt = 0
629
+ opt = 5
630
+ act = logact
631
+ if act&PgLOG.EXITLG:
632
+ act &= ~PgLOG.EXITLG
633
+ if PgLOG.PGLOG['DSCHECK']: opt |= 256
634
+
635
+ PgLOG.PGLOG['ERR2STD'] = ["Warning: "]
636
+ switch_logfile("gatherxml")
637
+ for d in META[c]:
638
+ cmd = "{} -d {}".format(CMD['DX'], d)
639
+ dcnt = 0
640
+ for file in META[c][d]:
641
+ cmd += " " + file
642
+ dcnt += 1
643
+
644
+ if dcnt > 0:
645
+ if PgSIG.start_background(cmd, act, opt, 1):
646
+ cnt += dcnt
647
+ elif PgLOG.PGLOG['SYSERR']:
648
+ PgDBI.record_dscheck_error(PgLOG.PGLOG['SYSERR'])
649
+ PgLOG.PGLOG['ERR2STD'] = []
650
+
651
+ if cnt > 0:
652
+ if PgSIG.PGSIG['BPROC'] > 1: PgSIG.check_background(None, 0, logact, 1)
653
+ if cnt > 1: PgLOG.pglog("Metadata deleted for {} files".format(cnt), PgLOG.WARNLG)
654
+
655
+ del META[c]
656
+ switch_logfile()
657
+ return cnt
658
+
659
+ #
660
+ # delete metadata for given file
661
+ #
662
+ def delete_file_metadata(dsid, file, logact = PgLOG.LOGWRN):
663
+
664
+ d = PgUtil.metadata_dataset_id(dsid)
665
+ opt = 5
666
+ if logact&PgLOG.EXITLG:
667
+ logact &= ~PgLOG.EXITLG
668
+ if PgLOG.PGLOG['DSCHECK']: opt |= 256
669
+
670
+ PgLOG.PGLOG['ERR2STD'] = ["Warning: "]
671
+ switch_logfile("gatherxml")
672
+ if not PgLOG.pgsystem("{} -d {} {}".format(CMD['DX'], d, file), logact, opt) and PgLOG.PGLOG['SYSERR']:
673
+ PgDBI.record_dscheck_error(PgLOG.PGLOG['SYSERR'])
674
+ PgLOG.PGLOG['ERR2STD'] = []
675
+ switch_logfile()
676
+
677
+ #
678
+ # process cached metadata moving actions cate: M or W
679
+ #
680
+ def process_meta_move(cate, logact = PgLOG.LOGWRN):
681
+
682
+ if cate == 'M': return 0
683
+ c = 'R' + cate
684
+ if c not in META: return 0
685
+ cnt = 0
686
+ opt = 5
687
+ act = logact
688
+ if act&PgLOG.EXITLG:
689
+ act &= ~PgLOG.EXITLG
690
+ if PgLOG.PGLOG['DSCHECK']: opt |= 256
691
+
692
+ PgLOG.PGLOG['ERR2STD'] = ["Warning: "]
693
+ switch_logfile("gatherxml")
694
+ for d in META[c]:
695
+ dmeta = META[c][d]
696
+ files = list(dmeta)
697
+ fcnt = len(files)
698
+ for i in range(fcnt):
699
+ file = files[i]
700
+ cmd = "{} -d {} ".format(CMD['RX'], d)
701
+ n = dmeta[file][0]
702
+ if n:
703
+ cmd += "-nd {} ".format(n)
704
+ elif i < fcnt - 1:
705
+ cmd += "-C "
706
+
707
+ cmd += "{} {}".format(file, dmeta[file][1])
708
+ if PgSIG.start_background(cmd, act, opt, 1):
709
+ cnt += 1
710
+ elif PgLOG.PGLOG['SYSERR']:
711
+ PgDBI.record_dscheck_error(PgLOG.PGLOG['SYSERR'])
712
+ PgLOG.PGLOG['ERR2STD'] = []
713
+
714
+ if cnt > 0:
715
+ if PgSIG.PGSIG['BPROC'] > 1: PgSIG.check_background(None, 0, logact, 1)
716
+ if cnt > 1: PgLOG.pglog("Metadata moved for {} files".format(cnt), PgLOG.WARNLG)
717
+
718
+ del META[c]
719
+ switch_logfile()
720
+
721
+ return cnt
722
+
723
+ #
724
+ # process cached metadata of getting group summary actions cate: M or W
725
+ #
726
+ def process_meta_summary(cate, logact = PgLOG.LOGWRN):
727
+
728
+ if cate == 'M': return 0
729
+ c = 'S' + cate
730
+ if c not in META: return 0
731
+ cnt = 0
732
+ opt = 5
733
+ ctype = cate.lower()
734
+ act = logact
735
+ if act&PgLOG.EXITLG:
736
+ act &= ~PgLOG.EXITLG
737
+ if PgLOG.PGLOG['DSCHECK']: opt |= 256
738
+
739
+ PgLOG.PGLOG['ERR2STD'] = ["Warning: "]
740
+ switch_logfile("gatherxml")
741
+ for d in META[c]:
742
+ for gindex in META[c][d]:
743
+ cmd = "{} -d {} -{} {}".format(CMD['SX'], d, ctype, gindex)
744
+ if PgSIG.start_background(cmd, act, opt, 1):
745
+ cnt += 1
746
+ elif PgLOG.PGLOG['SYSERR']:
747
+ PgDBI.record_dscheck_error(PgLOG.PGLOG['SYSERR'])
748
+ PgLOG.PGLOG['ERR2STD'] = []
749
+
750
+ if cnt > 0:
751
+ if PgSIG.PGSIG['BPROC'] > 1: PgSIG.check_background(None, 0, logact, 1)
752
+ if cnt > 1: PgLOG.pglog("Group Metadata summarized for {} groups".format(cnt), PgLOG.WARNLG)
753
+
754
+ del META[c]
755
+ switch_logfile()
756
+
757
+ return cnt
758
+
759
+ #
760
+ # find a top group index if given group index is not otherwise return itself
761
+ # cache the results for later use
762
+ #
763
+ def get_top_gindex(dsid, gindex, logact = PgLOG.LGEREX):
764
+
765
+ if gindex in TGIDXS: return TGIDXS[gindex]
766
+
767
+ gcnd = "dsid = '{}' AND gindex = {}".format(dsid, gindex)
768
+ pgrec = PgDBI.pgget("dsgroup", "pindex", gcnd, logact)
769
+ if pgrec and pgrec['pindex']:
770
+ tindex = get_top_gindex(dsid, pgrec['pindex'])
771
+ else:
772
+ tindex = gindex
773
+ TGIDXS[gindex] = tindex
774
+
775
+ return tindex
776
+
777
+ #
778
+ # cache file top group index for meta gathering
779
+ #
780
+ def cache_meta_tindex(dsid, id, type, logact = PgLOG.LGEREX):
781
+
782
+ pgrec = PgSplit.pgget_wfile(dsid, "tindex, gindex", "wid = {}".format(id), logact)
783
+
784
+ if pgrec:
785
+ if pgrec['tindex']:
786
+ tidx = pgrec['tindex']
787
+ else:
788
+ tidx = get_top_gindex(dsid, pgrec['gindex'], logact)
789
+ else:
790
+ tidx = 0
791
+
792
+ if tidx:
793
+ TIDXS[tidx] = 1
794
+ else:
795
+ TIDXS['all'] = 1
796
+
797
+ #
798
+ # reset the top group index values for the current and sub groups of
799
+ # given dsid and/or group index
800
+ # act == 2/4 reset for mss/web files, respectively 1 for both
801
+ #
802
+ def reset_top_gindex(dsid, gindex, act):
803
+
804
+ tcnt = 0
805
+ if act == 1: act = 12
806
+ tindex = get_top_gindex(dsid, gindex)
807
+ record = {'tindex' : tindex}
808
+ tcnd = "gindex = {} AND tindex <> {}".format(gindex, tindex)
809
+ dcnd = "dsid = '{}'".format(dsid)
810
+ if act&4:
811
+ cnt = PgSplit.pgupdt_wfile(dsid, record, tcnd, PgLOG.LGEREX)
812
+ if cnt > 0:
813
+ s = ('s' if cnt > 1 else '')
814
+ PgLOG.pglog("set tindex {} for {} web files in gindex {} of {}".format(tindex, cnt, gindex, dsid), PgLOG.WARNLG)
815
+ tcnt += cnt
816
+ if act&8:
817
+ cnt = PgDBI.pgupdt("sfile", record, dcnd + ' AND ' + tcnd, PgLOG.LGEREX)
818
+ if cnt > 0:
819
+ s = ('s' if cnt > 1 else '')
820
+ PgLOG.pglog("set tindex {} for {} saved files in gindex {} of {}".format(tindex, cnt, gindex, dsid), PgLOG.WARNLG)
821
+ tcnt += cnt
822
+
823
+ pcnd = "{} AND pindex = {}".format(dcnd, gindex)
824
+ pgrecs = PgDBI.pgmget("dsgroup", "gindex", pcnd, PgLOG.LGEREX)
825
+ cnt = len(pgrecs['gindex']) if pgrecs else 0
826
+
827
+ for i in range(cnt):
828
+ tcnt += reset_top_gindex(dsid, pgrecs['gindex'][i])
829
+
830
+ return tcnt
831
+
832
+ #
833
+ # reset metalink in table wfile
834
+ #
835
+ def set_meta_link(dsid, fname):
836
+
837
+ return PgLOG.pgsystem("{} -d {} {}".format(CMD['SL'], dsid, fname))