int DLL_DECL dpm_replicatex(const char *path, char f_type, const char *s_token, time_t ltime, char *pfn) { struct dpm_filestatus *filestatuses = NULL; char *from_turl; struct dpm_getfilereq getfilereq; struct dpm_getfilestatus *getfilestatus; int i; int nbreplies; char *p; static char *protocols[] = {"rfio"}; struct dpm_putfilereq putfilereq; struct dpm_putfilestatus *putfilestatus; int r = 0; char r_tokeng[CA_MAXDPMTOKENLEN+1]; char r_tokenp[CA_MAXDPMTOKENLEN+1]; int save_serrno; char sfn[CA_MAXSFNLEN+1]; struct Cns_filestatg statbuf; int status; char *surl; char *to_turl; char turl[CA_MAXSFNLEN+1]; if (s_token && strlen (s_token) > CA_MAXDPMTOKENLEN) { serrno = ENAMETOOLONG; return (-1); } if (strncmp (path, "srm://", 6) == 0 || (strncmp (path, CNS_ROOT, sizeof(CNS_ROOT)-1) == 0 && (*(path+sizeof(CNS_ROOT)-1) == '\0' || *(path+sizeof(CNS_ROOT)-1) == '/'))) { surl = (char *) path; memset (&getfilereq, 0, sizeof(getfilereq)); getfilereq.from_surl = surl; if ((status = dpm_get (1, &getfilereq, 1, protocols, NULL, 0, r_tokeng, &nbreplies, &getfilestatus)) < 0) return (-1); /* wait for request status "Done" or "Failed" */ while (status == DPM_QUEUED || status == DPM_ACTIVE) { if (getfilestatus->from_surl) free (getfilestatus->from_surl); if (getfilestatus->turl) free (getfilestatus->turl); if (getfilestatus->errstring) free (getfilestatus->errstring); free (getfilestatus); sleep ((r++ == 0) ? 1 : DEFPOLLINT); if ((status = dpm_getstatus_getreq (r_tokeng, 0, NULL, &nbreplies, &getfilestatus)) < 0) return (-1); } if (getfilestatus->turl) from_turl = getfilestatus->turl; if (getfilestatus->from_surl) free (getfilestatus->from_surl); if (getfilestatus->errstring) free (getfilestatus->errstring); free (getfilestatus); } else { if (Cns_statr (path, &statbuf) < 0) return (-1); strcpy (turl, "rfio://"); strcpy (turl + 7, path); p = strchr (turl + 7, ':'); *p = '/'; from_turl = turl; if (Cns_getpath (NULL, statbuf.fileid, sfn) < 0) return (-1); surl = sfn; } /* get turl for replica */ memset (&putfilereq, 0, sizeof(putfilereq)); putfilereq.to_surl = surl; putfilereq.f_type = f_type; if (s_token) strcpy(putfilereq.s_token, s_token); putfilereq.f_lifetime = ltime; if ((status = dpm_put (1, &putfilereq, 1, protocols, NULL, 4, 0, r_tokenp, &nbreplies, &putfilestatus)) < 0) return (-1); /* wait for request status "Done" or "Failed" */ r = 0; while (status == DPM_QUEUED || status == DPM_ACTIVE) { if (putfilestatus->to_surl) free (putfilestatus->to_surl); if (putfilestatus->turl) free (putfilestatus->turl); if (putfilestatus->errstring) free (putfilestatus->errstring); free (putfilestatus); sleep ((r++ == 0) ? 1 : DEFPOLLINT); if ((status = dpm_getstatus_putreq (r_tokenp, 0, NULL, &nbreplies, &putfilestatus)) < 0) return (-1); } if (putfilestatus->turl) to_turl = putfilestatus->turl; if (putfilestatus->to_surl) free (putfilestatus->to_surl); if (putfilestatus->errstring) free (putfilestatus->errstring); free (putfilestatus); status = rfio_rcp (from_turl, to_turl, 0); save_serrno = serrno; if (from_turl != turl) { free (from_turl); (void) dpm_relfiles (r_tokeng, 1, &surl, 0, &nbreplies, &filestatuses); dpm_free_filest (nbreplies, filestatuses); } filestatuses = NULL; if (status < 0) { (void) dpm_abortfiles (r_tokenp, 1, &surl, &nbreplies, &filestatuses); } else { status = dpm_putdone (r_tokenp, 1, &surl, &nbreplies, &filestatuses); save_serrno = serrno; if (status < 0 && nbreplies == 1 && filestatuses && *filestatuses->errstring) dpm_errmsg (NULL, "%s", filestatuses->errstring); } dpm_free_filest (nbreplies, filestatuses); serrno = save_serrno; if (pfn != NULL) { *pfn = '\0'; if ((p = strstr (to_turl, "rfio://"))) { p += 7; strcpy (pfn, p); if ((p = strchr (pfn, '/'))) *p = ':'; } if (!*pfn) { status = -1; serrno = ENOENT; } } free (to_turl); return (status); }
int dpmcopy_push (struct dpm_dbfd *dbfd, struct dpm_req *dpm_req, struct dpm_copy_filereq *cpr_entry, int nbfiles) { char errbuf[256]; char errstring[256]; struct dpm_filestatus *filestatuses; int *filstatus = NULL; char func[16]; struct dpm_getfilereq *getfilereqs; struct dpm_getfilestatus *getfilestatuses = NULL; int i; int j = 0; int nbgetreplies; int nbputreplies; int nbreplies; char *p; static char *protocols[] = {"gsiftp"}; struct dpm_putfilereq *putfilereqs; struct dpm_putfilestatus *putfilestatus = NULL; char *q; int r = 0; int r1; char r_tokeng[CA_MAXDPMTOKENLEN+1]; char *r_tokenp; dpm_dbrec_addr rec_addrf; char srm_endpoint[256]; int status; int statusg; strcpy (func, "dpmcopy_push"); if (nbfiles == 0) return (0); /* nothing to be done */ nb_file_err = 0; /* build the get/put requests */ if ((getfilereqs = calloc (nbfiles, sizeof(struct dpm_getfilereq))) == NULL || (putfilereqs = calloc (nbfiles, sizeof(struct dpm_putfilereq))) == NULL || (filstatus = calloc (nbfiles, sizeof(int))) == NULL) { dpm_req->status = DPM_FAILED | ENOMEM; return (-1); } for (i = 0; i < dpm_req->nbreqfiles; i++) { (void) dpm_start_tr (0, dbfd); if (dpm_get_cpr_by_fullid (dbfd, dpm_req->r_token, i, cpr_entry, 1, &rec_addrf) < 0) { dpm_abort_tr (dbfd); continue; } if (cpr_entry->status != DPM_QUEUED) { /* No need to process */ dpm_abort_tr (dbfd); if (cpr_entry->status == DPM_ABORTED || (cpr_entry->status & 0xF000) == DPM_FAILED) nb_file_err++; continue; } if ((p = strdup (cpr_entry->from_surl)) == NULL || (q = strdup (cpr_entry->to_surl)) == NULL) { cpr_entry->status = DPM_FAILED | ENOMEM; (void) upd_cpr (dbfd, &rec_addrf, cpr_entry); continue; } cpr_entry->status = DPM_ACTIVE; (void) upd_cpr (dbfd, &rec_addrf, cpr_entry); (getfilereqs+j)->from_surl = p; (putfilereqs+j)->to_surl = q; (putfilereqs+j)->f_lifetime = cpr_entry->f_lifetime; (putfilereqs+j)->f_type = cpr_entry->f_type == '_' ? '\0' : cpr_entry->f_type; strcpy ((putfilereqs+j)->s_token, cpr_entry->s_token); (putfilereqs+j)->ret_policy = cpr_entry->ret_policy == '_' ? '\0' : cpr_entry->ret_policy; (putfilereqs+j)->ac_latency = cpr_entry->ac_latency == '_' ? '\0' : cpr_entry->ac_latency; j++; } if (j == 0) return (0); /* nothing to be done */ dpm_seterrbuf (errbuf, sizeof(errbuf)); if (get_srm_endpoint (putfilereqs->to_surl, srm_endpoint, sizeof(srm_endpoint)) < 0) { dpm_req->status = DPM_FAILED | EINVAL; strcpy (dpm_req->errstring, "SRM endpoint too long"); return (-1); } /* get source TURL(s) */ dpmlogit (func, "calling dpm_get\n"); errbuf[0] = '\0'; *r_tokeng = '\0'; statusg = dpm_get (j, getfilereqs, 1, protocols, NULL, dpm_req->retrytime, r_tokeng, &nbgetreplies, &getfilestatuses); if (*r_tokeng) dpmlogit (func, "dpm_get returned request token %s\n", r_tokeng); /* wait for any source TURL ready */ while (1) { for (i = 0; i < j; i++) { if (*(filstatus+i)) continue; /* already processed */ if (! getfilestatuses) { if (statusg < 0) { *(filstatus+i) = DPM_FAILED | serrno; dpmcopy_set_errstring ("get failed", errbuf, NULL, errstring, sizeof(errstring)); (void) upd_cpr2 (dbfd, dpm_req->r_token, (getfilereqs+i)->from_surl, (putfilereqs+i)->to_surl, 0, *(filstatus+i), errstring, 0, cpr_entry); } continue; } if (statusg >= 0 && ((getfilestatuses+i)->status == DPM_QUEUED || (getfilestatuses+i)->status == DPM_ACTIVE)) continue; if ((getfilestatuses+i)->status != DPM_READY) { if ((getfilestatuses+i)->status < DPM_READY) *(filstatus+i) = statusg < 0 ? (DPM_FAILED | serrno) : statusg; else *(filstatus+i) = (getfilestatuses+i)->status; dpmcopy_set_errstring ("get failed", errbuf, (getfilestatuses+i)->errstring, errstring, sizeof(errstring)); (void) upd_cpr2 (dbfd, dpm_req->r_token, (getfilereqs+i)->from_surl, (putfilereqs+i)->to_surl, 0, *(filstatus+i), errstring, 0, cpr_entry); continue; } /* source TURL ready */ (putfilereqs+i)->requested_size = (getfilestatuses+i)->filesize; /* get destination TURL */ errbuf[0] = '\0'; r1 = 0; putfilestatus = NULL; r_tokenp = NULL; dpmlogit (func, "calling srmv2_put\n"); status = srmv2_put (1, putfilereqs+i, 1, protocols, (dpm_req->flags & 1), dpm_req->retrytime, &r_tokenp, &nbputreplies, &putfilestatus); if (r_tokenp) dpmlogit (func, "srmv2_put returned request token %s\n", r_tokenp); /* wait for destination TURL ready */ while (status == DPM_QUEUED || status == DPM_ACTIVE) { dpm_free_pfilest (nbputreplies, putfilestatus); sleep ((r1++ == 0) ? 1 : DEFPOLLINT); errbuf[0] = '\0'; putfilestatus = NULL; status = srmv2_getstatus_putreq (r_tokenp, 0, NULL, srm_endpoint, &nbputreplies, &putfilestatus, dpm_req->retrytime); } if (! putfilestatus) { *(filstatus+i) = status < 0 ? (DPM_FAILED | serrno) : status; dpmcopy_set_errstring ("put failed", errbuf, NULL, errstring, sizeof(errstring)); goto upd_cfr; } if (putfilestatus->status != DPM_READY) { if (putfilestatus->status < DPM_FAILED) *(filstatus+i) = status < 0 ? (DPM_FAILED | serrno) : status; else *(filstatus+i) = putfilestatus->status; dpmcopy_set_errstring ("put failed", errbuf, putfilestatus->errstring, errstring, sizeof(errstring)); goto upd_cfr; } /* destination TURL ready, copy file */ errbuf[0] = '\0'; *(filstatus+i) = DPM_ACTIVE; dpmlogit (func, "copying %s to %s\n", (getfilestatuses+i)->turl, putfilestatus->turl); status = dpm_copyfile ((getfilestatuses+i)->turl, putfilestatus->turl, 5, 0); filestatuses = NULL; if (status < 0) { dpmlogit (func, "dpm_copyfile returned %d, serrno = %d\n", status, serrno); status = DPM_FAILED | serrno; dpmcopy_set_errstring ("copy failed", errbuf, NULL, errstring, sizeof(errstring)); (void) srmv2_abortfiles (r_tokenp, 1, &putfilestatus->to_surl, &nbreplies, &filestatuses, dpm_req->retrytime); } else { dpmlogit (func, "dpm_copyfile returned %d\n", status); errbuf[0] = '\0'; dpmlogit (func, "calling srmv2_putdone\n"); status = srmv2_putdone (r_tokenp, 1, &putfilestatus->to_surl, &nbreplies, &filestatuses, dpm_req->retrytime); if (status < 0) { status = DPM_FAILED | serrno; dpmcopy_set_errstring ("putdone failed", errbuf, NULL, errstring, sizeof(errstring)); } else errstring[0] = '\0'; } dpm_free_filest (nbreplies, filestatuses); *(filstatus+i) = status ? status : DPM_DONE; /* try to get target SURL lifetime */ if (status == 0) { dpm_free_pfilest (nbputreplies, putfilestatus); putfilestatus = NULL; if (srmv2_getstatus_putreq (r_tokenp, 0, NULL, srm_endpoint, &nbputreplies, &putfilestatus, dpm_req->retrytime) == 0 && putfilestatus) cpr_entry->f_lifetime = putfilestatus->f_lifetime; } upd_cfr: filestatuses = NULL; (void) dpm_relfiles (r_tokeng, 1, &(getfilestatuses+i)->from_surl, 0, &nbreplies, &filestatuses); dpm_free_filest (nbreplies, filestatuses); (void) upd_cpr2 (dbfd, dpm_req->r_token, (getfilereqs+i)->from_surl, (putfilereqs+i)->to_surl, (*(filstatus+i) == DPM_DONE) ? (getfilestatuses+i)->filesize : 0, (*(filstatus+i) == DPM_DONE) ? 0 : *(filstatus+i), errstring, cpr_entry->f_lifetime, cpr_entry); dpm_free_pfilest (nbputreplies, putfilestatus); if (r_tokenp) free (r_tokenp); } for (i = 0; i < j; i++) { if (*(filstatus+i) == 0 || *(filstatus+i) == DPM_ACTIVE) break; } if (i >= j) break; /* no more pending file request */ dpm_free_gfilest (nbgetreplies, getfilestatuses); getfilestatuses = NULL; errbuf[0] = '\0'; sleep ((r++ == 0) ? 1 : DEFPOLLINT); statusg = dpm_getstatus_getreq (r_tokeng, 0, NULL, &nbgetreplies, &getfilestatuses); } return (0); }