rda-python-dsarch 3.0.17__py3-none-any.whl → 3.0.19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rda_python_dsarch/dsarch.py +648 -285
- rda_python_dsarch/dsarch.usg +18 -5
- rda_python_dsarch/pg_arch.py +53 -3
- {rda_python_dsarch-3.0.17.dist-info → rda_python_dsarch-3.0.19.dist-info}/METADATA +2 -2
- rda_python_dsarch-3.0.19.dist-info/RECORD +14 -0
- rda_python_dsarch-3.0.17.dist-info/RECORD +0 -14
- {rda_python_dsarch-3.0.17.dist-info → rda_python_dsarch-3.0.19.dist-info}/WHEEL +0 -0
- {rda_python_dsarch-3.0.17.dist-info → rda_python_dsarch-3.0.19.dist-info}/entry_points.txt +0 -0
- {rda_python_dsarch-3.0.17.dist-info → rda_python_dsarch-3.0.19.dist-info}/licenses/LICENSE +0 -0
- {rda_python_dsarch-3.0.17.dist-info → rda_python_dsarch-3.0.19.dist-info}/top_level.txt +0 -0
rda_python_dsarch/dsarch.py
CHANGED
|
@@ -58,6 +58,8 @@ class DsArch(PgArch, PgMeta):
|
|
|
58
58
|
self.BCKNOTES = {}
|
|
59
59
|
self.VINDEX = {}
|
|
60
60
|
self.CHGGRPS = {}
|
|
61
|
+
self.CPFILES = {} # file index -> copy/move child pname (or 1/0) of an -AL first pass
|
|
62
|
+
self.CPDIRS = {} # file index -> cross copy direction ('G','O','B','D') of an -AL first pass
|
|
61
63
|
self.ERRMSG = ''
|
|
62
64
|
|
|
63
65
|
def read_parameters(self):
|
|
@@ -115,34 +117,33 @@ class DsArch(PgArch, PgMeta):
|
|
|
115
117
|
if self.PGOPT['ACTS'] == self.OPTS['AH'][0]:
|
|
116
118
|
self.ALLCNT = len(self.params['HF']) if 'HF' in self.params else len(self.params['LF'])
|
|
117
119
|
if 'XC' in self.params:
|
|
118
|
-
self.crosscopy_help_files
|
|
120
|
+
self.archive_in_passes(self.crosscopy_help_files, 'Copy')
|
|
119
121
|
elif 'XM' in self.params:
|
|
120
|
-
self.crosscopy_help_files
|
|
122
|
+
self.archive_in_passes(self.crosscopy_help_files, 'Move')
|
|
121
123
|
else:
|
|
122
|
-
self.archive_help_files
|
|
124
|
+
self.archive_in_passes(self.archive_help_files)
|
|
123
125
|
if 'CL' in self.params: self.delete_local_files()
|
|
124
126
|
elif self.PGOPT['ACTS'] == self.OPTS['AQ'][0]:
|
|
125
127
|
if 'XC' in self.params:
|
|
126
128
|
self.ALLCNT = len(self.params['QF'])
|
|
127
|
-
self.crosscopy_backup_files
|
|
129
|
+
self.archive_in_passes(self.crosscopy_backup_files)
|
|
128
130
|
else:
|
|
129
131
|
self.archive_backup_file()
|
|
130
132
|
elif self.PGOPT['ACTS'] == self.OPTS['AS'][0]:
|
|
131
133
|
self.ALLCNT = len(self.params['SF']) if 'SF' in self.params else len(self.params['LF'])
|
|
132
134
|
self.cache_group_info(self.ALLCNT)
|
|
133
|
-
self.archive_saved_files
|
|
135
|
+
self.archive_in_passes(self.archive_saved_files)
|
|
134
136
|
if 'CL' in self.params: self.delete_local_files()
|
|
135
137
|
elif self.PGOPT['ACTS'] == self.OPTS['AW'][0]:
|
|
136
138
|
self.ALLCNT = len(self.params['WF']) if 'WF' in self.params else len(self.params['LF'])
|
|
137
139
|
if 'ML' in self.params and 'GX' in self.params: del self.params['ML']
|
|
138
140
|
self.cache_group_info(self.ALLCNT)
|
|
139
141
|
if 'XC' in self.params:
|
|
140
|
-
self.crosscopy_web_files
|
|
142
|
+
self.archive_in_passes(self.crosscopy_web_files, 'Copy')
|
|
141
143
|
elif 'XM' in self.params:
|
|
142
|
-
self.crosscopy_web_files
|
|
144
|
+
self.archive_in_passes(self.crosscopy_web_files, 'Move')
|
|
143
145
|
else:
|
|
144
|
-
self.archive_web_files
|
|
145
|
-
if self.PGSIG['BPROC'] > 1: self.set_webfile_info()
|
|
146
|
+
self.archive_in_passes(self.archive_web_files)
|
|
146
147
|
if 'CL' in self.params: self.delete_local_files()
|
|
147
148
|
elif self.PGOPT['ACTS'] & self.OPTS['CG'][0]:
|
|
148
149
|
self.ALLCNT = len(self.params['GI'])
|
|
@@ -206,17 +207,17 @@ class DsArch(PgArch, PgMeta):
|
|
|
206
207
|
(len(self.params['QF']) if 'QF' in self.params else 0))))
|
|
207
208
|
if 'DD' in self.params: self.record_delete_directory(None, self.params['DD'])
|
|
208
209
|
if 'HF' in self.params:
|
|
209
|
-
self.move_help_files
|
|
210
|
+
self.archive_in_passes(self.move_help_files)
|
|
210
211
|
elif 'TS' in self.params:
|
|
211
|
-
self.web_to_saved_files
|
|
212
|
+
self.archive_in_passes(self.web_to_saved_files)
|
|
212
213
|
elif 'TW' in self.params:
|
|
213
|
-
self.saved_to_web_files
|
|
214
|
+
self.archive_in_passes(self.saved_to_web_files)
|
|
214
215
|
elif 'SF' in self.params:
|
|
215
|
-
self.move_saved_files
|
|
216
|
+
self.archive_in_passes(self.move_saved_files)
|
|
216
217
|
elif 'WF' in self.params:
|
|
217
|
-
self.move_web_files
|
|
218
|
+
self.archive_in_passes(self.move_web_files)
|
|
218
219
|
else:
|
|
219
|
-
self.move_backup_files
|
|
220
|
+
self.archive_in_passes(self.move_backup_files)
|
|
220
221
|
if 'DD' in self.params: self.clean_delete_directory(self.PGOPT['wrnlog'])
|
|
221
222
|
elif self.PGOPT['ACTS'] == self.OPTS['RQ'][0]:
|
|
222
223
|
if 'WF' in self.params or 'SF' in self.params:
|
|
@@ -355,7 +356,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
355
356
|
else:
|
|
356
357
|
self.cmdlog()
|
|
357
358
|
|
|
358
|
-
def archive_web_files(self):
|
|
359
|
+
def archive_web_files(self, cpass=0):
|
|
359
360
|
"""
|
|
360
361
|
Archive local files as web files on GLADE and/or the object store.
|
|
361
362
|
|
|
@@ -369,6 +370,11 @@ class DsArch(PgArch, PgMeta):
|
|
|
369
370
|
|
|
370
371
|
Retries the whole batch if transient errors occur, stopping when the
|
|
371
372
|
error count stabilises. Sets self.RETSTAT on unresolved failures.
|
|
373
|
+
|
|
374
|
+
Args:
|
|
375
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
376
|
+
copy pass (copies in up to N child processes, no records) and then 2
|
|
377
|
+
for the record pass (see archive_in_passes())
|
|
372
378
|
"""
|
|
373
379
|
tname = 'wfile'
|
|
374
380
|
dftloc = None
|
|
@@ -379,7 +385,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
379
385
|
dslocflags = set()
|
|
380
386
|
dflags = {}
|
|
381
387
|
self.pglog("Archive {} Web file{} of {} ...".format(self.ALLCNT, s, dsid), self.WARNLG)
|
|
382
|
-
if 'ZD' in self.params or 'UZ' in self.params:
|
|
388
|
+
if cpass != 2 and ('ZD' in self.params or 'UZ' in self.params):
|
|
383
389
|
self.compress_localfile_list(self.PGOPT['CACT'], self.ALLCNT)
|
|
384
390
|
if 'QF' in self.params: self.params['QF'] = self.get_bid_numbers(self.params['QF'])
|
|
385
391
|
self.validate_multiple_values(tname, self.ALLCNT)
|
|
@@ -406,19 +412,15 @@ class DsArch(PgArch, PgMeta):
|
|
|
406
412
|
self.params['SZ'] = [0]*self.ALLCNT
|
|
407
413
|
self.OPTS['SZ'][2] |= 2
|
|
408
414
|
if 'MC' not in self.params: self.params['MC'] = [None]*self.ALLCNT
|
|
409
|
-
reorder = errcnt = metatotal = metacnt = self.ADDCNT = self.MODCNT =
|
|
415
|
+
reorder = errcnt = metatotal = metacnt = self.ADDCNT = self.MODCNT = acnt = ocnt = 0
|
|
410
416
|
perrcnt = self.ALLCNT
|
|
411
417
|
efiles = [1]*self.ALLCNT
|
|
412
|
-
if self.PGSIG['BPROC'] > 1:
|
|
413
|
-
afiles = [None]*self.ALLCNT
|
|
414
|
-
lfiles = [None]*self.ALLCNT
|
|
415
|
-
ofiles = [None]*self.ALLCNT
|
|
416
418
|
fnames = None
|
|
417
419
|
override = self.OVERRIDE
|
|
418
420
|
if not override and 'GF' in self.params: override = self.OVRIDE
|
|
419
421
|
while True:
|
|
420
422
|
for i in range(bidx, self.ALLCNT):
|
|
421
|
-
if
|
|
423
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
422
424
|
if metacnt >= self.PGOPT['RSMAX']:
|
|
423
425
|
metatotal += self.process_metadata("W", metacnt, self.PGOPT['emerol'])
|
|
424
426
|
metacnt = 0
|
|
@@ -470,14 +472,20 @@ class DsArch(PgArch, PgMeta):
|
|
|
470
472
|
if warch and locfile == afile: warch = 0
|
|
471
473
|
vsnctl = 1 if pgrec and pgrec['vindex'] and pgrec['data_size'] else 0
|
|
472
474
|
chksum = self.params['MC'][i]
|
|
475
|
+
gdone = odone = 0
|
|
476
|
+
if cpass == 2 and i in self.CPFILES: # copied in the -AL copy pass; recopy only what failed
|
|
477
|
+
(gdone, odone) = self.check_pass_copies(i, wfile, afile if warch else None, ofile if oarch else None, bucket, lsize)
|
|
478
|
+
if gdone: warch = 0; acnt += 1
|
|
479
|
+
if odone: oarch = 0; ocnt += 1
|
|
480
|
+
if self.PGLOG['DSCHECK'] and (gdone or odone) and not (warch or oarch): chksize += lsize
|
|
473
481
|
if warch and (vsnctl or not override):
|
|
474
482
|
info = self.check_local_file(afile, 1, self.PGOPT['emerol']|self.PFSIZE)
|
|
475
483
|
if info:
|
|
476
484
|
if pgrec and chksum and pgrec['checksum'] and pgrec['checksum'] == chksum:
|
|
477
|
-
self.pglog("Web-{}: Same-Checksum ARCHIVED at {}:{}".format(winfo, info['date_modified'], info['time_modified']), self.PGOPT['emllog'])
|
|
485
|
+
self.pglog("Web-{}: Same-Checksum ARCHIVED at {}:{}".format(winfo, info['date_modified'], info['time_modified']), (0 if cpass == 1 else self.PGOPT['emllog']))
|
|
478
486
|
warch = 0
|
|
479
487
|
elif not override and info['data_size'] == lsize:
|
|
480
|
-
self.pglog("Web-{}: Same-Size ARCHIVED at {}:{}".format(winfo, info['date_modified'], info['time_modified']), self.PGOPT['wrnlog'])
|
|
488
|
+
self.pglog("Web-{}: Same-Size ARCHIVED at {}:{}".format(winfo, info['date_modified'], info['time_modified']), (0 if cpass == 1 else self.PGOPT['wrnlog']))
|
|
481
489
|
warch = 0
|
|
482
490
|
elif vsnctl and not override:
|
|
483
491
|
self.pglog("Web-{}: Cannot rearchive version controlled file".format(winfo), self.PGOPT['extlog'])
|
|
@@ -493,10 +501,10 @@ class DsArch(PgArch, PgMeta):
|
|
|
493
501
|
info = self.check_object_file(ofile, bucket, 1, self.PGOPT['emerol'])
|
|
494
502
|
if info:
|
|
495
503
|
if pgrec and chksum and pgrec['checksum'] and pgrec['checksum'] == chksum:
|
|
496
|
-
self.pglog("Object-{}-{}: Same-Checksum ARCHIVED at {}:{}".format(bucket, ofile, info['date_modified'], info['time_modified']), self.PGOPT['emllog'])
|
|
504
|
+
self.pglog("Object-{}-{}: Same-Checksum ARCHIVED at {}:{}".format(bucket, ofile, info['date_modified'], info['time_modified']), (0 if cpass == 1 else self.PGOPT['emllog']))
|
|
497
505
|
oarch = 0
|
|
498
506
|
elif not override and info['data_size'] == lsize:
|
|
499
|
-
self.pglog("Object-{}-{}: Same-Size ARCHIVED at {}:{}".format(bucket, ofile, info['date_modified'], info['time_modified']), self.PGOPT['wrnlog'])
|
|
507
|
+
self.pglog("Object-{}-{}: Same-Size ARCHIVED at {}:{}".format(bucket, ofile, info['date_modified'], info['time_modified']), (0 if cpass == 1 else self.PGOPT['wrnlog']))
|
|
500
508
|
oarch = 0
|
|
501
509
|
elif vsnctl and not override:
|
|
502
510
|
self.pglog("Object-{}-{}: Cannot rearchive version controlled file".format(bucket, ofile), self.PGOPT['extlog'])
|
|
@@ -510,6 +518,10 @@ class DsArch(PgArch, PgMeta):
|
|
|
510
518
|
dflags['O'] = bucket
|
|
511
519
|
continue
|
|
512
520
|
if (warch + oarch) > 0:
|
|
521
|
+
if cpass == 1: # -AL copy pass: copy in a child process; the record pass sets the record
|
|
522
|
+
self.run_copy(i, self.copy_archive_file, afile if warch else None, ofile if oarch else None,
|
|
523
|
+
lfile, bucket, (replace if oarch else 0), self.PGOPT['emerol']|override)
|
|
524
|
+
continue
|
|
513
525
|
if warch:
|
|
514
526
|
if not self.local_copy_local(afile, lfile, self.PGOPT['emerol']|override):
|
|
515
527
|
errcnt += 1
|
|
@@ -526,40 +538,41 @@ class DsArch(PgArch, PgMeta):
|
|
|
526
538
|
continue
|
|
527
539
|
ocnt += 1
|
|
528
540
|
if self.PGLOG['DSCHECK']: chksize += lsize
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
if
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
self.
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
if gindex != pgrec['gindex'] and (gindex or (self.OPTS['GI'][2]&2) == 0):
|
|
558
|
-
metacnt += self.record_meta_summary('W', dsid, gindex, pgrec['gindex'])
|
|
559
|
-
if errcnt == 0 or errcnt >= perrcnt or self.PGLOG['DSCHECK']: break
|
|
541
|
+
if cpass == 1: continue # the record pass sets the record, also for a file not copied
|
|
542
|
+
if gdone: warch = 1 # as if copied in this pass, for the file info below
|
|
543
|
+
if odone: oarch = 1
|
|
544
|
+
if not fnames: fnames = self.get_field_keys(tname, None, "G") # get setting fields if not yet
|
|
545
|
+
info = None
|
|
546
|
+
if afile: # also when already in place, so a directory gets its real total size
|
|
547
|
+
info = self.check_local_file(afile, 1, self.PGOPT['emerol']|self.PFSIZE)
|
|
548
|
+
elif oarch:
|
|
549
|
+
info = self.check_object_file(ofile, bucket, 1, self.PGOPT['emerol'])
|
|
550
|
+
elif pgrec:
|
|
551
|
+
info = self.get_file_origin_info(wfile, pgrec)
|
|
552
|
+
elif locflag == 'O':
|
|
553
|
+
info = self.check_object_file(ofile, bucket, 1, self.PGOPT['emerol'])
|
|
554
|
+
wid = self.set_one_webfile(i, pgrec, wfile, fnames, type, info)
|
|
555
|
+
if not wid:
|
|
556
|
+
self.params['LF'][i] = self.params['WF'][i] = None
|
|
557
|
+
continue
|
|
558
|
+
if 'GX' in self.params and self.PGOPT['GXTYP'].find(type) > -1:
|
|
559
|
+
metacnt += self.record_meta_gather('W', dsid, wfile, self.params['DF'][i])
|
|
560
|
+
self.cache_meta_tindex(dsid, wid, 'W')
|
|
561
|
+
if pgrec and pgrec['meta_link'] and pgrec['meta_link'] != 'N':
|
|
562
|
+
if 'DX' in self.params or self.PGOPT['GXTYP'].find(type) < 0 and self.PGOPT['GXTYP'].find(pgrec['type']) > -1:
|
|
563
|
+
metacnt += self.record_meta_delete('W', dsid, wfile)
|
|
564
|
+
elif 'GI' in self.params:
|
|
565
|
+
gindex = self.params['GI'][i]
|
|
566
|
+
if gindex != pgrec['gindex'] and (gindex or (self.OPTS['GI'][2]&2) == 0):
|
|
567
|
+
metacnt += self.record_meta_summary('W', dsid, gindex, pgrec['gindex'])
|
|
568
|
+
if cpass == 1 or errcnt == 0 or errcnt >= perrcnt or self.PGLOG['DSCHECK']: break
|
|
560
569
|
perrcnt = errcnt
|
|
561
|
-
self.pglog("Rearchive failed {}/{} Web file{} for {}".format(errcnt, self.ALLCNT
|
|
570
|
+
self.pglog("Rearchive failed {}/{} Web file{} for {}".format(errcnt, self.ALLCNT, s, dsid), self.PGOPT['emllog'])
|
|
562
571
|
errcnt = self.reset_errmsg(0)
|
|
572
|
+
if cpass == 1: # the record pass checks the copies, retries failed ones and sets the records
|
|
573
|
+
self.wait_copy_children()
|
|
574
|
+
self.reset_errmsg(0) # the record pass finds and counts any error again
|
|
575
|
+
return
|
|
563
576
|
if errcnt:
|
|
564
577
|
if 'CL' in self.params: del self.params['CL']
|
|
565
578
|
self.RETSTAT = self.reset_errmsg(errcnt)
|
|
@@ -567,13 +580,6 @@ class DsArch(PgArch, PgMeta):
|
|
|
567
580
|
if efiles[i]: self.params['WF'][i] = ''
|
|
568
581
|
if self.PGLOG['DSCHECK']:
|
|
569
582
|
self.check_storage_dflags(dflags, self.PGLOG['DSCHECK'], self.PGOPT['emerol'])
|
|
570
|
-
if bgcnt:
|
|
571
|
-
self.check_background(None, 0, self.LOGWRN, 1)
|
|
572
|
-
for i in range(self.ALLCNT):
|
|
573
|
-
if afiles[i]:
|
|
574
|
-
self.validate_gladearch(afiles[i], lfiles[i], i)
|
|
575
|
-
if ofiles[i]:
|
|
576
|
-
self.validate_objectarch(ofiles[i], lfiles[i], bucket, i)
|
|
577
583
|
if acnt > 0:
|
|
578
584
|
self.pglog("{} of {} Web file{} archived for {}".format(acnt, self.ALLCNT, s, self.params['DS']), self.PGOPT['emllog'])
|
|
579
585
|
if ocnt > 0:
|
|
@@ -590,7 +596,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
590
596
|
if 'EM' in self.params: self.PGLOG['PRGMSG'] = ""
|
|
591
597
|
if dslocflags: self.set_dataset_locflag(dsid, dslocflags.pop())
|
|
592
598
|
|
|
593
|
-
def archive_help_files(self):
|
|
599
|
+
def archive_help_files(self, cpass=0):
|
|
594
600
|
"""
|
|
595
601
|
Archive local files as dataset help/documentation files on GLADE/object store.
|
|
596
602
|
|
|
@@ -598,6 +604,11 @@ class DsArch(PgArch, PgMeta):
|
|
|
598
604
|
file path (RTPATH['H<type>']) and registering records in the hfile table.
|
|
599
605
|
Handles both GLADE (warch) and object-store (oarch) destinations based on
|
|
600
606
|
the file's location flag. Sets self.RETSTAT on unresolved failures.
|
|
607
|
+
|
|
608
|
+
Args:
|
|
609
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
610
|
+
copy pass (copies in up to N child processes, no records) and then 2
|
|
611
|
+
for the record pass (see archive_in_passes())
|
|
601
612
|
"""
|
|
602
613
|
tname = 'hfile'
|
|
603
614
|
dsid = self.params['DS']
|
|
@@ -631,18 +642,14 @@ class DsArch(PgArch, PgMeta):
|
|
|
631
642
|
self.params['SZ'] = [0]*self.ALLCNT
|
|
632
643
|
self.OPTS['SZ'][2] |= 2
|
|
633
644
|
if 'MC' not in self.params: self.params['MC'] = [None]*self.ALLCNT
|
|
634
|
-
reorder = errcnt = self.ADDCNT = self.MODCNT =
|
|
645
|
+
reorder = errcnt = self.ADDCNT = self.MODCNT = acnt = ocnt = 0
|
|
635
646
|
perrcnt = self.ALLCNT
|
|
636
647
|
efiles = [1]*self.ALLCNT
|
|
637
|
-
if self.PGSIG['BPROC'] > 1:
|
|
638
|
-
afiles = [None]*self.ALLCNT
|
|
639
|
-
lfiles = [None]*self.ALLCNT
|
|
640
|
-
ofiles = [None]*self.ALLCNT
|
|
641
648
|
override = self.OVERRIDE
|
|
642
649
|
fnames = None
|
|
643
650
|
while True:
|
|
644
651
|
for i in range(bidx, self.ALLCNT):
|
|
645
|
-
if
|
|
652
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
646
653
|
if self.PGLOG['DSCHECK']:
|
|
647
654
|
self.set_dscheck_dcount(i, chksize, self.PGOPT['extlog'])
|
|
648
655
|
if 'EM' in self.params:
|
|
@@ -694,14 +701,20 @@ class DsArch(PgArch, PgMeta):
|
|
|
694
701
|
self.pglog("{}: Archive Help file from {} ...".format(hfile, locfile), self.WARNLG)
|
|
695
702
|
if harch and locfile == afile: harch = 0
|
|
696
703
|
chksum = self.params['MC'][i]
|
|
704
|
+
gdone = odone = 0
|
|
705
|
+
if cpass == 2 and i in self.CPFILES: # copied in the -AL copy pass; recopy only what failed
|
|
706
|
+
(gdone, odone) = self.check_pass_copies(i, hfile, afile if harch else None, ofile if oarch else None, bucket, lsize)
|
|
707
|
+
if gdone: harch = 0; acnt += 1
|
|
708
|
+
if odone: oarch = 0; ocnt += 1
|
|
709
|
+
if self.PGLOG['DSCHECK'] and (gdone or odone) and not (harch or oarch): chksize += lsize
|
|
697
710
|
if harch and not self.OVERRIDE:
|
|
698
711
|
info = self.check_local_file(afile, 1, self.PGOPT['emerol']|self.PFSIZE)
|
|
699
712
|
if info:
|
|
700
713
|
if pgrec and chksum and pgrec['checksum'] and pgrec['checksum'] == chksum:
|
|
701
|
-
self.pglog("Help-{}: Same-Checksum ARCHIVED at {}:{}".format(hinfo, info['date_modified'], info['time_modified']), self.PGOPT['emllog'])
|
|
714
|
+
self.pglog("Help-{}: Same-Checksum ARCHIVED at {}:{}".format(hinfo, info['date_modified'], info['time_modified']), (0 if cpass == 1 else self.PGOPT['emllog']))
|
|
702
715
|
harch = 0
|
|
703
716
|
elif info['data_size'] == lsize:
|
|
704
|
-
self.pglog("Help-{}: Same-Size ARCHIVED at {}:{}".format(hinfo, info['date_modified'], info['time_modified']), self.PGOPT['wrnlog'])
|
|
717
|
+
self.pglog("Help-{}: Same-Size ARCHIVED at {}:{}".format(hinfo, info['date_modified'], info['time_modified']), (0 if cpass == 1 else self.PGOPT['wrnlog']))
|
|
705
718
|
harch = 0
|
|
706
719
|
elif info is not None:
|
|
707
720
|
errcnt += 1
|
|
@@ -712,10 +725,10 @@ class DsArch(PgArch, PgMeta):
|
|
|
712
725
|
info = self.check_object_file(ofile, bucket, 1, self.PGOPT['emerol'])
|
|
713
726
|
if info:
|
|
714
727
|
if pgrec and chksum and pgrec['checksum'] and pgrec['checksum'] == chksum:
|
|
715
|
-
self.pglog("Object-{}-{}: Same-Checksum ARCHIVED at {}:{}".format(bucket, ofile, info['date_modified'], info['time_modified']), self.PGOPT['emllog'])
|
|
728
|
+
self.pglog("Object-{}-{}: Same-Checksum ARCHIVED at {}:{}".format(bucket, ofile, info['date_modified'], info['time_modified']), (0 if cpass == 1 else self.PGOPT['emllog']))
|
|
716
729
|
oarch = 0
|
|
717
730
|
elif not override and info['data_size'] == lsize:
|
|
718
|
-
self.pglog("Object-{}-{}: Same-Size ARCHIVED at {}:{}".format(bucket, ofile, info['date_modified'], info['time_modified']), self.PGOPT['wrnlog'])
|
|
731
|
+
self.pglog("Object-{}-{}: Same-Size ARCHIVED at {}:{}".format(bucket, ofile, info['date_modified'], info['time_modified']), (0 if cpass == 1 else self.PGOPT['wrnlog']))
|
|
719
732
|
oarch = 0
|
|
720
733
|
else:
|
|
721
734
|
replace = 1
|
|
@@ -725,6 +738,10 @@ class DsArch(PgArch, PgMeta):
|
|
|
725
738
|
dflags['O'] = bucket
|
|
726
739
|
continue
|
|
727
740
|
if (harch + oarch) > 0:
|
|
741
|
+
if cpass == 1: # -AL copy pass: copy in a child process; the record pass sets the record
|
|
742
|
+
self.run_copy(i, self.copy_archive_file, afile if harch else None, ofile if oarch else None,
|
|
743
|
+
lfile, bucket, (replace if oarch else 0), self.PGOPT['emerol']|override)
|
|
744
|
+
continue
|
|
728
745
|
if harch:
|
|
729
746
|
if not self.local_copy_local(afile, lfile, self.PGOPT['emerol']|override):
|
|
730
747
|
errcnt += 1
|
|
@@ -740,30 +757,31 @@ class DsArch(PgArch, PgMeta):
|
|
|
740
757
|
continue
|
|
741
758
|
ocnt += 1
|
|
742
759
|
if self.PGLOG['DSCHECK']: chksize += lsize
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
if
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
self.params['LF'][i] = self.params['WF'][i] = None
|
|
762
|
-
continue
|
|
763
|
-
if errcnt == 0 or errcnt >= perrcnt or self.PGLOG['DSCHECK']: break
|
|
760
|
+
if cpass == 1: continue # the record pass sets the record, also for a file not copied
|
|
761
|
+
if gdone: harch = 1 # as if copied in this pass, for the file info below
|
|
762
|
+
if odone: oarch = 1
|
|
763
|
+
if not fnames: fnames = self.get_field_keys(tname, None, "G") # get setting fields if not yet
|
|
764
|
+
info = None
|
|
765
|
+
if harch:
|
|
766
|
+
info = self.check_local_file(afile, 1, self.PGOPT['emerol']|self.PFSIZE)
|
|
767
|
+
elif oarch:
|
|
768
|
+
info = self.check_object_file(ofile, bucket, 1, self.PGOPT['emerol'])
|
|
769
|
+
elif pgrec:
|
|
770
|
+
info = self.get_file_origin_info(hfile, pgrec)
|
|
771
|
+
elif locflag == 'O':
|
|
772
|
+
info = self.check_object_file(ofile, bucket, 1, self.PGOPT['emerol'])
|
|
773
|
+
hid = self.set_one_helpfile(i, pgrec, hfile, fnames, type, info)
|
|
774
|
+
if not hid:
|
|
775
|
+
self.params['LF'][i] = self.params['WF'][i] = None
|
|
776
|
+
continue
|
|
777
|
+
if cpass == 1 or errcnt == 0 or errcnt >= perrcnt or self.PGLOG['DSCHECK']: break
|
|
764
778
|
perrcnt = errcnt
|
|
765
|
-
self.pglog("Rearchive failed {}/{} Help file{} for {}".format(errcnt, self.ALLCNT
|
|
779
|
+
self.pglog("Rearchive failed {}/{} Help file{} for {}".format(errcnt, self.ALLCNT, s, dsid), self.PGOPT['emllog'])
|
|
766
780
|
errcnt = self.reset_errmsg(0)
|
|
781
|
+
if cpass == 1: # the record pass checks the copies, retries failed ones and sets the records
|
|
782
|
+
self.wait_copy_children()
|
|
783
|
+
self.reset_errmsg(0) # the record pass finds and counts any error again
|
|
784
|
+
return
|
|
767
785
|
if errcnt:
|
|
768
786
|
if 'CL' in self.params: del self.params['CL']
|
|
769
787
|
self.RETSTAT = self.reset_errmsg(errcnt)
|
|
@@ -771,13 +789,6 @@ class DsArch(PgArch, PgMeta):
|
|
|
771
789
|
if efiles[i]: self.params['HF'][i] = ''
|
|
772
790
|
if self.PGLOG['DSCHECK']:
|
|
773
791
|
self.check_storage_dflags(dflags, self.PGLOG['DSCHECK'], self.PGOPT['emerol'])
|
|
774
|
-
if bgcnt:
|
|
775
|
-
self.check_background(None, 0, self.LOGWRN, 1)
|
|
776
|
-
for i in range(self.ALLCNT):
|
|
777
|
-
if afiles[i]:
|
|
778
|
-
self.validate_gladearch(afiles[i], lfiles[i], i)
|
|
779
|
-
if ofiles[i]:
|
|
780
|
-
self.validate_objectarch(ofiles[i], lfiles[i], bucket, i)
|
|
781
792
|
if acnt > 0:
|
|
782
793
|
self.pglog("{} of {} Help file{} archived for {}".format(acnt, self.ALLCNT, s, self.params['DS']), self.PGOPT['emllog'])
|
|
783
794
|
if ocnt > 0:
|
|
@@ -791,7 +802,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
791
802
|
self.reset_rdadb_version(dsid)
|
|
792
803
|
if 'EM' in self.params: self.PGLOG['PRGMSG'] = ""
|
|
793
804
|
|
|
794
|
-
def archive_saved_files(self):
|
|
805
|
+
def archive_saved_files(self, cpass=0):
|
|
795
806
|
"""
|
|
796
807
|
Archive local files as dataset saved files on GLADE.
|
|
797
808
|
|
|
@@ -799,6 +810,11 @@ class DsArch(PgArch, PgMeta):
|
|
|
799
810
|
type constraints, handles version control checks, and registers or updates
|
|
800
811
|
the saved file record in RDADB via set_one_savedfile(). Retries on
|
|
801
812
|
transient copy failures. Sets self.RETSTAT on unresolved failures.
|
|
813
|
+
|
|
814
|
+
Args:
|
|
815
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
816
|
+
copy pass (copies in up to N child processes, no records) and then 2
|
|
817
|
+
for the record pass (see archive_in_passes())
|
|
802
818
|
"""
|
|
803
819
|
tname = 'sfile'
|
|
804
820
|
dftloc = 'G'
|
|
@@ -808,7 +824,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
808
824
|
bidx = chksize = 0
|
|
809
825
|
dflags = {}
|
|
810
826
|
self.pglog("Archive {} Saved file{} of {} ...".format(self.ALLCNT, s, dsid), self.WARNLG)
|
|
811
|
-
if 'ZD' in self.params or 'UZ' in self.params:
|
|
827
|
+
if cpass != 2 and ('ZD' in self.params or 'UZ' in self.params):
|
|
812
828
|
self.compress_localfile_list(self.PGOPT['CACT'], self.ALLCNT)
|
|
813
829
|
if 'QF' in self.params: self.params['QF'] = self.get_bid_numbers(self.params['QF'])
|
|
814
830
|
self.validate_multiple_values(tname, self.ALLCNT)
|
|
@@ -832,18 +848,15 @@ class DsArch(PgArch, PgMeta):
|
|
|
832
848
|
self.params['SZ'] = [0]*self.ALLCNT
|
|
833
849
|
self.OPTS['SZ'][2] |= 2
|
|
834
850
|
if 'MC' not in self.params: self.params['MC'] = [None]*self.ALLCNT
|
|
835
|
-
reorder = errcnt = self.ADDCNT = self.MODCNT =
|
|
851
|
+
reorder = errcnt = self.ADDCNT = self.MODCNT = acnt = 0
|
|
836
852
|
perrcnt = self.ALLCNT
|
|
837
853
|
efiles = [1]*self.ALLCNT
|
|
838
|
-
if self.PGSIG['BPROC'] > 1:
|
|
839
|
-
afiles = [None]*self.ALLCNT
|
|
840
|
-
lfiles = [None]*self.ALLCNT
|
|
841
854
|
fnames = None
|
|
842
855
|
override = self.OVERRIDE
|
|
843
856
|
if not override and 'GF' in self.params: override = self.OVRIDE
|
|
844
857
|
while True:
|
|
845
858
|
for i in range(bidx, self.ALLCNT):
|
|
846
|
-
if
|
|
859
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
847
860
|
if self.PGLOG['DSCHECK']:
|
|
848
861
|
self.set_dscheck_dcount(i, chksize, self.PGOPT['extlog'])
|
|
849
862
|
if 'EM' in self.params:
|
|
@@ -895,14 +908,20 @@ class DsArch(PgArch, PgMeta):
|
|
|
895
908
|
self.pglog("{}: Archive Saved file from {} ...".format(sinfo, locfile), self.WARNLG)
|
|
896
909
|
vsnctl = 1 if pgrec and pgrec['vindex'] and pgrec['data_size'] else 0
|
|
897
910
|
chksum = self.params['MC'][i]
|
|
911
|
+
if cpass == 2 and i in self.CPFILES: # copied in the -AL copy pass; recopy only if it failed
|
|
912
|
+
(gdone, odone) = self.check_pass_copies(i, sfile, afile if sarch else None, None, None, lsize)
|
|
913
|
+
if gdone:
|
|
914
|
+
sarch = 0
|
|
915
|
+
acnt += 1
|
|
916
|
+
if self.PGLOG['DSCHECK']: chksize += lsize
|
|
898
917
|
if sarch and (vsnctl or not override):
|
|
899
918
|
info = self.check_local_file(afile, 1, self.PGOPT['emerol']|self.PFSIZE)
|
|
900
919
|
if info:
|
|
901
920
|
if pgrec and chksum and pgrec['checksum'] and pgrec['checksum'] == chksum:
|
|
902
|
-
self.pglog("Saved-{}: Same-Checksum ARCHIVED at {}:{}".format(sinfo, info['date_modified'], info['time_modified']), self.PGOPT['emllog'])
|
|
921
|
+
self.pglog("Saved-{}: Same-Checksum ARCHIVED at {}:{}".format(sinfo, info['date_modified'], info['time_modified']), (0 if cpass == 1 else self.PGOPT['emllog']))
|
|
903
922
|
sarch = 0
|
|
904
923
|
elif not override and info['data_size'] == lsize:
|
|
905
|
-
self.pglog("Saved-{}: Same-Size ARCHIVED at {}:{}".format(sinfo, info['date_modified'], info['time_modified']), self.PGOPT['wrnlog'])
|
|
924
|
+
self.pglog("Saved-{}: Same-Size ARCHIVED at {}:{}".format(sinfo, info['date_modified'], info['time_modified']), (0 if cpass == 1 else self.PGOPT['wrnlog']))
|
|
906
925
|
sarch = 0
|
|
907
926
|
elif vsnctl and not override:
|
|
908
927
|
self.pglog("Saved-{}: Cannot rearchive version controlled file".format(sinfo), self.PGOPT['extlog'])
|
|
@@ -914,29 +933,32 @@ class DsArch(PgArch, PgMeta):
|
|
|
914
933
|
dflags['G'] = self.PGLOG['DECSHOME']
|
|
915
934
|
continue
|
|
916
935
|
if sarch:
|
|
936
|
+
if cpass == 1: # -AL copy pass: copy in a child process; the record pass sets the record
|
|
937
|
+
self.run_copy(i, self.copy_archive_file, afile, None, lfile, None, 0, self.PGOPT['emerol']|override)
|
|
938
|
+
continue
|
|
917
939
|
if not self.local_copy_local(afile, lfile, self.PGOPT['emerol']|override):
|
|
918
940
|
errcnt += 1
|
|
919
941
|
efiles[i] = 1
|
|
920
942
|
continue
|
|
921
943
|
acnt += 1
|
|
922
944
|
if self.PGLOG['DSCHECK']: chksize += lsize
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
if not sid:
|
|
934
|
-
self.params['LF'][i] = self.params['SF'][i] = None
|
|
935
|
-
continue
|
|
936
|
-
if errcnt == 0 or errcnt >= perrcnt or self.PGLOG['DSCHECK']: break
|
|
945
|
+
if cpass == 1: continue # the record pass sets the record, also for a file not copied
|
|
946
|
+
if not fnames: fnames = self.get_field_keys(tname, None, "G") # get setting fields if not yet
|
|
947
|
+
info = self.check_local_file(afile, 1, self.PGOPT['emerol']|self.PFSIZE) # also when already in place
|
|
948
|
+
if not info and pgrec:
|
|
949
|
+
info = self.get_file_origin_info(sfile, pgrec)
|
|
950
|
+
sid = self.set_one_savedfile(i, pgrec, sfile, fnames, type, info)
|
|
951
|
+
if not sid:
|
|
952
|
+
self.params['LF'][i] = self.params['SF'][i] = None
|
|
953
|
+
continue
|
|
954
|
+
if cpass == 1 or errcnt == 0 or errcnt >= perrcnt or self.PGLOG['DSCHECK']: break
|
|
937
955
|
perrcnt = errcnt
|
|
938
956
|
self.pglog("Rearchive failed {}/{} Saved file{} for {}!".format(errcnt, self.ALLCNT, s, dsid), self.PGOPT['emllog'])
|
|
939
957
|
errcnt = self.reset_errmsg(0)
|
|
958
|
+
if cpass == 1: # the record pass checks the copies, retries failed ones and sets the records
|
|
959
|
+
self.wait_copy_children()
|
|
960
|
+
self.reset_errmsg(0) # the record pass finds and counts any error again
|
|
961
|
+
return
|
|
940
962
|
if errcnt:
|
|
941
963
|
if 'CL' in self.params: del self.params['CL']
|
|
942
964
|
self.RETSTAT = self.reset_errmsg(errcnt)
|
|
@@ -944,10 +966,6 @@ class DsArch(PgArch, PgMeta):
|
|
|
944
966
|
if efiles[i]: self.params['SF'][i] = ''
|
|
945
967
|
if self.PGLOG['DSCHECK']:
|
|
946
968
|
self.check_storage_dflags(dflags, self.PGLOG['DSCHECK'], self.PGOPT['emerol'])
|
|
947
|
-
if bgcnt:
|
|
948
|
-
self.check_background(None, 0, self.LOGWRN, 1)
|
|
949
|
-
for i in range(self.ALLCNT):
|
|
950
|
-
if afiles[i]: self.validate_gladearch(afiles[i], lfiles[i], i)
|
|
951
969
|
if acnt > 0:
|
|
952
970
|
self.pglog("{} of {} Saved file{} archived for {}".format(acnt, self.ALLCNT, s, dsid), self.PGOPT['emllog'])
|
|
953
971
|
if self.PGLOG['DSCHECK']:
|
|
@@ -959,12 +977,14 @@ class DsArch(PgArch, PgMeta):
|
|
|
959
977
|
self.reset_rdadb_version(dsid)
|
|
960
978
|
if 'EM' in self.params: self.PGLOG['PRGMSG'] = ""
|
|
961
979
|
|
|
962
|
-
def crosscopy_web_files(self, aname):
|
|
980
|
+
def crosscopy_web_files(self, aname, cpass=0):
|
|
963
981
|
"""
|
|
964
982
|
Cross-copy (or cross-move) web files between GLADE and the object store.
|
|
965
983
|
|
|
966
984
|
Args:
|
|
967
985
|
aname -- 'Copy' to copy files, 'Move' to move (deletes the source)
|
|
986
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
987
|
+
copy pass and 2 for the record pass (see archive_in_passes())
|
|
968
988
|
"""
|
|
969
989
|
tname = 'wfile'
|
|
970
990
|
dsid = self.params['DS']
|
|
@@ -981,18 +1001,14 @@ class DsArch(PgArch, PgMeta):
|
|
|
981
1001
|
if bidx == self.ALLCNT: return
|
|
982
1002
|
self.set_rearchive_filenumber(dsid, bidx, self.ALLCNT, 4)
|
|
983
1003
|
chksize = self.PGLOG['DSCHECK']['size']
|
|
984
|
-
reorder = errcnt = metatotal = metacnt = self.MODCNT =
|
|
1004
|
+
reorder = errcnt = metatotal = metacnt = self.MODCNT = acnt = ocnt = 0
|
|
985
1005
|
perrcnt = self.ALLCNT
|
|
986
1006
|
efiles = [1]*self.ALLCNT
|
|
987
1007
|
self.params['LC'] = ['B']*self.ALLCNT
|
|
988
|
-
if self.PGSIG['BPROC'] > 1:
|
|
989
|
-
afiles = [None]*self.ALLCNT
|
|
990
|
-
ofiles = [None]*self.ALLCNT
|
|
991
|
-
warchs = [None]*self.ALLCNT
|
|
992
1008
|
fnames = None
|
|
993
1009
|
while True:
|
|
994
1010
|
for i in range(bidx, self.ALLCNT):
|
|
995
|
-
if
|
|
1011
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
996
1012
|
if self.PGLOG['DSCHECK']:
|
|
997
1013
|
self.set_dscheck_dcount(i, chksize, self.PGOPT['extlog'])
|
|
998
1014
|
if metacnt >= self.PGOPT['RSMAX']:
|
|
@@ -1038,7 +1054,32 @@ class DsArch(PgArch, PgMeta):
|
|
|
1038
1054
|
elif (warch + oarch) == 0 and pgrec['locflag'] == 'B':
|
|
1039
1055
|
self.pglog(winfo + ": No need Cross {}, Both Web & Object Exist".format(aname), self.PGOPT['wrnlog'])
|
|
1040
1056
|
continue
|
|
1041
|
-
if
|
|
1057
|
+
if cpass == 1: # -AL copy pass: cross copy in a child process; the record pass does the rest
|
|
1058
|
+
if warch or oarch:
|
|
1059
|
+
cdir = self.CPDIRS[i] = 'G' if warch else 'O'
|
|
1060
|
+
self.run_copy(i, self.cross_copy_file, cdir, (afile if warch else ofile), (ofile if warch else afile),
|
|
1061
|
+
bucket, None, self.PGOPT['emerol']|self.OVERRIDE)
|
|
1062
|
+
continue
|
|
1063
|
+
cdone = None
|
|
1064
|
+
if cpass == 2 and i in self.CPDIRS: # cross copied in the copy pass; copy again only if it failed
|
|
1065
|
+
cdir = self.CPDIRS[i]
|
|
1066
|
+
if self.check_cross_copy(i, winfo, cdir, (afile if cdir == 'G' else ofile), bucket, pgrec['data_size']):
|
|
1067
|
+
cdone = cdir
|
|
1068
|
+
elif cdir == 'G':
|
|
1069
|
+
warch = 1
|
|
1070
|
+
else:
|
|
1071
|
+
oarch = 1
|
|
1072
|
+
if cdone == 'G':
|
|
1073
|
+
if aname == 'Move':
|
|
1074
|
+
self.params['LC'][i] = 'G'
|
|
1075
|
+
self.delete_object_file(ofile, bucket, self.PGOPT['extlog'])
|
|
1076
|
+
acnt += 1
|
|
1077
|
+
elif cdone == 'O':
|
|
1078
|
+
if aname == 'Move':
|
|
1079
|
+
self.params['LC'][i] = 'O'
|
|
1080
|
+
self.delete_local_file(afile, self.PGOPT['extlog'])
|
|
1081
|
+
ocnt += 1
|
|
1082
|
+
elif warch:
|
|
1042
1083
|
if not self.object_copy_local(afile, ofile, bucket, self.PGOPT['emerol']|self.OVERRIDE):
|
|
1043
1084
|
errcnt += 1
|
|
1044
1085
|
efiles[i] = 1
|
|
@@ -1058,46 +1099,37 @@ class DsArch(PgArch, PgMeta):
|
|
|
1058
1099
|
self.params['LC'][i] = 'O'
|
|
1059
1100
|
self.delete_local_file(afile, self.PGOPT['extlog'])
|
|
1060
1101
|
ocnt += 1
|
|
1061
|
-
if self.PGSIG['BPROC'] > 1:
|
|
1062
|
-
afiles[i] = afile
|
|
1063
|
-
ofiles[i] = ofile
|
|
1064
|
-
warchs[i] = warch
|
|
1065
|
-
bgcnt += 1
|
|
1066
1102
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
1067
|
-
if self.
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
if '
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
if
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
if errcnt == 0 or errcnt >= perrcnt or self.PGLOG['DSCHECK']: break
|
|
1103
|
+
if not fnames: fnames = self.get_field_keys(tname, None, "G") # get setting fields if not yet
|
|
1104
|
+
info = self.get_file_origin_info(wfile, pgrec)
|
|
1105
|
+
wid = self.set_one_webfile(i, pgrec, wfile, fnames, type, info)
|
|
1106
|
+
if not wid:
|
|
1107
|
+
self.params['WF'][i] = None
|
|
1108
|
+
continue
|
|
1109
|
+
if 'GX' in self.params and self.PGOPT['GXTYP'].find(type) > -1:
|
|
1110
|
+
metacnt += self.record_meta_gather('W', dsid, wfile, self.params['DF'][i] if 'DF' in self.params else pgrec['data_format'])
|
|
1111
|
+
self.cache_meta_tindex(dsid, wid, 'W')
|
|
1112
|
+
if pgrec['meta_link'] and pgrec['meta_link'] != 'N':
|
|
1113
|
+
if 'DX' in self.params or self.PGOPT['GXTYP'].find(type) < 0 and self.PGOPT['GXTYP'].find(pgrec['type']) > -1:
|
|
1114
|
+
metacnt += self.record_meta_delete('W', dsid, wfile)
|
|
1115
|
+
elif 'GI' in self.params:
|
|
1116
|
+
gindex = self.params['GI'][i]
|
|
1117
|
+
if gindex != pgrec['gindex'] and (gindex or (self.OPTS['GI'][2]&2) == 0):
|
|
1118
|
+
metacnt += self.record_meta_summary('W', dsid, gindex, pgrec['gindex'])
|
|
1119
|
+
if cpass == 1 or errcnt == 0 or errcnt >= perrcnt or self.PGLOG['DSCHECK']: break
|
|
1085
1120
|
perrcnt = errcnt
|
|
1086
1121
|
self.pglog("Recopy failed {}/{} Web file{} for {}".format(errcnt, self.ALLCNT, s, dsid), self.PGOPT['emllog'])
|
|
1087
1122
|
errcnt = self.reset_errmsg(0)
|
|
1123
|
+
if cpass == 1: # the record pass checks the copies, copies again failed ones and sets the records
|
|
1124
|
+
self.wait_copy_children()
|
|
1125
|
+
self.reset_errmsg(0) # the record pass finds and counts any error again
|
|
1126
|
+
return
|
|
1088
1127
|
if errcnt:
|
|
1089
1128
|
self.RETSTAT = self.reset_errmsg(errcnt)
|
|
1090
1129
|
for i in range(bidx, self.ALLCNT):
|
|
1091
1130
|
if efiles[i]: self.params['WF'][i] = ''
|
|
1092
1131
|
if self.PGLOG['DSCHECK']:
|
|
1093
1132
|
self.check_storage_dflags(dflags, self.PGLOG['DSCHECK'], self.PGOPT['emerol'])
|
|
1094
|
-
if bgcnt:
|
|
1095
|
-
self.check_background(None, 0, self.LOGWRN, 1)
|
|
1096
|
-
for i in range(self.ALLCNT):
|
|
1097
|
-
if warchs[i]:
|
|
1098
|
-
self.validate_gladearch(afiles[i], "{}-{}".format(bucket, ofiles[i]), i)
|
|
1099
|
-
elif ofiles[i]:
|
|
1100
|
-
self.validate_objectarch(ofiles[i], afiles[i], bucket, i)
|
|
1101
1133
|
astr = 'Moved' if aname == 'Move' else 'Copied'
|
|
1102
1134
|
if acnt > 0: self.pglog("{} of {} Web file{} Cross {} for {}".format(acnt, self.ALLCNT, s, astr, dsid), self.PGOPT['emllog'])
|
|
1103
1135
|
if ocnt > 0: self.pglog("{} of {} Object file{} Cross {} for {}".format(ocnt, self.ALLCNT, s, astr, dsid), self.PGOPT['emllog'])
|
|
@@ -1112,12 +1144,14 @@ class DsArch(PgArch, PgMeta):
|
|
|
1112
1144
|
self.reset_rdadb_version(dsid)
|
|
1113
1145
|
if 'EM' in self.params: self.PGLOG['PRGMSG'] = ""
|
|
1114
1146
|
|
|
1115
|
-
def crosscopy_help_files(self, aname):
|
|
1147
|
+
def crosscopy_help_files(self, aname, cpass=0):
|
|
1116
1148
|
"""
|
|
1117
1149
|
Cross-copy (or cross-move) help files between GLADE and the object store.
|
|
1118
1150
|
|
|
1119
1151
|
Args:
|
|
1120
1152
|
aname -- 'Copy' to copy files, 'Move' to move (deletes the source)
|
|
1153
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
1154
|
+
copy pass and 2 for the record pass (see archive_in_passes())
|
|
1121
1155
|
"""
|
|
1122
1156
|
tname = 'hfile'
|
|
1123
1157
|
dsid = self.params['DS']
|
|
@@ -1135,18 +1169,14 @@ class DsArch(PgArch, PgMeta):
|
|
|
1135
1169
|
if bidx == self.ALLCNT: return
|
|
1136
1170
|
self.set_rearchive_filenumber(dsid, bidx, self.ALLCNT, 4)
|
|
1137
1171
|
chksize = self.PGLOG['DSCHECK']['size']
|
|
1138
|
-
reorder = errcnt = self.MODCNT =
|
|
1172
|
+
reorder = errcnt = self.MODCNT = acnt = ocnt = 0
|
|
1139
1173
|
perrcnt = self.ALLCNT
|
|
1140
1174
|
efiles = [1]*self.ALLCNT
|
|
1141
1175
|
self.params['LC'] = ['B']*self.ALLCNT
|
|
1142
|
-
if self.PGSIG['BPROC'] > 1:
|
|
1143
|
-
afiles = [None]*self.ALLCNT
|
|
1144
|
-
ofiles = [None]*self.ALLCNT
|
|
1145
|
-
harchs = [None]*self.ALLCNT
|
|
1146
1176
|
fnames = None
|
|
1147
1177
|
while True:
|
|
1148
1178
|
for i in range(bidx, self.ALLCNT):
|
|
1149
|
-
if
|
|
1179
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
1150
1180
|
if self.PGLOG['DSCHECK']:
|
|
1151
1181
|
self.set_dscheck_dcount(i, chksize, self.PGOPT['extlog'])
|
|
1152
1182
|
if 'EM' in self.params:
|
|
@@ -1202,7 +1232,32 @@ class DsArch(PgArch, PgMeta):
|
|
|
1202
1232
|
elif not (harch or oarch) and pgrec['locflag'] == 'B':
|
|
1203
1233
|
self.pglog(hinfo + ": No need Cross {} Help file, on Both Glade & Object".format(aname), self.PGOPT['wrnlog'])
|
|
1204
1234
|
continue
|
|
1205
|
-
if
|
|
1235
|
+
if cpass == 1: # -AL copy pass: cross copy in a child process; the record pass does the rest
|
|
1236
|
+
if harch or oarch:
|
|
1237
|
+
cdir = self.CPDIRS[i] = 'G' if harch else 'O'
|
|
1238
|
+
self.run_copy(i, self.cross_copy_file, cdir, (afile if harch else ofile), (ofile if harch else afile),
|
|
1239
|
+
bucket, None, self.PGOPT['emerol']|self.OVERRIDE)
|
|
1240
|
+
continue
|
|
1241
|
+
cdone = None
|
|
1242
|
+
if cpass == 2 and i in self.CPDIRS: # cross copied in the copy pass; copy again only if it failed
|
|
1243
|
+
cdir = self.CPDIRS[i]
|
|
1244
|
+
if self.check_cross_copy(i, hinfo, cdir, (afile if cdir == 'G' else ofile), bucket, pgrec['data_size']):
|
|
1245
|
+
cdone = cdir
|
|
1246
|
+
elif cdir == 'G':
|
|
1247
|
+
harch = 1
|
|
1248
|
+
else:
|
|
1249
|
+
oarch = 1
|
|
1250
|
+
if cdone == 'G':
|
|
1251
|
+
if aname == 'Move':
|
|
1252
|
+
self.params['LC'][i] = 'G'
|
|
1253
|
+
self.delete_object_file(ofile, bucket, self.PGOPT['extlog'])
|
|
1254
|
+
acnt += 1
|
|
1255
|
+
elif cdone == 'O':
|
|
1256
|
+
if aname == 'Move':
|
|
1257
|
+
self.params['LC'][i] = 'O'
|
|
1258
|
+
self.delete_local_file(afile, self.PGOPT['extlog'])
|
|
1259
|
+
ocnt += 1
|
|
1260
|
+
elif harch:
|
|
1206
1261
|
if not self.object_copy_local(afile, ofile, bucket, self.PGOPT['emerol']|self.OVERRIDE):
|
|
1207
1262
|
errcnt += 1
|
|
1208
1263
|
efiles[i] = 1
|
|
@@ -1222,36 +1277,27 @@ class DsArch(PgArch, PgMeta):
|
|
|
1222
1277
|
self.params['LC'][i] = 'O'
|
|
1223
1278
|
self.delete_local_file(afile, self.PGOPT['extlog'])
|
|
1224
1279
|
ocnt += 1
|
|
1225
|
-
if self.PGSIG['BPROC'] > 1:
|
|
1226
|
-
afiles[i] = afile
|
|
1227
|
-
ofiles[i] = ofile
|
|
1228
|
-
harchs[i] = harch
|
|
1229
|
-
bgcnt += 1
|
|
1230
1280
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
1231
|
-
if self.
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
if errcnt == 0 or errcnt >= perrcnt or self.PGLOG['DSCHECK']: break
|
|
1281
|
+
if not fnames: fnames = self.get_field_keys(tname, None, "G") # get setting fields if not yet
|
|
1282
|
+
info = self.get_file_origin_info(hfile, pgrec)
|
|
1283
|
+
hid = self.set_one_helpfile(i, pgrec, hfile, fnames, type, info)
|
|
1284
|
+
if not hid:
|
|
1285
|
+
self.params['HF'][i] = None
|
|
1286
|
+
continue
|
|
1287
|
+
if cpass == 1 or errcnt == 0 or errcnt >= perrcnt or self.PGLOG['DSCHECK']: break
|
|
1239
1288
|
perrcnt = errcnt
|
|
1240
1289
|
self.pglog("Re{} {} Help file{} for {}".format(aname, errcnt, self.ALLCNT, s, dsid), self.PGOPT['emllog'])
|
|
1241
1290
|
errcnt = self.reset_errmsg(0)
|
|
1291
|
+
if cpass == 1: # the record pass checks the copies, copies again failed ones and sets the records
|
|
1292
|
+
self.wait_copy_children()
|
|
1293
|
+
self.reset_errmsg(0) # the record pass finds and counts any error again
|
|
1294
|
+
return
|
|
1242
1295
|
if errcnt:
|
|
1243
1296
|
self.RETSTAT = self.reset_errmsg(errcnt)
|
|
1244
1297
|
for i in range(bidx, self.ALLCNT):
|
|
1245
1298
|
if efiles[i]: self.params['SF'][i] = ''
|
|
1246
1299
|
if self.PGLOG['DSCHECK']:
|
|
1247
1300
|
self.check_storage_dflags(dflags, self.PGLOG['DSCHECK'], self.PGOPT['emerol'])
|
|
1248
|
-
if bgcnt:
|
|
1249
|
-
self.check_background(None, 0, self.LOGWRN, 1)
|
|
1250
|
-
for i in range(self.ALLCNT):
|
|
1251
|
-
if harchs[i]:
|
|
1252
|
-
self.validate_gladearch(afiles[i], "{}-{}".format(bucket, ofiles[i]), i)
|
|
1253
|
-
elif ofiles[i]:
|
|
1254
|
-
self.validate_objectarch(ofiles[i], afiles[i], bucket, i)
|
|
1255
1301
|
astr = 'Moved' if aname == 'Move' else 'Copied'
|
|
1256
1302
|
if acnt > 0: self.pglog("{} of {} Help file{} Cross {} for {}".format(acnt, self.ALLCNT, s, astr, dsid), self.PGOPT['emllog'])
|
|
1257
1303
|
if ocnt > 0: self.pglog("{} of {} Object file{} Cross {} for {}".format(ocnt, self.ALLCNT, s, astr, dsid), self.PGOPT['emllog'])
|
|
@@ -1838,13 +1884,17 @@ class DsArch(PgArch, PgMeta):
|
|
|
1838
1884
|
self.set_dscheck_dcount(self.ALLCNT, chksize, self.PGOPT['extlog'])
|
|
1839
1885
|
if 'EM' in self.params: self.PGLOG['PRGMSG'] = ""
|
|
1840
1886
|
|
|
1841
|
-
def crosscopy_backup_files(self):
|
|
1887
|
+
def crosscopy_backup_files(self, cpass=0):
|
|
1842
1888
|
"""
|
|
1843
1889
|
Cross-copy Quasar backup files between Globus endpoints.
|
|
1844
1890
|
|
|
1845
1891
|
Transfers backup files between gdex-quasar and gdex-quasar-drdata
|
|
1846
1892
|
endpoints using Globus transfer, updating RDADB records on completion.
|
|
1847
1893
|
Sets self.RETSTAT on transfer failures.
|
|
1894
|
+
|
|
1895
|
+
Args:
|
|
1896
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
1897
|
+
copy pass and 2 for the record pass (see archive_in_passes())
|
|
1848
1898
|
"""
|
|
1849
1899
|
tname = 'bfile'
|
|
1850
1900
|
qtype = 'D'
|
|
@@ -1864,16 +1914,13 @@ class DsArch(PgArch, PgMeta):
|
|
|
1864
1914
|
if bidx == self.ALLCNT: return
|
|
1865
1915
|
self.set_rearchive_filenumber(dsid, bidx, self.ALLCNT, 4)
|
|
1866
1916
|
chksize = self.PGLOG['DSCHECK']['size']
|
|
1867
|
-
reorder = errcnt = self.MODCNT =
|
|
1917
|
+
reorder = errcnt = self.MODCNT = bcnt = dcnt = 0
|
|
1868
1918
|
perrcnt = self.ALLCNT
|
|
1869
1919
|
efiles = [1]*self.ALLCNT
|
|
1870
|
-
if self.PGSIG['BPROC'] > 1:
|
|
1871
|
-
qfiles = [None]*self.ALLCNT
|
|
1872
|
-
barchs = [None]*self.ALLCNT
|
|
1873
1920
|
fnames = None
|
|
1874
1921
|
while True:
|
|
1875
1922
|
for i in range(bidx, self.ALLCNT):
|
|
1876
|
-
if
|
|
1923
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
1877
1924
|
if self.PGLOG['DSCHECK']:
|
|
1878
1925
|
self.set_dscheck_dcount(i, chksize, self.PGOPT['extlog'])
|
|
1879
1926
|
if 'EM' in self.params:
|
|
@@ -1912,7 +1959,26 @@ class DsArch(PgArch, PgMeta):
|
|
|
1912
1959
|
elif not (barch or darch) and pgrec['type'] == 'D':
|
|
1913
1960
|
self.pglog(binfo + ": No need Cross Copy, Both Backup & Drdata Exist", self.PGOPT['wrnlog'])
|
|
1914
1961
|
continue
|
|
1915
|
-
if
|
|
1962
|
+
if cpass == 1: # -AL copy pass: cross copy in a child process; the record pass sets the record
|
|
1963
|
+
if barch or darch:
|
|
1964
|
+
cdir = self.CPDIRS[i] = 'B' if barch else 'D'
|
|
1965
|
+
self.run_copy(i, self.cross_copy_file, cdir, qfile, qfile, (bpoint if barch else dpoint),
|
|
1966
|
+
(dpoint if barch else bpoint), self.PGOPT['emerol']|self.OVERRIDE)
|
|
1967
|
+
continue
|
|
1968
|
+
cdone = None
|
|
1969
|
+
if cpass == 2 and i in self.CPDIRS: # cross copied in the copy pass; copy again only if it failed
|
|
1970
|
+
cdir = self.CPDIRS[i]
|
|
1971
|
+
if self.check_cross_copy(i, binfo, cdir, bfile, (bpoint if cdir == 'B' else dpoint), pgrec['data_size']):
|
|
1972
|
+
cdone = cdir
|
|
1973
|
+
elif cdir == 'B':
|
|
1974
|
+
barch = 1
|
|
1975
|
+
else:
|
|
1976
|
+
darch = 1
|
|
1977
|
+
if cdone == 'B':
|
|
1978
|
+
bcnt += 1
|
|
1979
|
+
elif cdone == 'D':
|
|
1980
|
+
dcnt += 1
|
|
1981
|
+
elif barch:
|
|
1916
1982
|
bstat = self.endpoint_copy_endpoint(qfile, qfile, bpoint, dpoint, self.PGOPT['emerol']|self.OVERRIDE)
|
|
1917
1983
|
if bstat == self.FINISH: bstat = self.check_globus_finished(qfile, bpoint, self.PGOPT['emerol']|self.NOWAIT)
|
|
1918
1984
|
if not bstat:
|
|
@@ -1930,17 +1996,12 @@ class DsArch(PgArch, PgMeta):
|
|
|
1930
1996
|
dflags['D'] = dpoint
|
|
1931
1997
|
continue
|
|
1932
1998
|
dcnt += 1
|
|
1933
|
-
if self.PGSIG['BPROC'] > 1:
|
|
1934
|
-
qfiles[i] = qfile
|
|
1935
|
-
barchs[i] = barch
|
|
1936
|
-
bgcnt += 1
|
|
1937
1999
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
1938
|
-
if self.
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
continue
|
|
2000
|
+
if not fnames: fnames = self.get_field_keys(tname) # get setting fields if not yet
|
|
2001
|
+
bid = self.set_one_backfile(i, pgrec, bfile, fnames, qtype)
|
|
2002
|
+
if not bid:
|
|
2003
|
+
self.params['QF'][i] = None
|
|
2004
|
+
continue
|
|
1944
2005
|
if errcnt == 0 or errcnt >= perrcnt or self.PGLOG['DSCHECK']: break
|
|
1945
2006
|
perrcnt = errcnt
|
|
1946
2007
|
self.pglog("Recopy {} Quasar file{} for {}".format(errcnt, self.ALLCNT, s, dsid), self.PGOPT['emllog'])
|
|
@@ -1951,13 +2012,6 @@ class DsArch(PgArch, PgMeta):
|
|
|
1951
2012
|
if efiles[i]: self.params['QF'][i] = ''
|
|
1952
2013
|
if self.PGLOG['DSCHECK']:
|
|
1953
2014
|
self.check_storage_dflags(dflags, self.PGLOG['DSCHECK'], self.PGOPT['emerol'])
|
|
1954
|
-
if bgcnt:
|
|
1955
|
-
self.check_background(None, 0, self.LOGWRN, 1)
|
|
1956
|
-
for i in range(self.ALLCNT):
|
|
1957
|
-
if barchs[i]:
|
|
1958
|
-
self.validate_backarch(qfiles[i], "{}-{}".format(dpoint, qfiles[i]), bpoint, i)
|
|
1959
|
-
elif qfiles[i]:
|
|
1960
|
-
self.validate_backarch(qfiles[i], "{}-{}".format(bpoint, qfiles[i]), dpoint, i)
|
|
1961
2015
|
if bcnt > 0: self.pglog("{} of {} Backup file{} Cross Copied for {}".format(bcnt, self.ALLCNT, s, dsid), self.PGOPT['emllog'])
|
|
1962
2016
|
if dcnt > 0: self.pglog("{} of {} Drdata file{} Cross Copied for {}".format(dcnt, self.ALLCNT, s, dsid), self.PGOPT['emllog'])
|
|
1963
2017
|
if self.PGLOG['DSCHECK']:
|
|
@@ -1968,57 +2022,265 @@ class DsArch(PgArch, PgMeta):
|
|
|
1968
2022
|
self.reset_rdadb_version(dsid)
|
|
1969
2023
|
if 'EM' in self.params: self.PGLOG['PRGMSG'] = ""
|
|
1970
2024
|
|
|
1971
|
-
def
|
|
2025
|
+
def archive_in_passes(self, archfunc, *args):
|
|
1972
2026
|
"""
|
|
1973
|
-
|
|
2027
|
+
Run a file action once, or in two passes for -AL.
|
|
1974
2028
|
|
|
1975
|
-
|
|
1976
|
-
|
|
2029
|
+
Used for archive_web/help/saved_files, crosscopy_web/help/backup_files and
|
|
2030
|
+
move_web/help/saved/backup_files. With -AL N (N > 1, so PGSIG['MPROC'] > 1)
|
|
2031
|
+
the action runs twice:
|
|
2032
|
+
1. copy pass -- the usual checks, then the slow file work of each file (its
|
|
2033
|
+
copy, cross copy or moves) runs in one of up to N child processes
|
|
2034
|
+
(run_copy()); no records are set;
|
|
2035
|
+
2. record pass -- the usual single process loop; work the copy pass did is
|
|
2036
|
+
checked (check_pass_copies(), check_cross_copy(), pass_moved()) instead
|
|
2037
|
+
of done again, and done again only if it failed; source deletes of a
|
|
2038
|
+
cross move, records, dscheck progress and metadata are all done here
|
|
2039
|
+
exactly as without -AL.
|
|
1977
2040
|
|
|
1978
2041
|
Args:
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
"""
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
2042
|
+
archfunc -- bound action method taking its own args and then the pass
|
|
2043
|
+
number (0, 1 or 2) as keyword cpass
|
|
2044
|
+
args -- arguments of archfunc before cpass, such as 'Copy'/'Move'
|
|
2045
|
+
"""
|
|
2046
|
+
if self.PGSIG['MPROC'] < 2: return archfunc(*args)
|
|
2047
|
+
self.CPFILES = {}
|
|
2048
|
+
self.CPDIRS = {}
|
|
2049
|
+
archfunc(*args, cpass=1)
|
|
2050
|
+
archfunc(*args, cpass=2)
|
|
2051
|
+
self.CPFILES = {}
|
|
2052
|
+
self.CPDIRS = {}
|
|
2053
|
+
|
|
2054
|
+
def run_copy(self, i, copyfunc, *args):
|
|
2055
|
+
"""
|
|
2056
|
+
Run the copy of file *i* in a child process for the -AL copy pass.
|
|
2057
|
+
|
|
2058
|
+
Waits for a free child slot (up to PGSIG['MPROC'] running), forks, and runs
|
|
2059
|
+
copyfunc(*args) in the child, which then leaves with os._exit(): it skips the
|
|
2060
|
+
parent's exit handling, so it cannot close the parent's database connection,
|
|
2061
|
+
send email or end the run; NOQUIT also keeps an EXITLG error in the copy from
|
|
2062
|
+
exiting early. The parent records the child's process name in
|
|
2063
|
+
self.CPFILES[i] (its exit code then shows up in self.CEXITS) and returns at
|
|
2064
|
+
once. If no child can be started, the copy runs in the parent and
|
|
2065
|
+
self.CPFILES[i] is 1 or 0 for its result.
|
|
1990
2066
|
|
|
1991
|
-
|
|
2067
|
+
Args:
|
|
2068
|
+
i -- file index
|
|
2069
|
+
copyfunc -- function doing the copy; returns true on success
|
|
2070
|
+
args -- arguments of copyfunc
|
|
2071
|
+
"""
|
|
2072
|
+
for fh in (sys.stdout, sys.stderr): # nothing buffered is written twice by the child
|
|
2073
|
+
try:
|
|
2074
|
+
fh.flush()
|
|
2075
|
+
except Exception:
|
|
2076
|
+
pass
|
|
2077
|
+
pname = "dsarch_copy_{}".format(i)
|
|
2078
|
+
self.CEXITS.pop(pname, None)
|
|
2079
|
+
stat = self.start_child(pname, self.LOGWRN, 1)
|
|
2080
|
+
if stat <= 0: # cannot fork, copy in the parent
|
|
2081
|
+
self.CPFILES[i] = 1 if copyfunc(*args) else 0
|
|
2082
|
+
return self.CPFILES[i]
|
|
2083
|
+
if self.PGSIG['PPID'] > 1: # in the child process
|
|
2084
|
+
self.PGLOG['NOQUIT'] = 1
|
|
2085
|
+
ret = 0
|
|
2086
|
+
try:
|
|
2087
|
+
ret = copyfunc(*args)
|
|
2088
|
+
except BaseException as e:
|
|
2089
|
+
self.pglog("Copy {}: {}".format(i, str(e)), self.LOGERR)
|
|
2090
|
+
for fh in (sys.stdout, sys.stderr):
|
|
2091
|
+
try:
|
|
2092
|
+
fh.flush()
|
|
2093
|
+
except Exception:
|
|
2094
|
+
pass
|
|
2095
|
+
os._exit(0 if ret else 1)
|
|
2096
|
+
self.CPFILES[i] = pname # the child's exit code shows up in self.CEXITS[pname]
|
|
2097
|
+
return 1
|
|
2098
|
+
|
|
2099
|
+
def wait_copy_children(self):
|
|
2100
|
+
"""Wait until all child processes of the -AL copy pass are done."""
|
|
2101
|
+
if self.PGSIG['MPROC'] > 1: self.check_child(None, 0, self.LOGWRN, 1)
|
|
2102
|
+
|
|
2103
|
+
def copy_archive_file(self, afile, ofile, lfile, bucket, replace, logact):
|
|
2104
|
+
"""
|
|
2105
|
+
Copy one local file to GLADE and/or the object store; run in a copy pass child.
|
|
2106
|
+
|
|
2107
|
+
Args:
|
|
2108
|
+
afile -- absolute GLADE target path, or None for no GLADE copy
|
|
2109
|
+
ofile -- object store key, or None for no object copy
|
|
2110
|
+
lfile -- local source file
|
|
2111
|
+
bucket -- object store bucket
|
|
2112
|
+
replace -- true to delete the existing object first
|
|
2113
|
+
logact -- logging flags for the copies
|
|
2114
|
+
|
|
2115
|
+
Returns:
|
|
2116
|
+
1 if all copies succeeded, 0 otherwise
|
|
2117
|
+
"""
|
|
2118
|
+
if afile and not self.local_copy_local(afile, lfile, logact): return 0
|
|
2119
|
+
if ofile:
|
|
2120
|
+
if replace: self.delete_object_file(ofile, bucket)
|
|
2121
|
+
if not self.local_copy_object(ofile, lfile, bucket, None, logact): return 0
|
|
2122
|
+
return 1
|
|
2123
|
+
|
|
2124
|
+
def child_copy_failed(self, i):
|
|
2125
|
+
"""
|
|
2126
|
+
Return true if the -AL copy pass work of file *i* is known to have failed.
|
|
2127
|
+
|
|
2128
|
+
self.CPFILES[i] holds the child's process name, whose exit code is then in
|
|
2129
|
+
self.CEXITS, or 1/0 for work done in the parent; unknown counts as not failed.
|
|
2130
|
+
"""
|
|
2131
|
+
cstat = self.CPFILES.get(i)
|
|
2132
|
+
if isinstance(cstat, str): # done in a child: failed if it exited with an error
|
|
2133
|
+
ecode = self.CEXITS.get(cstat)
|
|
2134
|
+
return ecode is not None and ecode != 0
|
|
2135
|
+
return cstat == 0 # done in the parent: 1 or 0
|
|
2136
|
+
|
|
2137
|
+
def cross_copy_file(self, cdir, tofile, fromfile, topoint, frompoint, logact):
|
|
1992
2138
|
"""
|
|
1993
|
-
|
|
2139
|
+
Cross copy one file in the given direction; run in a copy pass child.
|
|
1994
2140
|
|
|
1995
2141
|
Args:
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2142
|
+
cdir -- 'G' object store to GLADE, 'O' GLADE to object store,
|
|
2143
|
+
'B'/'D' Globus copy to the Quasar backup/drdata endpoint
|
|
2144
|
+
tofile -- target path, object key or Quasar file
|
|
2145
|
+
fromfile -- source path, object key or Quasar file
|
|
2146
|
+
topoint -- object store bucket for 'G'/'O', target endpoint for 'B'/'D'
|
|
2147
|
+
frompoint -- source endpoint for 'B'/'D', None otherwise
|
|
2148
|
+
logact -- logging flags
|
|
2149
|
+
|
|
2150
|
+
Returns:
|
|
2151
|
+
a true value if the copy succeeded (Globus copies wait for their task)
|
|
2000
2152
|
"""
|
|
2001
|
-
|
|
2002
|
-
if
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2153
|
+
if cdir == 'G': return self.object_copy_local(tofile, fromfile, topoint, logact)
|
|
2154
|
+
if cdir == 'O': return self.local_copy_object(tofile, fromfile, topoint, None, logact)
|
|
2155
|
+
stat = self.endpoint_copy_endpoint(tofile, fromfile, topoint, frompoint, logact)
|
|
2156
|
+
if stat == self.FINISH: stat = self.check_globus_finished(tofile, topoint, logact|self.NOWAIT)
|
|
2157
|
+
return stat
|
|
2006
2158
|
|
|
2007
|
-
def
|
|
2159
|
+
def check_cross_copy(self, i, finfo, cdir, tofile, topoint, size):
|
|
2008
2160
|
"""
|
|
2009
|
-
|
|
2161
|
+
Check a cross copy, upload or download the -AL copy pass made, for the record pass.
|
|
2010
2162
|
|
|
2011
2163
|
Args:
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2164
|
+
i -- file index, the key of self.CPFILES
|
|
2165
|
+
finfo -- file description, for the message
|
|
2166
|
+
cdir -- copy direction, see cross_copy_file()
|
|
2167
|
+
tofile -- target path, object key or Quasar file
|
|
2168
|
+
topoint -- object store bucket or target endpoint
|
|
2169
|
+
size -- size in the file record, 0 to skip the size check
|
|
2170
|
+
|
|
2171
|
+
Returns:
|
|
2172
|
+
1 if the target holds the file, 0 if the copy is to be made again
|
|
2173
|
+
"""
|
|
2174
|
+
if not self.child_copy_failed(i):
|
|
2175
|
+
if cdir == 'G':
|
|
2176
|
+
info = self.check_local_file(tofile, 0, self.PGOPT['emerol']|self.PFSIZE)
|
|
2177
|
+
elif cdir == 'O':
|
|
2178
|
+
info = self.check_object_file(tofile, topoint, 0, self.PGOPT['emerol'])
|
|
2179
|
+
else:
|
|
2180
|
+
info = self.check_backup_file(tofile, topoint, 0, self.PGOPT['emerol'])
|
|
2181
|
+
if info and (not size or info['data_size'] == size): return 1
|
|
2182
|
+
self.pglog("{}: copy in child process failed, copy again".format(finfo), self.PGOPT['wrnlog'])
|
|
2183
|
+
return 0
|
|
2184
|
+
|
|
2185
|
+
def do_move(self, mtype, tofile, fromfile, where, logact):
|
|
2186
|
+
"""
|
|
2187
|
+
Do one step of a file's move: a move, an upload/download or a delete.
|
|
2188
|
+
|
|
2189
|
+
Args:
|
|
2190
|
+
mtype -- 'L' move a GLADE file, 'O' move an object, 'B' move a Quasar
|
|
2191
|
+
backup file, 'U' upload a GLADE file to the object store,
|
|
2192
|
+
'G' download an object to GLADE, 'X' delete an object,
|
|
2193
|
+
'Y' delete a GLADE file
|
|
2194
|
+
tofile -- new path, object key or Quasar file (None for a delete)
|
|
2195
|
+
fromfile -- old path, object key or Quasar file
|
|
2196
|
+
where -- bucket for 'O'/'U'/'G'/'X', endpoint for 'B', None otherwise
|
|
2197
|
+
logact -- logging flags
|
|
2198
|
+
|
|
2199
|
+
Returns:
|
|
2200
|
+
a true value if done (a move also when it was moved already)
|
|
2201
|
+
"""
|
|
2202
|
+
if mtype == 'L': return self.move_local_file(tofile, fromfile, logact)
|
|
2203
|
+
if mtype == 'O': return self.move_object_file(tofile, fromfile, where, where, logact)
|
|
2204
|
+
if mtype == 'B': return self.move_backup_file(tofile, fromfile, where, logact)
|
|
2205
|
+
if mtype == 'U': return self.local_copy_object(tofile, fromfile, where, None, logact)
|
|
2206
|
+
if mtype == 'G': return self.object_copy_local(tofile, fromfile, where, logact)
|
|
2207
|
+
if mtype == 'X': return self.delete_object_file(fromfile, where, logact)
|
|
2208
|
+
return self.delete_local_file(fromfile, logact)
|
|
2209
|
+
|
|
2210
|
+
def move_pass_files(self, moves, logact):
|
|
2211
|
+
"""
|
|
2212
|
+
Do the moves of one file in order; run in a copy pass child.
|
|
2213
|
+
|
|
2214
|
+
Args:
|
|
2215
|
+
moves -- list of (mtype, tofile, fromfile, where) steps, see do_move()
|
|
2216
|
+
logact -- logging flags
|
|
2217
|
+
|
|
2218
|
+
Returns:
|
|
2219
|
+
1 if all moves succeeded, 0 at the first failure
|
|
2220
|
+
"""
|
|
2221
|
+
for (mtype, tofile, fromfile, where) in moves:
|
|
2222
|
+
if not self.do_move(mtype, tofile, fromfile, where, logact): return 0
|
|
2223
|
+
return 1
|
|
2224
|
+
|
|
2225
|
+
def move_one(self, i, mtype, tofile, fromfile, where, logact):
|
|
2226
|
+
"""
|
|
2227
|
+
Move one file in the record pass, or the only pass without -AL.
|
|
2228
|
+
|
|
2229
|
+
When the -AL copy pass already moved it (target there, source gone) the
|
|
2230
|
+
move counts as done without another call; otherwise do_move() moves it,
|
|
2231
|
+
which also finishes a move that failed in its child process.
|
|
2232
|
+
"""
|
|
2233
|
+
if i in self.CPFILES and self.pass_moved(mtype, tofile, fromfile, where): return 1
|
|
2234
|
+
return self.do_move(mtype, tofile, fromfile, where, logact)
|
|
2235
|
+
|
|
2236
|
+
def pass_moved(self, mtype, tofile, fromfile, where):
|
|
2237
|
+
"""
|
|
2238
|
+
Return true if the target of a move exists and its source is gone, checked quietly.
|
|
2239
|
+
|
|
2240
|
+
The source counts as gone only when its check finds no file (None), not
|
|
2241
|
+
when the check itself fails (FAILURE), so an error leads to a real move.
|
|
2242
|
+
"""
|
|
2243
|
+
if mtype == 'L':
|
|
2244
|
+
check = lambda f: self.check_local_file(f, 0, 0)
|
|
2245
|
+
elif mtype == 'O':
|
|
2246
|
+
check = lambda f: self.check_object_file(f, where, 0, 0)
|
|
2247
|
+
else:
|
|
2248
|
+
check = lambda f: self.check_backup_file(f, where, 0, 0)
|
|
2249
|
+
return bool(check(tofile)) and check(fromfile) is None
|
|
2250
|
+
|
|
2251
|
+
def check_pass_copies(self, i, fname, afile, ofile, bucket, lsize):
|
|
2016
2252
|
"""
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2253
|
+
Check the targets the -AL copy pass copied a file to, for the record pass.
|
|
2254
|
+
|
|
2255
|
+
A copy whose child exited with an error counts as failed even when the
|
|
2256
|
+
target holds an older file of the same size (as with -OE); when the exit
|
|
2257
|
+
code is unknown, a target of size *lsize* counts as copied.
|
|
2258
|
+
|
|
2259
|
+
Args:
|
|
2260
|
+
i -- file index, the key of self.CPFILES
|
|
2261
|
+
fname -- archived file name, for the message
|
|
2262
|
+
afile -- GLADE target path the copy pass copied to, or None
|
|
2263
|
+
ofile -- object store key the copy pass copied to, or None
|
|
2264
|
+
bucket -- object store bucket
|
|
2265
|
+
lsize -- size of the local source file
|
|
2266
|
+
|
|
2267
|
+
Returns:
|
|
2268
|
+
(gdone, odone) -- 1 for each target that holds the file with size *lsize*;
|
|
2269
|
+
a 0 for a target given means its copy failed and is to be copied again
|
|
2270
|
+
"""
|
|
2271
|
+
gdone = odone = 0
|
|
2272
|
+
if self.child_copy_failed(i):
|
|
2273
|
+
self.pglog("{}: copy in child process failed, copy again".format(fname), self.PGOPT['wrnlog'])
|
|
2274
|
+
return (0, 0)
|
|
2275
|
+
if afile:
|
|
2276
|
+
info = self.check_local_file(afile, 1, self.PGOPT['emerol']|self.PFSIZE)
|
|
2277
|
+
if info and info['data_size'] == lsize: gdone = 1
|
|
2278
|
+
if ofile:
|
|
2279
|
+
info = self.check_object_file(ofile, bucket, 1, self.PGOPT['emerol'])
|
|
2280
|
+
if info and info['data_size'] == lsize: odone = 1
|
|
2281
|
+
if afile and not gdone or ofile and not odone:
|
|
2282
|
+
self.pglog("{}: copy in child process failed, copy again".format(fname), self.PGOPT['wrnlog'])
|
|
2283
|
+
return (gdone, odone)
|
|
2022
2284
|
|
|
2023
2285
|
def get_dataset_info(self):
|
|
2024
2286
|
"""
|
|
@@ -3222,7 +3484,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
3222
3484
|
self.ADDCNT += 1
|
|
3223
3485
|
return bid
|
|
3224
3486
|
|
|
3225
|
-
def move_web_files(self):
|
|
3487
|
+
def move_web_files(self, cpass=0):
|
|
3226
3488
|
"""
|
|
3227
3489
|
Rename or relocate web files on disk and update their RDADB records.
|
|
3228
3490
|
|
|
@@ -3230,6 +3492,11 @@ class DsArch(PgArch, PgMeta):
|
|
|
3230
3492
|
type changes (e.g. D→N). Supports -TS (to-saved) conversions and
|
|
3231
3493
|
updates backup file notes via save_move_info().
|
|
3232
3494
|
Sets self.RETSTAT on unresolved failures.
|
|
3495
|
+
|
|
3496
|
+
Args:
|
|
3497
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
3498
|
+
move pass (moves in up to N child processes, no records) and then 2
|
|
3499
|
+
for the record pass (see archive_in_passes())
|
|
3233
3500
|
"""
|
|
3234
3501
|
tname = 'wfile'
|
|
3235
3502
|
dsid = self.params['DS']
|
|
@@ -3295,7 +3562,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
3295
3562
|
self.validate_multiple_values(tname, self.ALLCNT, fnames)
|
|
3296
3563
|
reorder = metatotal = metacnt = wcnt = ocnt = self.MODCNT = 0
|
|
3297
3564
|
for i in range(bidx, self.ALLCNT):
|
|
3298
|
-
if i > bidx and ((i-bidx)%20) == 0:
|
|
3565
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
3299
3566
|
if metacnt > self.PGOPT['RSMAX']:
|
|
3300
3567
|
metatotal += self.process_metadata("W", metacnt, self.PGOPT['emerol'])
|
|
3301
3568
|
metacnt = 0
|
|
@@ -3335,8 +3602,14 @@ class DsArch(PgArch, PgMeta):
|
|
|
3335
3602
|
wmove = 0
|
|
3336
3603
|
elif pgrec['locflag'] == 'G':
|
|
3337
3604
|
omove = 0
|
|
3605
|
+
if cpass == 1: # -AL move pass: move the files in a child process; the record pass sets the record
|
|
3606
|
+
moves = []
|
|
3607
|
+
if wmove and aolds[i] != anews[i]: moves.append(('L', anews[i], aolds[i], None))
|
|
3608
|
+
if omove and oolds[i] != onews[i]: moves.append(('O', onews[i], oolds[i], bucket))
|
|
3609
|
+
if moves: self.run_copy(i, self.move_pass_files, moves, self.PGOPT['emerol']|self.OVERRIDE)
|
|
3610
|
+
continue
|
|
3338
3611
|
if wmove and aolds[i] != anews[i]:
|
|
3339
|
-
ret = self.
|
|
3612
|
+
ret = self.move_one(i, 'L', anews[i], aolds[i], None, self.PGOPT['emerol']|self.OVERRIDE)
|
|
3340
3613
|
if not ret:
|
|
3341
3614
|
self.RETSTAT = 1
|
|
3342
3615
|
continue
|
|
@@ -3344,7 +3617,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
3344
3617
|
wcnt += 1
|
|
3345
3618
|
self.set_web_move(pgrec)
|
|
3346
3619
|
if omove and oolds[i] != onews[i]:
|
|
3347
|
-
if not self.
|
|
3620
|
+
if not self.move_one(i, 'O', onews[i], oolds[i], bucket, self.PGOPT['emerol']|self.OVERRIDE):
|
|
3348
3621
|
self.RETSTAT = 1
|
|
3349
3622
|
continue
|
|
3350
3623
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
@@ -3359,6 +3632,10 @@ class DsArch(PgArch, PgMeta):
|
|
|
3359
3632
|
gindex = self.params['GI'][i]
|
|
3360
3633
|
if gindex != pgrec['gindex'] and (gindex or (self.OPTS['GI'][2]&2) == 0):
|
|
3361
3634
|
metacnt += self.record_meta_summary('W', dsid, gindex, pgrec['gindex'])
|
|
3635
|
+
if cpass == 1: # the record pass checks the moves, finishes failed ones and sets the records
|
|
3636
|
+
self.wait_copy_children()
|
|
3637
|
+
self.reset_errmsg(0) # the record pass finds and counts any error again
|
|
3638
|
+
return
|
|
3362
3639
|
self.pglog("{}/{}/{}, Disk/Object/Record, of {} Web file{} moved".format(wcnt, ocnt, self.MODCNT, self.ALLCNT, s), self.PGOPT['emllog'])
|
|
3363
3640
|
if metacnt > 0:
|
|
3364
3641
|
metatotal += self.process_metadata('W', metacnt, self.PGOPT['emerol'])
|
|
@@ -3372,12 +3649,17 @@ class DsArch(PgArch, PgMeta):
|
|
|
3372
3649
|
self.reset_rdadb_version(self.params['OD'])
|
|
3373
3650
|
if 'EM' in self.params: self.PGLOG['PRGMSG'] = ''
|
|
3374
3651
|
|
|
3375
|
-
def move_help_files(self):
|
|
3652
|
+
def move_help_files(self, cpass=0):
|
|
3376
3653
|
"""
|
|
3377
3654
|
Rename or relocate help files on disk and update their RDADB records.
|
|
3378
3655
|
|
|
3379
3656
|
Handles renaming within the same dataset and cross-dataset moves, along
|
|
3380
3657
|
with any type changes. Sets self.RETSTAT on unresolved failures.
|
|
3658
|
+
|
|
3659
|
+
Args:
|
|
3660
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
3661
|
+
move pass (moves in up to N child processes, no records) and then 2
|
|
3662
|
+
for the record pass (see archive_in_passes())
|
|
3381
3663
|
"""
|
|
3382
3664
|
tname = 'hfile'
|
|
3383
3665
|
dsid = self.params['DS']
|
|
@@ -3435,7 +3717,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
3435
3717
|
self.validate_multiple_values(tname, self.ALLCNT, fnames)
|
|
3436
3718
|
reorder = hcnt = ocnt = self.MODCNT = 0
|
|
3437
3719
|
for i in range(bidx, self.ALLCNT):
|
|
3438
|
-
if i > bidx and ((i-bidx)%20) == 0:
|
|
3720
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
3439
3721
|
if self.PGLOG['DSCHECK']:
|
|
3440
3722
|
self.set_dscheck_dcount(i, chksize, self.PGOPT['extlog'])
|
|
3441
3723
|
if 'EM' in self.params:
|
|
@@ -3458,20 +3740,30 @@ class DsArch(PgArch, PgMeta):
|
|
|
3458
3740
|
hmove = 0
|
|
3459
3741
|
elif pgrec['locflag'] == 'G':
|
|
3460
3742
|
omove = 0
|
|
3743
|
+
if cpass == 1: # -AL move pass: move the files in a child process; the record pass sets the record
|
|
3744
|
+
moves = []
|
|
3745
|
+
if hmove and aolds[i] != anews[i]: moves.append(('L', anews[i], aolds[i], None))
|
|
3746
|
+
if omove and oolds[i] != onews[i]: moves.append(('O', onews[i], oolds[i], bucket))
|
|
3747
|
+
if moves: self.run_copy(i, self.move_pass_files, moves, self.PGOPT['emerol']|self.OVERRIDE)
|
|
3748
|
+
continue
|
|
3461
3749
|
if hmove and aolds[i] != anews[i]:
|
|
3462
|
-
ret = self.
|
|
3750
|
+
ret = self.move_one(i, 'L', anews[i], aolds[i], None, self.PGOPT['emerol']|self.OVERRIDE)
|
|
3463
3751
|
if not ret:
|
|
3464
3752
|
self.RETSTAT = 1
|
|
3465
3753
|
continue
|
|
3466
3754
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
3467
3755
|
hcnt += 1
|
|
3468
3756
|
if omove and oolds[i] != onews[i]:
|
|
3469
|
-
if not self.
|
|
3757
|
+
if not self.move_one(i, 'O', onews[i], oolds[i], bucket, self.PGOPT['emerol']|self.OVERRIDE):
|
|
3470
3758
|
self.RETSTAT = 1
|
|
3471
3759
|
continue
|
|
3472
3760
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
3473
3761
|
ocnt += 1
|
|
3474
3762
|
if not self.set_one_helpfile(i, pgrec, hnews[i], fnames, tnews[i], None, tmpds): continue
|
|
3763
|
+
if cpass == 1: # the record pass checks the moves, finishes failed ones and sets the records
|
|
3764
|
+
self.wait_copy_children()
|
|
3765
|
+
self.reset_errmsg(0) # the record pass finds and counts any error again
|
|
3766
|
+
return
|
|
3475
3767
|
self.pglog("{}/{}/{}/{}, Disk/Object/Record, of {} Help file{} moved".format(hcnt, ocnt, self.MODCNT, self.ALLCNT, s), self.PGOPT['emllog'])
|
|
3476
3768
|
if self.PGLOG['DSCHECK']: self.set_dscheck_dcount(self.ALLCNT, 0, self.PGOPT['extlog'])
|
|
3477
3769
|
if 'ON' in self.params: reorder = self.reorder_files(dsid, self.params['ON'], tname)
|
|
@@ -3481,7 +3773,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
3481
3773
|
self.reset_rdadb_version(self.params['OD'])
|
|
3482
3774
|
if 'EM' in self.params: self.PGLOG['PRGMSG'] = ''
|
|
3483
3775
|
|
|
3484
|
-
def saved_to_web_files(self):
|
|
3776
|
+
def saved_to_web_files(self, cpass=0):
|
|
3485
3777
|
"""
|
|
3486
3778
|
Convert saved files to web files (-TS action).
|
|
3487
3779
|
|
|
@@ -3489,6 +3781,11 @@ class DsArch(PgArch, PgMeta):
|
|
|
3489
3781
|
store), creates a new wfile RDADB record, and removes the old sfile
|
|
3490
3782
|
record. Preserves backup links by updating bfile.note via save_move_info().
|
|
3491
3783
|
Sets self.RETSTAT on unresolved failures.
|
|
3784
|
+
|
|
3785
|
+
Args:
|
|
3786
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
3787
|
+
move pass (moves in up to N child processes, no records) and then 2
|
|
3788
|
+
for the record pass (see archive_in_passes())
|
|
3492
3789
|
"""
|
|
3493
3790
|
tname = 'wfile'
|
|
3494
3791
|
dsid = self.params['DS']
|
|
@@ -3566,7 +3863,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
3566
3863
|
fnames = None
|
|
3567
3864
|
reorder = metatotal = metacnt = wcnt = ocnt = dcnt = self.ADDCNT = self.MODCNT = 0
|
|
3568
3865
|
for i in range(bidx, self.ALLCNT):
|
|
3569
|
-
if i > bidx and ((i-bidx)%20) == 0:
|
|
3866
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
3570
3867
|
if metacnt > self.PGOPT['RSMAX']:
|
|
3571
3868
|
metatotal += self.process_metadata("W", metacnt, self.PGOPT['emerol'])
|
|
3572
3869
|
metacnt = 0
|
|
@@ -3604,8 +3901,16 @@ class DsArch(PgArch, PgMeta):
|
|
|
3604
3901
|
elif locflag == 'G':
|
|
3605
3902
|
omove = 0
|
|
3606
3903
|
dslocflags.add('G')
|
|
3904
|
+
if cpass == 1: # -AL move pass: move the file in a child process; the record pass sets the record
|
|
3905
|
+
moves = []
|
|
3906
|
+
if wmove: moves.append(('L', anews[i], aolds[i], None))
|
|
3907
|
+
if omove: moves.append(('U', onews[i], (anews[i] if wmove else aolds[i]), tobucket))
|
|
3908
|
+
if omove and not wmove: moves.append(('Y', None, aolds[i], None))
|
|
3909
|
+
if moves: self.run_copy(i, self.move_pass_files, moves, self.PGOPT['emerol']|self.OVERRIDE)
|
|
3910
|
+
continue
|
|
3911
|
+
inpass = cpass == 2 and i in self.CPFILES
|
|
3607
3912
|
if wmove:
|
|
3608
|
-
stat = self.
|
|
3913
|
+
stat = self.move_one(i, 'L', anews[i], aolds[i], None, self.PGOPT['emerol']|self.OVERRIDE)
|
|
3609
3914
|
sfrom = 0
|
|
3610
3915
|
if not stat:
|
|
3611
3916
|
self.RETSTAT = 1
|
|
@@ -3613,13 +3918,18 @@ class DsArch(PgArch, PgMeta):
|
|
|
3613
3918
|
wcnt += 1
|
|
3614
3919
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
3615
3920
|
if omove:
|
|
3616
|
-
|
|
3921
|
+
# upload from the new web path once the saved file was moved there
|
|
3922
|
+
if inpass and self.check_cross_copy(i, solds[i], 'O', onews[i], tobucket, pgrec['data_size']):
|
|
3923
|
+
stat = 1 # uploaded in the move pass
|
|
3924
|
+
else:
|
|
3925
|
+
stat = self.local_copy_object(onews[i], (aolds[i] if sfrom else anews[i]), tobucket, None, self.PGOPT['emerol']|self.OVERRIDE)
|
|
3617
3926
|
if not stat:
|
|
3618
3927
|
self.RETSTAT = 1
|
|
3619
3928
|
continue
|
|
3620
3929
|
ocnt += 1
|
|
3621
3930
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
3622
|
-
if sfrom
|
|
3931
|
+
if sfrom and (not inpass or self.check_local_file(aolds[i], 0, 0)):
|
|
3932
|
+
self.delete_local_file(aolds[i], self.PGOPT['emerol'])
|
|
3623
3933
|
if pgrec['bid'] and not self.params['QF'][i]: self.params['QF'][i] = pgrec['bid']
|
|
3624
3934
|
if pgrec['gindex'] and not self.params['GI'][i]: self.params['GI'][i] = pgrec['gindex']
|
|
3625
3935
|
if pgrec['data_size'] and not self.params['SZ'][i]: self.params['SZ'][i] = pgrec['data_size']
|
|
@@ -3637,6 +3947,10 @@ class DsArch(PgArch, PgMeta):
|
|
|
3637
3947
|
if 'GX' in self.params and self.PGOPT['GXTYP'].find(type) > -1:
|
|
3638
3948
|
metacnt += self.record_meta_gather('W', dsid, wnews[i], self.params['DF'][i])
|
|
3639
3949
|
self.cache_meta_tindex(dsid, wid, 'W')
|
|
3950
|
+
if cpass == 1: # the record pass checks the moves, finishes failed ones and sets the records
|
|
3951
|
+
self.wait_copy_children()
|
|
3952
|
+
self.reset_errmsg(0) # the record pass finds and counts any error again
|
|
3953
|
+
return
|
|
3640
3954
|
self.pglog("{}/{}/{}/{}, Disk/Object/RecordDelete/RecordAdd, of {} Saved file{} moved".format(wcnt, ocnt, dcnt, self.ADDCNT, self.ALLCNT, s), self.PGOPT['emllog'])
|
|
3641
3955
|
if metacnt > 0:
|
|
3642
3956
|
metatotal += self.process_metadata('W', metacnt, self.PGOPT['emerol'])
|
|
@@ -3844,12 +4158,17 @@ class DsArch(PgArch, PgMeta):
|
|
|
3844
4158
|
if (dcnt + reorder) > 0: self.reset_rdadb_version(dsid)
|
|
3845
4159
|
if 'EM' in self.params: self.PGLOG['PRGMSG'] = ""
|
|
3846
4160
|
|
|
3847
|
-
def move_saved_files(self):
|
|
4161
|
+
def move_saved_files(self, cpass=0):
|
|
3848
4162
|
"""
|
|
3849
4163
|
Rename or relocate saved files on disk and update their RDADB records.
|
|
3850
4164
|
|
|
3851
4165
|
Handles renaming within the same dataset and cross-dataset moves, along
|
|
3852
4166
|
with any type changes. Sets self.RETSTAT on unresolved failures.
|
|
4167
|
+
|
|
4168
|
+
Args:
|
|
4169
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
4170
|
+
move pass (moves in up to N child processes, no records) and then 2
|
|
4171
|
+
for the record pass (see archive_in_passes())
|
|
3853
4172
|
"""
|
|
3854
4173
|
tname = 'sfile'
|
|
3855
4174
|
dsid = self.params['DS']
|
|
@@ -3911,7 +4230,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
3911
4230
|
chksize = self.PGLOG['DSCHECK']['size']
|
|
3912
4231
|
reorder = self.MODCNT = scnt = 0
|
|
3913
4232
|
for i in range(bidx, self.ALLCNT):
|
|
3914
|
-
if i > bidx and ((i-bidx)%20) == 0:
|
|
4233
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
3915
4234
|
if self.PGLOG['DSCHECK']:
|
|
3916
4235
|
self.set_dscheck_dcount(i, chksize, self.PGOPT['extlog'])
|
|
3917
4236
|
if 'EM' in self.params:
|
|
@@ -3940,14 +4259,23 @@ class DsArch(PgArch, PgMeta):
|
|
|
3940
4259
|
not self.pgget("dsgroup", "", "{} and gindex = {}".format(dcnd, pgrec['gindex']), self.PGOPT['extlog'])):
|
|
3941
4260
|
self.pglog("Group Index {} is not in RDADB for {}\n".format(pgrec['gindex'], dsid) +
|
|
3942
4261
|
"Specify Original/New group index via options -OG/-GI", self.PGOPT['extlog'])
|
|
4262
|
+
if cpass == 1: # -AL move pass: move the files in a child process; the record pass sets the record
|
|
4263
|
+
moves = []
|
|
4264
|
+
if aolds[i] != anews[i]: moves.append(('L', anews[i], aolds[i], None))
|
|
4265
|
+
if moves: self.run_copy(i, self.move_pass_files, moves, self.PGOPT['emerol']|self.OVERRIDE)
|
|
4266
|
+
continue
|
|
3943
4267
|
if aolds[i] != anews[i]:
|
|
3944
|
-
if not self.
|
|
4268
|
+
if not self.move_one(i, 'L', anews[i], aolds[i], None, self.PGOPT['emerol']|self.OVERRIDE):
|
|
3945
4269
|
self.RETSTAT = 1
|
|
3946
4270
|
continue
|
|
3947
4271
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
3948
4272
|
scnt += 1
|
|
3949
4273
|
self.set_one_savedfile(i, pgrec, snews[i], fnames, tnews[i], None, tmpds)
|
|
3950
4274
|
if pgrec['bid']: self.save_move_info(pgrec['bid'], solds[i], type, 'S', self.params['OD'], snews[i], tnews[i], 'S', dsid)
|
|
4275
|
+
if cpass == 1: # the record pass checks the moves, finishes failed ones and sets the records
|
|
4276
|
+
self.wait_copy_children()
|
|
4277
|
+
self.reset_errmsg(0) # the record pass finds and counts any error again
|
|
4278
|
+
return
|
|
3951
4279
|
self.pglog("{}/{}, Disk/Record, of {} Saved file{} moved".format(scnt, self.MODCNT, self.ALLCNT, s), self.PGOPT['emllog'])
|
|
3952
4280
|
if self.PGLOG['DSCHECK']:
|
|
3953
4281
|
self.set_dscheck_dcount(self.ALLCNT, chksize, self.PGOPT['extlog'])
|
|
@@ -3959,13 +4287,18 @@ class DsArch(PgArch, PgMeta):
|
|
|
3959
4287
|
self.reset_rdadb_version(self.params['OD'])
|
|
3960
4288
|
if 'EM' in self.params: self.PGLOG['PRGMSG'] = ""
|
|
3961
4289
|
|
|
3962
|
-
def move_backup_files(self):
|
|
4290
|
+
def move_backup_files(self, cpass=0):
|
|
3963
4291
|
"""
|
|
3964
4292
|
Move Quasar backup files to a different dataset and update RDADB records.
|
|
3965
4293
|
|
|
3966
4294
|
Transfers ownership of bfile records to the target dataset (-OD) and
|
|
3967
4295
|
updates the backup archive note via save_move_info().
|
|
3968
4296
|
Sets self.RETSTAT on failures.
|
|
4297
|
+
|
|
4298
|
+
Args:
|
|
4299
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
4300
|
+
move pass (moves in up to N child processes, no records) and then 2
|
|
4301
|
+
for the record pass (see archive_in_passes())
|
|
3969
4302
|
"""
|
|
3970
4303
|
s = 's' if self.ALLCNT > 1 else ''
|
|
3971
4304
|
tname = 'bfile'
|
|
@@ -4014,7 +4347,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
4014
4347
|
chksize = self.PGLOG['DSCHECK']['size']
|
|
4015
4348
|
reorder = self.MODCNT = bcnt = dcnt = 0
|
|
4016
4349
|
for i in range(bidx, self.ALLCNT):
|
|
4017
|
-
if i > bidx and ((i-bidx)%20) == 0:
|
|
4350
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
4018
4351
|
if self.PGLOG['DSCHECK']:
|
|
4019
4352
|
self.set_dscheck_dcount(i, chksize, self.PGOPT['extlog'])
|
|
4020
4353
|
if 'EM' in self.params:
|
|
@@ -4037,20 +4370,31 @@ class DsArch(PgArch, PgMeta):
|
|
|
4037
4370
|
continue
|
|
4038
4371
|
dmove = bmove = 1
|
|
4039
4372
|
if type == 'B': dmove = 0
|
|
4373
|
+
if cpass == 1: # -AL move pass: move the files in a child process; the record pass sets the record
|
|
4374
|
+
moves = []
|
|
4375
|
+
if qolds[i] != qnews[i]:
|
|
4376
|
+
if bmove: moves.append(('B', qnews[i], qolds[i], bkend))
|
|
4377
|
+
if dmove: moves.append(('B', qnews[i], qolds[i], drend))
|
|
4378
|
+
if moves: self.run_copy(i, self.move_pass_files, moves, self.PGOPT['emerol']|self.OVERRIDE)
|
|
4379
|
+
continue
|
|
4040
4380
|
if qolds[i] != qnews[i]:
|
|
4041
4381
|
if bmove:
|
|
4042
|
-
if not self.
|
|
4382
|
+
if not self.move_one(i, 'B', qnews[i], qolds[i], bkend, self.PGOPT['emerol']|self.OVERRIDE):
|
|
4043
4383
|
self.RETSTAT = 1
|
|
4044
4384
|
continue
|
|
4045
4385
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
4046
4386
|
bcnt += 1
|
|
4047
4387
|
if dmove:
|
|
4048
|
-
if not self.
|
|
4388
|
+
if not self.move_one(i, 'B', qnews[i], qolds[i], drend, self.PGOPT['emerol']|self.OVERRIDE):
|
|
4049
4389
|
self.RETSTAT = 1
|
|
4050
4390
|
continue
|
|
4051
4391
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
4052
4392
|
dcnt += 1
|
|
4053
4393
|
self.set_one_backfile(i, pgrec, bnews[i], fnames, tnews[i], tmpds)
|
|
4394
|
+
if cpass == 1: # the record pass checks the moves, finishes failed ones and sets the records
|
|
4395
|
+
self.wait_copy_children()
|
|
4396
|
+
self.reset_errmsg(0) # the record pass finds and counts any error again
|
|
4397
|
+
return
|
|
4054
4398
|
self.pglog("{}/{}/{}, Quasar/Drdata/Record, of {} Backup file{} moved".format(bcnt, dcnt, self.MODCNT, self.ALLCNT, s), self.PGOPT['emllog'])
|
|
4055
4399
|
if self.PGLOG['DSCHECK']:
|
|
4056
4400
|
self.set_dscheck_dcount(self.ALLCNT, chksize, self.PGOPT['extlog'])
|
|
@@ -4062,7 +4406,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
4062
4406
|
self.reset_rdadb_version(self.params['OD'])
|
|
4063
4407
|
if 'EM' in self.params: self.PGLOG['PRGMSG'] = ""
|
|
4064
4408
|
|
|
4065
|
-
def web_to_saved_files(self):
|
|
4409
|
+
def web_to_saved_files(self, cpass=0):
|
|
4066
4410
|
"""
|
|
4067
4411
|
Convert web files to saved files (-TW action).
|
|
4068
4412
|
|
|
@@ -4070,6 +4414,11 @@ class DsArch(PgArch, PgMeta):
|
|
|
4070
4414
|
new sfile RDADB record, and removes the old wfile record. Optionally
|
|
4071
4415
|
also deletes the file from the object store. Preserves backup links.
|
|
4072
4416
|
Sets self.RETSTAT on unresolved failures.
|
|
4417
|
+
|
|
4418
|
+
Args:
|
|
4419
|
+
cpass -- 0 for a single pass; with -AL N, archive_in_passes() calls 1 for the
|
|
4420
|
+
move pass (moves in up to N child processes, no records) and then 2
|
|
4421
|
+
for the record pass (see archive_in_passes())
|
|
4073
4422
|
"""
|
|
4074
4423
|
s = 's' if self.ALLCNT > 1 else ''
|
|
4075
4424
|
tname = 'sfile'
|
|
@@ -4147,7 +4496,7 @@ class DsArch(PgArch, PgMeta):
|
|
|
4147
4496
|
fnames = None
|
|
4148
4497
|
metatotal = metacnt = reorder = wcnt = ocnt = dcnt = self.ADDCNT = self.MODCNT = 0
|
|
4149
4498
|
for i in range(bidx, self.ALLCNT):
|
|
4150
|
-
if i > bidx and ((i-bidx)%20) == 0:
|
|
4499
|
+
if cpass != 1 and i > bidx and ((i-bidx)%20) == 0:
|
|
4151
4500
|
if metacnt >= self.PGOPT['RSMAX']:
|
|
4152
4501
|
metatotal += self.process_meta_delete("W", self.PGOPT['emerol'])
|
|
4153
4502
|
metacnt = 0
|
|
@@ -4179,19 +4528,29 @@ class DsArch(PgArch, PgMeta):
|
|
|
4179
4528
|
wfrom = 0
|
|
4180
4529
|
elif locflag == 'G':
|
|
4181
4530
|
ofrom = 0
|
|
4531
|
+
if cpass == 1: # -AL move pass: move the file in a child process; the record pass sets the record
|
|
4532
|
+
moves = [('L', anews[i], aolds[i], None) if wfrom else ('G', anews[i], oolds[i], frombucket)]
|
|
4533
|
+
if ofrom: moves.append(('X', None, oolds[i], frombucket))
|
|
4534
|
+
self.run_copy(i, self.move_pass_files, moves, self.PGOPT['emerol']|self.OVERRIDE)
|
|
4535
|
+
continue
|
|
4536
|
+
inpass = cpass == 2 and i in self.CPFILES
|
|
4182
4537
|
if wfrom:
|
|
4183
|
-
stat = self.
|
|
4538
|
+
stat = self.move_one(i, 'L', anews[i], aolds[i], None, self.PGOPT['emerol']|self.OVERRIDE)
|
|
4184
4539
|
wfrom = 0
|
|
4185
4540
|
wcnt += 1
|
|
4186
4541
|
else:
|
|
4187
|
-
|
|
4542
|
+
if inpass and self.check_cross_copy(i, wolds[i], 'G', anews[i], None, pgrec['data_size']):
|
|
4543
|
+
stat = 1 # downloaded in the move pass
|
|
4544
|
+
else:
|
|
4545
|
+
stat = self.object_copy_local(anews[i], oolds[i], frombucket, self.PGOPT['emerol']|self.OVERRIDE)
|
|
4188
4546
|
ocnt += 1
|
|
4189
4547
|
if not stat:
|
|
4190
4548
|
self.RETSTAT = 1
|
|
4191
4549
|
continue
|
|
4192
4550
|
if self.PGLOG['DSCHECK']: chksize += pgrec['data_size']
|
|
4193
4551
|
if wfrom: self.delete_local_file(aolds[i], self.PGOPT['emerol'])
|
|
4194
|
-
if ofrom
|
|
4552
|
+
if ofrom and (not inpass or self.check_object_file(oolds[i], frombucket, 0, 0)):
|
|
4553
|
+
self.delete_object_file(oolds[i], frombucket, self.PGOPT['emerol'])
|
|
4195
4554
|
if self.PGOPT['GXTYP'].find(type) > -1 and ('DX' in self.params or pgrec and pgrec['meta_link'] and pgrec['meta_link'] != 'N' and 'KM' not in self.params):
|
|
4196
4555
|
metacnt += self.record_meta_delete('W', dsid, pgrec['wfile'])
|
|
4197
4556
|
if pgrec['bid'] and not self.params['QF'][i]: self.params['QF'][i] = pgrec['bid']
|
|
@@ -4208,6 +4567,10 @@ class DsArch(PgArch, PgMeta):
|
|
|
4208
4567
|
info = self.get_file_origin_info(snews[i], pgrec)
|
|
4209
4568
|
self.set_one_savedfile(i, None, snews[i], fnames, tnews[i], info, dsid, 12)
|
|
4210
4569
|
if pgrec['bid']: self.save_move_info(pgrec['bid'], wolds[i], type, 'W', self.params['OD'], snews[i], tnews[i], 'S', dsid)
|
|
4570
|
+
if cpass == 1: # the record pass checks the moves, finishes failed ones and sets the records
|
|
4571
|
+
self.wait_copy_children()
|
|
4572
|
+
self.reset_errmsg(0) # the record pass finds and counts any error again
|
|
4573
|
+
return
|
|
4211
4574
|
self.pglog("{}/{}/{}/{}, Disk/Object/RecordDelete/RecordAdd, of {} Web file{} moved".format(wcnt, ocnt, dcnt, self.ADDCNT, self.ALLCNT, s), self.PGOPT['emllog'])
|
|
4212
4575
|
if metacnt > 0:
|
|
4213
4576
|
metatotal += self.process_meta_delete('W', self.PGOPT['emerol'])
|