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,1655 @@
1
+ #
2
+ ###############################################################################
3
+ #
4
+ # Title : PgArch.py -- package for holding dsarch gobal variables and functions
5
+ #
6
+ # Author : Zaihua Ji, zjiucar.edu
7
+ # Date : 09/22/2020
8
+ # 2025-01-22 transferred to package rda_python_dsarch from
9
+ # https://github.com/NCAR/rda-shared-libraries.git
10
+ # Purpose : python library module for holding some global variables and
11
+ # functions for dsarch utility
12
+ #
13
+ # Github : https://github.com/NCAR/rda-python-dsarch.git
14
+ #
15
+ ###############################################################################
16
+ #
17
+ import time
18
+ import re
19
+ import os
20
+ from os import path as op
21
+ from rda_python_common import PgLOG
22
+ from rda_python_common import PgUtil
23
+ from rda_python_common import PgFile
24
+ from rda_python_common import PgOPT
25
+ from rda_python_common import PgCMD
26
+ from rda_python_common import PgSIG
27
+ from rda_python_common import PgDBI
28
+ from rda_python_common import PgSplit
29
+
30
+ RTPATH = {
31
+ 'dsid' : None, # dsid for the current caching info
32
+ 'A' : '', # ARCO reference file
33
+ 'D' : '', # normal web online data
34
+ 'N' : '', # online data for ncar users only
35
+ 'I' : '', # internal online data
36
+ 'U' : '', # unknown type of online data
37
+ 'O' : '', # document path
38
+ 'S' : '', # software path
39
+ 'HD' : '', # dataset help document path
40
+ 'HS' : '', # dataset help software path
41
+ 'SP' : '', # dataset savedpath
42
+ }
43
+
44
+ webpaths = {}
45
+ savedpaths = {}
46
+ grouptypes = {}
47
+ CORDERS = {}
48
+ CTYPE = ''
49
+
50
+ PgOPT.OPTS = { # (!= 0) - setting actions
51
+ 'AS' : [0x00000004, 'ArchiveSavedFile', 1],
52
+ 'AH' : [0x00000008, 'ArchiveHelpFile', 1],
53
+ 'AW' : [0x00000010, 'ArchiveWebFile', 1],
54
+ 'CG' : [0x00000040, 'ChangeGroup', 1],
55
+ 'TV' : [0x00000100, 'TerminateVersion', 1],
56
+ 'DG' : [0x00000200, 'DeleteGroup', 1],
57
+ 'DL' : [0x00000400, 'Delete', 1],
58
+ 'GS' : [0x00000800, 'GetSavedFile', 0],
59
+ 'GD' : [0x00001000, 'GetDataset', 0],
60
+ 'GG' : [0x00002000, 'GetGroup', 0],
61
+ 'GH' : [0x00004000, 'GetHelpFile', 0],
62
+ 'GW' : [0x00008000, 'GetWebFile', 0],
63
+ 'GV' : [0x00010000, 'GetVersion', 0],
64
+ 'MV' : [0x00040000, 'MoveFile', 1],
65
+ 'SS' : [0x00080000, 'SetSavedFile', 1],
66
+ 'SD' : [0x00100000, 'SetDataset', 4],
67
+ 'SG' : [0x00200000, 'SetGroup', 1],
68
+ 'SH' : [0x00400000, 'SetHelpFile', 1],
69
+ 'SW' : [0x00800000, 'SetWebFile', 1],
70
+ 'SV' : [0x01000000, 'SetVersion', 1],
71
+ 'UC' : [0x04000000, 'UpdateCache', 1],
72
+ 'UW' : [0x08000000, 'UpdateWeb', 1],
73
+ 'AQ' : [0x10000000, 'ArchiveQuasarFile', 1],
74
+ 'GQ' : [0x20000000, 'GetQuasarFile', 0],
75
+ 'SQ' : [0x40000000, 'SetQuasarFile', 1],
76
+ 'RQ' : [0x80000000, 'RestoreQuasarFile', 1],
77
+ 'GA' : [0x2000F800, 'GetALL', 0], # GD, GG, GH, GS, GW & GQ
78
+ 'SA' : [0x40F80000, 'SetALL', 2], # SD, SG, SH, SS, SW & SQ
79
+
80
+ 'BG' : [0, 'BackGround', 0],
81
+ 'CL' : [0, 'CleanLocal', 0],
82
+ 'FO' : [0, 'FormatOutput', 0],
83
+ 'DX' : [0, 'DeleteXML', 2],
84
+ 'EM' : [0, 'EmailNotice', 0],
85
+ 'GF' : [0, 'GrowingFile', 1],
86
+ 'GX' : [0, 'GatherXML', 3],
87
+ 'GZ' : [0, 'GMTZone', 0],
88
+ 'KM' : [0, 'KeepMetadata', 1],
89
+ 'KP' : [0, 'KeepPath', 1],
90
+ 'MD' : [0, 'MyDataset', 3],
91
+ 'NE' : [0, 'NoEmail', 0],
92
+ 'NT' : [0, 'NoTrim', 0],
93
+ 'NV' : [0, 'NewVersion', 1],
94
+ 'OE' : [0, 'OverrideExist', 1],
95
+ 'PE' : [0, 'ShowPeriod', 0],
96
+ 'RA' : [0, 'RetryArchive', 1],
97
+ 'RD' : [0, 'RemoveDir', 2],
98
+ 'RG' : [0, 'RecursiveGroup', 0],
99
+ 'RN' : [0, 'RelativeName', 1],
100
+ 'RO' : [0, 'ResetOrder', 2],
101
+ 'RS' : [0, 'GXRSOptions', 3],
102
+ 'RT' : [0, 'ResetTIndex', 3],
103
+ 'SC' : [0, 'SetChecksum', 2],
104
+ 'TO' : [0, 'TarOnly', 1],
105
+ 'TS' : [0, 'ToSaved', 2],
106
+ 'TT' : [0, 'TotalSummary', 0],
107
+ 'TW' : [0, 'ToWeb', 2],
108
+ 'UZ' : [0, 'UnzipData', 3],
109
+ 'WC' : [0, 'WithChecksum', 0],
110
+ 'WM' : [0, 'WithMetadata', 3],
111
+ 'WN' : [0, 'WithFileNumber',3],
112
+ 'XC' : [0, 'CrossCopy', 1],
113
+ 'XM' : [0, 'CrossMove', 1],
114
+ 'ZD' : [0, 'ZipData', 3],
115
+
116
+ 'AL' : [1, 'AsyncLimit', 17],
117
+ 'AO' : [1, 'ActionOption', 1], # default to <!>
118
+ 'BL' : [1, 'ButtonLimit', 17],
119
+ 'DD' : [1, 'DeleteDir', 1],
120
+ 'DS' : [1, 'Dataset', 0],
121
+ 'DV' : [1, 'Divider', 1], # default to <:>
122
+ 'ES' : [1, 'EqualSign', 1], # default to <=>
123
+ 'FL' : [1, 'FileLimit', 16],
124
+ 'FN' : [1, 'FieldNames', 0],
125
+ 'GL' : [1, 'GroupLevel', 16],
126
+ 'LD' : [1, 'LocalDirectory', 0],
127
+ 'LL' : [1, 'LocalFileList', 0],
128
+ 'LN' : [1, 'LoginName', 1],
129
+ 'OD' : [1, 'OriginDataset', 0],
130
+ 'OF' : [1, 'OutputFile', 0],
131
+ 'ON' : [1, 'OrderNames', 0],
132
+ 'PO' : [1, 'PatternOffset', 16],
133
+ 'QS' : [1, 'QsubOptions', 1],
134
+ 'UD' : [1, 'UseDSARCH', 0, 'YNIPW'], # Internal, Public, Web only, Y - ready for dsarch
135
+ 'VS' : [1, 'ValidSize', 17], # default to PgLOG.PGLOG['MINSIZE']
136
+ 'WI' : [1, 'WaitInternval', 1],
137
+
138
+ 'AF' : [2, 'ArchiveFormat', 1],
139
+ 'BD' : [2, 'BeginDate', 256],
140
+ 'BF' : [2, 'BackupFlag', 1, 'BDNP'],
141
+ 'BP' : [2, 'BatchProcess', 0, ''],
142
+ 'BS' : [2, 'BackStatus', 1, 'NTA'],
143
+ 'BT' : [2, 'BeginTime', 32],
144
+ 'DB' : [2, 'Debug', 0],
145
+ 'DE' : [2, 'Description', 65],
146
+ 'DF' : [2, 'DataFormat', 1],
147
+ 'DN' : [2, 'DOINumber', 1],
148
+ 'DO' : [2, 'DisplayOrder', 16],
149
+ 'ED' : [2, 'EndDate', 256],
150
+ 'ET' : [2, 'EndTime', 32],
151
+ 'EV' : [2, 'ExternalVersion', 1],
152
+ 'FD' : [2, 'FileDate', 257],
153
+ 'FS' : [2, 'FileStatus', 1, 'PI'],
154
+ 'FT' : [2, 'FileTime', 33],
155
+ 'GI' : [2, 'GroupIndex', 17],
156
+ 'GN' : [2, 'GroupName', 1],
157
+ 'GP' : [2, 'GroupPattern', 1],
158
+ 'GT' : [2, 'GroupType', 1, 'PI'],
159
+ 'HF' : [2, 'HelpFile', 0],
160
+ 'HT' : [2, 'HelpFileType', 129, PgOPT.PGOPT['HFTYP']],
161
+ 'ID' : [2, 'InitialDate', 257],
162
+ 'IF' : [2, 'InputFile', 0],
163
+ 'IV' : [2, 'InternalVersion', 0],
164
+ 'KV' : [2, 'KeyValue', 0],
165
+ 'LC' : [2, 'Location', 1, 'CGOBR'],
166
+ 'LF' : [2, 'LocalFile', 0],
167
+ 'MC' : [2, 'MD5Checksum', 0],
168
+ 'ML' : [2, 'MetaLink', 1],
169
+ 'ND' : [2, 'NoteDocument', 65],
170
+ 'NI' : [2, 'NoteInternal', 65],
171
+ 'NS' : [2, 'NoteSoftware', 65],
172
+ 'NW' : [2, 'NoteWeb', 65],
173
+ 'OB' : [2, 'OrderBy', 0],
174
+ 'OG' : [2, 'OriginGroup', 1],
175
+ 'OT' : [2, 'OriginType', 1],
176
+ 'PI' : [2, 'ParentIndex', 17],
177
+ 'QF' : [2, 'QuasarFile', 0],
178
+ 'QT' : [2, 'QuasarFileType', 129, 'BD'],
179
+ 'RF' : [2, 'OriginFile', 0],
180
+ 'SF' : [2, 'SavedFile', 0],
181
+ 'SP' : [2, 'SavedPath', 1],
182
+ 'SR' : [2, 'Source', 1],
183
+ 'ST' : [2, 'SavedFileType', 1, PgOPT.PGOPT['SDTYP']],
184
+ 'SZ' : [2, 'Size', 16],
185
+ 'TG' : [2, 'TopGroupIndex', 17],
186
+ 'TI' : [2, 'Title', 0],
187
+ 'TL' : [2, 'ThreddLink', 1],
188
+ 'VI' : [2, 'VersionIndex', 17],
189
+ 'VT' : [2, 'VersionStatus', 0, "PAH"],
190
+ 'WF' : [2, 'WebFile', 0],
191
+ 'WH' : [2, 'WebHome', 1],
192
+ 'WP' : [2, 'WebPath', 1],
193
+ 'WT' : [2, 'WebFileType', 1, PgOPT.PGOPT['WDTYP']],
194
+ 'WU' : [2, 'WebURL', 1],
195
+ }
196
+
197
+ PgOPT.ALIAS = {
198
+ 'AF' : ['FF', 'FileFormat', 'ExternalFormat'],
199
+ 'AL' : ['AsynchronousLimit'],
200
+ 'AO' : ['ActOption'],
201
+ 'AH' : ['ArchiveHelp', 'ArchHelp', 'ArchHelpFile'],
202
+ 'AQ' : ['ArchiveQuasar', 'ArchiveBackupFile', 'ArchiveBackup'],
203
+ 'AS' : ['ArchiveSaved', 'ArchSaved', 'ArchSavedFile'],
204
+ 'AW' : ['ArchiveWeb', 'ArchWeb', 'ArchWebFile'],
205
+ 'BG' : ['b'],
206
+ 'BP' : ['d', 'DelayedMode'],
207
+ 'CL' : ['CleanLocFile', 'CleanLocalFile'],
208
+ 'DD' : ['DeleteDirLevel', 'DeleteEmptyDir'],
209
+ 'DE' : ['Desc', 'Note', 'FileDesc', 'FileDescription'],
210
+ 'DF' : ['TF', 'ContentFormat'],
211
+ 'DL' : ['RM', 'Remove', 'DeleteFile', 'RemoveFile'],
212
+ 'DN' : ["DOI", "DOIName"],
213
+ 'DS' : ['Dsid', 'DatasetID'],
214
+ 'DV' : ['Delimiter', 'Separater'],
215
+ 'FL' : ['FileCountLimit'],
216
+ 'GF' : ['GrowingDataFile'],
217
+ 'GN' : ['GroupID'],
218
+ 'GM' : ['GetMSS'],
219
+ 'GQ' : ['GetQuasar', 'GetBackupFile', 'GetBackup'],
220
+ 'GS' : ['GetSaved'],
221
+ 'GT' : ['GroupDataType'],
222
+ 'GW' : ['GetWeb'],
223
+ 'GX' : ['Grid2XML'],
224
+ 'GZ' : ['GMT', 'GreenwichZone', 'UTC'],
225
+ 'KM' : ['KeepMeta'],
226
+ 'KP' : ['KeepLocalPath'],
227
+ 'HT' : ['HelpType'],
228
+ 'LC' : ['LocationFlag'],
229
+ 'LF' : ['LocFile', 'SourceFile'],
230
+ 'LL' : ['LocalList'],
231
+ 'ML' : ['MetadataLink'],
232
+ 'MX' : ['HtarMemberXML', 'MemberfileXML'],
233
+ 'ND' : ['DocumentNote', 'DescDocument'],
234
+ 'NI' : ['InternalNote', 'DescInternal', 'DI'],
235
+ 'NS' : ['SoftwareNote', 'DescSoftware'],
236
+ 'NW' : ['WebNote', 'DescWeb', 'DW'],
237
+ 'OB' : ['OrderByPattern'],
238
+ 'PI' : ['ParentGroupIndex'],
239
+ 'QS' : ['PBSOptions'],
240
+ 'QT' : ['QuasarType', 'BackupType'],
241
+ 'RD' : ['RemoveDirectory', 'RemoveEmptyDir'],
242
+ 'RG' : ['RepeatGroup'],
243
+ 'RN' : ['RelativePathName', 'RelativeFileName'],
244
+ 'RO' : ['Reorder'],
245
+ 'RQ' : ['RestoreQuasar', 'RestoreBackupFile', 'RestoreBackup'],
246
+ 'RT' : ['ResetTopGroup'],
247
+ 'SH' : ['SetHelp'],
248
+ 'SQ' : ['SetQuasar', 'SetBackupFile', 'SetBackup'],
249
+ 'SS' : ['SetSaved'],
250
+ 'ST' : ['SavedType', 'SavedArchiveType'],
251
+ 'SW' : ['SetWeb'],
252
+ 'TG' : ['TopGroup'],
253
+ 'TN' : ['TargetFileName'],
254
+ 'TS' : ['ToSavedFile', 'MovedToSaved'],
255
+ 'TW' : ['ToWebFile', 'MovedToWeb'],
256
+ 'UC' : ['UpdateCacheNumber'],
257
+ 'UD' : ['UseRDADB'],
258
+ 'HD' : ['UpdateHTML', 'GenerateHTML'],
259
+ 'UZ' : ['Uncompress', 'UncompressData', 'Unzip'],
260
+ 'WC' : ['ValidateChecksum', "WithMD5", "ValidateMD5"],
261
+ 'WH' : ['WebDataHome'],
262
+ 'WL' : ['WebLocal'],
263
+ 'WM' : ['WithMeta'],
264
+ 'WN' : ['WithNumber'],
265
+ 'WT' : ['WebType', 'WebArchiveType'],
266
+ 'WU' : ['URL', 'WebAddress'],
267
+ 'ZD' : ['Compress', 'CompressData', 'Zip']
268
+ }
269
+
270
+ #
271
+ # single letter short names for option 'FN' (Field Names) to retrieve info
272
+ # from RDADB; only the fields can be manipulated by this application are listed
273
+ #
274
+ # SHORTNM KEYS(PgOPT.OPTS) DBFIELD
275
+ PgOPT.TBLHASH['dataset'] = { # condition flag, 0-int, 1-string, -1-exclude
276
+ 'T' : ['TI', "title", 1],
277
+ 'S' : ['SP', "savedpath", 1],
278
+ 'H' : ['WH', "webhome", 1],
279
+ 'W' : ['WP', "webpath", 1],
280
+ 'F' : ['DF', "data_format", 1],
281
+ 'U' : ['UD', "use_rdadb", 1],
282
+ 'L' : ['LC', "locflag", 1],
283
+ 'Q' : ['BF', "backflag", 1],
284
+ 'V' : ['GL', "grouplevel", 0],
285
+ 'C' : ['FL', "filelimit", 0],
286
+ 'B' : ['BL', "buttonlimit", 0],
287
+ 'A' : ['ML', "meta_link", -1],
288
+ 'P' : ['NW', "wnote", -1],
289
+ 'I' : ['NI', "inote", -1],
290
+ 'D' : ['ND', "dnote", -1],
291
+ 'N' : ['NS', "snote", -1]
292
+ }
293
+
294
+ PgOPT.TBLHASH['dsperiod'] = {
295
+ 'G' : ['GI', "dsperiod.gindex", 0],
296
+ 'J' : ['BD', "date_start", 1],
297
+ 'K' : ['BT', "time_start", 1],
298
+ 'X' : ['ED', "date_end", 1],
299
+ 'Y' : ['ET', "time_end", 1]
300
+ }
301
+
302
+ PgOPT.TBLHASH['dsgroup'] = {
303
+ 'I' : ['GI', "gindex", 0],
304
+ 'G' : ['GN', "grpid", 1],
305
+ 'X' : ['PI', "pindex", 0],
306
+ 'T' : ['TI', "title", 1],
307
+ 'R' : ['GT', "grptype", 1],
308
+ 'Q' : ['BF', "backflag", 1],
309
+ 'P' : ['GP', "pattern", 1],
310
+ 'S' : ['SP', "savedpath", 1],
311
+ 'W' : ['WP', "webpath", 1],
312
+ 'A' : ['ML', "meta_link", 1],
313
+ 'D' : ['NW', "wnote", 1],
314
+ 'N' : ['NI', "inote", 1]
315
+ }
316
+
317
+ PgOPT.TBLHASH['wfile'] = {
318
+ 'F' : ['WF', "wfile", 1],
319
+ 'T' : ['WT', "wtype", 1, "wfile.type"],
320
+ 'C' : ['MC', "wfile.checksum", 1],
321
+ 'I' : ['GI', "gindex", 0],
322
+ 'X' : ['TG', "tindex", 0],
323
+ 'V' : ['VI', "vindex", 0],
324
+ 'M' : ['AF', "wfile.file_format", 1],
325
+ 'N' : ['DF', "wfile.data_format", 1],
326
+ 'O' : ['DO', "wfile.disp_order", -1],
327
+ 'B' : ['QF', "wfile.bid", 0],
328
+ 'Q' : ['QT', "btype", 1, "bfile.type"],
329
+ 'L' : ['LC', "locflag", 1],
330
+ 'H' : ['FS', "wfile.status", 1],
331
+ 'S' : ['SZ', "wfile.data_size", 0],
332
+ 'J' : ['FD', "wfile.date_modified", 1],
333
+ 'K' : ['FT', "wfile.time_modified", 1],
334
+ 'A' : ['ML', "wfile.meta_link", 1],
335
+ 'E' : ['TL', "thredd_link", 1],
336
+ 'D' : ['DE', "wfile.note", 1]
337
+ }
338
+
339
+ PgOPT.TBLHASH['sfile'] = {
340
+ 'F' : ['SF', "sfile", 1],
341
+ 'T' : ['ST', "stype", 1, "sfile.type"],
342
+ 'C' : ['MC', "sfile.checksum", 1],
343
+ 'I' : ['GI', "gindex", 0],
344
+ 'X' : ['TG', "tindex", 0],
345
+ 'V' : ['VI', "vindex", 0],
346
+ 'M' : ['AF', "sfile.file_format", 1],
347
+ 'N' : ['DF', "sfile.data_format", 1],
348
+ 'O' : ['DO', "sfile.disp_order", -1],
349
+ 'B' : ['QF', "sfile.bid", 0],
350
+ 'Q' : ['QT', "btype", 1, "bfile.type"],
351
+ 'L' : ['LC', "locflag", 1],
352
+ 'H' : ['FS', "sfile.status", 1],
353
+ 'S' : ['SZ', "sfile.data_size", 0],
354
+ 'J' : ['FD', "sfile.date_modified", 1],
355
+ 'K' : ['FT', "sfile.time_modified", 1],
356
+ 'D' : ['DE', "sfile.note", 1]
357
+ }
358
+
359
+ PgOPT.TBLHASH['bfile'] = {
360
+ 'F' : ['QF', "bfile", 1],
361
+ 'C' : ['MC', "checksum", 1],
362
+ 'M' : ['AF', "file_format", 1],
363
+ 'N' : ['DF', "data_format", 1],
364
+ 'O' : ['DO', "disp_order", -1],
365
+ 'T' : ['QT', "type", 1],
366
+ 'H' : ['BS', "status", 1],
367
+ 'S' : ['SZ', "data_size", 0],
368
+ 'J' : ['FD', "date_modified", 1],
369
+ 'K' : ['FT', "time_modified", 1],
370
+ 'D' : ['DE', "note", 1]
371
+ }
372
+
373
+ PgOPT.TBLHASH['hfile'] = {
374
+ 'F' : ['HF', "hfile", 1],
375
+ 'T' : ['HT', "type", 1],
376
+ 'L' : ['LC', "locflag", 1],
377
+ 'C' : ['MC', "checksum", 1],
378
+ 'M' : ['AF', "file_format", 1],
379
+ 'N' : ['DF', "data_format", 1],
380
+ 'O' : ['DO', "disp_order", -1],
381
+ 'H' : ['FS', "status", 1],
382
+ 'S' : ['SZ', "data_size", 0],
383
+ 'R' : ['SR', "source", 1],
384
+ 'I' : ['ID', "init_date", 1],
385
+ 'J' : ['FD', "date_modified", 1],
386
+ 'K' : ['FT', "time_modified", 1],
387
+ 'U' : ['WU', "url", 1],
388
+ 'D' : ['DE', "note", 1]
389
+ }
390
+
391
+ PgOPT.TBLHASH['dsvrsn'] = {
392
+ 'V' : ['VI', "vindex", 0],
393
+ 'I' : ['IV', "iversion", 0],
394
+ 'E' : ['EV', "eversion", 1],
395
+ 'D' : ['DN', "doi", 1],
396
+ 'S' : ['VT', "status", 1],
397
+ 'J' : ['BD', "start_date", 1],
398
+ 'K' : ['BT', "start_time", -1],
399
+ 'X' : ['ED', "end_date", 1],
400
+ 'Y' : ['ET', "end_time", -1],
401
+ 'N' : ['DE', "note", -1],
402
+ }
403
+
404
+ # global info to be used by the whole application
405
+ PgOPT.PGOPT['MSET'] = "SA"
406
+ #default fields for getting info
407
+ PgOPT.PGOPT['dataset'] = "SWFULQ"
408
+ PgOPT.PGOPT['dsperiod'] = "GJKXY"
409
+ PgOPT.PGOPT['dsgroup'] = "IGXTPQSW"
410
+ PgOPT.PGOPT['wfile'] = "FTIVMNLHS"
411
+ PgOPT.PGOPT['sfile'] = "FTIVMNLHS"
412
+ PgOPT.PGOPT['bfile'] = "FNMTHS"
413
+ PgOPT.PGOPT['hfile'] = 'FMNLTHSU'
414
+ PgOPT.PGOPT['dsvrsn'] = "VIEDSJX"
415
+ PgOPT.PGOPT['UACTS'] = (PgOPT.OPTS['AQ'][0]|PgOPT.OPTS['SD'][0]|PgOPT.OPTS['DL'][0])
416
+
417
+ #all fields for getting info
418
+ PgOPT.PGOPT['dsall'] = "TSHWFULQVCBAPIDNGJKXYIJKXY" # include 'pdall'
419
+ PgOPT.PGOPT['pdall'] = "GJKXY"
420
+ PgOPT.PGOPT['gpall'] = "IGXTRQPSWADN"
421
+ PgOPT.PGOPT['wfall'] = "FTCIXVMNOBQLHSJKAED"
422
+ PgOPT.PGOPT['sfall'] = "FTCIXVMNOBQLHSJKD"
423
+ PgOPT.PGOPT['bfall'] = "FNMOTHSCJKD"
424
+ PgOPT.PGOPT['hfall'] = 'FTLCMNOHSRIJKUD'
425
+ PgOPT.PGOPT['vrsnall'] = "VIEDSJKXYN"
426
+
427
+ # PgOPT.PGOPT['ofile'] reserved for original type 'B' hpps file name
428
+
429
+ PgOPT.params['AL'] = 0 # max number of asynchronous background processes
430
+ PgOPT.params['WI'] = 30 # wait interval continue update record in queue, in seconds
431
+
432
+ #
433
+ # get condition
434
+ #
435
+ def get_condition(tname, include = None, exclude = None, dojoin = 0):
436
+
437
+ if tname not in PgOPT.TBLHASH: return "" # should not happen
438
+ hash = PgOPT.TBLHASH[tname]
439
+
440
+ lname = (tname + '.') if dojoin or tname == 'dsperiod' else ''
441
+ condition = "{}dsid = '{}'".format(lname, PgOPT.params['DS'])
442
+ noand = 0
443
+ if tname == 'wfile':
444
+ types = PgOPT.params['WT'] if 'WT' in PgOPT.params else None
445
+ condition = ''
446
+ noand = 1
447
+
448
+ for key in hash:
449
+ flg = hash[key][2]
450
+ if flg < 0: continue
451
+ if include and include.find(key) < 0: continue
452
+ if exclude and exclude.find(key) > -1: continue
453
+ opt = hash[key][0]
454
+ fld = hash[key][3] if len(hash[key]) == 4 else hash[key][1]
455
+ if opt in PgOPT.params:
456
+ if opt == 'QF' and PgOPT.PGOPT['CACT'] != 'GQ':
457
+ values = get_bid_numbers(PgOPT.params[opt])
458
+ else:
459
+ values = PgOPT.params[opt]
460
+ condition += PgDBI.get_field_condition(fld, values, flg, noand)
461
+ noand = 0
462
+
463
+ return condition
464
+
465
+ #
466
+ # check if enough information entered on command line and/or input file
467
+ # for given action(s)
468
+ #
469
+ def check_enough_options(cact, acts):
470
+
471
+ errmsg = [
472
+ "Miss original group index per -OG(-OriginGroup)",
473
+ "miss file names per -SF(-SavedFile), -WF(-WebFile) or -QF(-QuasarFile)",
474
+ "miss Quasar file names per -QF(-QuasarFile)",
475
+ "Miss group index per -GI(-GroupIndex)",
476
+ "Miss dataset number per -DS(-Dataset)",
477
+ "Miss local file names per -LF(-LocalFile)",
478
+ "miss Help file names per -HF(-HelpFile)",
479
+ "Miss original dataset number per -OD(-OriginDataset)",
480
+ "Miss file names per -SF(-SavedFile), -WF(-WebFile), -HF(-HelpFile) Or -QF(-QuasarFile)",
481
+ "Miss Help file types per -HT(-HelpFileType)",
482
+ "Miss Quasar file types per -QT(-QuasarFileType)",
483
+ "Miss RDA Server file names per -WF(-WebFile)",
484
+ "Miss Saved file types per -ST(-SavedFileType)",
485
+ "13",
486
+ "14",
487
+ "Miss Use-RDADB flag, ('Y', 'P', 'W', 'I'), per -UD(-UseRDADB) for ",
488
+ "16",
489
+ "miss Saved file names per -SF(-SavedFile)",
490
+ "Miss Version Control Index per -VI(-VersionIndex)",
491
+ "Cannot specify field names per -FN(-FieldNames) for Action -GA(-GetAll)",
492
+ "20",
493
+ "Miss orignal File Names via -RF (-OriginFile) for Action -MV (-MoveFile)",
494
+ "22",
495
+ '23',
496
+ "Miss Data Format per -DF(-DataFormat)",
497
+ "25",
498
+ "Numbers of orignal/new groups per -OG(-OriginGroup)/-GI(-GroupIndex) do not match",
499
+ "Miss Compression Format, Z|GZ|ZIP|BZ2, per -AF(-ArchiveFormat)",
500
+ "Cannot Set Compression Format, Z|GZ|ZIP|BZ2, per -AF(-ArchiveFormat)",
501
+ "Orignal File Names provided via -RF (-OriginFile) for Action other than -MV (-MoveFile)",
502
+ "Miss order field name string per option -ON (-OrderNames) for Re-ordering",
503
+ '31'
504
+ ]
505
+ erridx = -1
506
+
507
+ if 'SC' in PgOPT.params and 'MC' in PgOPT.params: del PgOPT.params['SC']
508
+
509
+ if ('DS' in PgOPT.params and ('GI' in PgOPT.params or 'GN' in PgOPT.params) and
510
+ (acts&(PgOPT.OPTS['SG'][0]|PgOPT.OPTS['CG'][0])) == 0): PgOPT.validate_groups()
511
+
512
+ if 'LL' in PgOPT.params:
513
+ set_localfile_list(cact)
514
+ elif 'LD' in PgOPT.params:
515
+ build_localfile_list(cact, PgOPT.params['LD'])
516
+
517
+ if acts == PgOPT.OPTS['AH'][0]:
518
+ if 'DS' not in PgOPT.params:
519
+ erridx = 4
520
+ elif 'RF' in PgOPT.params:
521
+ erridx = 29
522
+ elif 'XC' in PgOPT.params or 'XM' in PgOPT.params:
523
+ if 'HF' not in PgOPT.params:
524
+ erridx = 6
525
+ elif 'LF' not in PgOPT.params:
526
+ erridx = 5
527
+ elif 'HT' not in PgOPT.params:
528
+ erridx = 9
529
+ elif 'DF' not in PgOPT.params:
530
+ erridx = 24
531
+ elif acts == PgOPT.OPTS['AQ'][0]:
532
+ if 'DS' not in PgOPT.params:
533
+ erridx = 4
534
+ elif 'QF' not in PgOPT.params:
535
+ erridx = 2
536
+ elif 'RF' in PgOPT.params:
537
+ erridx = 29
538
+ elif 'XC' not in PgOPT.params:
539
+ if 'QT' not in PgOPT.params:
540
+ erridx = 10
541
+ elif 'QF' not in PgOPT.params:
542
+ erridx = 2
543
+ elif acts == PgOPT.OPTS['AS'][0]:
544
+ if 'DS' not in PgOPT.params:
545
+ erridx = 4
546
+ elif 'RF' in PgOPT.params:
547
+ erridx = 29
548
+ elif 'ST' not in PgOPT.params:
549
+ erridx = 12
550
+ elif 'XC' in PgOPT.params or 'XM' in PgOPT.params:
551
+ if 'SF' not in PgOPT.params:
552
+ erridx = 17
553
+ elif 'LF' not in PgOPT.params:
554
+ erridx = 5
555
+ elif 'DF' not in PgOPT.params:
556
+ erridx = default_data_format(24)
557
+ elif acts == PgOPT.OPTS['AW'][0]:
558
+ if 'DS' not in PgOPT.params:
559
+ erridx = 4
560
+ elif 'RF' in PgOPT.params:
561
+ erridx = 29
562
+ elif 'XC' in PgOPT.params or 'XM' in PgOPT.params:
563
+ if 'WF' not in PgOPT.params:
564
+ erridx = 11
565
+ elif 'LF' not in PgOPT.params:
566
+ erridx = 5
567
+ elif 'DF' not in PgOPT.params:
568
+ erridx = default_data_format(24)
569
+ elif acts == PgOPT.OPTS['CG'][0]:
570
+ if 'DS' not in PgOPT.params:
571
+ erridx = 4
572
+ elif 'OG' not in PgOPT.params:
573
+ erridx = 0
574
+ elif 'GI' not in PgOPT.params:
575
+ erridx = 3
576
+ elif len(PgOPT.params['OG']) != len(PgOPT.params['GI']):
577
+ erridx = 26
578
+ elif acts == PgOPT.OPTS['DG'][0]:
579
+ if 'GI' not in PgOPT.params:
580
+ erridx = 3
581
+ elif 'DS' not in PgOPT.params:
582
+ erridx = 4
583
+ elif acts == PgOPT.OPTS['DL'][0]:
584
+ if 'DS' not in PgOPT.params:
585
+ erridx = 4
586
+ elif not ('HF' in PgOPT.params or 'SF' in PgOPT.params or 'QF' in PgOPT.params or 'WF' in PgOPT.params):
587
+ if 'GI' in PgOPT.params and ('ST' in PgOPT.params or 'WT' in PgOPT.params):
588
+ gather_delete_files()
589
+ else:
590
+ erridx = 8
591
+ elif acts&PgOPT.OPTS['GA'][0]:
592
+ if 'DS' not in PgOPT.params:
593
+ erridx = 4
594
+ elif (acts == PgOPT.OPTS['GA'][0] and 'FN' in PgOPT.params and
595
+ not re.match(r'^all$', PgOPT.params['FN'], re.I)):
596
+ erridx = 19
597
+ elif acts == PgOPT.OPTS['GV'][0]:
598
+ if 'DS' not in PgOPT.params: erridx = 4
599
+ elif acts == PgOPT.OPTS['MV'][0]:
600
+ if 'DS' not in PgOPT.params:
601
+ erridx = 4
602
+ elif not ('HF' in PgOPT.params or 'SF' in PgOPT.params or 'QF' in PgOPT.params or
603
+ 'WF' in PgOPT.params or 'RF' in PgOPT.params):
604
+ erridx = 8
605
+ elif not ('RF' in PgOPT.params or 'OD' in PgOPT.params or 'OT' in PgOPT.params):
606
+ if not ('TS' in PgOPT.params or 'TW' in PgOPT.params): erridx = 21
607
+ elif acts == PgOPT.OPTS['RQ'][0]:
608
+ if 'DS' not in PgOPT.params:
609
+ erridx = 4
610
+ elif not ('SF' in PgOPT.params or 'WF' in PgOPT.params or 'QF' in PgOPT.params):
611
+ erridx = 1
612
+ elif 'SF' in PgOPT.params and 'ST' not in PgOPT.params:
613
+ erridx = 12
614
+ elif acts == PgOPT.OPTS['SA'][0]:
615
+ if 'DS' not in PgOPT.params:
616
+ erridx = 4
617
+ elif acts == PgOPT.OPTS['SD'][0]:
618
+ if 'DS' not in PgOPT.params: erridx = 4
619
+ elif acts == PgOPT.OPTS['SG'][0]:
620
+ if 'DS' not in PgOPT.params:
621
+ erridx = 4
622
+ elif 'GI' not in PgOPT.params:
623
+ erridx = 3
624
+ elif acts == PgOPT.OPTS['SH'][0]:
625
+ if 'DS' not in PgOPT.params:
626
+ erridx = 4
627
+ elif 'HT' not in PgOPT.params:
628
+ erridx = 9
629
+ elif not ('HF' in PgOPT.params or 'ON' in PgOPT.params):
630
+ erridx = 30 if 'RO' in PgOPT.params else 6
631
+ elif 'RF' in PgOPT.params:
632
+ erridx = 29
633
+ elif acts == PgOPT.OPTS['SQ'][0]:
634
+ if 'DS' not in PgOPT.params:
635
+ erridx = 4
636
+ elif not ('QF' in PgOPT.params or 'ON' in PgOPT.params or 'WN' in PgOPT.params):
637
+ erridx = 30 if 'RO' in PgOPT.params else 2
638
+ elif 'RF' in PgOPT.params:
639
+ erridx = 29
640
+ elif acts == PgOPT.OPTS['SS'][0]:
641
+ if 'DS' not in PgOPT.params:
642
+ erridx = 4
643
+ elif not ('SF' in PgOPT.params or 'ON' in PgOPT.params or 'RD' in PgOPT.params or 'WN' in PgOPT.params or 'WM' in PgOPT.params or 'RT' in PgOPT.params):
644
+ erridx = 30 if 'RO' in PgOPT.params else 17
645
+ elif 'RF' in PgOPT.params:
646
+ erridx = 29
647
+ elif acts == PgOPT.OPTS['SV'][0]:
648
+ if 'DS' not in PgOPT.params:
649
+ erridx = 4
650
+ else:
651
+ validate_versions()
652
+ if 'VI' not in PgOPT.params: erridx = 18
653
+ elif acts == PgOPT.OPTS['SW'][0]:
654
+ if 'DS' not in PgOPT.params:
655
+ erridx = 4
656
+ elif not ('WF' in PgOPT.params or 'ON' in PgOPT.params or 'RD' in PgOPT.params or 'WN' in PgOPT.params or 'WM' in PgOPT.params or 'RT' in PgOPT.params):
657
+ erridx = 30 if 'RO' in PgOPT.params else 11
658
+ elif 'RF' in PgOPT.params:
659
+ erridx = 29
660
+ elif acts == PgOPT.OPTS['TV'][0]:
661
+ if 'VI' not in PgOPT.params:
662
+ erridx = 18
663
+ elif 'DS' not in PgOPT.params:
664
+ erridx = 4
665
+ validate_versions()
666
+ elif acts == PgOPT.OPTS['UC'][0] or acts == PgOPT.OPTS['UW'][0]:
667
+ if 'DS' not in PgOPT.params: erridx = 4
668
+
669
+ if erridx < 0:
670
+ if(PgOPT.OPTS[cact][2] > 0 and acts&PgOPT.PGOPT['UACTS'] == 0 and
671
+ PgDBI.use_rdadb(PgOPT.params['DS'], PgOPT.PGOPT['extlog']) == 'N' and
672
+ ('UD' not in PgOPT.params or PgOPT.params['UD'] == 'N')):
673
+ erridx = 15
674
+ errmsg[erridx] += PgOPT.params['DS']
675
+
676
+ if erridx >= 0: PgOPT.action_error(errmsg[erridx], cact)
677
+
678
+ PgOPT.set_uid("dsarch") # set uid before any action
679
+ if 'VS' in PgOPT.params: PgLOG.PGLOG['MINSIZE'] = PgOPT.params['VS'] # minimal size for a file to be valid for archive
680
+
681
+ PgLOG.PGLOG['RSOptions'] = " -R -S" if 'RS' in PgOPT.params else ''
682
+
683
+ if 'NE' in PgOPT.params:
684
+ PgLOG.PGLOG['LOGMASK'] &= ~PgLOG.EMLALL # turn off all email acts
685
+ if 'EM' in PgOPT.params: del PgOPT.params['EM']
686
+
687
+ if 'BP' in PgOPT.params:
688
+ if 'AL' in PgOPT.params: PgOPT.params['AL'] = 0
689
+ if 'EM' not in PgOPT.params: PgLOG.PGLOG['LOGMASK'] &= ~PgLOG.EMLALL # turn off email if not yet
690
+ PgOPT.PGOPT['emerol'] |= PgLOG.EXITLG
691
+ # set command line Batch options
692
+ PgCMD.set_batch_options(PgOPT.params, 1)
693
+ PgCMD.init_dscheck(0, '', "dsarch", PgOPT.params['DS'], cact, PgLOG.PGLOG['CURDIR'], PgOPT.params['LN'],
694
+ PgOPT.params['BP'], PgOPT.PGOPT['emerol'])
695
+ if 'EM' in PgOPT.params: PgOPT.PGOPT['emlerr'] = PgLOG.LOGERR|PgLOG.EMEROL
696
+
697
+ PgSIG.start_none_daemon('dsarch', PgOPT.PGOPT['CACT'], PgOPT.params['LN'], 1, PgOPT.params['WI'], 1, PgOPT.params['AL'])
698
+
699
+ #
700
+ # build local file list for given local directory and reset file sizes
701
+ #
702
+ def build_localfile_list(cact, dir):
703
+
704
+ chkopt = 32 if 'SC' in PgOPT.params else 0
705
+
706
+ if 'LF' in PgOPT.params:
707
+ PgOPT.action_error("Both Value Options -LF (-LocalFile) and -LD (-LocalDirecotry) present", cact)
708
+
709
+ locfiles = PgUtil.recursive_files((dir))
710
+ i = 0
711
+ for locfile in locfiles:
712
+ locinfo = PgFile.check_local_file(locfile, chkopt, PgOPT.PGOPT['extlog'])
713
+ if locinfo:
714
+ PgOPT.params['LF'][i] = locfile
715
+ if chkopt: PgOPT.params['MC'][i] = locinfo['checksum']
716
+ PgOPT.params['SZ'][i] = locinfo['data_size']
717
+ i += 1
718
+ else:
719
+ PgOPT.action_error("locfile: local file not exists", cact)
720
+
721
+ if chkopt: del PgOPT.params['SC']
722
+ if i == 0: PgOPT.action_error("NO local file found in Local Directory " + dir, cact)
723
+
724
+ #
725
+ # set local files for given local filelist and reset file sizes
726
+ #
727
+ def set_localfile_list(cact):
728
+
729
+ absolute = 0
730
+ listfile = PgOPT.params['LL']
731
+ chkopt = 32 if 'SC' in PgOPT.params else 0
732
+
733
+ if 'LF' in PgOPT.params:
734
+ PgOPT.action_error("Both Value Options -LF (-LocalFile) and -LL (-LocalFileList) present", cact)
735
+
736
+ i = 0
737
+ hi = open(listfile, 'r')
738
+ locfile = hi.realine()
739
+ while locfile:
740
+ locfile = locfile.strip()
741
+ locinfo = PgFile.check_local_file(locfile, chkopt, PgOPT.PGOPT['extlog'])
742
+ if locinfo:
743
+ PgOPT.params['LF'][i] = locfile
744
+ if chkopt: PgOPT.params['MC'][i] = locinfo['checksum']
745
+ PgOPT.params['SZ'][i] = locinfo['data_size']
746
+ i += 1
747
+ if not absolute and re.match(r'^/', locfile): absolute = 1
748
+ else:
749
+ PgOPT.action_error(locfile + ": local file not exists", cact)
750
+ hi.close()
751
+
752
+ if i == 0: PgOPT.action_error("NO local file found in " + listfile, cact)
753
+ if chkopt: del PgOPT.params['SC']
754
+ if absolute: del PgOPT.params['LL']
755
+
756
+ #
757
+ # compress local file list and reset file sizes
758
+ #
759
+ def compress_localfile_list(cact, cnt):
760
+
761
+ chkopt = 32 if 'SC' in PgOPT.params else 0
762
+ locfiles = PgOPT.compress_files(PgOPT.params['LF'], PgOPT.params['AF'], cnt)
763
+
764
+ for i in range(cnt):
765
+ locfile = locfiles[i]
766
+ if locfile == PgOPT.params['LF'][i]: continue
767
+ locinfo = PgFile.check_local_file(locfile, chkopt, PgOPT.PGOPT['extlog'])
768
+ if locinfo:
769
+ PgOPT.params['LF'][i] = locfile
770
+ PgOPT.params['SZ'][i] = locinfo['data_size']
771
+ if chkopt: PgOPT.params['MC'][i] = locinfo['checksum']
772
+ else:
773
+ PgOPT.action_error(locfile + ": local file not exists", cact)
774
+
775
+ if chkopt: del PgOPT.params['SC']
776
+
777
+ #
778
+ # get continue display order of an archived data file of given dataset (and group/mssid)
779
+ #
780
+ def get_next_disp_order(dsid = None, index = 0, table = None, type = None):
781
+
782
+ global CTYPE, CORDERS
783
+ if not dsid:
784
+ CORDERS = {} # reinitialize cached display orders
785
+ CTYPE = ''
786
+ return
787
+
788
+ if index not in CORDERS or (type and type != CTYPE):
789
+ CORDERS[index] = 0
790
+ if type: CTYPE = type
791
+ if table:
792
+ cnd = "dsid = '{}'".format(dsid)
793
+ if table == 'wfile':
794
+ cnd = "gindex = {}".format(index)
795
+ elif table == 'sfile':
796
+ cnd += " AND gindex = {}".format(index)
797
+ if type: cnd += " AND type = '{}'".format(type)
798
+ if table == 'wfile':
799
+ pgrec = PgSplit.pgget_wfile(dsid, "max(disp_order) max_order", cnd, PgOPT.PGOPT['extlog'])
800
+ else:
801
+ pgrec = PgDBI.pgget(table, "max(disp_order) max_order", cnd, PgOPT.PGOPT['extlog'])
802
+ if pgrec and pgrec['max_order']: CORDERS[index] = pgrec['max_order']
803
+
804
+ CORDERS[index] += 1
805
+ return CORDERS[index]
806
+
807
+ #
808
+ # identify and return matching data Ids from file name provided
809
+ #
810
+ def get_dsids(file, table, dsids):
811
+
812
+ fields = "dsid, " + table
813
+ if file.find('%') > -1:
814
+ fcnd = "{} LIKE '{}'"
815
+ else:
816
+ fcnd = "{} = '{}'"
817
+ pgrecs = PgDBI.pgmget(table, fields, fcnd.format(table, file), PgOPT.PGOPT['extlog'])
818
+ if not pgrecs and not re.match(r'^/', file):
819
+ pgrecs = PgDBI.pgmget(table, fields, "{} LIKE '%/{}'".format(table, file), PgOPT.PGOPT['extlog'])
820
+ if pgrecs:
821
+ count = len(pgrecs['dsid'])
822
+ while count > 0:
823
+ count -= 1
824
+ dsid = pgrecs['dsid'][count]
825
+ if dsid not in dsids:
826
+ dsids[dsid] = [pgrecs[table][count]]
827
+ else:
828
+ dsids[dsid].append(pgrecs[table][count])
829
+
830
+ #
831
+ # get one dataset number; failure if not or multiple
832
+ #
833
+ def get_dsid(files, table):
834
+
835
+ dsids = {}
836
+ for file in files:
837
+ get_dsids(file, table, dsids)
838
+
839
+ count = len(dsids)
840
+ if count == 1:
841
+ for dsid in dsids: return dsid
842
+
843
+ if count == 0:
844
+ PgLOG.pglog("No Dataset identified for given file information", PgOPT.PGOPT['extlog'])
845
+ else:
846
+ errmsg = "{} Datasets identified for given file information:".format(count)
847
+ for dsid in sorted(dsids):
848
+ pgrec = PgDBI.pgget('dataset', 'title', "dsid = '{}'".format(dsid), PgOPT.PGOPT['extlog'])
849
+ errmsg += "\n{} - {}".format(dsid, pgrec['title'])
850
+ cnt = len(dsids[dsid])
851
+ for j in range(cnt):
852
+ errmsg += "\n {}. {}".format(j+1, dsids[dsid][j])
853
+
854
+ PgLOG.pglog(errmsg + "\nProvide one Dataset via Info option -DS(-Dataset) to run 'dsarch'!", PgOPT.PGOPT['extlog'])
855
+
856
+ return None
857
+
858
+ #
859
+ # reorder the files for group/dataset
860
+ #
861
+ def reorder_files(dsid, onames, table):
862
+
863
+ chkgrp = 1
864
+ gcnd = cnd = "dsid = '{}'".format(dsid)
865
+ if table == "wfile":
866
+ type = "Web"
867
+ idfld = "wid"
868
+ gcnd = "webcnt > 0"
869
+ cnd = "status <> 'D'"
870
+ elif table == "sfile":
871
+ type = "Saved"
872
+ idfld = "sid"
873
+ gcnd += " AND savedcnt > 0"
874
+ elif table == "bfile":
875
+ type = "Backup"
876
+ idfld = "bid"
877
+ chkgrp = 0
878
+ elif table == "hfile":
879
+ type = "Help"
880
+ idfld = "hid"
881
+ chkgrp = 0
882
+
883
+ PgLOG.pglog("Reorder {} files for {} ...".format(type, dsid), PgOPT.PGOPT['wrnlog'])
884
+ fields = "{}, disp_order".format(idfld)
885
+ ocnd = ''
886
+ if onames:
887
+ flds = PgOPT.append_order_fields(onames, 'IO', table)
888
+ fields += ', ' + PgOPT.get_string_fields(flds, table)
889
+ if 'OB' not in PgOPT.params:
890
+ ocnd = PgOPT.get_order_string(onames, table, "I")
891
+ elif 'OB' not in PgOPT.params:
892
+ ocnd = " ORDER BY " + idfld
893
+
894
+ groups = [0]
895
+ if chkgrp:
896
+ if 'GI' in PgOPT.params:
897
+ groups = PgOPT.params['GI']
898
+ else:
899
+ pgrecs = PgDBI.pgmget("dsgroup", "gindex", gcnd, PgOPT.PGOPT['extlog'])
900
+ if pgrecs: groups.extend(pgrecs['gindex'])
901
+ cnd += " AND gindex = "
902
+ grpcnt = len(groups)
903
+
904
+ ccnt = changed = 0
905
+ for i in range(grpcnt):
906
+ gindex = groups[i]
907
+ if chkgrp:
908
+ if i and gindex == groups[i-1]: continue
909
+ fcnd = "{}{}{}".format(cnd, gindex, ocnd)
910
+ else:
911
+ fcnd = "{}{}".format(cnd, ocnd)
912
+ if table == 'wfile':
913
+ pgrecs = PgSplit.pgmget_wfile(dsid, fields, fcnd, PgOPT.PGOPT['extlog'])
914
+ else:
915
+ pgrecs = PgDBI.pgmget(table, fields, fcnd, PgOPT.PGOPT['extlog'])
916
+ cnt = len(pgrecs[idfld]) if pgrecs else 0
917
+ if cnt < 2: continue
918
+ if 'OB' in PgOPT.params or re.search(r'P', onames, re.I):
919
+ pgrecs = PgUtil.sorthash(pgrecs, flds, PgOPT.TBLHASH[table], PgOPT.params['OB'])
920
+ gchng = 0
921
+ for j in range(cnt):
922
+ if not (pgrecs['disp_order'][j] and (j+1) == pgrecs['disp_order'][j]):
923
+ record = {'disp_order' : j+1}
924
+ if table == 'wfile':
925
+ gchng += PgSplit.pgupdt_wfile(dsid, record, "{} = {}".format(idfld, pgrecs[idfld][j]), PgOPT.PGOPT['extlog'])
926
+ else:
927
+ gchng += PgDBI.pgupdt(table, record, "{} = {}".format(idfld, pgrecs[idfld][j]), PgOPT.PGOPT['extlog'])
928
+ if gchng > 0:
929
+ s = 's' if gchng > 1 else ''
930
+ gmsg = "-G{}".format(gindex) if gindex else ''
931
+ PgLOG.pglog("{} {} file{} reordered for {}{}!".format(gchng, type, s, dsid, gmsg), PgOPT.PGOPT['wrnlog'])
932
+ changed += gchng
933
+ ccnt += 1
934
+
935
+ if ccnt > 1:
936
+ PgLOG.pglog("{} {} files reordered for {}!".format(changed, type, dsid), PgOPT.PGOPT['wrnlog'])
937
+ elif ccnt == 0:
938
+ PgLOG.pglog("No {} file needs reorder for {}!".format(type, dsid), PgOPT.PGOPT['wrnlog'])
939
+
940
+ return changed
941
+
942
+ #
943
+ # set default data format and return -1
944
+ #
945
+ def default_data_format(erridx):
946
+
947
+ pgrec = PgDBI.pgget("dataset", "data_format", "dsid = '{}'".format(PgOPT.params['DS']), PgOPT.PGOPT['extlog'])
948
+ if pgrec['data_format']:
949
+ PgOPT.params['DF'] = [pgrec['data_format']]
950
+ erridx = -1
951
+ PgOPT.OPTS['DF'][2] |= 2 # set auto-generated flag
952
+
953
+ return erridx
954
+
955
+ #
956
+ # dump out total file size and count
957
+ #
958
+ def print_statistics(sizes):
959
+
960
+ count = len(sizes)
961
+ total = 0
962
+
963
+ for i in range(count):
964
+ total += sizes[i]
965
+
966
+ PgOPT.OUTPUT.write("#File Count: {}\n".format(count))
967
+ PgOPT.OUTPUT.write("#Total Bytes: {}\n".format(total))
968
+
969
+ #
970
+ # get a group type for given index
971
+ #
972
+ def get_group_type(dsid, gindex):
973
+
974
+ if not gindex: return 'P' # default to P
975
+
976
+ if gindex not in grouptypes: # try to cache it
977
+ pgrec = PgDBI.pgget("dsgroup", "grptype", "dsid = '{}' AND gindex = {}".format(PgOPT.params['DS'], gindex), PgOPT.PGOPT['extlog'])
978
+ grouptypes[gindex] = 'I' if pgrec and pgrec['grptype'] == 'I' else 'P'
979
+
980
+ return grouptypes[gindex]
981
+
982
+ #
983
+ # intialize the group info of patterns, webpaths and savedpaths for given dataset ID
984
+ # and set group IDs if missed
985
+ #
986
+ def cache_group_info(count, noauto = 0):
987
+
988
+ global webpaths, savedpaths, grouptypes
989
+
990
+ pgrec = PgDBI.pgget("dataset", "webpath, savedpath", "dsid = '{}'".format(PgOPT.params['DS']), PgOPT.PGOPT['extlog'])
991
+ if not pgrec: PgLOG.pglog("Cannot get dataset info for '{}'".format(PgOPT.params['DS']), PgOPT.PGOPT['extlog'])
992
+
993
+ webpaths = {0 : pgrec['webpath']}
994
+ savedpaths = {0 : pgrec['savedpath']}
995
+ grouptypes = {}
996
+
997
+ if not count or 'GI' in PgOPT.params: return
998
+
999
+ PgOPT.params['GI'] = [0]*count # initialize group index to 0
1000
+
1001
+ if 'PO' in PgOPT.params:
1002
+ mcnt = count
1003
+ else:
1004
+ if 'WF' in PgOPT.params:
1005
+ files = PgOPT.params['WF']
1006
+ fname = "wfile"
1007
+ mcnt = count = len(files)
1008
+ elif 'SF' in PgOPT.params:
1009
+ files = PgOPT.params['SF']
1010
+ fname = "sfile"
1011
+ mcnt = count = len(files)
1012
+ else:
1013
+ fname = None
1014
+ mcnt = count
1015
+
1016
+ if fname:
1017
+ gidx = 0
1018
+ for i in range(count):
1019
+ if fname == 'wfile':
1020
+ pgrec = PgSplit.pgget_wfile(PgOPT.params['DS'], "gindex", "{} = '{}'".format(fname, files[i]), PgOPT.PGOPT['extlog'])
1021
+ else:
1022
+ pgrec = PgDBI.pgget(fname, "gindex", "dsid = '{}' AND {} = '{}'".format(PgOPT.params['DS'], fname, files[i]), PgOPT.PGOPT['extlog'])
1023
+ if pgrec and pgrec['gindex']:
1024
+ if(pgrec['gindex'] != gidx and
1025
+ not PgDBI.pgget("dsgroup", "", "dsid = '{}' and gindex = {}".format(PgOPT.params['DS'], pgrec['gindex']), PgOPT.PGOPT['extlog'])):
1026
+ PgLOG.pglog("Group Index {} found for {} of {} is not in RDADB".format(pgrec['gindex'], fname, PgOPT.params['DS']), PgOPT.PGOPT['extlog'])
1027
+ PgOPT.params['GI'][i] = gidx = pgrec['gindex']
1028
+ mcnt -= 1
1029
+
1030
+ if mcnt == count: PgOPT.OPTS['GI'][2] |= 2 # set auto-generated flag
1031
+ if noauto or mcnt == 0: return # stop if no auto matching
1032
+
1033
+ pgrecs = PgDBI.pgmget("dsgroup", "gindex, pattern", "dsid = '{}' AND pattern > ' ' ORDER BY pattern".format(PgOPT.params['DS']), PgOPT.PGOPT['extlog'])
1034
+ pcnt = len(pgrecs['gindex']) if pgrecs else 0
1035
+ if not pcnt:
1036
+ if 'PO' in PgOPT.params:
1037
+ PgLOG.pglog("Missing Group Patterns for set groups of " + PgOPT.params['DS'], PgOPT.PGOPT['emlerr'])
1038
+ return
1039
+
1040
+ if 'WF' in PgOPT.params:
1041
+ files = PgOPT.params['WF']
1042
+ elif 'SF' in PgOPT.params:
1043
+ files = PgOPT.params['SF']
1044
+ elif 'LF' in PgOPT.params:
1045
+ files = PgOPT.params['LF']
1046
+ else:
1047
+ return
1048
+
1049
+ offset = (PgOPT.params['PO'] if 'PO' in PgOPT.params else -1)
1050
+ count = len(files)
1051
+ tmpfiles = [None]*count
1052
+ for i in range(count):
1053
+ if PgOPT.params['GI'][i]: continue
1054
+ tmpfiles[i] = op.basename(files[i])
1055
+ if offset > 0: tmpfiles[i] = tmpfiles[i][offset:]
1056
+ files = tmpfiles
1057
+
1058
+ s = 's' if mcnt > 1 else ''
1059
+ if pcnt > 5:
1060
+ PgLOG.pglog("Initialize group index for {} file{} via ".format(mcnt, s) +
1061
+ "{} pattern match ...".format("Binary" if offset > -1 else "Simple"), PgOPT.PGOPT['wrnlog'])
1062
+ k = int(pcnt/2) # initial index for pattern search
1063
+ mcnt = 0
1064
+ for i in range(count):
1065
+ if not files[i]: continue # skip group index found already
1066
+ j = -1
1067
+ bname = files[i]
1068
+ # search adjecent three pattern first
1069
+ if re.match(r'^{}'.format(pgrecs['pattern'][k]), bname):
1070
+ j = k
1071
+ elif k < (pcnt-1) and re.search(pgrecs['pattern'][k+1], bname):
1072
+ j = k+1
1073
+ elif k > 0 and re.search(pgrecs['pattern'][k-1], bname):
1074
+ j = k-1
1075
+ elif offset < 0: # simple searh
1076
+ j = k+2
1077
+ while j < pcnt: # search up
1078
+ if re.search(pgrecs['pattern'][j], bname): break
1079
+ j += 1
1080
+ if j >= pcnt:
1081
+ j = k-2
1082
+ while j >= 0: # search down
1083
+ if re.search(pgrecs['pattern'][j], bname): break
1084
+ j -= 1
1085
+ else: # binary search
1086
+ if k < (pcnt - 2): # search top section
1087
+ j = PgUtil.psearch(k+2, pcnt, bname, pgrecs['pattern'])
1088
+ if j < 0 and k > 1: # search bottom section
1089
+ j = PgUtil.psearch(0, k-1, bname, pgrecs['pattern'])
1090
+
1091
+ if j > -1: # matched
1092
+ k = j
1093
+ PgOPT.params['GI'][i] = pgrecs['gindex'][k]
1094
+ mcnt += 1
1095
+
1096
+ s = 's' if count > 1 else ''
1097
+ PgLOG.pglog("{} of {} file{} found matching group index of {}".format( mcnt, count, s, PgOPT.params['DS']), PgOPT.PGOPT['emlerr'])
1098
+
1099
+ if mcnt > 0:
1100
+ PgOPT.OPTS['GI'][2] &= ~(2) # remove auto-generated flag
1101
+ PgOPT.OPTS['GI'][2] |= 16 # set writable auto-generated flag
1102
+
1103
+ #
1104
+ # change a wfile permission on disk according to the file status
1105
+ #
1106
+ def change_wfile_mode(dsid, wfile, type, ostat, nstat):
1107
+
1108
+ if ostat == nstat: return
1109
+ if not RTPATH['dsid']: cache_rtpath(dsid)
1110
+ nm = 0o600 if nstat == 'I' else PgLOG.PGLOG['FILEMODE']
1111
+ PgFile.set_local_mode(PgLOG.join_paths(RTPATH[type], wfile), nmode = nm)
1112
+
1113
+ #
1114
+ # get group WEB file path for given file index and/or file name
1115
+ # opt = 0 - relative path to rtpath
1116
+ # 1 - absolute path
1117
+ # 2 - relative path to rtpath/webpath
1118
+ # 3 - full url path as PgLOG.PGLOG['DSSURL']...
1119
+ # 4 - bit for ignore web path
1120
+ #
1121
+ def get_web_path(i, fname, opt = 0, type = None, init = 0):
1122
+
1123
+ addwp = 1
1124
+ rtpath = None
1125
+ if init or not RTPATH['dsid']: cache_rtpath(PgOPT.params['DS'], init)
1126
+ if not type: type = PgOPT.params['WT'][i] if 'WT' in PgOPT.params and PgOPT.params['WT'][i] else 'D'
1127
+ rtpath = RTPATH[type]
1128
+
1129
+ if opt > 3:
1130
+ addwp = 0
1131
+ opt -= 4
1132
+
1133
+ if fname and re.match(r'^/', fname):
1134
+ if opt == 3:
1135
+ return get_url_path(fname)
1136
+ elif opt == 1 or not re.match(r'^{}/'.format(rtpath), fname):
1137
+ return fname
1138
+ fname = re.sub(r'^{}/'.format(rtpath), '', fname,1) # remove rtpath if exists
1139
+
1140
+ # find datset/group/user-defined subpath
1141
+ if 'WP' not in PgOPT.params:
1142
+ gindex = PgOPT.params['GI'][i] if 'GI' in PgOPT.params and PgOPT.params['GI'][i] else 0
1143
+ if gindex in webpaths:
1144
+ webpath = webpaths[gindex]
1145
+ else:
1146
+ webpath = PgDBI.get_group_field_path(gindex, PgOPT.params['DS'], 'webpath')
1147
+ webpaths[gindex] = webpath if webpath else ""
1148
+ elif len(PgOPT.params['WP']) == 1:
1149
+ webpath = PgOPT.params['WP'][0]
1150
+ else:
1151
+ webpath = PgOPT.params['WP'][i]
1152
+
1153
+ if webpath and re.match(r'^{}/'.format(rtpath), webpath) and opt != 1:
1154
+ webpath = re.sub(r'^{}/'.format(rtpath), '', webpath, 1) # remove rtpath if exists
1155
+
1156
+ if fname:
1157
+ if opt == 2:
1158
+ fname = PgLOG.join_paths(webpath, fname, 1) # remove webpath if exists
1159
+ else:
1160
+ if addwp: fname = PgLOG.join_paths(webpath, fname)
1161
+ if opt != 0: fname = PgLOG.join_paths(rtpath, fname)
1162
+ elif opt == 0:
1163
+ if webpath: fname = webpath
1164
+ elif opt != 2:
1165
+ if addwp: fname = PgLOG.join_paths(rtpath, webpath)
1166
+
1167
+ if opt == 3: fname = get_url_path(fname)
1168
+
1169
+ return fname
1170
+
1171
+ #
1172
+ # get help file path for given file name
1173
+ # opt = 0 - relative path to rtpath
1174
+ # 1 - absolute path
1175
+ # 2 - full url path
1176
+ #
1177
+ def get_help_path(i, fname, opt = 0, type = None, url = None, init = 0):
1178
+
1179
+ rtpath = None
1180
+ if init or not RTPATH['dsid']: cache_rtpath(PgOPT.params['DS'], init)
1181
+ if not type: type = PgOPT.params['HT'][i] if 'HT' in PgOPT.params and PgOPT.params['HT'][i] else 'D'
1182
+ rtpath = RTPATH['H' + type]
1183
+
1184
+ if fname and re.match(r'^/', fname):
1185
+ if opt == 2: return get_url_path(fname, url)
1186
+ if opt == 1 or not re.match(r'^{}/'.format(rtpath), fname): return fname
1187
+ fname = re.sub(r'^{}/'.format(rtpath), '', fname, 1) # remove rtpath if exists
1188
+
1189
+ if opt == 1:
1190
+ fname = PgLOG.join_paths(rtpath, fname)
1191
+ elif opt == 2:
1192
+ fname = get_url_path(fname, url)
1193
+
1194
+ return fname
1195
+
1196
+ #
1197
+ # get group saved file path for given file index and/or file name
1198
+ # opt = 0 - relative path to rtpath
1199
+ # 1 - absolute path
1200
+ # 2 - relative path to rtpath/savedpath
1201
+ # 4 - bit for ignore saved path
1202
+ #
1203
+ def get_saved_path(i, fname, opt = 0, type = None, init = 0):
1204
+
1205
+ addsp = 1
1206
+ rtpath = None
1207
+
1208
+ if init or not RTPATH['dsid']: cache_rtpath(PgOPT.params['DS'], init)
1209
+ if not type: type = PgOPT.params['ST'][i] if 'ST' in PgOPT.params and PgOPT.params['ST'][i] else 'P'
1210
+ rtpath = "{}/{}".format(RTPATH['SP'], type)
1211
+
1212
+ if opt > 3:
1213
+ addsp = 0
1214
+ opt -= 4
1215
+
1216
+ if fname and re.match(r'^/', fname):
1217
+ if opt == 1 or not re.match(r'^{}/'.format(rtpath), fname): return fname
1218
+ fname = re.sub(r'^{}/'.format(rtpath), '', fname, 1) # remove rtpath if exists
1219
+
1220
+ # find datset/group/user-defined subpath
1221
+ if 'SP' not in PgOPT.params:
1222
+ gindex = PgOPT.params['GI'][i] if 'GI' in PgOPT.params and PgOPT.params['GI'][i] else 0
1223
+ if gindex in savedpaths:
1224
+ savedpath = savedpaths[gindex]
1225
+ else:
1226
+ savedpath = savedpath = PgDBI.get_group_field_path(gindex, PgOPT.params['DS'], "savedpath")
1227
+ savedpaths[gindex] = savedpath if savedpath else ""
1228
+ elif len(PgOPT.params['SP']) == 1:
1229
+ savedpath = PgOPT.params['SP'][0]
1230
+ else:
1231
+ savedpath = PgOPT.params['SP'][i]
1232
+
1233
+ if savedpath and opt != 1:
1234
+ ms = re.match(r'^(({}|{})/)'.format(rtpath, type), savedpath)
1235
+ if ms: savedpath = re.sub(ms.group(1), '', savedpath, 1) # remove rtpath or leading type if exists
1236
+
1237
+ if fname:
1238
+ if opt == 2:
1239
+ fname = PgLOG.join_paths(savedpath, fname, 1) # remove savedpath if exists
1240
+ else:
1241
+ if addsp: fname = PgLOG.join_paths(savedpath, fname)
1242
+ if opt != 0: fname = PgLOG.join_paths(rtpath, fname)
1243
+ elif opt == 0:
1244
+ if savedpath: fname = savedpath
1245
+ elif opt != 2:
1246
+ if addsp: fname = PgLOG.join_paths(rtpath, savedpath)
1247
+
1248
+ return fname
1249
+
1250
+ #
1251
+ # get web file path with leading url
1252
+ #
1253
+ def get_url_path(fname, url = None):
1254
+
1255
+ if re.match(r'^{}'.format(PgLOG.PGLOG['DSSDATA']), fname):
1256
+ fname = re.sub(r'^{}'.format(PgLOG.PGLOG['DSSDATA']), '', fname) # remove DSSDATA from file name
1257
+ elif re.match(r'^{}'.format(PgLOG.PGLOG['DSSWEB']), fname):
1258
+ fname = re.sub(r'^{}'.format(PgLOG.PGLOG['DSSWEB']), '', fname) # remove DSSWEB from file name
1259
+
1260
+ if not url: url = PgLOG.PGLOG['DSSURL']
1261
+ return PgLOG.join_paths(url, fname)
1262
+ #
1263
+ # get get object path
1264
+ #
1265
+ def get_object_path(fname, dsid, hpath = None):
1266
+
1267
+ opath = "web/datasets/{}/{}".format(dsid, hpath) if hpath else dsid
1268
+
1269
+ return PgLOG.join_paths(opath, fname)
1270
+
1271
+ #
1272
+ # view file counts for given dsid/gindex
1273
+ #
1274
+ def view_filenumber(dsid, gindex, cnt = 0):
1275
+
1276
+ if cnt:
1277
+ grecs = gindex
1278
+ else:
1279
+ cnt = 1
1280
+ grecs = [gindex]
1281
+
1282
+ fields = ("dwebcnt, webcnt, cdwcnt, nwebcnt, dweb_size, nweb_size, savedcnt, saved_size")
1283
+ for i in range(cnt):
1284
+ if grecs[i] == 0:
1285
+ table = "dataset"
1286
+ cnd = "dsid = '{}'".format(dsid)
1287
+ head = dsid
1288
+ else:
1289
+ table = "dsgroup"
1290
+ cnd = "dsid = '{}' AND gindex = {}".format(dsid, grecs[i])
1291
+ head = "{}-G{}".format(dsid, grecs[i])
1292
+ pgrec = PgDBI.pgget(table, fields, cnd, PgOPT.PGOPT['extlog'])
1293
+ if pgrec:
1294
+ msg = ''
1295
+ if pgrec['webcnt']:
1296
+ if pgrec['dwebcnt']: msg += " DS-{} DC-{}".format(pgrec['dweb_size'], pgrec['dwebcnt'])
1297
+ if pgrec['cdwcnt']: msg += " CDC-{}".format(pgrec['cdwcnt'])
1298
+ if pgrec['nwebcnt']: msg += " NS-{} NC-{}".format(pgrec['nweb_size'], pgrec['nwebcnt'])
1299
+ msg += " WC-{}".format(pgrec['webcnt'])
1300
+ if pgrec['savedcnt']:
1301
+ msg += " SS-{} SC-{}".format(pgrec['saved_size'], pgrec['savedcnt'])
1302
+
1303
+ if msg: print("{}:{}".format(head, msg))
1304
+
1305
+ #
1306
+ # get quasar backup file id numbers for given backup file names
1307
+ #
1308
+ def get_bid_numbers(bfiles):
1309
+
1310
+ bids = []
1311
+ if not bfiles: return bids
1312
+ dcnd = "dsid = '{}'".format(PgOPT.params['DS'])
1313
+ chksign = 1
1314
+ for bfile in bfiles:
1315
+ if not bfile:
1316
+ bids.append(0)
1317
+ chksign = 0
1318
+ elif isinstance(bfile, int):
1319
+ bids.append(bfile)
1320
+ chksign = 0
1321
+ elif re.match(r'^\d+$', bfile):
1322
+ bids.append(int(bfile))
1323
+ chksign = 0
1324
+ elif chksign and bfile in PgDBI.PGSIGNS:
1325
+ bids.append(bfile)
1326
+ else:
1327
+ chksign = 0
1328
+ bcnd = "bfile = '{}'".format(bfile)
1329
+ pgrec = PgDBI.pgget("bfile", "bid", "{} AND {}".format(dcnd, bcnd), PgOPT.PGOPT['extlog'])
1330
+ if not pgrec: pgrec = PgDBI.pgget("bfile", "bid", bcnd, PgOPT.PGOPT['extlog'])
1331
+ if pgrec:
1332
+ bids.append(pgrec['bid'])
1333
+ else:
1334
+ bids.append(0)
1335
+
1336
+ return bids
1337
+
1338
+ #
1339
+ # build a backup filelist from given web/saved files
1340
+ #
1341
+ def build_backup_filelist():
1342
+
1343
+ dsid = PgOPT.params['DS']
1344
+ dscnd = "dsid = '{}'".format(dsid)
1345
+ if 'QF' not in PgOPT.params:
1346
+ PgOPT.params['QF'] = []
1347
+ bids = []
1348
+ else:
1349
+ bids = get_bid_numbers(PgOPT.params['QF'])
1350
+ if 'WF' in PgOPT.params:
1351
+ fcnt = len(PgOPT.params['WF'])
1352
+ if 'WT' not in PgOPT.params: PgOPT.params['WT'] = ['D']*fcnt
1353
+ for i in range(fcnt):
1354
+ type = PgOPT.params['WT'][i]
1355
+ file = get_web_path(i, PgOPT.params['WF'][i], 0, type)
1356
+ fstr = "{}: Type {} Web File of {}".format(file, type, dsid)
1357
+ typecnd = "type = '{}'".format(type)
1358
+ pgrec = PgSplit.pgget_wfile(dsid, 'bid', "{} AND wfile = '{}'".format(typecnd, file))
1359
+ if not pgrec: PgLOG.pglog(fstr + "not in RDADB", PgLOG.LGEREX)
1360
+ bid = pgrec['bid']
1361
+ if not bid: PgLOG.pglog(fstr + "not backed up", PgLOG.LGEREX)
1362
+ if file != PgOPT.params['WF'][i]: PgOPT.params['WF'][i] = file
1363
+ if bid in bids: continue
1364
+ pgrec = PgDBI.pgget('bfile', 'bfile', "bid = '{}'".format(bid))
1365
+ if not pgrec: PgLOG.pglog("{}: Backup Id {} not in RDADB".format(bid), PgLOG.LGEREX)
1366
+ bids.append(bid)
1367
+ PgOPT.params['QF'].append(pgrec['bfile'])
1368
+
1369
+ if 'SF' in PgOPT.params:
1370
+ fcnt = len(PgOPT.params['SF'])
1371
+ for i in range(fcnt):
1372
+ type = PgOPT.params['ST'][i]
1373
+ file = get_saved_path(i, PgOPT.params['SF'][i], 0, type)
1374
+ fstr = "{}: Type {} Saved File of {}".format(file, type, dsid)
1375
+ typecnd = "type = '{}'".format(type)
1376
+ pgrec = PgDBI.pgget('sfile', 'bid', "{} AND {} AND sfile = '{}'".format(dscnd, typecnd, file))
1377
+ if not pgrec: PgLOG.pglog(fstr + "not in RDADB", PgLOG.LGEREX)
1378
+ bid = pgrec['bid']
1379
+ if not bid: PgLOG.pglog(fstr + "not backed up", PgLOG.LGEREX)
1380
+ if file != PgOPT.params['SF'][i]: PgOPT.params['SF'][i] = file
1381
+ if bid in bids: continue
1382
+ pgrec = PgDBI.pgget('bfile', 'bfile', "bid = '{}'".format(bid))
1383
+ if not pgrec: PgLOG.pglog("{}: Backup Id {} not in RDADB".format(fstr, bid), PgLOG.LGEREX)
1384
+ bids.append(bid)
1385
+ PgOPT.params['QF'].append(pgrec['bfile'])
1386
+
1387
+ #
1388
+ # get Quasar backup files for given ids
1389
+ #
1390
+ def get_quasar_backfiles(bids):
1391
+
1392
+ count = len(bids) if bids else 0
1393
+
1394
+ bfiles = ['']*count
1395
+ for i in range(count):
1396
+ if not bids[i]: continue
1397
+ if not isinstance(bids[i], int):
1398
+ if not re.match(r'^\d+$', bids[i]):
1399
+ bfiles[i] = bids[i]
1400
+ continue
1401
+ pgrec = PgDBI.pgget("bfile", "bfile", "bid = {}".format(bids[i]), PgOPT.PGOPT['extlog'])
1402
+ if pgrec: bfiles[i] = pgrec['bfile']
1403
+
1404
+ return bfiles
1405
+
1406
+ #
1407
+ # get file names for reset group
1408
+ #
1409
+ def get_filenames(tname):
1410
+
1411
+ tmpgs = PgOPT.params['GI']
1412
+ PgOPT.params['GI'] = PgOPT.params['OG']
1413
+ PgLOG.pglog("Get file names of {} for reset group ...".format(PgOPT.params['DS']), PgOPT.PGOPT['wrnlog'])
1414
+ if 'GI' in PgOPT.params or 'GN' in PgOPT.params: PgOPT.validate_groups()
1415
+ if tname == 'wfile':
1416
+ pgrecs = PgSplit.pgmget_wfile(PgOPT.params['DS'], tname, get_condition(tname), PgOPT.PGOPT['extlog'])
1417
+ else:
1418
+ pgrecs = PgDBI.pgmget(tname, tname, get_condition(tname), PgOPT.PGOPT['extlog'])
1419
+ PgOPT.params['GI'] = tmpgs
1420
+
1421
+ return (pgrecs[tname] if pgrecs else None)
1422
+
1423
+ #
1424
+ # get mss/web file names with relative path
1425
+ #
1426
+ def get_relative_names(files, gindices, types, saved = 0):
1427
+
1428
+ savegi = PgOPT.params['GI'] if 'GI' in PgOPT.params else None
1429
+ count = len(files)
1430
+ PgOPT.params['GI'] = gindices
1431
+ for i in range(count):
1432
+ if saved:
1433
+ files[i] = get_saved_path(i, files[i], 2, types[i])
1434
+ else:
1435
+ files[i] = get_web_path(i, files[i], 2, types[i])
1436
+ PgOPT.params['GI'] = savegi
1437
+
1438
+ return files
1439
+
1440
+ #
1441
+ # reorder filelist
1442
+ #
1443
+ def reorder_filelist(table):
1444
+
1445
+ cnt = reorder_files(PgOPT.params['DS'], PgOPT.params['ON'], table)
1446
+ if cnt > 0: PgDBI.reset_rdadb_version(PgOPT.params['DS'])
1447
+
1448
+ #
1449
+ # get public group type
1450
+ #
1451
+ def get_public_gtype(types, ptype, ptype2 = None):
1452
+
1453
+ if not types: return None
1454
+
1455
+ for type in types:
1456
+ if type != ptype and not (ptype2 and type == ptype2): return None
1457
+
1458
+ return 'P'
1459
+
1460
+ #
1461
+ # get the data/doc/sofeware directory for given dataset id
1462
+ #
1463
+ def cache_rtpath(dsid, force = 0):
1464
+
1465
+ if not force and RTPATH['dsid'] and RTPATH['dsid'] == dsid: return
1466
+
1467
+ RTPATH['dsid'] = dsid
1468
+ RTPATH['D'] = "{}/{}".format(PgLOG.PGLOG['DSDHOME'], dsid)
1469
+ RTPATH['A'] = RTPATH['N'] = RTPATH['I'] = RTPATH['U'] = RTPATH['D']
1470
+ RTPATH['H'] = "{}/{}".format(PgLOG.PGLOG['DSHHOME'], dsid)
1471
+ RTPATH['HD'] = RTPATH['O'] = "{}/{}".format(RTPATH['H'], PgOPT.HPATH['D'])
1472
+ RTPATH['HS'] = RTPATH['S'] = "{}/{}".format(RTPATH['H'], PgOPT.HPATH['S'])
1473
+ RTPATH['SP'] = "{}/{}".format(PgLOG.PGLOG['DECSHOME'], dsid)
1474
+
1475
+ #
1476
+ # gather file list for deleting
1477
+ #
1478
+ def gather_delete_files():
1479
+
1480
+ pgrecs = None
1481
+ if 'ST' in PgOPT.params:
1482
+ if 'RG' in PgOPT.params: get_subgroups("GS")
1483
+ pgrecs = PgDBI.pgmget("sfile", "sfile SF, gindex GI, type ST", get_condition('sfile', "IT"))
1484
+ elif 'WT' in PgOPT.params:
1485
+ if 'RG' in PgOPT.params: get_subgroups("GW")
1486
+ pgrecs = PgSplit.pgmget_wfile(PgOPT.params['DS'], "wfile WF, gindex GI, type WT", get_condition('wfile', "IT"))
1487
+
1488
+ if not pgrecs: PgLOG.pglog("No file to delete for given condition", PgOPT.PGOPT['extlog'])
1489
+
1490
+ for opt in pgrecs:
1491
+ PgOPT.params[opt.upper()] = pgrecs[opt]
1492
+
1493
+ #
1494
+ # gather subgroups
1495
+ #
1496
+ def get_subgroups(cact):
1497
+
1498
+ gindices = []
1499
+ dcnd = "dsid = '{}'".format(PgOPT.params['DS'])
1500
+ gtype = None
1501
+ if cact == "GG":
1502
+ if 'GT' in PgOPT.params: gtype = get_public_gtype(PgOPT.params['GT'], 'P')
1503
+ for gidx in PgOPT.params['GI']:
1504
+ subs = PgOPT.get_all_subgroups(dcnd, gidx, gtype)
1505
+ gindices.extend(subs)
1506
+ else:
1507
+ if cact == "GS":
1508
+ cfld = "savedcnt"
1509
+ elif cact == 'GW':
1510
+ cfld = 'webcnt'
1511
+ if 'WT' in PgOPT.params:
1512
+ if get_public_gtype(PgOPT.params['WT'], 'D'):
1513
+ cfld = "dwebcnt"
1514
+ elif get_public_gtype(PgOPT.params['WT'], 'N'):
1515
+ cfld = "nwebcnt"
1516
+ for gidx in PgOPT.params['GI']:
1517
+ subs = PgOPT.get_data_subgroups(dcnd, gidx, cfld)
1518
+ if subs: gindices.extend(subs)
1519
+
1520
+ if gindices: PgOPT.params['GI'] = gindices
1521
+
1522
+ #
1523
+ # clean empty directories for given dataset and groups
1524
+ #
1525
+ def clean_dataset_directory(saved):
1526
+
1527
+ cnt = len(PgOPT.params['GI']) if 'GI' in PgOPT.params else 1
1528
+
1529
+ types = ()
1530
+ if saved:
1531
+ if 'ST' in PgLOG.params: types = set(PgLOG.params['ST'])
1532
+ else:
1533
+ if 'WT' in PgLOG.params: types = set(PgLOG.params['WT'])
1534
+
1535
+ if types:
1536
+ cdirs = ()
1537
+ for i in range(cnt):
1538
+ if i > 0 and PgOPT.params['GI'][i] == PgOPT.params['GI'][i-1]: continue
1539
+ for type in types:
1540
+ if saved:
1541
+ cdirs.add(get_saved_path(i, None, 1, type))
1542
+ else:
1543
+ cdirs.add(get_web_path(i, None, 1, type))
1544
+ for cdir in cdirs:
1545
+ PgFile.clean_empty_directory(cdir, PgLOG.PGLOG['GPFSHOST'])
1546
+
1547
+ #
1548
+ # validate given version indices
1549
+ #
1550
+ def validate_versions():
1551
+
1552
+ if PgOPT.OPTS['VI'][2]&8 == 8: return # already validated
1553
+
1554
+ PgOPT.OPTS['VI'][2] |= 8 # set validated flag
1555
+ vcnt = len(PgOPT.params['VI']) if 'VI' in PgOPT.params else 0
1556
+ if not vcnt:
1557
+ if PgOPT.PGOPT['CACT'] == 'SV':
1558
+ if 'NV' not in PgOPT.params: PgOPT.action_error("Add Mode option -NV for new version control record")
1559
+ PgOPT.params['VI'] = [0]
1560
+ return
1561
+
1562
+ for i in range(vcnt):
1563
+ val = PgOPT.params['VI'][i]
1564
+ if not val:
1565
+ if 'NV' not in PgOPT.params:
1566
+ PgOPT.action_error("Mode option -NV must be present to add new version control record")
1567
+ continue
1568
+
1569
+ if i and val == PgOPT.params['VI'][i-1]: continue
1570
+ pgrec = PgDBI.pgget("dsvrsn", "dsid", "vindex = {}".format(val), PgOPT.PGOPT['extlog'])
1571
+ if not pgrec:
1572
+ PgOPT.action_error("Version Control Index val is not in RDADB")
1573
+ elif pgrec['dsid'] != PgOPT.params['DS']:
1574
+ PgOPT.action_error("Version Control Index {} is for {}".format(val, pgrec['dsid']))
1575
+
1576
+ #
1577
+ # validate local files for getting MD5 checksum
1578
+ #
1579
+ def validate_md5_checksum(allcnt):
1580
+
1581
+ if 'SC' in PgOPT.params and PgOPT.params['MC']:
1582
+ del PgOPT.params['SC']
1583
+ elif 'MC' not in PgOPT.params:
1584
+ PgOPT.params['MC'] = ['']*allcnt # create place hold for MD5 cehcksum
1585
+ i = 0
1586
+ if 'LF' in PgOPT.params:
1587
+ while i < allcnt:
1588
+ if not op.exists(PgOPT.params['LF'][i]): break
1589
+ i += 1
1590
+ else:
1591
+ i = 0
1592
+ if i >= allcnt:
1593
+ PgOPT.OPTS['MC'][2] |= 16
1594
+ if 'SC' not in PgOPT.params: PgOPT.params['SC'] = 1
1595
+ else:
1596
+ if 'SC' in PgOPT.params:
1597
+ s = 's' if allcnt > 1 else ''
1598
+ PgLOG.pglog("Cannot locate local files for md5 checksums!", PgOPT.PGOPT['emlerr'])
1599
+ del PgOPT.params['SC']
1600
+ if 'MC' in PgOPT.params: del PgOPT.params['MC']
1601
+
1602
+ #
1603
+ # append moving info to bfile.note
1604
+ #
1605
+ def save_move_info(bid, ffile, ftype, fftype, fdsid, tfile, ttype, tftype, tdsid):
1606
+
1607
+ bcnd = "bid = {}".format(bid)
1608
+ flds = 'note'
1609
+ if fftype != tftype: flds += ', scount, wcount'
1610
+ pgrec = PgDBI.pgget('bfile', flds, bcnd, PgLOG.LGEREX)
1611
+ if not pgrec: return 0
1612
+
1613
+ sftype = ('Web' if fftype == 'W' else 'Saved')
1614
+ note = ">MV {} Type {} {} File {} To".format(fdsid, ftype, sftype, ffile)
1615
+ if tdsid != fdsid: note += ' ' + tdsid
1616
+ if ttype != ftype: note += ' Type ' + ttype
1617
+ if tftype != fftype: note += (' Web' if tftype == 'W' else ' Saved')
1618
+ note += ' File'
1619
+ if tfile != ffile: note += ' ' + tfile
1620
+ note += '\n'
1621
+ if pgrec['note']:
1622
+ if pgrec['note'][-1] != '\n': pgrec['note'] += "\n"
1623
+ pgrec['note'] += note
1624
+ else:
1625
+ pgrec['note'] = note
1626
+ if fftype == 'W' and tftype == 'S':
1627
+ pgrec['scount'] += 1
1628
+ pgrec['wcount'] -= 1
1629
+ elif fftype == 'S' and tftype == 'W':
1630
+ pgrec['scount'] -= 1
1631
+ pgrec['wcount'] += 1
1632
+
1633
+ return PgDBI.pgupdt('bfile', pgrec, bcnd, PgLOG.LGEREX)
1634
+
1635
+ #
1636
+ # set dataset location flag
1637
+ #
1638
+ def set_dataset_locflag(dsid, locflag):
1639
+
1640
+ dscnd = "dsid = '{}'".format(dsid)
1641
+ if PgDBI.pgget('dataset', '', "{} AND locflag = '{}'".format(dscnd, locflag)): return
1642
+ cnd = "type = 'D' AND status = 'P' AND locflag <> '{}'".format(locflag)
1643
+ if PgDBI.pgget_wfile(dsid, '', cnd): return
1644
+
1645
+ PgDBI.pgexec("UPDATE dataset SET locflag = '{}' WHERE {}".format(locflag, dscnd))
1646
+
1647
+ #
1648
+ # get dataset location flag
1649
+ #
1650
+ def get_dataset_locflag(dsid):
1651
+
1652
+ dscnd = "dsid = '{}'".format(dsid)
1653
+ pgrec = PgDBI.pgget('dataset', 'locflag', dscnd)
1654
+
1655
+ return pgrec['locflag'] if pgrec else 'G'