Back to index

nordugrid-arc-nox  1.1.0~rc6
DataPointRLS.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00002 
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006 
00007 #ifdef WIN32 
00008 #include <arc/win32.h>
00009 #include <fcntl.h>
00010 #endif
00011 
00012 #include <arc/DateTime.h>
00013 #include <arc/GUID.h>
00014 #include <arc/Logger.h>
00015 #include <arc/StringConv.h>
00016 #include <arc/globusutils/GlobusWorkarounds.h>
00017 
00018 #include "DataPointRLS.h"
00019 #include "RLS.h"
00020 
00021 #define globus_rls_free_result(err) \
00022   globus_rls_client_error_info(err, NULL, NULL, 0, GLOBUS_FALSE)
00023 
00024 namespace Arc {
00025 
00026   static bool proxy_initialized = false;
00027 
00028   Logger DataPointRLS::logger(DataPoint::logger, "RLS");
00029 
00030   DataPointRLS::DataPointRLS(const URL& url, const UserConfig& usercfg)
00031     : DataPointIndex(url, usercfg),
00032       guid_enabled(false) {
00033     valid_url_options.push_back("guid");
00034     globus_module_activate(GLOBUS_COMMON_MODULE);
00035     globus_module_activate(GLOBUS_IO_MODULE);
00036     globus_module_activate(GLOBUS_RLS_CLIENT_MODULE);
00037     if (!proxy_initialized)
00038       proxy_initialized = GlobusRecoverProxyOpenSSL();
00039     std::string guidopt = url.Option("guid", "no");
00040     if ((guidopt == "yes") || (guidopt == ""))
00041       guid_enabled = true;
00042   }
00043 
00044   DataPointRLS::~DataPointRLS() {
00045     globus_module_deactivate(GLOBUS_RLS_CLIENT_MODULE);
00046     globus_module_deactivate(GLOBUS_IO_MODULE);
00047     globus_module_deactivate(GLOBUS_COMMON_MODULE);
00048   }
00049 
00050   Plugin* DataPointRLS::Instance(PluginArgument *arg) {
00051     DataPointPluginArgument *dmcarg =
00052       dynamic_cast<DataPointPluginArgument*>(arg);
00053     if (!dmcarg)
00054       return NULL;
00055     if (((const URL&)(*dmcarg)).Protocol() != "rls")
00056       return NULL;
00057     // Make this code non-unloadable because Globus
00058     // may have problems with unloading
00059     Glib::Module* module = dmcarg->get_module();
00060     PluginsFactory* factory = dmcarg->get_factory();
00061     if(factory && module) factory->makePersistent(module);
00062     return new DataPointRLS(*dmcarg, *dmcarg);
00063   }
00064 
00065   static const char* get_path_str(const URL& url) {
00066     const std::string& path = url.Path();
00067     if(path.empty() || (path[0] != '/')) return path.c_str();
00068     return (path.c_str()+1);
00069   }
00070 
00071   static bool path_empty(const URL& url) {
00072     const std::string& path = url.Path();
00073     if(path.empty()) return true;
00074     if((path.length() == 1) && (path[0] == '/')) return true;
00075     return false;
00076   }
00077 
00078   static globus_result_t globus_rls_client_lrc_attr_put(globus_rls_handle_t *h, char *key,
00079                                                         globus_rls_attribute_t *attr,
00080                                                         int overwrite) {
00081     globus_result_t err;
00082     int errcode;
00083     err = globus_rls_client_lrc_attr_add(h, key, attr);
00084     if (err != GLOBUS_SUCCESS) {
00085       err = globus_rls_client_error_info(err, &errcode, NULL, 0, GLOBUS_TRUE);
00086       if ((overwrite) && (errcode == GLOBUS_RLS_DBERROR)) {
00087         /* guess this can mean duplicate entry */
00088         globus_result_t err_ = globus_rls_client_lrc_attr_remove(h, key, attr);
00089         globus_rls_free_result(err_);
00090         if (err_ != GLOBUS_SUCCESS)
00091           return err;
00092         return globus_rls_client_lrc_attr_put(h, key, attr, 0);
00093       }
00094       if (errcode != GLOBUS_RLS_ATTR_NEXIST)
00095         return err;
00096       globus_rls_free_result(err);
00097       err = globus_rls_client_lrc_attr_create(h, attr->name,
00098                                               attr->objtype, attr->type);
00099       if (err != GLOBUS_SUCCESS)
00100         return err;
00101       err = globus_rls_client_lrc_attr_add(h, key, attr);
00102     }
00103     return err;
00104   }
00105 
00106   class meta_resolve_rls_t {
00107   public:
00108     DataPointRLS& dprls;
00109     bool source;
00110     DataStatus success;
00111     bool obtained_info;
00112     std::string guid;
00113     meta_resolve_rls_t(DataPointRLS& d, bool s)
00114       : dprls(d),
00115         source(s),
00116         success(DataStatus::NoLocationError),
00117         obtained_info(false) {}
00118   };
00119 
00120   static bool meta_resolve_callback(globus_rls_handle_t *h,
00121                                     const URL& rlsurl, void *arg) {
00122     return ((meta_resolve_rls_t*)arg)->dprls.ResolveCallback(h, rlsurl, arg);
00123   }
00124 
00125   URL DataPointRLS::AddPFN(const URL& purl,bool source) {
00126     if(source) return purl;
00127     bool se_uses_lfn = false;
00128     std::string u = purl.fullstr();
00129     if (purl.Protocol() == "se") {
00130       u += "?";
00131       se_uses_lfn = true;
00132     } else {
00133       u += "/";
00134     }
00135     if (guid_enabled) {
00136       std::string guid = UUID();
00137       if ((!se_uses_lfn) && (!pfn_path.empty()))
00138         u += pfn_path;
00139       else
00140         u += guid;
00141     }
00142     else if ((!se_uses_lfn) && (!pfn_path.empty()))
00143       u += pfn_path;
00144     else
00145       u += get_path_str(url);
00146     return URL(u);
00147   }
00148 
00149 
00150   bool DataPointRLS::ResolveCallback(globus_rls_handle_t *h,
00151                                      const URL& rlsurl, void *arg) {
00152     bool& source(((meta_resolve_rls_t*)arg)->source);
00153     DataStatus& success(((meta_resolve_rls_t*)arg)->success);
00154     bool& obtained_info(((meta_resolve_rls_t*)arg)->obtained_info);
00155     std::string& guid(((meta_resolve_rls_t*)arg)->guid);
00156 
00157     char errmsg[MAXERRMSG + 32];
00158     globus_result_t err;
00159     int errcode;
00160 
00161     // Ask LRC if it contains file of interest
00162 
00163     if (guid_enabled && source && guid.empty()) {
00164       // map lfn->guid (only once)
00165       globus_rls_attribute_t opr;
00166       opr.type = globus_rls_attr_type_str;
00167       opr.val.s = const_cast<char*>(get_path_str(url));
00168       int off = 0;
00169       globus_list_t *guids = NULL;
00170       err = globus_rls_client_lrc_attr_search(h, const_cast<char*>("lfn"),
00171                                               globus_rls_obj_lrc_lfn,
00172                                               globus_rls_attr_op_eq, &opr,
00173                                               NULL, &off, 1, &guids);
00174       if (err != GLOBUS_SUCCESS) {
00175         globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00176                                      GLOBUS_FALSE);
00177         logger.msg(INFO, "Failed to find GUID for specified LFN in %s: %s",
00178                    rlsurl.str(), errmsg);
00179         return true;
00180       }
00181       if (!guids) {
00182         logger.msg(INFO, "There is no GUID for specified LFN in %s",
00183                    rlsurl.str());
00184         return true;
00185       }
00186       globus_rls_attribute_object_t *obattr =
00187         (globus_rls_attribute_object_t*)globus_list_first(guids);
00188       guid = obattr->key;
00189       globus_rls_client_free_list(guids);
00190     }
00191     globus_list_t *pfns_list = NULL;
00192     if (source) {
00193       if (!guid.empty())
00194         err = globus_rls_client_lrc_get_pfn
00195                 (h, const_cast<char*>(guid.c_str()), 0, 0, &pfns_list);
00196       else
00197         err = globus_rls_client_lrc_get_pfn
00198                 (h, const_cast<char*>(get_path_str(url)), 0, 0, &pfns_list);
00199     } else {
00200       err = globus_rls_client_lrc_get_pfn
00201               (h, const_cast<char*>("__storage_service__"), 0, 0, &pfns_list);
00202     }
00203     if (err != GLOBUS_SUCCESS) {
00204       globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00205                                    GLOBUS_FALSE);
00206       if (errcode == GLOBUS_RLS_INVSERVER) {
00207         return true;
00208       } else if (errcode == GLOBUS_RLS_LFN_NEXIST) {
00209         return true;
00210       } else { // do not know
00211         logger.msg(INFO, "Warning: can't get PFNs from server %s: %s",
00212                    rlsurl.str(), errmsg);
00213         return true;
00214       }
00215     }
00216     if (!success) {
00217       success = DataStatus::Success; // got something
00218       if (source)
00219         registered = true;
00220     }
00221     if (url.Locations().size() == 0) {
00222       for (globus_list_t *lp = pfns_list; lp; lp = globus_list_rest(lp)) {
00223         globus_rls_string2_t *str2 =
00224           (globus_rls_string2_t*)globus_list_first(lp);
00225         URL pfn(str2->s2);
00226         for (std::map<std::string, std::string>::const_iterator i =
00227                url.CommonLocOptions().begin();
00228              i != url.CommonLocOptions().end(); i++) {
00229           pfn.AddOption(i->first, i->second, false);
00230         }
00231         URL pfn_ = AddPFN(pfn,source);
00232         logger.msg(VERBOSE, "Adding location: %s - %s", rlsurl.str(), pfn.str());
00233         AddLocation(pfn_, rlsurl.str());
00234       }
00235     } else {
00236       for (std::list<URLLocation>::const_iterator loc = url.Locations().begin();
00237            loc != url.Locations().end(); loc++) {
00238         if(source) {
00239           // for source find subset of locations registered in RLS
00240           for (globus_list_t *lp = pfns_list; lp; lp = globus_list_rest(lp)) {
00241             globus_rls_string2_t *str2 =
00242               (globus_rls_string2_t*)globus_list_first(lp);
00243             URL pfn(str2->s2);
00244             // for RLS URLs are used instead of metanames
00245             if (pfn == *loc) {
00246               logger.msg(VERBOSE, "Adding location: %s - %s",
00247                          rlsurl.str(), pfn.str());
00248               for (std::map<std::string, std::string>::const_iterator i =
00249                      url.CommonLocOptions().begin();
00250                    i != url.CommonLocOptions().end(); i++) {
00251                 pfn.AddOption(i->first, i->second, false);
00252               }
00253               URL pfn_ = AddPFN(pfn,source);
00254               AddLocation(pfn_, rlsurl.str());
00255               break;
00256             }
00257           }
00258         } else {
00259           // for destination accept specified locations
00260           URL pfn_(*loc);
00261           for (std::map<std::string, std::string>::const_iterator i =
00262                  url.CommonLocOptions().begin();
00263             i != url.CommonLocOptions().end(); i++) {
00264             pfn_.AddOption(i->first, i->second, false);
00265           }
00266           pfn_ = AddPFN(pfn_,source);
00267           AddLocation(pfn_, rlsurl.str());
00268         }
00269       }
00270     }
00271     globus_rls_client_free_list(pfns_list);
00272     if (!obtained_info) {
00273       /* obtain metadata - assume it is same everywhere */
00274       globus_list_t *attr_list;
00275       if (!guid.empty())
00276         err = globus_rls_client_lrc_attr_value_get
00277                 (h, const_cast<char*>(guid.c_str()),
00278                 NULL, globus_rls_obj_lrc_lfn, &attr_list);
00279       else
00280         err = globus_rls_client_lrc_attr_value_get
00281                 (h, const_cast<char*>(get_path_str(url)),
00282                 NULL, globus_rls_obj_lrc_lfn, &attr_list);
00283       if (err != GLOBUS_SUCCESS) {
00284         globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00285                                      GLOBUS_FALSE);
00286         if (errcode == GLOBUS_RLS_ATTR_NEXIST)
00287           return true;
00288         logger.msg(INFO, "Warning: Failed to obtain attributes from %s: %s",
00289                    rlsurl.str(), errmsg);
00290         return true;
00291       }
00292       registered = true; // even for destination
00293       for (globus_list_t *lpa = attr_list; lpa; lpa = globus_list_rest(lpa)) {
00294         globus_rls_attribute_t *attr =
00295           (globus_rls_attribute_t*)globus_list_first(lpa);
00296         if (attr->type != globus_rls_attr_type_str)
00297           continue;
00298         logger.msg(VERBOSE, "Attribute: %s - %s", attr->name, attr->val.s);
00299         if (strcmp(attr->name, "filechecksum") == 0) {
00300           if (!CheckCheckSum())
00301             SetCheckSum(attr->val.s);
00302         }
00303         else if (strcmp(attr->name, "size") == 0) {
00304           if (!CheckSize())
00305             SetSize(stringtoull(attr->val.s));
00306         }
00307         else if (strcmp(attr->name, "modifytime") == 0) {
00308           if (!CheckCreated()) {
00309             Time created(attr->val.s);
00310             if (created == -1)
00311               created.SetTime(stringtoull(attr->val.s));
00312             SetCreated(created);
00313           }
00314         }
00315         else if (strcmp(attr->name, "created") == 0)
00316           if (!CheckCreated()) {
00317             Time created(attr->val.s);
00318             if (created == -1)
00319               created.SetTime(stringtoull(attr->val.s));
00320             SetCreated(created);
00321           }
00322       }
00323       globus_rls_client_free_list(attr_list);
00324       obtained_info = true;
00325     }
00326     return true;
00327   }
00328 
00329   /* perform resolve operation, which can take long time */
00330   DataStatus DataPointRLS::Resolve(bool source) {
00331     resolved = false;
00332     registered = false;
00333     if (url.Host().empty()) {
00334       logger.msg(INFO, "RLS URL must contain host");
00335       if (source)
00336         return DataStatus::ReadResolveError;
00337       else
00338         return DataStatus::WriteResolveError;
00339     }
00340     if (source) {
00341       if (get_path_str(url)[0] == 0) {
00342         logger.msg(INFO, "Source must contain LFN");
00343         return DataStatus::ReadResolveError;
00344       }
00345       std::list<URL> rlis;
00346       std::list<URL> lrcs;
00347       rlis.push_back(url.ConnectionURL());
00348       lrcs.push_back(url.ConnectionURL());
00349       meta_resolve_rls_t arg(*this, source);
00350       rls_find_lrcs(rlis, lrcs, true, false,
00351                     &meta_resolve_callback, (void*)&arg);
00352       if (!arg.success)
00353         return arg.success;
00354     }
00355     else {
00356       if (get_path_str(url) == 0) {
00357         logger.msg(INFO, "Destination must contain LFN");
00358         return DataStatus::WriteResolveError;
00359       }
00360       std::list<URL> rlis;
00361       std::list<URL> lrcs;
00362       rlis.push_back(url.ConnectionURL());
00363       lrcs.push_back(url.ConnectionURL());
00364       if (url.Locations().size() == 0)
00365         logger.msg(INFO, "Locations are missing in destination RLS url - "
00366                    "will use those registered with special name");
00367       meta_resolve_rls_t arg(*this, source);
00368       rls_find_lrcs(rlis, lrcs, true, false,
00369                     &meta_resolve_callback, (void*)&arg);
00370       if (!arg.success)
00371         return arg.success;
00372       if (!HaveLocations()) {
00373         logger.msg(INFO, "No locations found for destination");
00374         return DataStatus::WriteResolveError;
00375       }
00376 /*
00377       // This part is done directly in callback. The difference
00378       // is that instead of "arbitrary" LRC the one provided by
00379       // callback is used
00380       // Make pfns
00381       std::list<URL>::iterator lrc_p = lrcs.begin();
00382       for (std::list<URLLocation>::iterator loc = locations.begin();
00383            loc != locations.end();) {
00384         // AddPFN
00385         if (!loc->Name().empty()) {
00386           logger.msg(VERBOSE, "Using location: %s - %s",
00387                      loc->Name(), loc->str());
00388           ++loc;
00389         }
00390         // Use arbitrary lrc
00391         else if (lrc_p == lrcs.end()) {   // no LRC
00392           logger.msg(VERBOSE, "Removing location: %s - %s",
00393                      loc->Name(), loc->str());
00394           loc = locations.erase(loc);
00395         }
00396         else {
00397           *loc = URLLocation(*loc, lrc_p->str());
00398           ++lrc_p;
00399           if (lrc_p == lrcs.end())
00400             lrc_p = lrcs.begin();
00401           logger.msg(VERBOSE, "Using location: %s - %s",
00402                      loc->Name(), loc->str());
00403           ++loc;
00404         }
00405       }
00406 */
00407     }
00408     if (CheckCheckSum()) logger.msg(VERBOSE, "meta_get_data: checksum: %s", GetCheckSum());
00409     if (CheckSize()) logger.msg(VERBOSE, "meta_get_data: size: %llu", GetSize());
00410     if (CheckCreated()) logger.msg(VERBOSE, "meta_get_data: created: %s", GetCreated().str());
00411     resolved = true;
00412     return DataStatus::Success;
00413   }
00414 
00415   DataStatus DataPointRLS::PreRegister(bool replication, bool force) {
00416     if (url.Host().empty()) {
00417       logger.msg(INFO, "RLS URL must contain host");
00418       return DataStatus::PreRegisterError;
00419     }
00420     if (replication) { /* replicating inside same lfn */
00421       if (!registered) { /* for replication it must be there */
00422         logger.msg(ERROR, "LFN is missing in RLS (needed for replication)");
00423         return DataStatus::PreRegisterError;
00424       }
00425       return DataStatus::Success;
00426     }
00427     if (registered)  /* algorithm require this to be new file */
00428       if (!force) {
00429         logger.msg(ERROR, "LFN already exists in replica");
00430         return DataStatus::PreRegisterError;
00431       }
00432     /* RLS does not support LFN only in database - hence doing nothing here */
00433     return DataStatus::Success;
00434   }
00435 
00436   DataStatus DataPointRLS::PostRegister(bool replication) {
00437     globus_rls_handle_t *h;
00438     char errmsg[MAXERRMSG + 32];
00439     globus_result_t err;
00440     int errcode;
00441 
00442     if (url.Host().empty()) {
00443       logger.msg(INFO, "RLS URL must contain host");
00444       return DataStatus::PostRegisterError;
00445     }
00446     err = globus_rls_client_connect
00447             (const_cast<char*>(url.ConnectionURL().c_str()), &h);
00448     if (err != GLOBUS_SUCCESS) {
00449       globus_rls_client_error_info(err, NULL, errmsg, MAXERRMSG + 32,
00450                                    GLOBUS_FALSE);
00451       logger.msg(INFO, "Failed to connect to RLS server: %s", errmsg);
00452       return DataStatus::PostRegisterError;
00453     }
00454     // assume that is RLI and try to resolve for special/any name
00455 
00456     std::string pfn;
00457     std::string guid;
00458     pfn = CurrentLocation().str();
00459     // it is always better to register pure url
00460     std::string rls_lfn = get_path_str(url);
00461     if (!replication)
00462       if (guid_enabled) {
00463         for (;;) {
00464           // generate guid
00465           guid = UUID();
00466           // store in LRC
00467           err = globus_rls_client_lrc_create
00468                   (h, const_cast<char*>(guid.c_str()),
00469                   const_cast<char*>(pfn.c_str()));
00470           if (err != GLOBUS_SUCCESS) {
00471             err = globus_rls_client_error_info(err, &errcode, NULL, 0,
00472                                                GLOBUS_TRUE);
00473             if (errcode == GLOBUS_RLS_LFN_EXIST) {
00474               globus_rls_free_result(err);
00475               continue;
00476             }
00477           }
00478           rls_lfn = guid;
00479           break;
00480         }
00481         if (err != GLOBUS_SUCCESS) {
00482           globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00483                                        GLOBUS_FALSE);
00484           logger.msg(INFO, "Failed to create GUID in RLS: %s", errmsg);
00485           globus_rls_client_close(h);
00486           return DataStatus::PostRegisterError;
00487         }
00488         // Check if there is no same LFN
00489         globus_rls_attribute_t opr;
00490         opr.type = globus_rls_attr_type_str;
00491         opr.val.s = const_cast<char*>(get_path_str(url));
00492         int off = 0;
00493         globus_list_t *guids = NULL;
00494         err = globus_rls_client_lrc_attr_search(h, const_cast<char*>("lfn"),
00495                                                 globus_rls_obj_lrc_lfn,
00496                                                 globus_rls_attr_op_eq,
00497                                                 &opr, NULL, &off, 1, &guids);
00498         if (err != GLOBUS_SUCCESS) {
00499           globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00500                                        GLOBUS_FALSE);
00501           if ((errcode != GLOBUS_RLS_LFN_NEXIST) &&
00502               (errcode != GLOBUS_RLS_ATTR_NEXIST) &&
00503               (errcode != GLOBUS_RLS_ATTR_VALUE_NEXIST)) {
00504             logger.msg(INFO, "Failed to check for existing LFN in %s: %s",
00505                        url.str(), errmsg);
00506             globus_rls_client_close(h);
00507             return DataStatus::PostRegisterError;
00508           }
00509         }
00510         if (guids) {
00511           globus_rls_client_free_list(guids);
00512           logger.msg(INFO, "There is same LFN in %s", url.str());
00513           globus_rls_client_close(h);
00514           return DataStatus::PostRegisterError;
00515         }
00516         // add LFN
00517         globus_rls_attribute_t attr;
00518         attr.objtype = globus_rls_obj_lrc_lfn;
00519         attr.type = globus_rls_attr_type_str;
00520         attr.name = const_cast<char*>("lfn");
00521         attr.val.s = const_cast<char*>(get_path_str(url));
00522         err = globus_rls_client_lrc_attr_put
00523                 (h, const_cast<char*>(rls_lfn.c_str()), &attr, 0);
00524         if (err != GLOBUS_SUCCESS) {
00525           globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00526                                        GLOBUS_FALSE);
00527           logger.msg(INFO, "Failed to add LFN-GUID to RLS: %s", errmsg);
00528           globus_rls_client_close(h);
00529           return DataStatus::PostRegisterError;
00530         }
00531       }
00532       else {
00533         err = globus_rls_client_lrc_create
00534                 (h, const_cast<char*>(get_path_str(url)),
00535                 const_cast<char*>(pfn.c_str()));
00536         if (err != GLOBUS_SUCCESS) {
00537           err = globus_rls_client_error_info(err, &errcode, NULL, 0,
00538                                              GLOBUS_TRUE);
00539           if (errcode == GLOBUS_RLS_LFN_EXIST) {
00540             globus_rls_free_result(err);
00541             err = globus_rls_client_lrc_add
00542                     (h, const_cast<char*>(get_path_str(url)),
00543                     const_cast<char*>(pfn.c_str()));
00544           }
00545         }
00546       }
00547     else {
00548       if (guid_enabled) {
00549         // get guid
00550         globus_rls_attribute_t opr;
00551         opr.type = globus_rls_attr_type_str;
00552         opr.val.s = const_cast<char*>(get_path_str(url));
00553         int off = 0;
00554         globus_list_t *guids = NULL;
00555         err = globus_rls_client_lrc_attr_search(h, const_cast<char*>("lfn"),
00556                                                 globus_rls_obj_lrc_lfn,
00557                                                 globus_rls_attr_op_eq,
00558                                                 &opr, NULL, &off, 1, &guids);
00559         if (err != GLOBUS_SUCCESS) {
00560           globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00561                                        GLOBUS_FALSE);
00562           logger.msg(INFO, "Failed to find GUID for specified LFN in %s: %s",
00563                      url.str(), errmsg);
00564           globus_rls_client_close(h);
00565           return DataStatus::PostRegisterError;
00566         }
00567         if (!guids) {
00568           logger.msg(INFO, "There is no GUID for specified LFN in %s",
00569                      url.str());
00570           globus_rls_client_close(h);
00571           return DataStatus::PostRegisterError;
00572         }
00573         globus_rls_attribute_object_t *obattr =
00574           (globus_rls_attribute_object_t*)globus_list_first(guids);
00575         guid = obattr->key;
00576         globus_rls_client_free_list(guids);
00577         rls_lfn = guid;
00578       }
00579       err = globus_rls_client_lrc_add
00580               (h, const_cast<char*>(rls_lfn.c_str()),
00581               const_cast<char*>(pfn.c_str()));
00582     }
00583     if (err != GLOBUS_SUCCESS) {
00584       globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00585                                    GLOBUS_FALSE);
00586       if (errcode != GLOBUS_RLS_MAPPING_EXIST) {
00587         logger.msg(INFO, "Failed to create/add LFN-PFN mapping: %s", errmsg);
00588         globus_rls_client_close(h);
00589         return DataStatus::PostRegisterError;
00590       }
00591     }
00592     globus_rls_attribute_t attr;
00593     std::string attr_val;
00594     attr.objtype = globus_rls_obj_lrc_lfn;
00595     attr.type = globus_rls_attr_type_str;
00596     attr.name = const_cast<char*>("filetype");
00597     attr.val.s = const_cast<char*>("file");
00598     err = globus_rls_client_lrc_attr_put
00599             (h, const_cast<char*>(rls_lfn.c_str()), &attr, 0);
00600     if (err != GLOBUS_SUCCESS) {
00601       globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00602                                    GLOBUS_FALSE);
00603       if (errcode != GLOBUS_RLS_ATTR_EXIST)
00604         logger.msg(INFO, "Warning: failed to add attribute to RLS: %s",
00605                    errmsg);
00606     }
00607     if (CheckSize()) {
00608       attr.name = const_cast<char*>("size");
00609       attr_val = tostring(GetSize());
00610       attr.val.s = const_cast<char*>(attr_val.c_str());
00611       err = globus_rls_client_lrc_attr_put
00612               (h, const_cast<char*>(rls_lfn.c_str()), &attr, 0);
00613       if (err != GLOBUS_SUCCESS) {
00614         globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00615                                      GLOBUS_FALSE);
00616         if (errcode != GLOBUS_RLS_ATTR_EXIST)
00617           logger.msg(INFO, "Warning: failed to add attribute to RLS: %s",
00618                      errmsg);
00619       }
00620     }
00621     if (CheckCheckSum()) {
00622       attr.name = const_cast<char*>("filechecksum");
00623       attr_val = GetCheckSum();
00624       attr.val.s = const_cast<char*>(attr_val.c_str());
00625       err = globus_rls_client_lrc_attr_put
00626               (h, const_cast<char*>(rls_lfn.c_str()), &attr, 0);
00627       if (err != GLOBUS_SUCCESS) {
00628         globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00629                                      GLOBUS_FALSE);
00630         if (errcode != GLOBUS_RLS_ATTR_EXIST)
00631           logger.msg(INFO, "Warning: failed to add attribute to RLS: %s",
00632                      errmsg);
00633       }
00634     }
00635     if (CheckCreated()) {
00636       attr.name = const_cast<char*>("modifytime");
00637       attr_val = GetCreated();
00638       attr.val.s = const_cast<char*>(attr_val.c_str());
00639       err = globus_rls_client_lrc_attr_put
00640               (h, const_cast<char*>(rls_lfn.c_str()), &attr, 0);
00641       if (err != GLOBUS_SUCCESS) {
00642         globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00643                                      GLOBUS_FALSE);
00644         if (errcode != GLOBUS_RLS_ATTR_EXIST)
00645           logger.msg(INFO, "Warning: failed to add attribute to RLS: %s",
00646                      errmsg);
00647       }
00648     }
00649     if (url.Options().size() > 0)
00650       for (std::map<std::string, std::string>::const_iterator pos =
00651              url.Options().begin(); pos != url.Options().end(); pos++) {
00652         attr.name = const_cast<char*>(pos->first.c_str());
00653         attr.val.s = const_cast<char*>(pos->second.c_str());
00654         err = globus_rls_client_lrc_attr_put
00655                 (h, const_cast<char*>(rls_lfn.c_str()), &attr, 0);
00656         if (err != GLOBUS_SUCCESS) {
00657           globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00658                                        GLOBUS_FALSE);
00659           if (errcode != GLOBUS_RLS_ATTR_EXIST)
00660             logger.msg(INFO, "Warning: failed to add attribute to RLS: %s",
00661                        errmsg);
00662         }
00663       }
00664     globus_rls_client_close(h);
00665     return DataStatus::Success;
00666   }
00667 
00668   DataStatus DataPointRLS::PreUnregister(bool) {
00669     return DataStatus::Success;
00670   }
00671 
00672   class meta_unregister_rls_t {
00673   public:
00674     DataPointRLS& dprls;
00675     bool all;
00676     DataStatus success;
00677     std::string guid;
00678     meta_unregister_rls_t(DataPointRLS& d, bool a)
00679       : dprls(d),
00680         all(a),
00681         success(DataStatus::Success) {}
00682   };
00683 
00684   static bool meta_unregister_callback(globus_rls_handle_t *h,
00685                                        const URL& rlsurl, void *arg) {
00686     return ((meta_unregister_rls_t*)arg)->dprls.UnregisterCallback(h, rlsurl, arg);
00687   }
00688 
00689   bool DataPointRLS::UnregisterCallback(globus_rls_handle_t *h,
00690                                         const URL& rlsurl, void *arg) {
00691     bool& all(((meta_unregister_rls_t*)arg)->all);
00692     DataStatus& success(((meta_unregister_rls_t*)arg)->success);
00693     std::string& guid(((meta_unregister_rls_t*)arg)->guid);
00694 
00695     int lrc_offset = 0;
00696     int lrc_limit = 0;
00697     globus_result_t err;
00698     int errcode;
00699     char errmsg[MAXERRMSG + 32];
00700     globus_list_t *pfns_list;
00701     if (guid_enabled && guid.empty()) {
00702       // map lfn->guid (only once)
00703       globus_rls_attribute_t opr;
00704       opr.type = globus_rls_attr_type_str;
00705       opr.val.s = const_cast<char*>(get_path_str(url));
00706       int off = 0;
00707       globus_list_t *guids = NULL;
00708       err = globus_rls_client_lrc_attr_search(h, const_cast<char*>("lfn"),
00709                                               globus_rls_obj_lrc_lfn,
00710                                               globus_rls_attr_op_eq,
00711                                               &opr, NULL, &off, 1, &guids);
00712       if (err != GLOBUS_SUCCESS) {
00713         globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00714                                      GLOBUS_FALSE);
00715         logger.msg(DEBUG, "Failed to find GUID for specified LFN in %s: %s",
00716                    rlsurl.str(), errmsg);
00717         return true;
00718       }
00719       if (!guids) {
00720         logger.msg(DEBUG, "There is no GUID for specified LFN in %s",
00721                    rlsurl.str());
00722         return true;
00723       }
00724       globus_rls_attribute_object_t *obattr =
00725         (globus_rls_attribute_object_t*)globus_list_first(guids);
00726       guid = obattr->key;
00727       globus_rls_client_free_list(guids);
00728     }
00729     if (all) {
00730       if (!guid.empty())
00731         err = globus_rls_client_lrc_get_pfn
00732                 (h, const_cast<char*>(guid.c_str()),
00733                 &lrc_offset, lrc_limit, &pfns_list);
00734       else
00735         err = globus_rls_client_lrc_get_pfn
00736                 (h, const_cast<char*>(get_path_str(url)),
00737                 &lrc_offset, lrc_limit, &pfns_list);
00738       if (err != GLOBUS_SUCCESS) {
00739         globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00740                                      GLOBUS_FALSE);
00741         logger.msg(INFO, "Warning: Failed to retrieve LFN/PFNs from %s: %s",
00742                    rlsurl.str(), errmsg);
00743         success = DataStatus::UnregisterError;
00744         return true;
00745       }
00746       for (globus_list_t *lp = pfns_list; lp; lp = globus_list_rest(lp)) {
00747         globus_rls_string2_t *str2 =
00748           (globus_rls_string2_t*)globus_list_first(lp);
00749         URL pfn(str2->s2);
00750         if (pfn.Protocol() == "se")
00751           logger.msg(VERBOSE, "SE location will be unregistered automatically");
00752         else {
00753           err = globus_rls_client_lrc_delete(h, str2->s1, str2->s2);
00754           if (err != GLOBUS_SUCCESS) {
00755             globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00756                                          GLOBUS_FALSE);
00757             if ((errcode != GLOBUS_RLS_MAPPING_NEXIST) &&
00758                 (errcode != GLOBUS_RLS_LFN_NEXIST) &&
00759                 (errcode != GLOBUS_RLS_PFN_NEXIST)) {
00760               logger.msg(INFO, "Warning: Failed to delete LFN/PFN from %s: %s",
00761                          rlsurl.str(), errmsg);
00762               success = DataStatus::UnregisterError;
00763               continue;
00764             }
00765           }
00766         }
00767       }
00768       globus_rls_client_free_list(pfns_list);
00769     }
00770     else { // ! all
00771       err = globus_rls_client_lrc_delete
00772               (h, const_cast<char*>(get_path_str(url)),
00773               const_cast<char*>(CurrentLocation().str().c_str()));
00774       if (err != GLOBUS_SUCCESS) {
00775         globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00776                                      GLOBUS_FALSE);
00777         if ((errcode != GLOBUS_RLS_MAPPING_NEXIST) &&
00778             (errcode != GLOBUS_RLS_LFN_NEXIST) &&
00779             (errcode != GLOBUS_RLS_PFN_NEXIST)) {
00780           logger.msg(INFO, "Warning: Failed to delete LFN/PFN from %s: %s",
00781                      rlsurl.str(), errmsg);
00782           success = DataStatus::UnregisterError;
00783         }
00784       }
00785     }
00786     return true;
00787   }
00788 
00789   DataStatus DataPointRLS::Unregister(bool all) {
00790     if (url.Host().empty()) {
00791       logger.msg(INFO, "RLS URL must contain host");
00792       return DataStatus::UnregisterError;
00793     }
00794     if (!all) {
00795       if (!LocationValid()) {
00796         logger.msg(ERROR, "Location is missing");
00797         return DataStatus::UnregisterError;
00798       }
00799       if (CurrentLocation().Protocol() == "se") {
00800         logger.msg(VERBOSE, "SE location will be unregistered automatically");
00801         return DataStatus::Success;
00802       }
00803     }
00804     if (!guid_enabled) {
00805       globus_rls_handle_t *h;
00806       char errmsg[MAXERRMSG + 32];
00807       globus_result_t err;
00808       int errcode;
00809       globus_list_t *pfns_list;
00810 
00811       err = globus_rls_client_connect
00812               (const_cast<char*>(url.ConnectionURL().c_str()), &h);
00813       if (err != GLOBUS_SUCCESS) {
00814         globus_rls_client_error_info(err, NULL, errmsg, MAXERRMSG + 32,
00815                                      GLOBUS_FALSE);
00816         logger.msg(INFO, "Failed to connect to RLS server: %s", errmsg);
00817         return DataStatus::UnregisterError;
00818       }
00819       // first find all LRC servers storing required information
00820       globus_list_t *lrcs = NULL;
00821       globus_rls_string2_t lrc_direct;
00822       globus_bool_t free_lrcs = GLOBUS_FALSE;
00823       lrc_direct.s1 = const_cast<char*>(get_path_str(url));
00824       lrc_direct.s2 = NULL; // for current connection
00825       int lrc_offset = 0;
00826       int lrc_limit = 0;
00827       err = globus_rls_client_rli_get_lrc
00828               (h, const_cast<char*>(get_path_str(url)),
00829               &lrc_offset, lrc_limit, &lrcs);
00830       if (err != GLOBUS_SUCCESS) {
00831         globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00832                                      GLOBUS_FALSE);
00833         if (errcode == GLOBUS_RLS_LFN_NEXIST) {
00834           logger.msg(INFO, "LFN must be already deleted, try LRC anyway");
00835           lrcs = NULL;
00836         }
00837         else if (errcode != GLOBUS_RLS_INVSERVER) {
00838           logger.msg(INFO, "Failed to retrieve LFN/LRC: %s", errmsg);
00839           globus_rls_client_close(h);
00840           return DataStatus::UnregisterError;
00841         }
00842         // Probably that is LRC server only.
00843         globus_list_insert(&lrcs, &lrc_direct);
00844       }
00845       else
00846         free_lrcs = GLOBUS_TRUE;
00847       err = GLOBUS_SUCCESS;
00848       // TODO: sort by lrc and cache connections
00849       DataStatus success = DataStatus::Success;
00850       for (globus_list_t *p = lrcs; p; p = globus_list_rest(p)) {
00851         globus_rls_string2_t *str2 =
00852           (globus_rls_string2_t*)globus_list_first(p);
00853         char *lrc = str2->s2;
00854         globus_rls_handle_t *h_;
00855         if (lrc) {
00856           err = globus_rls_client_connect(lrc, &h_);
00857           if (err != GLOBUS_SUCCESS) {
00858             globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00859                                          GLOBUS_FALSE);
00860             logger.msg(INFO, "Warning: Failed to connect to LRC at %s: %s",
00861                        lrc, errmsg);
00862             success = DataStatus::UnregisterError;
00863             continue;
00864           }
00865         }
00866         else
00867           h_ = h; // This server is already connected
00868         if (all) {
00869           err = globus_rls_client_lrc_get_pfn
00870                   (h_, const_cast<char*>(get_path_str(url)),
00871                   &lrc_offset, lrc_limit, &pfns_list);
00872           if (err != GLOBUS_SUCCESS) {
00873             globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00874                                          GLOBUS_FALSE);
00875             if ((errcode != GLOBUS_RLS_MAPPING_NEXIST) &&
00876                 (errcode != GLOBUS_RLS_LFN_NEXIST) &&
00877                 (errcode != GLOBUS_RLS_PFN_NEXIST)) {
00878               logger.msg(INFO,
00879                          "Warning: Failed to retrieve LFN/PFNs from %s: %s",
00880                          lrc ? lrc : url.ConnectionURL(), errmsg);
00881               if (lrc)
00882                 globus_rls_client_close(h_);
00883               success = DataStatus::UnregisterError;
00884               continue;
00885             }
00886             // Probably no such LFN - good, less work to do
00887             pfns_list = NULL;
00888           }
00889           for (globus_list_t *lp = pfns_list; lp; lp = globus_list_rest(lp)) {
00890             globus_rls_string2_t *str2 =
00891               (globus_rls_string2_t*)globus_list_first(lp);
00892             URL pfn(str2->s1);
00893             if (pfn.Protocol() == "se")
00894               logger.msg(VERBOSE,
00895                          "SE location will be unregistered automatically");
00896             else {
00897               err = globus_rls_client_lrc_delete
00898                       (h_, const_cast<char*>(get_path_str(url)), str2->s1);
00899               if (err != GLOBUS_SUCCESS) {
00900                 globus_rls_client_error_info(err, &errcode, errmsg,
00901                                              MAXERRMSG + 32, GLOBUS_FALSE);
00902                 if ((errcode != GLOBUS_RLS_MAPPING_NEXIST) &&
00903                     (errcode != GLOBUS_RLS_LFN_NEXIST) &&
00904                     (errcode != GLOBUS_RLS_PFN_NEXIST)) {
00905                   logger.msg(INFO,
00906                              "Warning: Failed to delete LFN/PFN from %s: %s",
00907                              lrc ? lrc : url.ConnectionURL(), errmsg);
00908                   if (lrc)
00909                     globus_rls_client_close(h_);
00910                   success = DataStatus::UnregisterError;
00911                   continue;
00912                 }
00913               }
00914             }
00915           }
00916           if (pfns_list)
00917             globus_rls_client_free_list(pfns_list);
00918         }
00919         else { // ! all
00920           err = globus_rls_client_lrc_delete
00921                   (h_, const_cast<char*>(get_path_str(url)),
00922                   const_cast<char*>(CurrentLocation().str().c_str()));
00923           if (err != GLOBUS_SUCCESS) {
00924             globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00925                                          GLOBUS_FALSE);
00926             if ((errcode != GLOBUS_RLS_MAPPING_NEXIST) &&
00927                 (errcode != GLOBUS_RLS_LFN_NEXIST) &&
00928                 (errcode != GLOBUS_RLS_PFN_NEXIST)) {
00929               logger.msg(INFO, "Warning: Failed to delete LFN/PFN from %s: %s",
00930                          lrc, errmsg);
00931               if (lrc)
00932                 globus_rls_client_close(h_);
00933               success = DataStatus::UnregisterError;
00934               continue;
00935             }
00936           }
00937         }
00938         if (lrc)
00939           globus_rls_client_close(h_);
00940       }
00941       globus_rls_client_close(h);
00942       if (free_lrcs)
00943         globus_rls_client_free_list(lrcs);
00944       else
00945         globus_list_free(lrcs);
00946       if (!success) {
00947         registered = false;
00948         ClearLocations();
00949       }
00950       return success;
00951     }
00952     else { // guid_enabled
00953       std::list<URL> rlis;
00954       std::list<URL> lrcs;
00955       rlis.push_back(url.ConnectionURL());
00956       lrcs.push_back(url.ConnectionURL());
00957       meta_unregister_rls_t arg(*this, all);
00958       rls_find_lrcs(rlis, lrcs, true, false,
00959                     &meta_unregister_callback, (void*)&arg);
00960       if (!arg.success) {
00961         registered = false;
00962         ClearLocations();
00963       }
00964       return arg.success;
00965     }
00966   }
00967 
00968   static bool get_attributes(globus_rls_handle_t *h, const std::string& lfn,
00969                              FileInfo& f) {
00970     globus_list_t *attr_list;
00971     char errmsg[MAXERRMSG + 32];
00972     globus_result_t err;
00973     int errcode;
00974     err = globus_rls_client_lrc_attr_value_get
00975             (h, const_cast<char*>(lfn.c_str()),
00976             NULL, globus_rls_obj_lrc_lfn, &attr_list);
00977     if (err != GLOBUS_SUCCESS) {
00978       globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
00979                                    GLOBUS_FALSE);
00980       if (errcode != GLOBUS_RLS_ATTR_NEXIST)
00981         // logger.msg(INFO, "Warning: Failed to retrieve attributes: %s",
00982         // errmsg);
00983         return false;
00984       return true;
00985     }
00986     for (globus_list_t *pa = attr_list; pa; pa = globus_list_rest(pa)) {
00987       globus_rls_attribute_t *attr =
00988         (globus_rls_attribute_t*)globus_list_first(pa);
00989       if (attr->type != globus_rls_attr_type_str)
00990         continue;
00991       // logger.msg(VERBOSE, "Attribute: %s - %s", attr->name, attr->val.s);
00992       if (strcmp(attr->name, "filechecksum") == 0)
00993         f.SetCheckSum(attr->val.s);
00994       else if (strcmp(attr->name, "size") == 0)
00995         f.SetSize(stringtoull(attr->val.s));
00996       else if (strcmp(attr->name, "modifytime") == 0) {
00997         Time created(attr->val.s);
00998         if (created == -1)
00999           created.SetTime(stringtoull(attr->val.s));
01000         f.SetCreated(created);
01001       }
01002       else if (strcmp(attr->name, "created") == 0) {
01003         Time created(attr->val.s);
01004         if (created == -1)
01005           created.SetTime(stringtoull(attr->val.s));
01006         f.SetCreated(created);
01007       }
01008     }
01009     globus_rls_client_free_list(attr_list);
01010     return true;
01011   }
01012 
01013   class list_files_rls_t {
01014   public:
01015     DataPointRLS& dprls;
01016     std::list<FileInfo>& files;
01017     DataStatus success;
01018     bool resolve;
01019     std::string guid;
01020     list_files_rls_t(DataPointRLS& d, std::list<FileInfo>& f,
01021                      bool r)
01022       : dprls(d),
01023         files(f),
01024         success(DataStatus::Success),
01025         resolve(r) {}
01026   };
01027 
01028   static bool list_files_callback(globus_rls_handle_t *h,
01029                                   const URL& rlsurl, void *arg) {
01030     return ((list_files_rls_t*)arg)->dprls.ListFilesCallback(h, rlsurl, arg);
01031   }
01032 
01033   bool DataPointRLS::ListFilesCallback(globus_rls_handle_t *h,
01034                                        const URL& rlsurl, void *arg) {
01035     std::list<FileInfo>& files(((list_files_rls_t*)arg)->files);
01036     DataStatus& success(((list_files_rls_t*)arg)->success);
01037     bool& resolve(((list_files_rls_t*)arg)->resolve);
01038     std::string& guid(((list_files_rls_t*)arg)->guid);
01039 
01040     int lrc_offset = 0;
01041     globus_result_t err;
01042     int errcode;
01043     char errmsg[MAXERRMSG + 32];
01044     globus_list_t *pfns = NULL;
01045     if (guid_enabled && !path_empty(url) && guid.empty()) {
01046       // looking gor guid only once
01047       // looking for guid only if lfn specified
01048       globus_rls_attribute_t opr;
01049       opr.type = globus_rls_attr_type_str;
01050       opr.val.s = const_cast<char*>(get_path_str(url));
01051       int off = 0;
01052       globus_list_t *guids = NULL;
01053       err = globus_rls_client_lrc_attr_search(h, const_cast<char*>("lfn"),
01054                                               globus_rls_obj_lrc_lfn,
01055                                               globus_rls_attr_op_eq,
01056                                               &opr, NULL, &off, 1, &guids);
01057       if (err != GLOBUS_SUCCESS) {
01058         globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
01059                                      GLOBUS_FALSE);
01060         logger.msg(INFO, "Failed to find GUID for specified LFN in %s: %s",
01061                    rlsurl.str(), errmsg);
01062         return true;
01063       }
01064       if (!guids) {
01065         logger.msg(INFO, "There is no GUID for specified LFN in %s",
01066                    rlsurl.str());
01067         return true;
01068       }
01069       globus_rls_attribute_object_t *obattr =
01070         (globus_rls_attribute_object_t*)globus_list_first(guids);
01071       guid = obattr->key;
01072       globus_rls_client_free_list(guids);
01073     }
01074     if (!guid.empty())
01075       err = globus_rls_client_lrc_get_pfn
01076               (h, const_cast<char*>(guid.c_str()), &lrc_offset, 1000, &pfns);
01077     else if (!path_empty(url))
01078       err = globus_rls_client_lrc_get_pfn
01079               (h, const_cast<char*>(get_path_str(url)), &lrc_offset, 1000, &pfns);
01080     else
01081       err = globus_rls_client_lrc_get_pfn_wc(h, const_cast<char*>("*"),
01082                                              rls_pattern_unix,
01083                                              &lrc_offset, 1000, &pfns);
01084     if (err != GLOBUS_SUCCESS) {
01085       globus_rls_client_error_info(err, &errcode, errmsg, MAXERRMSG + 32,
01086                                    GLOBUS_FALSE);
01087       if (errcode == GLOBUS_RLS_LFN_NEXIST) {
01088         logger.msg(VERBOSE, "No LFNs found in %s", rlsurl.str());
01089         success = DataStatus::Success;
01090         return true;
01091       }
01092       logger.msg(INFO, "Failed to retrieve list of LFNs/PFNs from %s",
01093                  rlsurl.str());
01094       return true;
01095     }
01096     success = DataStatus::Success;
01097     std::string last_lfn = "";
01098     std::string last_guid = "";
01099     for (globus_list_t *p = pfns; p; p = globus_list_rest(p)) {
01100       globus_rls_string2_t *str2 =
01101         (globus_rls_string2_t*)globus_list_first(p);
01102       std::string lfn(str2->s1);
01103       URL pfn(str2->s2);
01104       if (guid_enabled) {
01105         if (lfn != last_guid) {
01106           last_guid = lfn;
01107           last_lfn = "";
01108           // get real lfn
01109           globus_list_t *lfn_list = NULL;
01110           err = globus_rls_client_lrc_attr_value_get
01111                   (h, const_cast<char*>(lfn.c_str()),
01112                   const_cast<char*>("lfn"), globus_rls_obj_lrc_lfn, &lfn_list);
01113           if (err != GLOBUS_SUCCESS) {
01114             globus_rls_client_error_info(err, &errcode, errmsg,
01115                                          MAXERRMSG + 32, GLOBUS_FALSE);
01116             continue;
01117           }
01118           if (lfn_list == NULL)
01119             continue;
01120           globus_rls_attribute_t *attr =
01121             (globus_rls_attribute_t*)globus_list_first(lfn_list);
01122           if (attr->type != globus_rls_attr_type_str) {
01123             globus_rls_client_free_list(lfn_list);
01124             continue;
01125           }
01126           // use only first lfn (TODO: all lfns)
01127           last_lfn = attr->val.s;
01128           globus_rls_client_free_list(lfn_list);
01129         }
01130         if (!last_lfn.empty()) {
01131           logger.msg(VERBOSE, "lfn: %s(%s) - %s",
01132                      last_lfn, last_guid, pfn.str());
01133           std::list<FileInfo>::iterator f;
01134           for (f = files.begin(); f != files.end(); ++f)
01135             if (f->GetName() == last_lfn)
01136               break;
01137           if (f == files.end()) {
01138             f = files.insert(files.end(), FileInfo(last_lfn.c_str()));
01139             if (resolve)
01140               get_attributes(h, last_guid, *f);
01141           }
01142           f->AddURL(pfn);
01143         }
01144       }
01145       else { // !guid_enabled
01146         logger.msg(VERBOSE, "lfn: %s - pfn: %s", lfn, pfn.str());
01147         std::list<FileInfo>::iterator f;
01148         for (f = files.begin(); f != files.end(); ++f)
01149           if (f->GetName() == lfn)
01150             break;
01151         if (f == files.end()) {
01152           f = files.insert(files.end(), FileInfo(lfn));
01153           if (resolve)
01154             get_attributes(h, lfn, *f);
01155         }
01156         f->AddURL(pfn);
01157       }
01158     }
01159     globus_rls_client_free_list(pfns);
01160     return true;
01161   }
01162 
01163   DataStatus DataPointRLS::ListFiles(std::list<FileInfo>& files, bool long_list, bool resolve, bool metadata) {
01164     std::list<URL> rlis;
01165     std::list<URL> lrcs;
01166     if (url.Host().empty()) {
01167       logger.msg(INFO, "RLS URL must contain host");
01168       return DataStatus::ListError;
01169     }
01170     rlis.push_back(url.ConnectionURL());
01171     lrcs.push_back(url.ConnectionURL());
01172 
01173     list_files_rls_t arg(*this, files, long_list);
01174     rls_find_lrcs(rlis, lrcs, true, false,
01175                   &list_files_callback, (void*)&arg);
01176     return arg.success;
01177   }
01178 
01179 } // namespace Arc
01180 
01181 Arc::PluginDescriptor PLUGINS_TABLE_NAME[] = {
01182   { "rls", "HED:DMC", 0, &Arc::DataPointRLS::Instance },
01183   { NULL, NULL, 0, NULL }
01184 };