inline int gridftp_rw_commit_put(const Glib::Quark & scope, GridFTPFileDesc* desc) { char buffer[2]; if (is_write_only(desc->open_flags)) { gfal_log(GFAL_VERBOSE_TRACE, "Commit change for the current stream PUT ... "); gridftp_write_stream(GFAL_GRIDFTP_SCOPE_WRITE, desc->stream, buffer, 0, true); gfal_log(GFAL_VERBOSE_TRACE, "Committed with success ... "); } return 0; }
void gridftp_unlink_internal(gfal2_context_t context, GridFTPSessionHandler* sess, const char * path) { gfal_log(GFAL_VERBOSE_TRACE, " -> [GridFTPModule::unlink] "); GridFTPRequestState req(sess); // get connection session globus_result_t res = globus_ftp_client_delete(req.handler->get_ftp_client_handle(), path, req.handler->get_ftp_client_operationattr(), globus_ftp_client_done_callback, &req); gfal_globus_check_result(GFAL_GRIDFTP_SCOPE_UNLINK, res); req.wait(GFAL_GRIDFTP_SCOPE_UNLINK); gfal_log(GFAL_VERBOSE_TRACE, " <- [GridFTPModule::unlink] "); }
extern "C" ssize_t gfal_gridftp_writeG(plugin_handle ch, gfal_file_handle fd, const void* buff, size_t s_buff, GError** err) { g_return_val_err_if_fail(ch != NULL && fd != NULL, -1, err, "[gfal_gridftp_writeG][gridftp] Invalid parameters"); GError * tmp_err = NULL; int ret = -1; gfal_log(GFAL_VERBOSE_TRACE, " -> [gfal_gridftp_writeG]"); CPP_GERROR_TRY ret = (int) ((static_cast<GridFTPModule*>(ch))->write(fd, buff, s_buff)); CPP_GERROR_CATCH(&tmp_err); gfal_log(GFAL_VERBOSE_TRACE, " [gfal_gridftp_writeG] <-"); G_RETURN_ERR(ret, tmp_err, err); }
// open C bind extern "C" gfal_file_handle gfal_gridftp_openG(plugin_handle handle, const char* url, int flag, mode_t mode, GError** err) { g_return_val_err_if_fail(handle != NULL && url != NULL, NULL, err, "[gfal_gridftp_openG][gridftp] Invalid parameters"); GError * tmp_err = NULL; gfal_file_handle ret = NULL; gfal_log(GFAL_VERBOSE_TRACE, " -> [gfal_gridftp_openG]"); CPP_GERROR_TRY ret = ((static_cast<GridFTPModule*>(handle))->open(url, flag, mode)); CPP_GERROR_CATCH(&tmp_err); gfal_log(GFAL_VERBOSE_TRACE, " [gfal_gridftp_openG]<-"); G_RETURN_ERR(ret, tmp_err, err); }
virtual ~GridFTPFileDesc() { gfal_log(GFAL_VERBOSE_TRACE, "destroy descriptor for %s", url.c_str()); delete stream; delete request; delete handler; }
extern "C" int gfal_gridftp_unlinkG(plugin_handle handle, const char* url, GError** err) { g_return_val_err_if_fail(handle != NULL && url != NULL, -1, err, "[gfal_gridftp_unlinkG][gridftp] Invalid parameters"); GError * tmp_err = NULL; int ret = -1; gfal_log(GFAL_VERBOSE_TRACE, " -> [gfal_gridftp_unlinkG]"); CPP_GERROR_TRY (static_cast<GridFTPModule*>(handle))->unlink(url); ret = 0; CPP_GERROR_CATCH(&tmp_err); gfal_log(GFAL_VERBOSE_TRACE, " [gfal_gridftp_unlinkG] <-"); G_RETURN_ERR(ret, tmp_err, err); }
ssize_t GridFTPModule::read(gfal_file_handle handle, void* buffer, size_t count) { GridFTPFileDesc* desc = static_cast<GridFTPFileDesc*>(gfal_file_handle_get_fdesc(handle)); ssize_t ret; Glib::Mutex::Lock locker(desc->lock); if (desc->is_not_seeked() && is_read_only(desc->open_flags) && desc->stream != NULL) { gfal_log(GFAL_VERBOSE_TRACE, " read in the GET main flow ... "); ret = gridftp_read_stream(GFAL_GRIDFTP_SCOPE_READ, desc->stream, buffer, count); } else { gfal_log(GFAL_VERBOSE_TRACE, " read with a pread ... "); ret = gridftp_rw_internal_pread(_handle_factory, desc, buffer, count, desc->current_offset); } desc->current_offset += ret; return ret; }
extern "C" off_t gfal_gridftp_lseekG(plugin_handle ch, gfal_file_handle fd, off_t offset, int whence, GError** err) { g_return_val_err_if_fail(ch != NULL && fd != NULL, -1, err, "[gfal_gridftp_lseekG][gridftp] Invalid parameters"); GError * tmp_err = NULL; off_t ret = -1; gfal_log(GFAL_VERBOSE_TRACE, " -> [gfal_gridftp_lseekG]"); CPP_GERROR_TRY ret = ((static_cast<GridFTPModule*>(ch))->lseek(fd, offset, whence)); CPP_GERROR_CATCH(&tmp_err); gfal_log(GFAL_VERBOSE_TRACE, " [gfal_gridftp_lseekG]<-"); G_RETURN_ERR(ret, tmp_err, err); }
GridFTPFileDesc(GridFTPSessionHandler* h, GridFTPRequestState* r, GridFTPStreamState * s, const std::string & _url, int flags) : handler(h), request(r), stream(s) { gfal_log(GFAL_VERBOSE_TRACE, "create descriptor for %s", _url.c_str()); this->open_flags = flags; current_offset = 0; url = _url; }
// gridFTP open is restricted by the protocol : READ or Write but not both // gfal_file_handle GridFTPModule::open(const char* url, int flag, mode_t mode) { GridFTPSessionHandler *handler = new GridFTPSessionHandler(_handle_factory, url); GridFTPStreamState* stream = new GridFTPStreamState(handler); GridFTPRequestState* request = new GridFTPRequestState(handler); std::auto_ptr<GridFTPFileDesc> desc(new GridFTPFileDesc(handler, request, stream, url, flag)); gfal_log(GFAL_VERBOSE_TRACE, " -> [GridFTPModule::open] "); globus_result_t res; // check ENOENT condition for R_ONLY if (is_read_only(desc->open_flags) && this->exists(url) == false) { char err_buff[2048]; snprintf(err_buff, 2048, " gridftp open error : %s on url %s", strerror(ENOENT), url); throw Gfal::CoreException(GFAL_GRIDFTP_SCOPE_OPEN, err_buff, ENOENT); } if (is_read_only(desc->open_flags)) { gfal_log(GFAL_VERBOSE_TRACE, " -> initialize FTP GET global operations... "); res = globus_ftp_client_get( desc->stream->handler->get_ftp_client_handle(), url, desc->stream->handler->get_ftp_client_operationattr(), NULL, globus_ftp_client_done_callback, desc->request); gfal_globus_check_result(GFAL_GRIDFTP_SCOPE_OPEN, res); } else if (is_write_only(desc->open_flags)) { gfal_log(GFAL_VERBOSE_TRACE, " -> initialize FTP PUT global operations ... "); res = globus_ftp_client_put( desc->stream->handler->get_ftp_client_handle(), url, desc->stream->handler->get_ftp_client_operationattr(), NULL, globus_ftp_client_done_callback, desc->request); gfal_globus_check_result(GFAL_GRIDFTP_SCOPE_OPEN, res); } else { gfal_log(GFAL_VERBOSE_TRACE, " -> no operation initialization, switch to partial read/write mode..."); desc->reset(); } gfal_log(GFAL_VERBOSE_TRACE, " <- [GridFTPModule::open] "); return gfal_file_handle_new2(gridftp_plugin_name(), (gpointer) desc.release(), NULL, url); }
/** * set buff_err to the current gfal error, reentrant function * @return pointer to buff_err for convenience */ char* gfal_str_GError_r(GError** err, char* buff_err, size_t s_err){ if(err==NULL || *err==NULL){ gfal_log(GFAL_VERBOSE_DEBUG,"copy string NULL error"); g_strlcpy(buff_err,"[gfal] No Error reported", s_err); }else{ g_strlcpy(buff_err,"[gfal]", s_err); g_strlcat(buff_err, (*err)->message, s_err); } return buff_err; }
/** * \brief display the full GError message on stderr and free the memory associated */ void gfal_release_GError(GError** err) { if(err==NULL || *err==NULL){ gfal_log(GFAL_VERBOSE_DEBUG," release NULL error"); return; } g_printerr("[gfal] %s\n", (*err)->message); g_clear_error(err); *err=NULL; }
GridFTPSimpleListReader::GridFTPSimpleListReader(GridFTPModule* gsiftp, const char* path) { GridFTPFactory* factory = gsiftp->get_session_factory(); this->handler = new GridFTPSessionHandler(factory, path); this->request_state = new GridFTPRequestState(this->handler); this->stream_state = new GridFTPStreamState(this->handler); gfal_log(GFAL_VERBOSE_TRACE, " -> [GridftpSimpleListReader::GridftpSimpleListReader]"); globus_result_t res = globus_ftp_client_list( // start req this->handler->get_ftp_client_handle(), path, this->handler->get_ftp_client_operationattr(), globus_ftp_client_done_callback, this->request_state); gfal_globus_check_result(GridFTPSimpleReaderQuark, res); stream_buffer = new GridFTPStreamBuffer(this->stream_state, GridFTPSimpleReaderQuark); gfal_log(GFAL_VERBOSE_TRACE, " <- [GridftpSimpleListReader::GridftpSimpleListReader]"); }
struct dirent* GridFTPSimpleListReader::readdir() { gfal_log(GFAL_VERBOSE_TRACE, " -> [GridftpSimpleListReader::readdir]"); std::string line; std::istream in(stream_buffer); if (!std::getline(in, line)) return NULL; if (gridftp_readdir_parser(line, &dbuffer) != 0) { throw Glib::Error(GridFTPSimpleReaderQuark, EINVAL, Glib::ustring("Error parsing GridFTP line: ").append(line)); } // Workaround for LCGUTIL-295 // Some endpoints return the absolute path when listing an empty directory if (dbuffer.d_name[0] == '/' || dbuffer.d_name[0] == '\0') return NULL; gfal_log(GFAL_VERBOSE_VERBOSE, " list file %s ", dbuffer.d_name); gfal_log(GFAL_VERBOSE_TRACE, " [GridftpSimpleListReader::readdir] <- "); return &dbuffer; }
// internal pread, do a read query with offset on a different descriptor, do not change the position of the current one. ssize_t gridftp_rw_internal_pread(GridFTPFactory * factory, GridFTPFileDesc* desc, void* buffer, size_t s_buff, off_t offset) { // throw Gfal::CoreException gfal_log(GFAL_VERBOSE_TRACE, " -> [GridFTPModule::internal_pread]"); GridFTPSessionHandler handler(factory, desc->url); GridFTPRequestState request_state(&handler); GridFTPStreamState stream_state(&handler); globus_result_t res = globus_ftp_client_partial_get( handler.get_ftp_client_handle(), desc->url.c_str(), handler.get_ftp_client_operationattr(), NULL, offset, offset + s_buff, globus_ftp_client_done_callback, &request_state); gfal_globus_check_result(GFAL_GRIDFTP_SCOPE_INTERNAL_PREAD, res); ssize_t r_size = gridftp_read_stream(GFAL_GRIDFTP_SCOPE_INTERNAL_PREAD, &stream_state, buffer, s_buff); request_state.wait(GFAL_GRIDFTP_SCOPE_INTERNAL_PREAD); gfal_log(GFAL_VERBOSE_TRACE, "[GridFTPModule::internal_pread] <-"); return r_size; }
// internal pwrite, do a write query with offset on a different descriptor, do not change the position of the current one. ssize_t gridftp_rw_internal_pwrite(GridFTPFactory * factory, GridFTPFileDesc* desc, const void* buffer, size_t s_buff, off_t offset) { // throw Gfal::CoreException gfal_log(GFAL_VERBOSE_TRACE, " -> [GridFTPModule::internal_pwrite]"); GridFTPSessionHandler handler(factory, desc->url); GridFTPRequestState request_state(&handler); GridFTPStreamState stream(&handler); globus_result_t res = globus_ftp_client_partial_put( stream.handler->get_ftp_client_handle(), desc->url.c_str(), stream.handler->get_ftp_client_operationattr(), NULL, offset, offset + s_buff, globus_ftp_client_done_callback, &request_state); gfal_globus_check_result(GFAL_GRIDFTP_SCOPE_INTERNAL_PWRITE, res); ssize_t r_size = gridftp_write_stream(GFAL_GRIDFTP_SCOPE_INTERNAL_PWRITE, &stream, buffer, s_buff, false); // write block request_state.wait(GFAL_GRIDFTP_SCOPE_INTERNAL_PWRITE); gfal_log(GFAL_VERBOSE_TRACE, "[GridFTPModule::internal_pwrite] <-"); return r_size; }
/* * Implementation of gfal_open * */ int gfal_posix_internal_open(const char* path, int flag, mode_t mode){ GError* tmp_err=NULL; gfal_handle handle; int key = -1; gfal_log(GFAL_VERBOSE_TRACE, "%s ->",__func__); if((handle = gfal_posix_instance()) == NULL){ errno = EIO; return -1; } key = gfal2_open(handle, path, flag, &tmp_err); if(tmp_err){ gfal_posix_register_internal_error(handle, "[gfal_open]", tmp_err); errno = tmp_err->code; }else errno=0; return key; }
int gfal_srm_checksumG_fallback(plugin_handle handle, const char* url, const char* check_type, char * checksum_buffer, size_t buffer_length, off_t start_offset, size_t data_length, gboolean turl_fallback, GError ** err){ gfal_log(GFAL_VERBOSE_TRACE, " [gfal_srm_checksumG] ->"); gfal_log(GFAL_VERBOSE_DEBUG, "[gfal_srm_checksumG] try to get checksum %s for %s", check_type, url); char buffer_type[GFAL_URL_MAX_LEN]={0}; GError * tmp_err=NULL; gfal_srmv2_opt* opts = (gfal_srmv2_opt*)handle; const gboolean srm_url = srm_check_url(url); int res = -1; // try SRM checksum only if full file checksum is requested if(srm_url && start_offset==0 && data_length==0 ) { res = gfal_srm_cheksumG_internal(handle, url, checksum_buffer, buffer_length, buffer_type, GFAL_URL_MAX_LEN, &tmp_err); } // Make sure the returned type matches the requested one if(res == 0) { gfal_log(GFAL_VERBOSE_DEBUG, "registered checksum type %s", buffer_type); if(strncasecmp(check_type, buffer_type,GFAL_URL_MAX_LEN) != 0){ // does not match the correct type // this can be because checksum is nto populated on DPM server, cause the first gsiftp checksum calculation res = -1; // cancel result } } // If we got no error, but neither a valid checksum, // fallback into the turl if(res != 0 && !tmp_err && turl_fallback){ gfal_log(GFAL_VERBOSE_TRACE, "\t\tNo valid SRM checksum, fallback to the TURL checksum"); char buff_turl[GFAL_URL_MAX_LEN]; char *res_turl; if(srm_url){ // SRM URL do TURL resolution if( (res = gfal_srm_getTURL_checksum(handle, url, buff_turl, GFAL_URL_MAX_LEN, &tmp_err)) >= 0){ res_turl = buff_turl; }else{ res = -1; } }else{ // native protocol -> act like this res_turl = (char*)url; res =0; } if(res == 0){ gfal_log(GFAL_VERBOSE_TRACE, "\t\t\tExecute checksum on turl %s", res_turl); res= gfal2_checksum(opts->handle, res_turl, check_type, 0,0, checksum_buffer, buffer_length, &tmp_err); } } // If no fallback, then return an empty value else if (!turl_fallback && (tmp_err || res != 0)) { res = 0; memset(checksum_buffer, '\0', buffer_length); } G_RETURN_ERR(res, tmp_err, err); }
struct rfio_proto_ops * gfal_rfio_internal_loader_base(GError** err){ void *dlhandle=NULL; struct rfio_proto_ops * pops = NULL; GError* tmp_err=NULL; char *p; char* libname=NULL; p = getenv ("LCG_RFIO_TYPE"); if (p && strcmp (p, "dpm") == 0) { libname = libdpm_name; } else if (p && strcmp (p, "castor") == 0) { libname= libcastor_name; } if( libname != NULL){ gfal_log(GFAL_VERBOSE_VERBOSE, " lib rfio defined in LCG_RFIO_TYPE : %s", libname); if( (dlhandle = dlopen(libname, RTLD_LAZY)) == NULL){ gfal2_set_error(&tmp_err, gfal2_get_plugin_rfio_quark(), EPROTONOSUPPORT, __func__, " library %s for the rfio_plugin cannot be loaded properly, failure : %s ", libname, dlerror()); } }else{ gfal_log(GFAL_VERBOSE_VERBOSE, "lib rfio is not defined in LCG_RFIO_TYPE, try to found it "); char* tab_lib[] = { libdpm_name, libcastor_name, NULL}; char** p = tab_lib; while(*p != NULL){ if((dlhandle = dlopen (*p, RTLD_LAZY)) != NULL){ gfal_log(GFAL_VERBOSE_VERBOSE, "rfio library %s found! configured to use it", *p); break; } p++; } if(!dlhandle){ gfal2_set_error(&tmp_err, gfal2_get_plugin_rfio_quark(), EPROTONOSUPPORT, __func__, "Unable to find %s or %s, failure : %s ", libcastor_name, libdpm_name, dlerror()); } } if(dlhandle){ pops = g_new0(struct rfio_proto_ops, 1); pops->geterror = (int (*) ()) dlsym (dlhandle, "rfio_serrno"); pops->serror_r = (char* (*) (char*, size_t)) dlsym(dlhandle, "rfio_serror_r"); pops->access = (int (*) (const char *, int)) dlsym (dlhandle, "rfio_access"); pops->chmod = (int (*) (const char *, mode_t)) dlsym (dlhandle, "rfio_chmod"); pops->close = (int (*) (int)) dlsym (dlhandle, "rfio_close"); pops->closedir = (int (*) (DIR *)) dlsym (dlhandle, "rfio_closedir"); pops->lseek = (off_t (*) (int, off_t, int)) dlsym (dlhandle, "rfio_lseek"); pops->lseek64 = (off64_t (*) (int, off64_t, int)) dlsym (dlhandle, "rfio_lseek64"); pops->lstat = (int (*) (const char *, struct stat *)) dlsym (dlhandle, "rfio_lstat"); pops->lstat64 = (int (*) (const char *, struct stat64 *)) dlsym (dlhandle, "rfio_lstat64"); pops->mkdir = (int (*) (const char *, mode_t)) dlsym (dlhandle, "rfio_mkdir"); pops->open = (int (*) (const char *, int, ...)) dlsym (dlhandle, "rfio_open"); pops->opendir = (DIR * (*) (const char *)) dlsym (dlhandle, "rfio_opendir"); pops->read = (ssize_t (*) (int, void *, size_t)) dlsym (dlhandle, "rfio_read"); pops->readdir = (struct dirent * (*) (DIR *)) dlsym (dlhandle, "rfio_readdir"); pops->readdir64 = (struct dirent64 * (*) (DIR *)) dlsym (dlhandle, "rfio_readdir64"); pops->rename = (int (*) (const char *, const char *)) dlsym (dlhandle, "rfio_rename"); pops->rmdir = (int (*) (const char *)) dlsym (dlhandle, "rfio_rmdir"); pops->setfilchg = (ssize_t (*) (int, const void *, size_t)) dlsym (dlhandle, "rfio_HsmIf_FirstWrite"); pops->stat = (int (*) (const char *, struct stat *)) dlsym (dlhandle, "rfio_stat"); pops->stat64 = (int (*) (const char *, struct stat64 *)) dlsym (dlhandle, "rfio_stat64"); pops->unlink = (int (*) (const char *)) dlsym (dlhandle, "rfio_unlink"); pops->write = (ssize_t (*) (int, const void *, size_t)) dlsym (dlhandle, "rfio_write"); } if(tmp_err) gfal2_propagate_prefixed_error(err, tmp_err, __func__); return pops; }