Back to index

nordugrid-arc-nox  1.1.0~rc6
DataPointSRM.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 #endif
00010 
00011 #include <cstdlib>
00012 
00013 #include <globus_io.h>
00014 #include <glibmm/fileutils.h>
00015 
00016 #include <arc/Thread.h>
00017 #include <arc/StringConv.h>
00018 #include <arc/Logger.h>
00019 #include <arc/URL.h>
00020 #include <arc/UserConfig.h>
00021 #include <arc/data/DataBuffer.h>
00022 #include <arc/data/DataCallback.h>
00023 #include <arc/data/CheckSum.h>
00024 #include <arc/globusutils/GlobusWorkarounds.h>
00025 
00026 
00027 #include "DataPointSRM.h"
00028 
00029 namespace Arc {
00030 
00031   Logger DataPointSRM::logger(DataPoint::logger, "SRM");
00032 
00033   static bool proxy_initialized = false;
00034 
00035   DataPointSRM::DataPointSRM(const URL& url, const UserConfig& usercfg)
00036     : DataPointDirect(url, usercfg),
00037       srm_request(NULL),
00038       r_handle(NULL),
00039       reading(false),
00040       writing(false),
00041       timeout(false) {
00042     valid_url_options.push_back("protocol");
00043     valid_url_options.push_back("spacetoken");
00044     globus_module_activate(GLOBUS_GSI_GSSAPI_MODULE);
00045     globus_module_activate(GLOBUS_IO_MODULE);
00046     if (!proxy_initialized)
00047       proxy_initialized = GlobusRecoverProxyOpenSSL();
00048   }
00049 
00050   DataPointSRM::~DataPointSRM() {
00051     globus_module_deactivate(GLOBUS_GSI_GSSAPI_MODULE);
00052     globus_module_deactivate(GLOBUS_IO_MODULE);
00053     if (r_handle)
00054       delete r_handle;
00055     if (srm_request)
00056       delete srm_request;
00057   }
00058 
00059   Plugin* DataPointSRM::Instance(PluginArgument *arg) {
00060     DataPointPluginArgument *dmcarg = dynamic_cast<DataPointPluginArgument*>(arg);
00061     if (!dmcarg)
00062       return NULL;
00063     if (((const URL&)(*dmcarg)).Protocol() != "srm")
00064       return NULL;
00065     // Make this code non-unloadable because Globus
00066     // may have problems with unloading
00067     Glib::Module* module = dmcarg->get_module();
00068     PluginsFactory* factory = dmcarg->get_factory();
00069     if(factory && module) factory->makePersistent(module);
00070     return new DataPointSRM(*dmcarg, *dmcarg);
00071   }
00072 
00073   DataStatus DataPointSRM::Check() {
00074 
00075     SRMClient *client = SRMClient::getInstance(url.fullstr(), timeout, usercfg.UtilsDirPath());
00076     if (!client) {
00077       if (timeout)
00078         return DataStatus::CheckErrorRetryable;
00079       return DataStatus::CheckError;
00080     }
00081 
00082     if (url.HTTPOption("SFN", "") == "")
00083       srm_request = new SRMClientRequest(url.str());
00084     else
00085       srm_request = new SRMClientRequest(url.Protocol() + "://" + url.Host() + "/" + url.HTTPOption("SFN"));
00086     
00087     if (!srm_request) {
00088       delete client;
00089       client = NULL;
00090       return DataStatus::CheckError;
00091     }
00092 
00093     logger.msg(VERBOSE, "Check: looking for metadata: %s", CurrentLocation().str());
00094     srm_request->long_list(true);
00095     std::list<struct SRMFileMetaData> metadata;
00096 
00097     SRMReturnCode res = client->info(*srm_request, metadata);
00098     delete srm_request;
00099     srm_request = NULL;
00100     delete client;
00101     client = NULL;
00102 
00103     if (res != SRM_OK) {
00104       if (res == SRM_ERROR_TEMPORARY) return DataStatus::CheckErrorRetryable;
00105       return DataStatus::CheckError;
00106     }
00107     
00108     if (metadata.empty())
00109       return DataStatus::CheckError;
00110     if (metadata.front().size > 0) {
00111       logger.msg(INFO, "Check: obtained size: %lli", metadata.front().size);
00112       SetSize(metadata.front().size);
00113     }
00114     if (metadata.front().checkSumValue.length() > 0 &&
00115         metadata.front().checkSumType.length() > 0) {
00116       std::string csum(metadata.front().checkSumType + ":" + metadata.front().checkSumValue);
00117       logger.msg(INFO, "Check: obtained checksum: %s", csum);
00118       SetCheckSum(csum);
00119     }
00120     if (metadata.front().createdAtTime > 0) {
00121       logger.msg(INFO, "Check: obtained creation date: %s", Time(metadata.front().createdAtTime).str());
00122       SetCreated(Time(metadata.front().createdAtTime));
00123     }
00124 
00125     return DataStatus::Success;
00126   }
00127 
00128   DataStatus DataPointSRM::Remove() {
00129 
00130     SRMClient *client = SRMClient::getInstance(url.fullstr(), timeout, usercfg.UtilsDirPath());
00131     if (!client) {
00132       if (timeout)
00133         return DataStatus::DeleteErrorRetryable;
00134       return DataStatus::DeleteError;
00135     }
00136 
00137     // take out options in srm url
00138     std::string canonic_url;
00139     if (!url.HTTPOption("SFN").empty())
00140       canonic_url = url.Protocol() + "://" + url.Host() + "/" + url.HTTPOption("SFN");
00141     else
00142       canonic_url = url.Protocol() + "://" + url.Host() + url.Path();
00143 
00144     srm_request = new SRMClientRequest(canonic_url);
00145 
00146     if (!srm_request) {
00147       delete client;
00148       client = NULL;
00149       return DataStatus::DeleteError;
00150     }
00151     logger.msg(VERBOSE, "remove_srm: deleting: %s", CurrentLocation().str());
00152 
00153     SRMReturnCode res = client->remove(*srm_request);
00154     delete client;
00155     client = NULL;
00156     delete srm_request;
00157     srm_request = NULL;
00158 
00159     if (res != SRM_OK) {
00160       if (res == SRM_ERROR_TEMPORARY) return DataStatus::DeleteErrorRetryable;              
00161       return DataStatus::DeleteError;
00162     }
00163 
00164     return DataStatus::Success;
00165   }
00166 
00167   DataStatus DataPointSRM::StartReading(DataBuffer& buf) {
00168 
00169     logger.msg(VERBOSE, "StartReading");
00170     if (reading)
00171       return DataStatus::IsReadingError;
00172     if (writing)
00173       return DataStatus::IsWritingError;
00174 
00175     reading = true;
00176     buffer = &buf;
00177 
00178     SRMClient *client = SRMClient::getInstance(url.fullstr(), timeout, usercfg.UtilsDirPath(), buffer->speed.get_max_inactivity_time());
00179     if (!client) {
00180       reading = false;
00181       if (timeout)
00182         return DataStatus::ReadStartErrorRetryable;
00183       return DataStatus::ReadStartError;
00184     }
00185 
00186     // take out options in srm url
00187     std::string canonic_url;
00188     if (!url.HTTPOption("SFN").empty())
00189       canonic_url = url.Protocol() + "://" + url.Host() + "/" + url.HTTPOption("SFN");
00190     else
00191       canonic_url = url.Protocol() + "://" + url.Host() + url.Path();
00192 
00193     if (srm_request)
00194       delete srm_request;
00195     srm_request = new SRMClientRequest(canonic_url);
00196     
00197     if (!srm_request) {
00198       delete client;
00199       client = NULL;
00200       return DataStatus::ReadStartError;
00201     }
00202     std::list<std::string> turls;
00203     SRMReturnCode res = client->getTURLs(*srm_request, turls);
00204     client->disconnect();
00205     delete client;
00206     client = NULL;
00207     
00208     if (res != SRM_OK) {
00209       if (res == SRM_ERROR_TEMPORARY) return DataStatus::ReadStartErrorRetryable;
00210       return DataStatus::ReadStartError;
00211     }
00212 
00213     std::srand(time(NULL));
00214 
00215     // Choose handled URL randomly
00216     for (;;) {
00217       if (turls.size() <= 0)
00218         break;
00219       int n = (int)((std::rand() * ((double)(turls.size() - 1))) / RAND_MAX + 0.25);
00220       std::list<std::string>::iterator i = turls.begin();
00221       for (; n; ++i, ++n) {}
00222       if (i == turls.end())
00223         continue;
00224       // Avoid redirection to SRM
00225       logger.msg(VERBOSE, "Checking URL returned by SRM: %s", *i);
00226       if (strncasecmp(i->c_str(), "srm://", 6) == 0) {
00227         turls.erase(i);
00228         continue;
00229       }
00230       // Try to use this TURL + old options
00231       r_url = *i;
00232       {
00233         std::map<std::string, std::string> options = url.Options();
00234         if (!options.empty())
00235           for (std::map<std::string, std::string>::iterator oi = options.begin(); oi != options.end(); oi++)
00236             r_url.AddOption((*oi).first, (*oi).second);
00237       }
00238       r_handle = new DataHandle(r_url, usercfg);
00239       // check if url can be handled
00240       if (!r_handle) {
00241         turls.erase(i);
00242         continue;
00243       }
00244       if ((*r_handle)->IsIndex()) {
00245         delete r_handle;
00246         r_handle = NULL;
00247         turls.erase(i);
00248         continue;
00249       }
00250       break;
00251     }
00252 
00253     if (!r_handle) {
00254       logger.msg(INFO, "SRM returned no useful Transfer URLs: %s", url.str());
00255       return DataStatus::ReadStartError;
00256     }
00257 
00258     (*r_handle)->SetAdditionalChecks(false); // checks at higher levels are always done on SRM metadata
00259     (*r_handle)->SetSecure(force_secure);
00260     (*r_handle)->Passive(force_passive);
00261 
00262     logger.msg(INFO, "Redirecting to new URL: %s", (*r_handle)->CurrentLocation().str());
00263     if (!(*r_handle)->StartReading(buf)) {
00264       delete r_handle;
00265       r_handle = NULL;
00266       reading = false;
00267       return DataStatus::ReadStartError;
00268     }
00269     return DataStatus::Success;
00270   }
00271 
00272   DataStatus DataPointSRM::StopReading() {
00273 
00274     if (!reading) {
00275       delete srm_request;
00276       srm_request = NULL;
00277       return DataStatus::ReadStopError;
00278     }
00279     reading = false;
00280 
00281     DataStatus r = DataStatus::Success;
00282     if (r_handle) {
00283       r = (*r_handle)->StopReading();
00284       delete r_handle;
00285     }
00286     
00287     if (srm_request) {
00288       SRMClient *client = SRMClient::getInstance(url.fullstr(), timeout, usercfg.UtilsDirPath(), buffer->speed.get_max_inactivity_time());
00289       if (client) {
00290         if(buffer->error_read() || srm_request->status() == SRM_REQUEST_SHOULD_ABORT) {
00291           client->abort(*srm_request);
00292         } else if (srm_request->status() == SRM_REQUEST_FINISHED_SUCCESS) {
00293           client->releaseGet(*srm_request);
00294         }
00295         delete client;
00296         client = NULL;
00297       }
00298       delete srm_request;
00299     }
00300     r_handle = NULL;
00301     srm_request = NULL;
00302     return r;
00303   }
00304 
00305   DataStatus DataPointSRM::StartWriting(DataBuffer& buf,
00306                                         DataCallback *space_cb) {
00307 
00308     logger.msg(VERBOSE, "StartWriting");
00309     if (reading)
00310       return DataStatus::IsReadingError;
00311     if (writing)
00312       return DataStatus::IsWritingError;
00313 
00314     writing = true;
00315     buffer = &buf;
00316 
00317     SRMClient *client = SRMClient::getInstance(url.fullstr(), timeout, usercfg.UtilsDirPath(), buffer->speed.get_max_inactivity_time());
00318     if (!client) {
00319       writing = false;
00320       if (timeout)
00321         return DataStatus::WriteStartErrorRetryable;
00322       return DataStatus::WriteStartError;
00323     }
00324 
00325     // take out options in srm url
00326     std::string canonic_url;
00327     if (!url.HTTPOption("SFN").empty())
00328       canonic_url = url.Protocol() + "://" + url.Host() + "/" + url.HTTPOption("SFN");
00329     else
00330       canonic_url = url.Protocol() + "://" + url.Host() + url.Path();
00331 
00332     if (srm_request)
00333       delete srm_request;
00334     srm_request = new SRMClientRequest(canonic_url);
00335     if (!srm_request) {
00336       delete client;
00337       client = NULL;
00338       return DataStatus::WriteStartError;
00339     }
00340 
00341     // set space token
00342     std::string space_token = url.Option("spacetoken");
00343     if (space_token.empty()) {
00344       if (client->getVersion().compare("v2.2") == 0)
00345         // only print message if using v2.2
00346         logger.msg(VERBOSE, "No space token specified");
00347     }
00348     else {
00349       if (client->getVersion().compare("v2.2") != 0)
00350         // print warning if not using srm2.2
00351         logger.msg(WARNING, "Warning: Using SRM protocol v1 which does not support space tokens");
00352       else {
00353         logger.msg(VERBOSE, "Using space token description %s", space_token);
00354         // get token from SRM that matches description
00355         std::list<std::string> tokens;
00356         if (client->getSpaceTokens(tokens, space_token) != SRM_OK)
00357           // not critical so log a warning
00358           logger.msg(WARNING, "Warning: Error looking up space tokens matching description %s. Will copy without using token", space_token);
00359         else if (tokens.empty())
00360           // not critical so log a warning
00361           logger.msg(WARNING, "Warning: No space tokens found matching description! Will copy without using token");
00362         else {
00363           // take the first one in the list
00364           logger.msg(VERBOSE, "Using space token %s", tokens.front());
00365           srm_request->space_token(tokens.front());
00366         }
00367       }
00368     }
00369 
00370     std::list<std::string> turls;
00371     SRMReturnCode res = client->putTURLs(*srm_request, turls);
00372     client->disconnect();
00373     delete client;
00374     client = NULL;
00375     
00376     if (res != SRM_OK) {
00377       if (res == SRM_ERROR_TEMPORARY) return DataStatus::WriteStartErrorRetryable;
00378       return DataStatus::WriteStartError;
00379     }
00380 
00381     std::srand(time(NULL));
00382 
00383     // Choose handled URL randomly
00384     for (;;) {
00385       if (turls.size() <= 0)
00386         break;
00387       int n = (int)((std::rand() * ((double)(turls.size() - 1))) / RAND_MAX + 0.25);
00388       std::list<std::string>::iterator i = turls.begin();
00389       for (; n; ++i, ++n) {}
00390       if (i == turls.end())
00391         continue;
00392       // Avoid redirection to SRM
00393       logger.msg(VERBOSE, "Checking URL returned by SRM: %s", *i);
00394       if (strncasecmp(i->c_str(), "srm://", 6) == 0) {
00395         turls.erase(i);
00396         continue;
00397       }
00398       // Try to use this TURL + old options
00399       r_url = *i;
00400       {
00401         std::map<std::string, std::string> options = url.Options();
00402         if (!options.empty())
00403           for (std::map<std::string, std::string>::iterator oi = options.begin(); oi != options.end(); oi++)
00404             r_url.AddOption((*oi).first, (*oi).second);
00405       }
00406       r_handle = new DataHandle(r_url, usercfg);
00407       // check if url can be handled
00408       if (!r_handle) {
00409         turls.erase(i);
00410         continue;
00411       }
00412       if ((*r_handle)->IsIndex()) {
00413         delete r_handle;
00414         r_handle = NULL;
00415         turls.erase(i);
00416         continue;
00417       }
00418       break;
00419     }
00420 
00421     if (!r_handle) {
00422       logger.msg(INFO, "SRM returned no useful Transfer URLs: %s", url.str());
00423       return DataStatus::WriteStartError;
00424     }
00425 
00426     logger.msg(INFO, "Redirecting to new URL: %s", (*r_handle)->CurrentLocation().str());
00427     if (!(*r_handle)->StartWriting(buf)) {
00428       delete r_handle;
00429       r_handle = NULL;
00430       reading = false;
00431       return DataStatus::WriteStartError;
00432     }
00433     return DataStatus::Success;
00434   }
00435 
00436   DataStatus DataPointSRM::StopWriting() {
00437 
00438     if (!writing) {
00439       delete srm_request;
00440       srm_request = NULL;
00441       return DataStatus::WriteStopError;
00442     }
00443     writing = false;
00444 
00445     DataStatus r = DataStatus::Success;
00446     if (r_handle) {
00447       r = (*r_handle)->StopWriting();
00448       // disable checksum check at this level if was done at lower level
00449       // gsiftp turls should provide checksum
00450       if ((*r_handle)->ProvidesMeta())
00451         additional_checks = false; 
00452       delete r_handle;
00453       r_handle = NULL;
00454     }
00455       
00456     if (!r) {
00457       SRMClient *client = SRMClient::getInstance(url.fullstr(), timeout, usercfg.UtilsDirPath(), buffer->speed.get_max_inactivity_time());
00458       if(client) {
00459         client->abort(*srm_request);
00460         delete client;
00461         client = NULL;
00462       }
00463       delete srm_request;
00464       srm_request = NULL;
00465       return r;
00466     }
00467 
00468     SRMClient * client = SRMClient::getInstance(url.fullstr(), timeout, usercfg.UtilsDirPath(), buffer->speed.get_max_inactivity_time());
00469     if(client) {
00470       // call abort if failure, or releasePut on success
00471       if(buffer->error() || srm_request->status() == SRM_REQUEST_SHOULD_ABORT) 
00472         client->abort(*srm_request);
00473       else {
00474         // checksum verification
00475         // TODO: checksum for writing to srm is not enabled in DataMover
00476         const CheckSumAny * cs = (CheckSumAny*)buffer->checksum_object();
00477         if(additional_checks && cs && *cs && buffer->checksum_valid()) {
00478           char buf[100];
00479           cs->print(buf,100);
00480           std::string checksum = buf;
00481           if (cs->Type() == CheckSumAny::adler32) {
00482             // get checksum info for checksum verification
00483             logger.msg(DEBUG, "start_reading_srm: looking for metadata: %s", url.str());
00484             srm_request->long_list(true);
00485             std::list<struct SRMFileMetaData> metadata;
00486             SRMReturnCode res = client->info(*srm_request,metadata);
00487             if (res != SRM_OK) {
00488               client->abort(*srm_request);
00489               if (res == SRM_ERROR_TEMPORARY)
00490                 return DataStatus::WriteStopErrorRetryable;              
00491               return DataStatus::WriteStopError;
00492             }
00493             /* provide some metadata */
00494             if(!metadata.empty()){
00495               if(metadata.front().checkSumValue.length() > 0 &&
00496                  metadata.front().checkSumType.length() > 0) {
00497                 std::string csum(metadata.front().checkSumType+":"+metadata.front().checkSumValue);
00498                 logger.msg(INFO, "start_reading_srm: obtained checksum: %s", csum);
00499                 if (checksum.substr(0, checksum.find(':')) == metadata.front().checkSumType) { // should always be true
00500                   if (checksum.substr(checksum.find(':')+1) == metadata.front().checkSumValue) {
00501                     logger.msg(VERBOSE, "Calculated transfer checksum %s matches checksum reported by SRM destination %s", checksum, csum);
00502                   }
00503                   else {
00504                     logger.msg(VERBOSE, "Error: Checksum mismatch between calculated checksum %s and checksum reported by SRM destination ", checksum, csum);
00505                     r = DataStatus::WriteStopErrorRetryable;
00506                   }
00507                 }
00508                 else 
00509                   logger.msg(VERBOSE, "Checksum type of SRM and calculated checksum %s differ, cannot compare", checksum);
00510               }
00511             }
00512           }
00513           else 
00514             logger.msg(VERBOSE, "Checksum type of SRM and calculated checksum %s differ, cannot compare", checksum);
00515         }
00516         if (r) {
00517           if (srm_request->status() == SRM_REQUEST_FINISHED_SUCCESS)
00518             client->releasePut(*srm_request);
00519         } else {
00520           client->abort(*srm_request);
00521         }
00522       }
00523     }
00524     delete srm_request;
00525     srm_request = NULL;
00526     delete client;
00527     client=NULL;
00528     return r;
00529   }
00530 
00531   DataStatus DataPointSRM::ListFiles(std::list<FileInfo>& files,
00532                                      bool long_list,
00533                                      bool resolve,
00534                                      bool metadata) {
00535 
00536     SRMClient * client = SRMClient::getInstance(url.fullstr(), timeout, usercfg.UtilsDirPath());
00537     if(!client) {
00538       if (timeout)
00539         return DataStatus::ListErrorRetryable;
00540       return DataStatus::ListError;
00541     }
00542     
00543     std::string canonic_url;
00544     if (!url.HTTPOption("SFN").empty())
00545       canonic_url = url.Protocol() + "://" + url.Host() + "/" + url.HTTPOption("SFN");
00546     else
00547       canonic_url = url.Protocol() + "://" + url.Host() + url.Path();
00548 
00549     if (srm_request)
00550       delete srm_request;
00551     srm_request = new SRMClientRequest(canonic_url);
00552     if (!srm_request) {
00553       delete client;
00554       client = NULL;
00555       return DataStatus::ListError;
00556     }
00557     logger.msg(VERBOSE, "ListFiles: looking for metadata: %s", CurrentLocation().str());
00558     if (long_list || metadata) srm_request->long_list(true);
00559     std::list<struct SRMFileMetaData> srm_metadata;
00560 
00561     // get info from SRM
00562     int recursion = 0;
00563     if (metadata) recursion = -1; // get info on directory rather than contents
00564     SRMReturnCode res = client->info(*srm_request, srm_metadata, recursion);
00565     /* Reverted back to gsi protocol by default so this code is not needed
00566     if (res == SRM_ERROR_SOAP) {
00567       logger.msg(ERROR, "Retrying with gsi protocol...\n");
00568       URL gsiurl(url);
00569       gsiurl.AddOption("protocol", "gsi", true);
00570       client = SRMClient::getInstance(std::string(gsiurl.fullstr()));
00571       if(!client) return DataStatus::ListError;
00572       res = client->info(*srm_request, srm_metadata, recursion);
00573     }*/
00574     delete client;
00575     client = NULL;
00576     delete srm_request;
00577     srm_request = NULL;
00578 
00579     if (res != SRM_OK) {
00580       if (res == SRM_ERROR_TEMPORARY) return DataStatus::ListErrorRetryable;   
00581       return DataStatus::ListError;
00582     }
00583 
00584     if (srm_metadata.empty()) {
00585       return DataStatus::Success;
00586     }
00587     // set URL attributes for surl requested (file or dir)
00588     if(srm_metadata.front().size > 0)
00589       SetSize(srm_metadata.front().size);
00590     if(srm_metadata.front().checkSumType.length() > 0 &&
00591        srm_metadata.front().checkSumValue.length() > 0) {
00592       std::string csum(srm_metadata.front().checkSumType+":"+srm_metadata.front().checkSumValue);
00593       SetCheckSum(csum);
00594     }
00595     if(srm_metadata.front().createdAtTime > 0) 
00596       SetCreated(Time(srm_metadata.front().createdAtTime));
00597 
00598     // set FileInfo attributes for surl requested and any files within a dir
00599     for (std::list<struct SRMFileMetaData>::iterator i = srm_metadata.begin();
00600          i != srm_metadata.end();
00601          ++i) {
00602 
00603       std::list<FileInfo>::iterator f =
00604         files.insert(files.end(), FileInfo(i->path));
00605       f->SetMetaData("path", i->path);
00606       
00607       if (i->fileType == SRM_FILE) {
00608         f->SetType(FileInfo::file_type_file);
00609         f->SetMetaData("type", "file");
00610       }
00611       else if (i->fileType == SRM_DIRECTORY) {
00612         f->SetType(FileInfo::file_type_dir);
00613         f->SetMetaData("type", "dir");
00614       }
00615 
00616       if (i->size >= 0) {
00617         f->SetSize(i->size);
00618         f->SetMetaData("size", tostring(i->size));
00619       }
00620       if (i->createdAtTime > 0) {
00621         f->SetCreated(Time(i->createdAtTime));
00622         f->SetMetaData("ctime", (Time(i->createdAtTime)).str());
00623       }
00624       if (i->checkSumType.length() > 0 &&
00625           i->checkSumValue.length() > 0) {
00626         std::string csum(i->checkSumType + ":" + i->checkSumValue);
00627         f->SetCheckSum(csum);
00628         f->SetMetaData("checksum", csum);
00629       }
00630       if (i->fileLocality == SRM_ONLINE) {
00631         f->SetLatency("ONLINE");
00632         f->SetMetaData("latency", "ONLINE");
00633       }
00634       else if (i->fileLocality == SRM_NEARLINE) {
00635         f->SetLatency("NEARLINE");
00636         f->SetMetaData("latency", "NEARLINE");
00637       }
00638       if(!i->arrayOfSpaceTokens.empty()) f->SetMetaData("spacetokens", i->arrayOfSpaceTokens);
00639       if(!i->owner.empty()) f->SetMetaData("owner", i->owner);
00640       if(!i->group.empty()) f->SetMetaData("group", i->group);
00641       if(!i->permission.empty()) f->SetMetaData("accessperm", i->permission);
00642       if(i->lastModificationTime > 0)
00643         f->SetMetaData("mtime", (Time(i->lastModificationTime)).str());
00644       if(i->lifetimeLeft != 0) f->SetMetaData("lifetimeleft", tostring(i->lifetimeLeft));
00645       if(i->lifetimeAssigned != 0) f->SetMetaData("lifetimeassigned", tostring(i->lifetimeAssigned));
00646   
00647       if (i->retentionPolicy == SRM_REPLICA) f->SetMetaData("retentionpolicy", "REPLICA");
00648       else if (i->retentionPolicy == SRM_OUTPUT) f->SetMetaData("retentionpolicy", "OUTPUT");
00649       else if (i->retentionPolicy == SRM_CUSTODIAL)  f->SetMetaData("retentionpolicy", "CUSTODIAL");
00650 
00651       if (i->fileStorageType == SRM_VOLATILE) f->SetMetaData("filestoragetype", "VOLATILE");
00652       else if (i->fileStorageType == SRM_DURABLE) f->SetMetaData("filestoragetype", "DURABLE");
00653       else if (i->fileStorageType == SRM_PERMANENT) f->SetMetaData("filestoragetype", "PERMANENT"); 
00654 
00655     }
00656     return DataStatus::Success;
00657   }
00658 
00659   const std::string DataPointSRM::DefaultCheckSum() const {
00660     return std::string("adler32");
00661   }
00662 
00663 } // namespace Arc
00664 
00665 Arc::PluginDescriptor PLUGINS_TABLE_NAME[] = {
00666   { "srm", "HED:DMC", 0, &Arc::DataPointSRM::Instance },
00667   { NULL, NULL, 0, NULL }
00668 };