Back to index

nordugrid-arc-nox  1.1.0~rc6
InfoCache.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <glibmm/fileutils.h>
00006 #include <glibmm/miscutils.h>
00007 
00008 #include <InfoCache.h>
00009 #include <arc/Logger.h>
00010 #include <arc/ArcRegex.h>
00011 #include <arc/StringConv.h>
00012 #include <sys/stat.h>
00013 #include <sys/types.h>
00014 #include <iostream>
00015 #include <fstream>
00016 #include <cstdio>
00017 
00018 #ifdef WIN32
00019 #include <arc/win32.h>
00020 #endif
00021 
00022 namespace Arc {
00023 
00024 static Logger logger(Logger::getRootLogger(), "InfoCache");
00025 
00026 static RegularExpression id_regex("@id=\"([a-zA-Z0-9_\\\\-]*)\"");
00027 
00028 static void merge_xml(std::string& path_base, XMLNode &node)
00029 {
00030     Glib::Dir dir(path_base);
00031     std::string d;
00032     
00033     while ((d = dir.read_name()) != "") {
00034         std::string path_fl1 = Glib::build_filename(path_base, d);
00035         //std::cout << "merge_xml f1: " << path_fl1 << std::endl;
00036         if (Glib::file_test(path_fl1, Glib::FILE_TEST_IS_REGULAR)) {
00037             std::string xml_str = Glib::file_get_contents(path_fl1);
00038             XMLNode n(xml_str);
00039             XMLNode c;
00040             for (int i = 0; (bool)(c = n.Child(i)); i++) {
00041                     node.NewChild(c);
00042             }
00043         }
00044     }
00045 }
00046 
00047 static bool create_directory(const std::string dir) {
00048     if (!Glib::file_test(dir, Glib::FILE_TEST_IS_DIR)) {
00049         // create directory
00050         if (mkdir(dir.c_str(), 0700) != 0) {
00051             logger.msg(ERROR,"cannot create directory: %s",dir);
00052             return false;
00053         }
00054     }
00055     return true;
00056 }
00057 
00058 // --------------------------------------------------------------------------------
00059 
00060 InfoCache::InfoCache(const Config &cfg, const std::string &service_id)
00061 {
00062     std::string cfg_s;
00063     cfg.GetXML(cfg_s);
00064     logger.msg(DEBUG,"Cache configuration: %s",cfg_s);
00065     std::string root = std::string(const_cast<Config&>(cfg)["CacheRoot"]);
00066     if(root.empty()) {
00067         logger.msg(ERROR,"Missing cache root in configuration");
00068         return;
00069     }
00070     if(service_id.empty()) {
00071         logger.msg(ERROR,"Missing service id");
00072         return;
00073     }
00074     logger.msg(DEBUG,"Cache root: %s",root);
00075     if (!create_directory(root)) return;
00076     std::string id(service_id);
00077     std::string sdir = Glib::build_filename(root, id);
00078     if (!create_directory(sdir)) return;
00079     path_base=sdir;
00080     logger.msg(DEBUG,"Cache directory: %s",path_base);
00081 }
00082 
00083 InfoCache::~InfoCache()
00084 {
00085     // NOP
00086 }
00087 
00088 static void clean_path(std::string s)
00089 {
00090     size_t idx;
00091     do {
00092         idx = s.find("//", 0);
00093         if (idx != std::string::npos) {
00094             s.replace(idx, 2, "/", 0, 1);
00095         }
00096     } while (idx != std::string::npos);
00097 }
00098 
00099 static bool set_path(const std::string &path_base,const std::list<std::string> &tokens,const XMLNode &node)
00100 {
00101     if(tokens.size() < 1) return false;
00102     std::string dir = path_base;
00103     const std::list<std::string>::const_iterator itLastElement = --tokens.end();
00104     for (std::list<std::string>::const_iterator it = tokens.begin();
00105          it != itLastElement; it++) {
00106         dir = Glib::build_filename(dir, *it);
00107         if (!create_directory(dir)) return false;
00108     };
00109     std::string file = Glib::build_filename(dir, tokens.back() + ".xml");
00110     // Workaround needed to save namespaces properly.
00111     // TODO: solve it in some better way.
00112     XMLNode doc; node.New(doc);
00113     return doc.SaveToFile(file);
00114 }
00115 
00116 static bool unset_path(const std::string &path_base,const std::list<std::string> &tokens)
00117 {
00118     if(tokens.size() < 1) return false;
00119     std::string dir = path_base;
00120     const std::list<std::string>::const_iterator itLastElement = --tokens.end();
00121     for (std::list<std::string>::const_iterator it = tokens.begin();
00122          it != itLastElement; it++) {
00123         dir = Glib::build_filename(dir, *it);
00124         if (!create_directory(dir)) return false;
00125     };
00126     std::string file = Glib::build_filename(dir, tokens.back() + ".xml");
00127     return (::remove(file.c_str()) == 0);
00128 }
00129 
00130 static bool get_path(const std::string &path_base,const std::list<std::string> &tokens,XMLNode &node)
00131 {
00132     if(tokens.size() < 1) return false;
00133     std::string dir = path_base;
00134     const std::list<std::string>::const_iterator itLastElement = --tokens.end();
00135     for (std::list<std::string>::const_iterator it = tokens.begin();
00136          it != itLastElement; it++) {
00137         dir = Glib::build_filename(dir, *it);
00138         if (!create_directory(dir)) return false;
00139     };
00140     std::string file = Glib::build_filename(dir, tokens.back() + ".xml");
00141     return node.ReadFromFile(file);
00142 }
00143 
00144 bool InfoCache::Set(const char *xml_path, XMLNode &value)
00145 {
00146     if (path_base.empty()) {
00147         logger.msg(ERROR,"InfoCache object is not set up");
00148         return false;
00149     }
00150     if (xml_path[0] != '/') {
00151         logger.msg(ERROR,"Invalid path in Set(): %s",xml_path);
00152         return false;
00153     }
00154     std::string p(xml_path);
00155     clean_path(p);
00156     std::list<std::string> tokens;
00157     tokenize(p, tokens, "/");
00158     bool ret;
00159     ret = set_path(path_base, tokens, value);
00160     return ret;
00161 }
00162 
00163 bool InfoCache::Unset(const char *xml_path)
00164 {
00165     if (path_base.empty()) {
00166         logger.msg(ERROR,"InfoCache object is not set up");
00167         return false;
00168     }
00169     if (xml_path[0] != '/') {
00170         logger.msg(ERROR,"Invalid path in Set(): %s",xml_path);
00171         return false;
00172     }
00173     std::string p(xml_path);
00174     clean_path(p);
00175     std::list<std::string> tokens;
00176     tokenize(p, tokens, "/");
00177     bool ret;
00178     ret = unset_path(path_base, tokens);
00179     return ret;
00180 }
00181 
00182 bool InfoCache::Get(const char *xml_path, XMLNodeContainer &result)
00183 {
00184     if (path_base.empty()) {
00185         logger.msg(ERROR,"InfoCache object is not set up");
00186         return false;
00187     }
00188     if (xml_path[0] != '/') {
00189         logger.msg(ERROR,"Invalid path in Get(): %s",xml_path);
00190         return false;
00191     }
00192     std::string p(xml_path);
00193     clean_path(p);
00194     std::list<std::string> tokens;
00195     tokenize(p, tokens, "/");
00196     if (tokens.size() <= 0) {
00197         NS ns;
00198         XMLNode node(ns, "InfoDoc");
00199         merge_xml(path_base, node);
00200         result.AddNew(node);
00201         return true;
00202     }
00203     XMLNode node;
00204     return get_path(path_base,tokens,node);
00205 }
00206 
00207 bool InfoCache::Query(const char *path, const char *query, XMLNodeContainer &result)
00208 {
00209     if (path_base.empty()) {
00210         logger.msg(ERROR,"InfoCache object is not set up");
00211         return false;
00212     }
00213     XMLNodeContainer gc;
00214     Get(path, gc);
00215     NS ns;
00216     
00217     for (int i = 0; i < gc.Size(); i++) {
00218         XMLNode node = gc[i];
00219         XMLNodeList xresult = node.XPathLookup(query,ns);
00220         result.AddNew(xresult);
00221     }
00222     return true;
00223 }
00224 
00225 // --------------------------------------------------------------------------------
00226 
00227 InfoCacheInterface::InfoCacheInterface(Config &cfg, std::string &service_id):
00228                                        cache(cfg,service_id)
00229 {
00230 }
00231 
00232 InfoCacheInterface::~InfoCacheInterface(void)
00233 {
00234 }
00235 
00236 void InfoCacheInterface::Get(const std::list<std::string>& path,XMLNodeContainer& result)
00237 {
00238     std::string xml_path;
00239     for(std::list<std::string>::const_iterator cur_name = path.begin();
00240         cur_name != path.end(); ++cur_name) {
00241         xml_path+="/"+(*cur_name);
00242     };
00243     if(xml_path.empty()) xml_path="/";
00244     cache.Get(xml_path,result);
00245 }
00246 
00247 void InfoCacheInterface::Get(XMLNode xpath,XMLNodeContainer& result)
00248 {
00249     std::string query = xpath;
00250     if(!cache.Query("/",query.c_str(),result)) return;
00251     return;
00252 }
00253 
00254 } // namespace Arc
00255