<commit_before>/*
**
** Author(s):
**  - Herve Cuche <hcuche@aldebaran-robotics.com>
**
** Copyright (C) 2011 Aldebaran Robotics
*/

#include <string>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>

#include <fstream>

#include <tinyxml/tinyxml.h>

#include <qimessaging/value.hpp>
#include <qimessaging/signature.hpp>
#include <qipreference/preference.hpp>

namespace qi {
  namespace pref {

    class PreferenceMapPrivate
    {
    public:
      PreferenceMapPrivate();
      ~PreferenceMapPrivate();

      int parse_attribs(TiXmlElement* element,
                        std::map<std::string, std::string> &attribs);
      std::map<std::string, qi::Value> parse(TiXmlNode* parent);

      void getKeys(std::vector<std::string> &key,
                   qi::Value values,
                   const std::string &prefix);

      void saveKeys(const std::string &tag,
                    const qi::Value &value,
                    int indent);

    public:
      std::map<std::string, qi::Value> _values;

      std::stringstream _ss;

    protected:
    private:
      qi::Value xmlToValue(const std::string &type,
                           const std::string &value);

      std::string getType(const qi::Value &value);
      std::string getValue(const std::string &type,
                           qi::Value value);

    };

    PreferenceMapPrivate::PreferenceMapPrivate()
    {
    }

    PreferenceMapPrivate::~PreferenceMapPrivate()
    {
    }

    int PreferenceMapPrivate::parse_attribs(TiXmlElement* element,
                                            std::map<std::string, std::string> &attribs)
    {
      if (!element)
        return 0;

      TiXmlAttribute* attrib = element->FirstAttribute();
      std::map<std::string, std::string> att;
      int i = 0;
      while (attrib)
      {
        std::stringstream ss;
        ss << attrib->Name();
        std::stringstream ss1;
        ss1 << attrib->Value();

        attribs[ss.str()] = ss1.str();

        attrib = attrib->Next();
        ++i;
      }

      return i;
    }

    qi::Value PreferenceMapPrivate::xmlToValue(const std::string &type,
                                               const std::string &value)
    {
      if (type == "bool")
      {
        if (value == "true")
        {
          qi::Value v(true);
          return v;
        }
        else if (value == "false")
        {
          qi::Value v(false);
          return v;
        }
      }
      if (type == "char")
      {
        std::stringstream ss;
        ss << value;

        char res;
        ss >> res;

        qi::Value v(res);
        return v;
      }
      if (type == "int")
      {
        std::stringstream ss;
        ss << value;

        int res;
        ss >> res;

        qi::Value v(res);
        return v;
      }
      if (type == "unsigned int")
      {
        std::stringstream ss;
        ss << value;

        unsigned int res;
        ss >> res;

        qi::Value v(res);
        return v;
      }
      if (type == "long long")
      {
        std::stringstream ss;
        ss << value;

        long long res;
        ss >> res;

        qi::Value v(res);
        return v;
      }
      if (type == "unsigned long long")
      {
        std::stringstream ss;
        ss << value;

        unsigned long long res;
        ss >> res;

        qi::Value v(res);
        return v;
      }
      if (type == "float")
      {
        std::stringstream ss;
        ss << value;

        float res;
        ss >> res;

        qi::Value v(res);
        return v;
      }
      if (type == "double")
      {
        std::stringstream ss;
        ss << value;

        double res;
        ss >> res;

        qi::Value v(res);
        return v;
      }
      if (type == "string")
      {
        qi::Value v(value);
        return v;
      }
    }

    std::map<std::string, qi::Value> PreferenceMapPrivate::parse(TiXmlNode* parent)
    {
      if (!parent)
      {
        std::cerr << "Invalid node!" << std::endl;
        return qi::ValueMap();
      }

      TiXmlNode* child;
      int num = 0;
      std::map<std::string, std::string> attribs;

      int t = parent->Type();
      switch (t)
      {
      case TiXmlNode::DOCUMENT:
        break;

      case TiXmlNode::ELEMENT:
        num = parse_attribs(parent->ToElement(), attribs);
        break;

      case TiXmlNode::COMMENT:
        break;

      case TiXmlNode::UNKNOWN:
        break;

      case TiXmlNode::TEXT:
        break;

      case TiXmlNode::DECLARATION:
        break;

      default:
        break;
      }

      if (attribs.find("name") != attribs.end() &&
          attribs.find("type") != attribs.end() &&
          attribs.find("value") != attribs.end())
      {
        qi::ValueMap mValue;
        qi::Value v = xmlToValue(attribs.find("type")->second,
                                 attribs.find("value")->second);

        mValue[attribs.find("name")->second] = v;
        return mValue;
      }
      else if (attribs.find("name") != attribs.end() &&
               attribs.find("type") != attribs.end())
      {
        if (attribs.find("type")->second == "array")
        {
          qi::Value v(qi::Value::Map);
          qi::ValueMap mValue;

          for (child = parent->FirstChild(); child != 0; child = child->NextSibling())
          {
            qi::ValueMap mTmpValue;
            mTmpValue = parse(child);
            v.value<qi::ValueMap>()[(mTmpValue.begin())->first] = (mTmpValue.begin())->second;
          }

          mValue[attribs.find("name")->second] = v;
          return mValue;
        }
      }
      else if (attribs.find("name") != attribs.end())
      {
        qi::Value v(qi::Value::Map);
        qi::ValueMap mValue;

        for (child = parent->FirstChild(); child != 0; child = child->NextSibling())
        {
          qi::ValueMap mTmpValue;
          mTmpValue = parse(child);
          v.value<qi::ValueMap>()[(mTmpValue.begin())->first] = (mTmpValue.begin())->second;
        }

        mValue[attribs.find("name")->second] = v;
        return mValue;
      }

      qi::ValueMap mTmpValue;
      for (child = parent->FirstChild(); child != 0; child = child->NextSibling())
      {
        mTmpValue = parse(child);
      }
      return  mTmpValue;
    }

    PreferenceMap::PreferenceMap()
    {
      _private = new PreferenceMapPrivate;
    }

    PreferenceMap::~PreferenceMap()
    {
      delete _private;
    }

    void PreferenceMap::load(const std::string &file)
    {
      TiXmlDocument doc(file.c_str());
      if(doc.LoadFile())
        _private->_values = _private->parse(&doc);
      else
        printf("Cannot open file!\n");
    }

    std::string PreferenceMapPrivate::getType(const qi::Value &value)
    {
      if (value._private.type == qi::Value::Bool)
        return "bool";
      if (value._private.type == qi::Value::Char)
        return "char";
      if (value._private.type == qi::Value::Int32)
        return "int";
      if (value._private.type == qi::Value::UInt32)
        return "unsigned int";
      if (value._private.type == qi::Value::Int64)
        return "long long";
      if (value._private.type == qi::Value::UInt64)
        return "unsigned long long";
      if (value._private.type == qi::Value::Float)
        return "float";
      if (value._private.type == qi::Value::Double)
        return "double";
      if (value._private.type == qi::Value::String)
        return "string";
      if (value._private.type == qi::Value::Map)
        return "array";

      return "";
    }

    std::string PreferenceMapPrivate::getValue(const std::string &type,
                                               qi::Value value)
    {
      std::stringstream ss;

      if (type == "bool")
      {
        if (value.toBool())
          ss << "true";
        else
          ss << "false";
      }

      if (type == "char")
        ss << value.toChar();

      if (type == "int")
        ss << value.toInt32();

      if (type == "unsigned int")
        ss << value.toUInt32();

      if (type == "long long")
        ss << value.toInt64();

      if (type == "unsigned long long")
        ss << value.toUInt64();

      if (type == "float")
        ss << value.toFloat();

      if (type == "double")
        ss << value.toDouble();

      if (type == "string")
        ss << value.toString();

      return ss.str();
    }

    void PreferenceMapPrivate::saveKeys(const std::string &tag,
                                        const qi::Value &value,
                                        int indent)
    {
      qi::Value v = value;
      qi::ValueMap vm = v.toMap();
      qi::ValueMap::iterator it = vm.begin();
      for (; it != vm.end(); ++it)
      {
        for (int i = 0; i < indent; ++i)
          _ss << "\t";

        std::string type = getType(it->second);
        _ss << "<" << tag
            << " type=\"" << type << "\" "
            << "name=\"" << it->first << "\" ";

        if (type == "array")
        {
          _ss << ">" << std::endl;
          saveKeys(tag, it->second, indent + 1);
          for (int i = 0; i < indent; ++i)
            _ss << "\t";

          _ss << "</" << tag << ">" << std::endl;
        }
        else
        {
          _ss << "value=\"" << getValue(type, it->second) << "\" />" << std::endl;
        }

      }
      return;
    }

    // FIXME
    void PreferenceMap::save(const std::string &file)
    {
      std::filebuf fb;
      fb.open(file.c_str(), std::ios::out);
      std::ostream _os(&fb);

      qi::ValueMap::iterator it = _private->_values.begin();
      std::string s = it->first;

      _private->_ss << "<?xml version = '1.0' encoding = 'UTF-8'?>" << std::endl;
      _private->_ss << "<ModulePreference xmlns=" << "\"\" "
                    << "schemaLocation=" << "\"\" "
                    << "name=\"" << s << "\" >" << std::endl;

      if (it->second._private.type == qi::Value::Map)
        _private->saveKeys("Preference", it->second, 1);

      _private->_ss << "</ModulePreference>" << std::endl;
      _os << _private->_ss.str();

      fb.close();
    }

    // get a value
    const qi::Value &PreferenceMap::get(const std::string &name)
    {
      int start = 0;
      int end = name.find("/");

      if (end == 0)
      {
        start++;
        end = name.find("/", start);
      }

      std::vector<std::string> vect;
      for (; end != std::string::npos ; start = end + 1, end = name.find("/", start))
        vect.push_back(name.substr(start, end - start));

      if (start < name.size())
        vect.push_back(name.substr(start, end));

      if (vect.empty())
        return qi::Value();

      qi::ValueMap vm = _private->_values;
      qi::ValueMap::iterator it;
      for (int i = 0; i < vect.size(); ++i)
      {
        it = vm.find(vect[i]);
        if (it == vm.end())
          break;
        else if (i != vect.size() - 1)
        {
          qi::Value v = (it->second);
          if (v._private.type == qi::Value::Map)
          {
            vm = (it->second).value<qi::ValueMap>();
          }
          else
          {
            break;
          }
        }
        else
          return (it->second);
      }

      return qi::Value();
    }

    void PreferenceMap::set(const std::string &name,
                            const qi::Value &val)
    {
      int start = 0;
      int end = name.find("/");
      qi::Value v = val;

      if (end == 0)
      {
        start++;
        end = name.find("/", start);
      }

      std::vector<std::string> vect;
      for (; end != std::string::npos ; start = end + 1, end = name.find("/", start))
        vect.push_back(name.substr(start, end - start));

      if (start < name.size())
        vect.push_back(name.substr(start, end));

      if (vect.empty())
        return;

      qi::ValueMap *vm = &_private->_values;
      qi::ValueMap::iterator it;
      for (int i = 0; i < vect.size(); ++i)
      {
        it = vm->find(vect[i]);
        if (it == vm->end())
          break;
        else if (i != vect.size() - 1)
        {
          qi::Value v = (it->second);
          if (v._private.type == qi::Value::Map)
          {
            vm = &(it->second).value<qi::ValueMap>();
          }
          else
          {
            break;
          }
        }
        else
        {
          (*vm)[it->first] = v;
          break;
        }
      }

      return;
    }

    // delete a preference entry
    void PreferenceMap::remove(const std::string &name)
    {
      int start = 0;
      int end = name.find("/");

      if (end == 0)
      {
        start++;
        end = name.find("/", start);
      }

      std::vector<std::string> vect;
      for (; end != std::string::npos ; start = end + 1, end = name.find("/", start))
        vect.push_back(name.substr(start, end - start));

      if (start < name.size())
        vect.push_back(name.substr(start, end));

      if (vect.empty())
        return;

      qi::ValueMap *vm = &_private->_values;
      qi::ValueMap::iterator it;
      for (int i = 0; i < vect.size(); ++i)
      {
        it = vm->find(vect[i]);
        if (it == vm->end())
          break;
        else if (i != vect.size() - 1)
        {
          qi::Value v = (it->second);
          if (v._private.type == qi::Value::Map)
          {
            vm = &(it->second).value<qi::ValueMap>();
          }
          else
          {
            break;
          }
        }
        else
        {
          vm->erase(it);
          break;
        }
      }

      return;
    }

    void PreferenceMapPrivate::getKeys(std::vector<std::string> &key,
                                       qi::Value values,
                                       const std::string &prefix)
    {
      qi::ValueMap vm = values.toMap();
      qi::ValueMap::iterator it = vm.begin();
      for (; it != vm.end(); ++it)
      {
        std::string s = prefix + "/" + it->first;
        key.push_back(s);
        if (it->second._private.type == qi::Value::Map)
          getKeys(key, it->second, s);
      }
      return;
    }

    // find existing keys, which names start with `prefix'
    std::vector<std::string> PreferenceMap::keys(const std::string &prefix)
    {
      std::vector<std::string> k;
      qi::ValueMap::iterator it = _private->_values.begin();
      std::string s = it->first;
      k.push_back(s);
      if (it->second._private.type == qi::Value::Map)
        _private->getKeys(k, it->second, s);

      if (prefix.empty())
        return k;
      else
      {
        std::vector<std::string> res;
        for (int i = 0; i < k.size(); ++i)
        {
          if (prefix[0] == '/')
          {
            if (k[i].find(&prefix[1]) == 0)
            {
              res.push_back("/" + k[i]);
            }
          }
          else
          {
            if (k[i].find(prefix) == 0)
            {
              res.push_back(k[i]);
            }
          }
        }
        return res;
      }
    }

    // return all values
    std::map<std::string, qi::Value> PreferenceMap::values()
    {
      return _private->_values;
    }

  } // !pref
} // !qi
<commit_msg>qipreference: clean qipreference source code.<commit_after>/*
**
** Author(s):
**  - Herve Cuche <hcuche@aldebaran-robotics.com>
**
** Copyright (C) 2011 Aldebaran Robotics
*/

#include <string>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>

#include <fstream>

#include <tinyxml/tinyxml.h>

#include <qimessaging/value.hpp>
#include <qimessaging/signature.hpp>
#include <qipreference/preference.hpp>

namespace qi {
  namespace pref {

    class PreferenceMapPrivate
    {
    public:
      PreferenceMapPrivate();
      ~PreferenceMapPrivate();

      void parse_attribs(TiXmlElement* element,
                         std::map<std::string, std::string> &attribs);

      std::map<std::string, qi::Value> parse(TiXmlNode* parent);

      void getAllKeys(std::vector<std::string> &key,
                      const qi::Value &values,
                      const std::string &prefix);

      void saveKeys(const std::string &tag,
                    const qi::Value &value,
                    int indent);

    public:
      std::map<std::string, qi::Value> _values;

      std::stringstream _ss;

    protected:
    private:
      qi::Value xmlToValue(const std::string &type,
                           const std::string &value);

      std::string getType(const qi::Value &value);
      std::string getValueToString(const std::string &type,
                                   const qi::Value &value);

      template <typename T>
      qi::Value typeToValue(const std::string &value);
    };

    PreferenceMapPrivate::PreferenceMapPrivate()
    {
    }

    PreferenceMapPrivate::~PreferenceMapPrivate()
    {
    }

    void PreferenceMapPrivate::parse_attribs(TiXmlElement* element,
                                             std::map<std::string, std::string> &attribs)
    {
      if (!element)
        return;

      TiXmlAttribute* attrib = element->FirstAttribute();
      std::map<std::string, std::string> att;
      for (; attrib != NULL; attrib = attrib->Next())
        attribs[std::string(attrib->Name())] = std::string(attrib->Value());
    }

    template <typename T>
    qi::Value PreferenceMapPrivate::typeToValue(const std::string &value)
    {
      std::stringstream ss;
      ss << value;

      T res;
      ss >> res;

      return qi::Value(res);
    }

    qi::Value PreferenceMapPrivate::xmlToValue(const std::string &type,
                                               const std::string &value)
    {
      if (type == "bool")
      {
        if (value == "true")
          return qi::Value(true);
        else
          return qi::Value(false);
      }
      if (type == "char")
        return typeToValue<char>(value);
      if (type == "int")
        return typeToValue<int>(value);
      if (type == "unsigned int")
        return typeToValue<unsigned int>(value);
      if (type == "long long")
        return typeToValue<long long>(value);
      if (type == "unsigned long long")
        return typeToValue<unsigned long long>(value);
      if (type == "float")
        return typeToValue<float>(value);
      if (type == "double")
        return typeToValue<double>(value);
      if (type == "string")
        return qi::Value(value);
    }

    std::map<std::string, qi::Value> PreferenceMapPrivate::parse(TiXmlNode* parent)
    {
      if (!parent)
      {
        std::cerr << "Invalid node!" << std::endl;
        return qi::ValueMap();
      }

      TiXmlNode* child;
      std::map<std::string, std::string> attribs;

      int t = parent->Type();
      switch (t)
      {
      case TiXmlNode::DOCUMENT:
        break;

      case TiXmlNode::ELEMENT:
        parse_attribs(parent->ToElement(), attribs);
        break;

      case TiXmlNode::COMMENT:
        break;

      case TiXmlNode::UNKNOWN:
        break;

      case TiXmlNode::TEXT:
        break;

      case TiXmlNode::DECLARATION:
        break;

      default:
        break;
      }

      std::map<std::string, std::string>::iterator name = attribs.find("name");
      std::map<std::string, std::string>::iterator type = attribs.find("type");
      std::map<std::string, std::string>::iterator value = attribs.find("value");

      if (name != attribs.end() &&
          type != attribs.end() &&
          value != attribs.end())
      {
        qi::ValueMap mValue;
        mValue[name->second] = xmlToValue(type->second, value->second);

        return mValue;
      }
      else if (name != attribs.end() &&
               type != attribs.end())
      {
        if (type->second == "array")
        {
          qi::Value v(qi::Value::Map);
          qi::ValueMap mValue;

          for (child = parent->FirstChild(); child != 0; child = child->NextSibling())
          {
            qi::ValueMap mTmpValue;
            mTmpValue = parse(child);
            v.value<qi::ValueMap>()[(mTmpValue.begin())->first] = (mTmpValue.begin())->second;
          }

          mValue[name->second] = v;
          return mValue;
        }
      }
      else if (name != attribs.end())
      {
        qi::Value v(qi::Value::Map);
        qi::ValueMap mValue;

        for (child = parent->FirstChild(); child != 0; child = child->NextSibling())
        {
          qi::ValueMap mTmpValue;
          mTmpValue = parse(child);
          v.value<qi::ValueMap>()[(mTmpValue.begin())->first] = (mTmpValue.begin())->second;
        }

        mValue[name->second] = v;
        return mValue;
      }

      qi::ValueMap mTmpValue;
      for (child = parent->FirstChild(); child != 0; child = child->NextSibling())
      {
        mTmpValue = parse(child);
      }
      return  mTmpValue;
    }

    PreferenceMap::PreferenceMap()
    {
      _private = new PreferenceMapPrivate;
    }

    PreferenceMap::~PreferenceMap()
    {
      delete _private;
    }

    void PreferenceMap::load(const std::string &file)
    {
      TiXmlDocument doc(file.c_str());
      if(doc.LoadFile())
        _private->_values = _private->parse(&doc);
      else
        printf("Cannot open file!\n");
    }

    std::string PreferenceMapPrivate::getType(const qi::Value &value)
    {
      if (value.type() == qi::Value::Bool)
        return "bool";
      if (value.type() == qi::Value::Char)
        return "char";
      if (value.type() == qi::Value::Int32)
        return "int";
      if (value.type() == qi::Value::UInt32)
        return "unsigned int";
      if (value.type() == qi::Value::Int64)
        return "long long";
      if (value.type() == qi::Value::UInt64)
        return "unsigned long long";
      if (value.type() == qi::Value::Float)
        return "float";
      if (value.type() == qi::Value::Double)
        return "double";
      if (value.type() == qi::Value::String)
        return "string";
      if (value.type() == qi::Value::Map)
        return "array";

      return "";
    }

    std::string PreferenceMapPrivate::getValueToString(const std::string &type,
                                                       const qi::Value &value)
    {
      std::stringstream ss;

      if (type == "bool")
      {
        if (value.toBool())
          ss << "true";
        else
          ss << "false";
      }

      if (type == "char")
        ss << value.toChar();
      if (type == "int")
        ss << value.toInt32();
      if (type == "unsigned int")
        ss << value.toUInt32();
      if (type == "long long")
        ss << value.toInt64();
      if (type == "unsigned long long")
        ss << value.toUInt64();
      if (type == "float")
        ss << value.toFloat();
      if (type == "double")
        ss << value.toDouble();
      if (type == "string")
        ss << value.toString();

      return ss.str();
    }

    void PreferenceMapPrivate::saveKeys(const std::string &tag,
                                        const qi::Value &value,
                                        int indent)
    {
      qi::ValueMap vm = value.toMap();
      for (qi::ValueMap::iterator it = vm.begin(); it != vm.end(); ++it)
      {
        for (int i = 0; i < indent; ++i)
          _ss << "\t";

        std::string type = getType(it->second);
        _ss << "<" << tag
            << " type=\"" << type << "\" "
            << "name=\"" << it->first << "\" ";

        if (type == "array")
        {
          _ss << ">" << std::endl;
          saveKeys(tag, it->second, indent + 1);
          for (int i = 0; i < indent; ++i)
            _ss << "\t";

          _ss << "</" << tag << ">" << std::endl;
        }
        else
        {
          _ss << "value=\"" << getValueToString(type, it->second) << "\" />" << std::endl;
        }
      }
    }

    void PreferenceMap::save(const std::string &file)
    {
      std::ofstream f;
      f.open(file.c_str());
      _private->_ss.clear();

      qi::ValueMap::iterator it = _private->_values.begin();
      std::string s = it->first;

      _private->_ss << "<?xml version = '1.0' encoding = 'UTF-8'?>" << std::endl;
      _private->_ss << "<ModulePreference xmlns=" << "\"\" "
                    << "schemaLocation=" << "\"\" "
                    << "name=\"" << s << "\" >" << std::endl;

      if (it->second.type() == qi::Value::Map)
        _private->saveKeys("Preference", it->second, 1);

      _private->_ss << "</ModulePreference>" << std::endl;

      f << _private->_ss.str();
      f.close();
    }

    std::vector<std::string> getVectorPath(const std::string& path)
    {
      int start = 0;
      int end = path.find("/");

      if (end == 0)
      {
        start++;
        end = path.find("/", start);
      }

      std::vector<std::string> vect;
      for (; end != std::string::npos ; start = end + 1, end = path.find("/", start))
        vect.push_back(path.substr(start, end - start));

      if (start < path.size())
        vect.push_back(path.substr(start, end));

      return vect;
    }

    const qi::Value &PreferenceMap::get(const std::string &name)
    {

      std::vector<std::string> vect = getVectorPath(name);

      if (vect.empty())
        return qi::Value();

      qi::ValueMap vm = _private->_values;
      qi::ValueMap::iterator it;
      for (int i = 0; i < vect.size(); ++i)
      {
        it = vm.find(vect[i]);
        if (it == vm.end())
          break;
        else if (i != vect.size() - 1)
        {
          if ((it->second).type() == qi::Value::Map)
          {
            vm = (it->second).value<qi::ValueMap>();
          }
          else
          {
            break;
          }
        }
        else
          return (it->second);
      }

      return qi::Value();
    }

    void PreferenceMap::set(const std::string &name,
                            const qi::Value &val)
    {
      std::vector<std::string> vect = getVectorPath(name);

      if (vect.empty())
        return;

      qi::ValueMap *vm = &_private->_values;
      qi::ValueMap::iterator it;
      for (int i = 0; i < vect.size(); ++i)
      {
        it = vm->find(vect[i]);
        if (it == vm->end())
          break;
        else if (i != vect.size() - 1)
        {
          if ((it->second).type() == qi::Value::Map)
          {
            vm = &(it->second).value<qi::ValueMap>();
          }
          else
          {
            break;
          }
        }
        else
        {
          (*vm)[it->first] = val;
          break;
        }
      }

      return;
    }

    void PreferenceMap::remove(const std::string &name)
    {
      std::vector<std::string> vect = getVectorPath(name);

      if (vect.empty())
        return;

      qi::ValueMap *vm = &_private->_values;
      qi::ValueMap::iterator it;
      for (int i = 0; i < vect.size(); ++i)
      {
        it = vm->find(vect[i]);
        if (it == vm->end())
          break;
        else if (i != vect.size() - 1)
        {
          if ((it->second).type() == qi::Value::Map)
          {
            vm = &(it->second).value<qi::ValueMap>();
          }
          else
          {
            break;
          }
        }
        else
        {
          vm->erase(it);
          break;
        }
      }

      return;
    }

    void PreferenceMapPrivate::getAllKeys(std::vector<std::string> &key,
                                          const qi::Value &values,
                                          const std::string &prefix)
    {
      qi::ValueMap vm = values.toMap();
      qi::ValueMap::iterator it = vm.begin();
      for (; it != vm.end(); ++it)
      {
        std::string s = prefix + "/" + it->first;
        key.push_back(s);
        if (it->second.type() == qi::Value::Map)
          getAllKeys(key, it->second, s);
      }
      return;
    }

    std::vector<std::string> PreferenceMap::keys(const std::string &prefix)
    {
      std::vector<std::string> allKeys;
      std::vector<std::string> key;
      qi::ValueMap::iterator it = _private->_values.begin();

      // Get all keys for the map
      allKeys.push_back(it->first);
      if (it->second.type() == qi::Value::Map)
        _private->getAllKeys(allKeys, it->second, it->first);

      if (prefix.empty())
        return allKeys;
      else
      {
        // Only return keys with prefix
        for (int i = 0; i < allKeys.size(); ++i)
        {
          // Check first char
          if (prefix[0] == '/' && allKeys[i].find(&prefix[1]) == 0)
            key.push_back("/" + allKeys[i]);
          else if (allKeys[i].find(prefix) == 0)
            key.push_back(allKeys[i]);
        }
      }

      return key;
    }

    std::map<std::string, qi::Value> PreferenceMap::values()
    {
      return _private->_values;
    }

  } // !pref
} // !qi
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// Tests for the UdpSocketManager interface.
// Note: This tests UdpSocketManager together with UdpSocketWrapper,
// due to the way the code is full of static-casts to the platform dependent
// subtypes.
// It also uses the static UdpSocketManager object.
// The most important property of these tests is that they do not leak memory.

#include "udp_socket_wrapper.h"
#include "udp_socket_manager_wrapper.h"
#include "gtest/gtest.h"

TEST(UdpSocketManager, CreateCallsInitAndDoesNotLeakMemory) {
  WebRtc_Word32 id = 42;
  WebRtc_UWord8 threads = 1;
  webrtc::UdpSocketManager* mgr = webrtc::UdpSocketManager::Create(id, threads);
  // Create is supposed to have called init on the object.
  EXPECT_EQ(false, mgr->Init(id, threads))
      << "Init should return false since Create is supposed to call it.";
  webrtc::UdpSocketManager::Return();
}

// Creates a socket and adds it to the socket manager, and then removes it
// before destroying the socket manager.
TEST(UdpSocketManager, AddAndRemoveSocketDoesNotLeakMemory) {
  WebRtc_Word32 id = 42;
  WebRtc_UWord8 threads = 1;
  webrtc::UdpSocketManager* mgr = webrtc::UdpSocketManager::Create(id, threads);
  webrtc::UdpSocketWrapper* socket
       = webrtc::UdpSocketWrapper::CreateSocket(id,
                                                mgr,
                                                NULL,  // CallbackObj
                                                NULL,  // IncomingSocketCallback
                                                false,  // ipV6Enable
                                                false);  // disableGQOS
  // The constructor will do AddSocket on the manager.
  EXPECT_EQ(true, mgr->RemoveSocket(socket));
  webrtc::UdpSocketManager::Return();
}

// Creates a socket and add it to the socket manager, but does not remove it
// before destroying the socket manager.
// This should also destroy the socket.
TEST(UdpSocketManager, UnremovedSocketsGetCollectedAtManagerDeletion) {
  WebRtc_Word32 id = 42;
  WebRtc_UWord8 threads = 1;
  webrtc::UdpSocketManager* mgr = webrtc::UdpSocketManager::Create(id, threads);
  webrtc::UdpSocketWrapper* unused_socket
       = webrtc::UdpSocketWrapper::CreateSocket(id,
                                                mgr,
                                                NULL,  // CallbackObj
                                                NULL,  // IncomingSocketCallback
                                                false,  // ipV6Enable
                                                false);  // disableGQOS
  // The constructor will do AddSocket on the manager.
  unused_socket = NULL;
  webrtc::UdpSocketManager::Return();
}
<commit_msg>Disabled UnremovedSocketsGetCollectedAtManagerDeletion in UdpSocketManager unittest.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// Tests for the UdpSocketManager interface.
// Note: This tests UdpSocketManager together with UdpSocketWrapper,
// due to the way the code is full of static-casts to the platform dependent
// subtypes.
// It also uses the static UdpSocketManager object.
// The most important property of these tests is that they do not leak memory.

#include "udp_socket_wrapper.h"
#include "udp_socket_manager_wrapper.h"
#include "gtest/gtest.h"

TEST(UdpSocketManager, CreateCallsInitAndDoesNotLeakMemory) {
  WebRtc_Word32 id = 42;
  WebRtc_UWord8 threads = 1;
  webrtc::UdpSocketManager* mgr = webrtc::UdpSocketManager::Create(id, threads);
  // Create is supposed to have called init on the object.
  EXPECT_EQ(false, mgr->Init(id, threads))
      << "Init should return false since Create is supposed to call it.";
  webrtc::UdpSocketManager::Return();
}

// Creates a socket and adds it to the socket manager, and then removes it
// before destroying the socket manager.
TEST(UdpSocketManager, AddAndRemoveSocketDoesNotLeakMemory) {
  WebRtc_Word32 id = 42;
  WebRtc_UWord8 threads = 1;
  webrtc::UdpSocketManager* mgr = webrtc::UdpSocketManager::Create(id, threads);
  webrtc::UdpSocketWrapper* socket
       = webrtc::UdpSocketWrapper::CreateSocket(id,
                                                mgr,
                                                NULL,  // CallbackObj
                                                NULL,  // IncomingSocketCallback
                                                false,  // ipV6Enable
                                                false);  // disableGQOS
  // The constructor will do AddSocket on the manager.
  EXPECT_EQ(true, mgr->RemoveSocket(socket));
  webrtc::UdpSocketManager::Return();
}

// Creates a socket and add it to the socket manager, but does not remove it
// before destroying the socket manager.
// This should also destroy the socket.
TEST(UdpSocketManager, DISABLED_UnremovedSocketsGetCollectedAtManagerDeletion) {
  WebRtc_Word32 id = 42;
  WebRtc_UWord8 threads = 1;
  webrtc::UdpSocketManager* mgr = webrtc::UdpSocketManager::Create(id, threads);
  webrtc::UdpSocketWrapper* unused_socket
       = webrtc::UdpSocketWrapper::CreateSocket(id,
                                                mgr,
                                                NULL,  // CallbackObj
                                                NULL,  // IncomingSocketCallback
                                                false,  // ipV6Enable
                                                false);  // disableGQOS
  // The constructor will do AddSocket on the manager.
  unused_socket = NULL;
  webrtc::UdpSocketManager::Return();
}
<|endoftext|>


<commit_before>#include <cmath>
#include <ctime>
#include <iostream>
#include <random>
#include <set>
#include <vector>
#include <unordered_map>

namespace {

inline size_t GenerateMaskWithRightOnes(size_t onesCount) {
    return (1ull << onesCount) - 1ull;
}

class TCacheSet {
public:
    TCacheSet(size_t waysCount)
        : TicksTimer(0)
        , CacheWays(waysCount)
    {}

    bool Touch(size_t cacheLineNum) {
        ++TicksTimer;
        // CacheLine2LastTouch[cacheLineNum] = TicksTimer;
        TCacheLine* minTickLine = nullptr;
        size_t minTickTime = TicksTimer;
        for (auto& activeLine : CacheWays) {
            if (activeLine.LineNum != cacheLineNum) {
                if (activeLine.LineNum == -1) {
                    activeLine.TouchTick = TicksTimer;
                    activeLine.LineNum = cacheLineNum;
                    return false;
                }
                if (activeLine.TouchTick < minTickTime) {
                    minTickTime = activeLine.TouchTick;
                    minTickLine = &activeLine;
                }
            } else {
                activeLine.TouchTick = TicksTimer;
                ++CacheHits;
                return true;
            }
        }
        minTickLine->LineNum = cacheLineNum;
        minTickLine->TouchTick = TicksTimer;
        return false;
    }

    size_t GetCacheHits() const {
        return CacheHits;
    }

    size_t GetCacheMisses() const {
        return TicksTimer - CacheHits;
    }

private:
    struct TCacheLine {
        size_t LineNum = -1;
        size_t TouchTick = 0;
    };

private:
    size_t TicksTimer;
    std::vector<TCacheLine> CacheWays; // Contains LineNum == -1 if free
    // std::unordered_map<size_t, size_t> CacheLine2LastTouch;

    size_t CacheHits;
};

class TCache {
public:
    TCache(size_t cacheSize, size_t cacheLineSize, size_t waysCount)
        : CacheSize(cacheSize)
        , CacheLineSize(cacheLineSize)
        , WaysCount(waysCount)
        , BlocksCount(CacheSize / CacheLineSize)
        , SetsCount(BlocksCount / WaysCount)
        , BlockOffsetSize(static_cast<size_t>(log2(CacheLineSize)))
        , ShiftedIndexMask(GenerateMaskWithRightOnes(static_cast<size_t>(log2(SetsCount))))
        , InvBlockMask(~GenerateMaskWithRightOnes(BlockOffsetSize))
        , CacheSets(SetsCount, {WaysCount})
    {}

    /// @return true if needed cache line is in cache
    bool Touch(const void* ptr) {
        // std::cerr << std::oct << GetIndexFromPtr(ptr) << "\t->\t" << GetCacheLineNumFromPtr(ptr) << std::endl;
        return CacheSets[GetIndexFromPtr(ptr)].Touch(GetCacheLineNumFromPtr(ptr));
    }

    std::vector<size_t> GetCacheMisses() const {
        std::vector<size_t> result;
        result.reserve(SetsCount);
        for (const auto& cacheSet : CacheSets) {
            result.push_back(cacheSet.GetCacheMisses());
        }
        return result;
    }

private:
    size_t GetIndexFromPtr(const void* ptr) {
        return ((size_t)ptr >> BlockOffsetSize) & ShiftedIndexMask;
    }

    size_t GetCacheLineNumFromPtr(const void* ptr) {
        return (size_t)ptr & InvBlockMask;
    }

private:
    const size_t CacheSize;
    const size_t CacheLineSize;
    const size_t WaysCount;
    const size_t BlocksCount;
    const size_t SetsCount;
    const size_t BlockOffsetSize;

    const size_t ShiftedIndexMask;
    const size_t InvBlockMask;

    std::vector<TCacheSet> CacheSets;
};

void PrintStats(const TCache& cache) {
    auto misses = cache.GetCacheMisses();
    // auto hits = cache.GetCacheHits();
    for (size_t i = 0; i < misses.size(); ++i) {
        std::cerr << i << ")\t" << misses[i] << std::endl;
    }
}

void MultSimpleTooled(TCache& cache,
                      const float* __restrict a,
                      const float* __restrict b,
                      float* __restrict c,
                      int n)
{
    for (int i = 0; i < n; ++i) {
        if (i == 0) {
            //>-- i = 0
            cache.Touch(&i);
            //<-- i = 0
            //>-- i < n
            cache.Touch(&i);
            cache.Touch(&n);
            //<-- i < n
        }

        for (int j = 0; j < n; ++j) {
            if (j == 0) {
                //>-- j = 0
                cache.Touch(&j);
                //<-- j = 0
                //>-- j < n
                cache.Touch(&j);
                cache.Touch(&n);
                //<-- j < n
            }

            //>-- c[i * n + j]
            cache.Touch(&i);
            cache.Touch(&j);
            cache.Touch(&n);
            cache.Touch(&c);
            cache.Touch(&c[i * n + j]);
            //<-- c[i * n + j]

            c[i * n + j] = 0.f;
            for (int k = 0; k < n; ++k) {
                if (k == 0) {
                    //>-- k = 0
                    cache.Touch(&k);
                    //<-- k = 0
                    //>-- k < n
                    cache.Touch(&k);
                    cache.Touch(&n);
                    //<-- k < n
                }

                cache.Touch(&i);
                cache.Touch(&j);
                cache.Touch(&k);
                cache.Touch(&n);
                cache.Touch(&a);
                cache.Touch(&b);
                cache.Touch(&c);
                cache.Touch(&a[i * n + k]);
                cache.Touch(&b[k * n + j]);
                cache.Touch(&c[i * n + j]);

                c[i * n + j] += a[i * n + k] * b[k * n + j];

                //>-- ++k
                cache.Touch(&k);
                //<-- ++k
                //>-- k < n
                cache.Touch(&k);
                cache.Touch(&n);
                //<-- k < n
            }

            //>-- ++j
            cache.Touch(&j);
            //<-- ++j
            //>-- j < n
            cache.Touch(&j);
            cache.Touch(&n);
            //<-- j < n
        }

        //>-- ++i
        cache.Touch(&i);
        //<-- ++i
        //>-- i < n
        cache.Touch(&i);
        cache.Touch(&n);
        //<-- i < n
    }
}

void MultSimple(const float* __restrict a, const float* __restrict b, float* __restrict c, int n)
{
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            c[i * n + j] = 0.f;
            for (int k = 0; k < n; ++k) {
                c[i * n + j] += a[i * n + k] * b[k * n + j];
            }
        }
    }
}

void FillRandom(float* a, int n)
{
    std::default_random_engine eng;
    std::uniform_real_distribution<float> dist;

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            a[i * n + j] = dist(eng);
        }
    }
}

}

int main(int argc, char* argv[])
{
    const int n = atoi(argv[1]);
    std::cerr << "n = " << n << std::endl;

    float* a = new float[n * n];
    float* b = new float[n * n];
    float* c = new float[n * n];

    FillRandom(a, n);
    FillRandom(b, n);

    TCache cache(3*1024*1024 /* 32kb */, 64 /* 64b */, 12 /* ways */);
    {
        const auto startTime = std::clock();
        MultSimpleTooled(cache, a, b, c, n);
        const auto endTime = std::clock();

        std::cerr << "timeSimple: " << double(endTime - startTime) / CLOCKS_PER_SEC << '\n';
    }
    PrintStats(cache);

    delete[] a;
    delete[] b;
    delete[] c;
}

<commit_msg>Parametrize.<commit_after>#include <cmath>
#include <ctime>
#include <iostream>
#include <random>
#include <set>
#include <vector>
#include <unordered_map>

namespace {

inline size_t GenerateMaskWithRightOnes(size_t onesCount) {
    return (1ull << onesCount) - 1ull;
}

class TCacheSet {
public:
    TCacheSet(size_t waysCount)
        : TicksTimer(0)
        , CacheWays(waysCount)
    {}

    bool Touch(size_t cacheLineNum) {
        ++TicksTimer;
        // CacheLine2LastTouch[cacheLineNum] = TicksTimer;
        TCacheLine* minTickLine = nullptr;
        size_t minTickTime = TicksTimer;
        for (auto& activeLine : CacheWays) {
            if (activeLine.LineNum != cacheLineNum) {
                if (activeLine.LineNum == -1) {
                    activeLine.TouchTick = TicksTimer;
                    activeLine.LineNum = cacheLineNum;
                    return false;
                }
                if (activeLine.TouchTick < minTickTime) {
                    minTickTime = activeLine.TouchTick;
                    minTickLine = &activeLine;
                }
            } else {
                activeLine.TouchTick = TicksTimer;
                ++CacheHits;
                return true;
            }
        }
        minTickLine->LineNum = cacheLineNum;
        minTickLine->TouchTick = TicksTimer;
        return false;
    }

    size_t GetCacheHits() const {
        return CacheHits;
    }

    size_t GetCacheMisses() const {
        return TicksTimer - CacheHits;
    }

    double GetCacheMissRate() const {
        return GetCacheMisses() / (TicksTimer * 1.0);
    }

private:
    struct TCacheLine {
        size_t LineNum = -1;
        size_t TouchTick = 0;
    };

private:
    size_t TicksTimer;
    std::vector<TCacheLine> CacheWays; // Contains LineNum == -1 if free
    // std::unordered_map<size_t, size_t> CacheLine2LastTouch;

    size_t CacheHits;
};

class TCache {
public:
    TCache(size_t cacheSize, size_t cacheLineSize, size_t waysCount)
        : CacheSize(cacheSize)
        , CacheLineSize(cacheLineSize)
        , WaysCount(waysCount)
        , BlocksCount(CacheSize / CacheLineSize)
        , SetsCount(BlocksCount / WaysCount)
        , BlockOffsetSize(static_cast<size_t>(log2(CacheLineSize)))
        , ShiftedIndexMask(GenerateMaskWithRightOnes(static_cast<size_t>(log2(SetsCount))))
        , InvBlockMask(~GenerateMaskWithRightOnes(BlockOffsetSize))
        , CacheSets(SetsCount, {WaysCount})
    {}

    /// @return true if needed cache line is in cache
    bool Touch(const void* ptr) {
        return CacheSets[GetIndexFromPtr(ptr)].Touch(GetCacheLineNumFromPtr(ptr));
    }

    void PrintStats() const {
        size_t cacheSetIdx = 0;
        for (const auto& cacheSet : CacheSets) {
            std::cout << cacheSetIdx << ")\t"
                      << cacheSet.GetCacheMisses() << "\t"
                      << cacheSet.GetCacheMissRate() << std::endl;
            ++cacheSetIdx;
        }
    }

private:
    size_t GetIndexFromPtr(const void* ptr) {
        return ((size_t)ptr >> BlockOffsetSize) & ShiftedIndexMask;
    }

    size_t GetCacheLineNumFromPtr(const void* ptr) {
        return (size_t)ptr & InvBlockMask;
    }

private:
    const size_t CacheSize;
    const size_t CacheLineSize;
    const size_t WaysCount;
    const size_t BlocksCount;
    const size_t SetsCount;
    const size_t BlockOffsetSize;

    const size_t ShiftedIndexMask;
    const size_t InvBlockMask;

    std::vector<TCacheSet> CacheSets;
};

void MultSimpleTooled(TCache& cache,
                      const float* __restrict a,
                      const float* __restrict b,
                      float* __restrict c,
                      int n)
{
    for (int i = 0; i < n; ++i) {
        if (i == 0) {
            //>-- i = 0
            cache.Touch(&i);
            //<-- i = 0
            //>-- i < n
            cache.Touch(&i);
            cache.Touch(&n);
            //<-- i < n
        }

        for (int j = 0; j < n; ++j) {
            if (j == 0) {
                //>-- j = 0
                cache.Touch(&j);
                //<-- j = 0
                //>-- j < n
                cache.Touch(&j);
                cache.Touch(&n);
                //<-- j < n
            }

            //>-- c[i * n + j]
            cache.Touch(&i);
            cache.Touch(&j);
            cache.Touch(&n);
            cache.Touch(&c);
            cache.Touch(&c[i * n + j]);
            //<-- c[i * n + j]

            c[i * n + j] = 0.f;
            for (int k = 0; k < n; ++k) {
                if (k == 0) {
                    //>-- k = 0
                    cache.Touch(&k);
                    //<-- k = 0
                    //>-- k < n
                    cache.Touch(&k);
                    cache.Touch(&n);
                    //<-- k < n
                }

                cache.Touch(&i);
                cache.Touch(&j);
                cache.Touch(&k);
                cache.Touch(&n);
                cache.Touch(&a);
                cache.Touch(&b);
                cache.Touch(&c);
                cache.Touch(&a[i * n + k]);
                cache.Touch(&b[k * n + j]);
                cache.Touch(&c[i * n + j]);

                c[i * n + j] += a[i * n + k] * b[k * n + j];

                //>-- ++k
                cache.Touch(&k);
                //<-- ++k
                //>-- k < n
                cache.Touch(&k);
                cache.Touch(&n);
                //<-- k < n
            }

            //>-- ++j
            cache.Touch(&j);
            //<-- ++j
            //>-- j < n
            cache.Touch(&j);
            cache.Touch(&n);
            //<-- j < n
        }

        //>-- ++i
        cache.Touch(&i);
        //<-- ++i
        //>-- i < n
        cache.Touch(&i);
        cache.Touch(&n);
        //<-- i < n
    }
}

void MultSimple(const float* __restrict a, const float* __restrict b, float* __restrict c, int n)
{
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            c[i * n + j] = 0.f;
            for (int k = 0; k < n; ++k) {
                c[i * n + j] += a[i * n + k] * b[k * n + j];
            }
        }
    }
}

void FillRandom(float* a, int n)
{
    std::default_random_engine eng;
    std::uniform_real_distribution<float> dist;

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            a[i * n + j] = dist(eng);
        }
    }
}

}

int main(int argc, char* argv[])
{
    const int n = atoi(argv[1]);
    const size_t cacheSizeKB    = atoi(argv[2]);
    const size_t cacheLineSizeB = atoi(argv[3]);
    const size_t waysCount      = atoi(argv[4]);
    std::cout << "n = " << n << std::endl;
    std::cout << "Cache: " << cacheSizeKB << "KB, "
              << waysCount << " ways with "
              << cacheLineSizeB << "b cache line." << std::endl;
    float* a = new float[n * n];
    float* b = new float[n * n];
    float* c = new float[n * n];

    FillRandom(a, n);
    FillRandom(b, n);

    TCache cache(cacheSizeKB * 1024 /* kb */, cacheLineSizeB /* b */, waysCount /* ways */);
    {
        const auto startTime = std::clock();
        MultSimpleTooled(cache, a, b, c, n);
        const auto endTime = std::clock();

        std::cout << "timeSimple: " << double(endTime - startTime) / CLOCKS_PER_SEC << '\n';
    }
    cache.PrintStats();

    delete[] a;
    delete[] b;
    delete[] c;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: cmdmailmsg.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2004-06-17 11:34:14 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _CMDMAILMSG_HXX_
#include "cmdmailmsg.hxx"
#endif

#ifndef _COM_SUN_STAR_URI_XEXTERNALURIREFERENCETRANSLATOR_HPP_
#include <com/sun/star/uri/XExternalUriReferenceTranslator.hpp>
#endif

#ifndef _COM_SUN_STAR_URI_EXTERNALURIREFERENCETRANSLATOR_HPP_
#include <com/sun/star/uri/ExternalUriReferenceTranslator.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_RUNTIMEEXCEPTION_HPP_
#include <com/sun/star/uno/RuntimeException.hpp>
#endif

//------------------------------------------------------------------------
// namespace directives
//------------------------------------------------------------------------

using com::sun::star::lang::IllegalArgumentException;
using com::sun::star::lang::WrappedTargetException;
using com::sun::star::container::NoSuchElementException;
using com::sun::star::container::XNameAccess;
using rtl::OUString;
using osl::MutexGuard;

using namespace cppu;
using namespace com::sun::star::uno;

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setRecipient( const ::rtl::OUString& aRecipient )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_aRecipient = aRecipient;
}

//------------------------------------------------
//
//------------------------------------------------

::rtl::OUString SAL_CALL CmdMailMsg::getRecipient(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_aRecipient;
}

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setCcRecipient( const Sequence< OUString >& aCcRecipient )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_CcRecipients = aCcRecipient;
}

//------------------------------------------------
//
//------------------------------------------------

Sequence< OUString > SAL_CALL CmdMailMsg::getCcRecipient(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_CcRecipients;
}

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setBccRecipient( const Sequence< OUString >& aBccRecipient )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_BccRecipients = aBccRecipient;
}

//------------------------------------------------
//
//------------------------------------------------

Sequence< OUString > SAL_CALL CmdMailMsg::getBccRecipient(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_BccRecipients;
}

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setOriginator( const OUString& aOriginator )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_aOriginator = aOriginator;
}

//------------------------------------------------
//
//------------------------------------------------

OUString SAL_CALL CmdMailMsg::getOriginator(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_aOriginator;
}

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setSubject( const OUString& aSubject )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_aSubject = aSubject;
}

//------------------------------------------------
//
//------------------------------------------------

OUString SAL_CALL CmdMailMsg::getSubject(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_aSubject;
}

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setAttachement( const Sequence< ::rtl::OUString >& aAttachment )
    throw (IllegalArgumentException, RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_Attachments = aAttachment;
    sal_Int32 n = m_Attachments.getLength();
    if (n > 0) {
        Reference< com::sun::star::uri::XExternalUriReferenceTranslator >
            translator(
                com::sun::star::uri::ExternalUriReferenceTranslator::create(
                    m_xContext));
        for (sal_Int32 i = 0; i < n; ++i) {
            OUString external(
                translator->translateToExternal(m_Attachments[i]));
            if (external.getLength() == 0
                && m_Attachments[i].getLength() != 0)
            {
                throw RuntimeException(
                    (OUString(
                        RTL_CONSTASCII_USTRINGPARAM(
                            "Cannot translate URI reference to external"
                            " format: "))
                     + m_Attachments[i]),
                    static_cast< cppu::OWeakObject * >(this));
            }
            m_Attachments[i] = external;
        }
    }
}

//------------------------------------------------
//
//------------------------------------------------

Sequence< OUString > SAL_CALL CmdMailMsg::getAttachement(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_Attachments;
}

//------------------------------------------------
//
//------------------------------------------------

Any SAL_CALL CmdMailMsg::getByName( const OUString& aName )
    throw (NoSuchElementException, WrappedTargetException, RuntimeException)
{
    MutexGuard aGuard( m_aMutex );

    if( 0 == aName.compareToAscii( "from" ) &&  m_aOriginator.getLength() )
        return makeAny( m_aOriginator );

    else if( 0 == aName.compareToAscii( "to" ) &&  m_aRecipient.getLength() )
        return makeAny( m_aRecipient );

    else if( 0 == aName.compareToAscii( "cc" ) &&  m_CcRecipients.getLength() )
        return makeAny( m_CcRecipients );

    else if( 0 == aName.compareToAscii( "bcc" ) &&  m_BccRecipients.getLength() )
        return makeAny( m_BccRecipients );

    else if( 0 == aName.compareToAscii( "subject" ) &&  m_aSubject.getLength() )
        return makeAny( m_aSubject );

    else if( 0 == aName.compareToAscii( "attachment" ) &&  m_Attachments.getLength() )
        return makeAny( m_Attachments );

   throw NoSuchElementException( OUString::createFromAscii( "key not found: ") + aName,
        static_cast < XNameAccess * > (this) );
}

//------------------------------------------------
//
//------------------------------------------------

Sequence< OUString > SAL_CALL CmdMailMsg::getElementNames(  )
    throw (::com::sun::star::uno::RuntimeException)
{
    MutexGuard aGuard( m_aMutex );

    sal_Int32 nItems = 0;
    Sequence< OUString > aRet( 6 );

    if( m_aOriginator.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "from" );

    if( m_aRecipient.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "to" );

    if( m_CcRecipients.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "cc" );

    if( m_BccRecipients.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "bcc" );

    if( m_aSubject.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "subject" );

    if( m_Attachments.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "attachment" );

    aRet.realloc( nItems );
    return aRet;
}

//------------------------------------------------
//
//------------------------------------------------

 sal_Bool SAL_CALL CmdMailMsg::hasByName( const ::rtl::OUString& aName )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );

    if( 0 == aName.compareToAscii( "from" ) &&  m_aOriginator.getLength() )
        return sal_True;

    else if( 0 == aName.compareToAscii( "to" ) &&  m_aRecipient.getLength() )
        return sal_True;

    else if( 0 == aName.compareToAscii( "cc" ) &&  m_CcRecipients.getLength() )
        return sal_True;

    else if( 0 == aName.compareToAscii( "bcc" ) &&  m_BccRecipients.getLength() )
        return sal_True;

    else if( 0 == aName.compareToAscii( "subject" ) &&  m_aSubject.getLength() )
        return sal_True;

    else if( 0 == aName.compareToAscii( "attachment" ) &&  m_Attachments.getLength() )
        return sal_True;

    return sal_False;
}

//------------------------------------------------
//
//------------------------------------------------

Type SAL_CALL CmdMailMsg::getElementType(  )
    throw (RuntimeException)
{
    // returning void for multi type container
    return Type();
}

//------------------------------------------------
//
//------------------------------------------------

sal_Bool SAL_CALL CmdMailMsg::hasElements(  )
    throw (RuntimeException)
{
    return 0 != getElementNames().getLength();
}
<commit_msg>INTEGRATION: CWS shellfix01 (1.3.30); FILE MERGED 2004/09/14 07:06:16 obr 1.3.30.1: #i30170# attachments now passed as system paths<commit_after>/*************************************************************************
 *
 *  $RCSfile: cmdmailmsg.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2004-10-22 08:14:19 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _CMDMAILMSG_HXX_
#include "cmdmailmsg.hxx"
#endif

#ifndef _COM_SUN_STAR_URI_XEXTERNALURIREFERENCETRANSLATOR_HPP_
#include <com/sun/star/uri/XExternalUriReferenceTranslator.hpp>
#endif

#ifndef _COM_SUN_STAR_URI_EXTERNALURIREFERENCETRANSLATOR_HPP_
#include <com/sun/star/uri/ExternalUriReferenceTranslator.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_RUNTIMEEXCEPTION_HPP_
#include <com/sun/star/uno/RuntimeException.hpp>
#endif

//------------------------------------------------------------------------
// namespace directives
//------------------------------------------------------------------------

using com::sun::star::lang::IllegalArgumentException;
using com::sun::star::lang::WrappedTargetException;
using com::sun::star::container::NoSuchElementException;
using com::sun::star::container::XNameAccess;
using rtl::OUString;
using osl::MutexGuard;

using namespace cppu;
using namespace com::sun::star::uno;

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setRecipient( const ::rtl::OUString& aRecipient )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_aRecipient = aRecipient;
}

//------------------------------------------------
//
//------------------------------------------------

::rtl::OUString SAL_CALL CmdMailMsg::getRecipient(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_aRecipient;
}

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setCcRecipient( const Sequence< OUString >& aCcRecipient )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_CcRecipients = aCcRecipient;
}

//------------------------------------------------
//
//------------------------------------------------

Sequence< OUString > SAL_CALL CmdMailMsg::getCcRecipient(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_CcRecipients;
}

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setBccRecipient( const Sequence< OUString >& aBccRecipient )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_BccRecipients = aBccRecipient;
}

//------------------------------------------------
//
//------------------------------------------------

Sequence< OUString > SAL_CALL CmdMailMsg::getBccRecipient(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_BccRecipients;
}

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setOriginator( const OUString& aOriginator )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_aOriginator = aOriginator;
}

//------------------------------------------------
//
//------------------------------------------------

OUString SAL_CALL CmdMailMsg::getOriginator(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_aOriginator;
}

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setSubject( const OUString& aSubject )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_aSubject = aSubject;
}

//------------------------------------------------
//
//------------------------------------------------

OUString SAL_CALL CmdMailMsg::getSubject(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_aSubject;
}

//------------------------------------------------
//
//------------------------------------------------

void SAL_CALL CmdMailMsg::setAttachement( const Sequence< ::rtl::OUString >& aAttachment )
    throw (IllegalArgumentException, RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    m_Attachments = aAttachment;
}

//------------------------------------------------
//
//------------------------------------------------

Sequence< OUString > SAL_CALL CmdMailMsg::getAttachement(  )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );
    return m_Attachments;
}

//------------------------------------------------
//
//------------------------------------------------

Any SAL_CALL CmdMailMsg::getByName( const OUString& aName )
    throw (NoSuchElementException, WrappedTargetException, RuntimeException)
{
    MutexGuard aGuard( m_aMutex );

    if( 0 == aName.compareToAscii( "from" ) &&  m_aOriginator.getLength() )
        return makeAny( m_aOriginator );

    else if( 0 == aName.compareToAscii( "to" ) &&  m_aRecipient.getLength() )
        return makeAny( m_aRecipient );

    else if( 0 == aName.compareToAscii( "cc" ) &&  m_CcRecipients.getLength() )
        return makeAny( m_CcRecipients );

    else if( 0 == aName.compareToAscii( "bcc" ) &&  m_BccRecipients.getLength() )
        return makeAny( m_BccRecipients );

    else if( 0 == aName.compareToAscii( "subject" ) &&  m_aSubject.getLength() )
        return makeAny( m_aSubject );

    else if( 0 == aName.compareToAscii( "attachment" ) &&  m_Attachments.getLength() )
        return makeAny( m_Attachments );

   throw NoSuchElementException( OUString::createFromAscii( "key not found: ") + aName,
        static_cast < XNameAccess * > (this) );
}

//------------------------------------------------
//
//------------------------------------------------

Sequence< OUString > SAL_CALL CmdMailMsg::getElementNames(  )
    throw (::com::sun::star::uno::RuntimeException)
{
    MutexGuard aGuard( m_aMutex );

    sal_Int32 nItems = 0;
    Sequence< OUString > aRet( 6 );

    if( m_aOriginator.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "from" );

    if( m_aRecipient.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "to" );

    if( m_CcRecipients.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "cc" );

    if( m_BccRecipients.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "bcc" );

    if( m_aSubject.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "subject" );

    if( m_Attachments.getLength() )
        aRet[nItems++] = OUString::createFromAscii( "attachment" );

    aRet.realloc( nItems );
    return aRet;
}

//------------------------------------------------
//
//------------------------------------------------

 sal_Bool SAL_CALL CmdMailMsg::hasByName( const ::rtl::OUString& aName )
    throw (RuntimeException)
{
    MutexGuard aGuard( m_aMutex );

    if( 0 == aName.compareToAscii( "from" ) &&  m_aOriginator.getLength() )
        return sal_True;

    else if( 0 == aName.compareToAscii( "to" ) &&  m_aRecipient.getLength() )
        return sal_True;

    else if( 0 == aName.compareToAscii( "cc" ) &&  m_CcRecipients.getLength() )
        return sal_True;

    else if( 0 == aName.compareToAscii( "bcc" ) &&  m_BccRecipients.getLength() )
        return sal_True;

    else if( 0 == aName.compareToAscii( "subject" ) &&  m_aSubject.getLength() )
        return sal_True;

    else if( 0 == aName.compareToAscii( "attachment" ) &&  m_Attachments.getLength() )
        return sal_True;

    return sal_False;
}

//------------------------------------------------
//
//------------------------------------------------

Type SAL_CALL CmdMailMsg::getElementType(  )
    throw (RuntimeException)
{
    // returning void for multi type container
    return Type();
}

//------------------------------------------------
//
//------------------------------------------------

sal_Bool SAL_CALL CmdMailMsg::hasElements(  )
    throw (RuntimeException)
{
    return 0 != getElementNames().getLength();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Vasily i. Redkin <vir@ctm.ru>
 * License: MIT (See LICENSE.txt or http://www.opensource.org/licenses/MIT)
 */
#ifndef CHILDPROCESS_HPP_INCLUDED
#define CHILDPROCESS_HPP_INCLUDED
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h> // for strerror
#include <stdlib.h> // for exit

#include <string>
#include "eventdispatcher.hpp"

class ReadBuffer
{
	private:
		std::string m_buf;
		int m_fd;
	public:
		int fd() const { return m_fd; }
		bool fd(int fd) {
			m_fd = fd;
			// Set non-blocking
			long arg;
			if( (arg = fcntl(m_fd, F_GETFL, NULL)) < 0) {
				fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));
				exit(0);
			}
			arg |= O_NONBLOCK;
			if( fcntl(m_fd, F_SETFL, arg) < 0) {
				fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));
				exit(0);
			}
			return true;
		}
		int do_read();
		bool readline(std::string & s);
};

class Family;
class ChildProcess:public AsyncReader, public ChildProc
{
	private:
		int m_pid;
		int m_fdo;
		int m_fde;
		Family * m_family;
		ReadBuffer m_bufo;
		ReadBuffer m_bufe;
	public:
		ChildProcess(Family * f):m_family(f) { }
		virtual ~ChildProcess() { }
		int pid() const { return m_pid; }
		bool start();
		virtual int can_read(int fd);
		virtual void dead(int status);
		virtual int kill(int signal);
};

#endif /* CHILDPROCESS_HPP_INCLUDED */

<commit_msg>Fixed header for Linux<commit_after>/*
 * Copyright (c) 2012 Vasily i. Redkin <vir@ctm.ru>
 * License: MIT (See LICENSE.txt or http://www.opensource.org/licenses/MIT)
 */
#ifndef CHILDPROCESS_HPP_INCLUDED
#define CHILDPROCESS_HPP_INCLUDED
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h> // for strerror
#include <stdlib.h> // for exit

#include <string>
#include "eventdispatcher.hpp"

class ReadBuffer
{
	private:
		std::string m_buf;
		int m_fd;
	public:
		int fd() const { return m_fd; }
		bool fd(int fd) {
			m_fd = fd;
			// Set non-blocking
			long arg;
			if( (arg = fcntl(m_fd, F_GETFL, NULL)) < 0) {
				fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));
				exit(0);
			}
			arg |= O_NONBLOCK;
			if( fcntl(m_fd, F_SETFL, arg) < 0) {
				fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));
				exit(0);
			}
			return true;
		}
		int do_read();
		bool readline(std::string & s);
};

class Family;
class ChildProcess:public AsyncReader, public ChildProc
{
	private:
		int m_pid;
		int m_fdo;
		int m_fde;
		Family * m_family;
		ReadBuffer m_bufo;
		ReadBuffer m_bufe;
	public:
		ChildProcess(Family * f):m_family(f) { }
		virtual ~ChildProcess() { }
		int pid() const { return m_pid; }
		bool start();
		virtual int can_read(int fd);
		virtual void dead(int status);
		virtual int kill(int signal);
};

#endif /* CHILDPROCESS_HPP_INCLUDED */

<|endoftext|>


<commit_before>/*
Copyright (c) 2012-2014 The SSDB Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
*/
#include <pthread.h>
#include <time.h>
#include "../include.h"
#include "../util/log.h"
#include "ttl.h"

#define EXPIRATION_LIST_KEY "\xff\xff\xff\xff\xff|EXPIRE_LIST|KV"
#define BATCH_SIZE    1000

ExpirationHandler::ExpirationHandler(SSDB *ssdb){
	this->ssdb = ssdb;
	this->thread_quit = false;
	this->list_name = EXPIRATION_LIST_KEY;
	this->first_timeout = INT64_MAX;
	this->start();
}

ExpirationHandler::~ExpirationHandler(){
	Locking l(&this->mutex);
	this->stop();
	ssdb = NULL;
}

void ExpirationHandler::start(){
	thread_quit = false;
	pthread_t tid;
	int err = pthread_create(&tid, NULL, &ExpirationHandler::thread_func, this);
	if(err != 0){
		log_fatal("can't create thread: %s", strerror(err));
		exit(0);
	}
}

void ExpirationHandler::stop(){
	thread_quit = true;
	for(int i=0; i<100; i++){
		if(!thread_quit){
			break;
		}
		usleep(10 * 1000);
	}
}

int ExpirationHandler::set_ttl(const Bytes &key, int64_t ttl){
	int64_t expired = time_ms() + ttl * 1000;
	char data[30];
	int size = snprintf(data, sizeof(data), "%" PRId64, expired);
	if(size <= 0){
		log_error("snprintf return error!");
		return -1;
	}

	int ret = ssdb->zset(this->list_name, key, Bytes(data, size));
	if(ret == -1){
		return -1;
	}
	if(expired < first_timeout){
		first_timeout = expired;
	}
	std::string s_key = key.String();
	if(!fast_keys.empty() && expired <= fast_keys.max_score()){
		fast_keys.add(s_key, expired);
		if(fast_keys.size() > BATCH_SIZE){
			log_debug("pop_back");
			fast_keys.pop_back();
		}
	}else{
		fast_keys.del(s_key);
		//log_debug("don't put in fast_keys");
	}

	return 0;
}

int ExpirationHandler::del_ttl(const Bytes &key){
	// 这样用是有 bug 的, 虽然 fast_keys 为空, 不代表整个 ttl 队列为空
	// if(!this->fast_keys.empty()){
	if(first_timeout != INT64_MAX){
		fast_keys.del(key.String());
		ssdb->zdel(this->list_name, key);
	}
	return 0;
}

int64_t ExpirationHandler::get_ttl(const Bytes &key){
	std::string score;
	if(ssdb->zget(this->list_name, key, &score) == 1){
		int64_t ex = str_to_int64(score);
		return (ex - time_ms())/1000;
	}
	return -1;
}

void ExpirationHandler::load_expiration_keys_from_db(int num){
	ZIterator *it;
	it = ssdb->zscan(this->list_name, "", "", "", num);
	int n = 0;
	while(it->next()){
		n ++;
		std::string &key = it->key;
		int64_t score = str_to_int64(it->score);
		if(score < 2000000000){
			// older version compatible
			score *= 1000;
		}
		fast_keys.add(key, score);
	}
	delete it;
	log_debug("load %d keys into fast_keys", n);
}

void ExpirationHandler::expire_loop(){
	Locking l(&this->mutex);
	if(!this->ssdb){
		return;
	}

	if(this->fast_keys.empty()){
		this->load_expiration_keys_from_db(BATCH_SIZE);
		if(this->fast_keys.empty()){
			this->first_timeout = INT64_MAX;
			return;
		}
	}

	int64_t score;
	std::string key;
	if(this->fast_keys.front(&key, &score)){
		this->first_timeout = score;

		if(score <= time_ms()){
			log_debug("expired %s", key.c_str());
			ssdb->del(key);
			ssdb->zdel(this->list_name, key);
			this->fast_keys.pop_front();
		}
	}
}

void* ExpirationHandler::thread_func(void *arg){
	ExpirationHandler *handler = (ExpirationHandler *)arg;

	while(!handler->thread_quit){
		if(handler->first_timeout > time_ms()){
			usleep(10 * 1000);
			continue;
		}
		handler->expire_loop();
	}

	log_debug("ExpirationHandler thread quit");
	handler->thread_quit = false;
	return (void *)NULL;
}
<commit_msg>update<commit_after>/*
Copyright (c) 2012-2014 The SSDB Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
*/
#include <pthread.h>
#include <time.h>
#include "../include.h"
#include "../util/log.h"
#include "ttl.h"

#define EXPIRATION_LIST_KEY "\xff\xff\xff\xff\xff|EXPIRE_LIST|KV"
#define BATCH_SIZE    1000

ExpirationHandler::ExpirationHandler(SSDB *ssdb){
	this->ssdb = ssdb;
	this->thread_quit = false;
	this->list_name = EXPIRATION_LIST_KEY;
	this->first_timeout = 0;
	this->start();
}

ExpirationHandler::~ExpirationHandler(){
	Locking l(&this->mutex);
	this->stop();
	ssdb = NULL;
}

void ExpirationHandler::start(){
	thread_quit = false;
	pthread_t tid;
	int err = pthread_create(&tid, NULL, &ExpirationHandler::thread_func, this);
	if(err != 0){
		log_fatal("can't create thread: %s", strerror(err));
		exit(0);
	}
}

void ExpirationHandler::stop(){
	thread_quit = true;
	for(int i=0; i<100; i++){
		if(!thread_quit){
			break;
		}
		usleep(10 * 1000);
	}
}

int ExpirationHandler::set_ttl(const Bytes &key, int64_t ttl){
	int64_t expired = time_ms() + ttl * 1000;
	char data[30];
	int size = snprintf(data, sizeof(data), "%" PRId64, expired);
	if(size <= 0){
		log_error("snprintf return error!");
		return -1;
	}

	int ret = ssdb->zset(this->list_name, key, Bytes(data, size));
	if(ret == -1){
		return -1;
	}
	if(expired < first_timeout){
		first_timeout = expired;
	}
	std::string s_key = key.String();
	if(!fast_keys.empty() && expired <= fast_keys.max_score()){
		fast_keys.add(s_key, expired);
		if(fast_keys.size() > BATCH_SIZE){
			log_debug("pop_back");
			fast_keys.pop_back();
		}
	}else{
		fast_keys.del(s_key);
		//log_debug("don't put in fast_keys");
	}

	return 0;
}

int ExpirationHandler::del_ttl(const Bytes &key){
	// 这样用是有 bug 的, 虽然 fast_keys 为空, 不代表整个 ttl 队列为空
	// if(!this->fast_keys.empty()){
	if(first_timeout != INT64_MAX){
		fast_keys.del(key.String());
		ssdb->zdel(this->list_name, key);
	}
	return 0;
}

int64_t ExpirationHandler::get_ttl(const Bytes &key){
	std::string score;
	if(ssdb->zget(this->list_name, key, &score) == 1){
		int64_t ex = str_to_int64(score);
		return (ex - time_ms())/1000;
	}
	return -1;
}

void ExpirationHandler::load_expiration_keys_from_db(int num){
	ZIterator *it;
	it = ssdb->zscan(this->list_name, "", "", "", num);
	int n = 0;
	while(it->next()){
		n ++;
		std::string &key = it->key;
		int64_t score = str_to_int64(it->score);
		if(score < 2000000000){
			// older version compatible
			score *= 1000;
		}
		fast_keys.add(key, score);
	}
	delete it;
	log_debug("load %d keys into fast_keys", n);
}

void ExpirationHandler::expire_loop(){
	Locking l(&this->mutex);
	if(!this->ssdb){
		return;
	}

	if(this->fast_keys.empty()){
		this->load_expiration_keys_from_db(BATCH_SIZE);
		if(this->fast_keys.empty()){
			this->first_timeout = INT64_MAX;
			return;
		}
	}

	int64_t score;
	std::string key;
	if(this->fast_keys.front(&key, &score)){
		this->first_timeout = score;

		if(score <= time_ms()){
			log_debug("expired %s", key.c_str());
			ssdb->del(key);
			ssdb->zdel(this->list_name, key);
			this->fast_keys.pop_front();
		}
	}
}

void* ExpirationHandler::thread_func(void *arg){
	ExpirationHandler *handler = (ExpirationHandler *)arg;

	while(!handler->thread_quit){
		if(handler->first_timeout > time_ms()){
			usleep(10 * 1000);
			continue;
		}
		handler->expire_loop();
	}

	log_debug("ExpirationHandler thread quit");
	handler->thread_quit = false;
	return (void *)NULL;
}
<|endoftext|>


<commit_before>/* author: @gwzz
 *
 */
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include "graph.h"
#include "support.h"
#include "sctfile.h"

using namespace std;

// Pre-define hierarchy array
// CUI: array of top nodes concept id of each hierarchy
// ConName: array of the name of each hierarchy
const long long CUI[19] = {123037004, 404684003, 308916002, 272379006, 363787002, 410607006, 373873005, 78621006, 260787004, 71388002, 362981000, 419891008, 243796009, 900000000000441003, 48176007, 370115009, 123038009, 254291000, 105590001};
const string ConName[19] = {"Body_structure", "Clinical_finding", "Environment_or_geographical_location", "Event", "Observable_entity", "Organism", "Pharmaceutical_biologic_product", "Physical_force", "Physical_object", "Procedure", "Qualifier_value", "Record_artifact", "Situation_with_explicit_context", "SNOMED_CT_Model_Component", "Social_context", "Special_Concept", "Specimen", "Staging_and_scales", "Substance"};

// define global variables
// node_map: store all the concepts [key,value]
// reversed_node_map: store reversed node_map [value,key]
// nodeFile, relationFile, out_put_file, as variable name
string nodeFile = "2016nodes.txt";
string relationFile = "2016relation.txt";

int main(int argc, char* argv[])
{
  if (argc < 2)
  {
    std::cerr << "Usage: " << argv[0] << " SNOMED_CT_FILE_PATH" << std::endl;
    return 1;
  }
  string out_put_folder = "/Users/zhuwei/Desktop/sct_nodes_within_hierarchy/";
  std::cout<< argc << "  " << argv[1] << endl;
  SctFile sf(argv[1]);
  long long top_node;
  std::map<long long, int> node_map;
  std::map<int, long long> reversed_node_map;
  std::vector<long long> output_vector;
  std::string sline;
  std::vector<std::string> relation;
  std::vector<std::string> nodes;

    // Read in node file
  fstream fin;
  fin.open(nodeFile,ios::in);
  while (getline(fin, sline)){
    nodes.push_back(sline);
  }
  fin.close();
  for (int i = 0; i < nodes.size(); ++i){
    node_map[std::stoll(nodes[i])] = i;
  }

  for (map<long long, int>::iterator i = node_map.begin(); i != node_map.end(); ++i)
    reversed_node_map[i->second] = i->first;

  int nodeSize = node_map.size();
  fin.open(relationFile,ios::in);
  while (getline(fin, sline)){
    relation.push_back(sline);
  }
  fin.close();
  // initialize graph g
  Graph g(nodeSize);
  std::vector<long long> is_a_relationship;
  for (auto i : relation){
    is_a_relationship.clear();
    is_a_relationship = Split(i, ',');
    g.addEdge(node_map[is_a_relationship[1]],node_map[is_a_relationship[0]]);
  }

  string out_put_file;
  for (int i = 0; i < 19; ++i){
    output_vector.clear();
    out_put_file.clear();
    out_put_file = out_put_folder + ConName[i];
    top_node = CUI[i];
    output_vector = g.DFS(node_map[top_node]);
    fstream fout;
    fout.open(out_put_file,ios::app);
    for (auto o : output_vector){
        fout << reversed_node_map[o] << endl;
    }
    fout.close();
  }

    return 0;
}<commit_msg>minor!<commit_after>/* author: @gwzz
 *
 */
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include "graph.h"
#include "support.h"
#include "sctfile.h"

using namespace std;

// Pre-define hierarchy array
// CUI: array of top nodes concept id of each hierarchy
// ConName: array of the name of each hierarchy
const long long CUI[19] = {123037004, 404684003, 308916002, 272379006, 363787002, 410607006, 373873005, 78621006, 260787004, 71388002, 362981000, 419891008, 243796009, 900000000000441003, 48176007, 370115009, 123038009, 254291000, 105590001};
const string ConName[19] = {"Body_structure", "Clinical_finding", "Environment_or_geographical_location", "Event", "Observable_entity", "Organism", "Pharmaceutical_biologic_product", "Physical_force", "Physical_object", "Procedure", "Qualifier_value", "Record_artifact", "Situation_with_explicit_context", "SNOMED_CT_Model_Component", "Social_context", "Special_Concept", "Specimen", "Staging_and_scales", "Substance"};

// define global variables
// node_map: store all the concepts [key,value]
// reversed_node_map: store reversed node_map [value,key]
// nodeFile, relationFile, out_put_file, as variable name
string nodeFile = "2016nodes.txt";
string relationFile = "2016relation.txt";

int main(int argc, char* argv[])
{
  if (argc < 2)
  {
    std::cerr << "Usage: " << argv[0] << " SNOMED_CT_FILE_PATH" << std::endl;
    return 1;
  }
  string out_put_folder = "/Users/zhuwei/Desktop/sct_nodes_within_hierarchy/";
  SctFile sf(argv[1]);
  long long top_node;
  std::map<long long, int> node_map;
  std::map<int, long long> reversed_node_map;
  std::vector<long long> output_vector;
  std::string sline;
  std::vector<std::string> relation;
  std::vector<std::string> nodes;

    // Read in node file
  fstream fin;
  fin.open(nodeFile,ios::in);
  while (getline(fin, sline)){
    nodes.push_back(sline);
  }
  fin.close();
  for (int i = 0; i < nodes.size(); ++i){
    node_map[std::stoll(nodes[i])] = i;
  }

  for (map<long long, int>::iterator i = node_map.begin(); i != node_map.end(); ++i)
    reversed_node_map[i->second] = i->first;

  int nodeSize = node_map.size();
  fin.open(relationFile,ios::in);
  while (getline(fin, sline)){
    relation.push_back(sline);
  }
  fin.close();
  // initialize graph g
  Graph g(nodeSize);
  std::vector<long long> is_a_relationship;
  for (auto i : relation){
    is_a_relationship.clear();
    is_a_relationship = Split(i, ',');
    g.addEdge(node_map[is_a_relationship[1]],node_map[is_a_relationship[0]]);
  }

  string out_put_file;
  for (int i = 0; i < 19; ++i){
    output_vector.clear();
    out_put_file.clear();
    out_put_file = out_put_folder + ConName[i];
    top_node = CUI[i];
    output_vector = g.DFS(node_map[top_node]);
    fstream fout;
    fout.open(out_put_file,ios::app);
    for (auto o : output_vector){
        fout << reversed_node_map[o] << endl;
    }
    fout.close();
  }

    return 0;
}<|endoftext|>


<commit_before>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2016 University of Hull                                                          */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  hugh/field/base.cpp                                                             */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// include i/f header

#include "hugh/field/base.hpp"

// includes, system

#include <algorithm>              // std::find<>
#include <boost/io/ios_state.hpp> // boost::io::ios_all_saver
#include <iomanip>                // std::dec, std::hex, std::right, std::setw, std::showbase
#include <ostream>                // std::ostream
#include <stdexcept>              // std::logic_error

// includes, project

#include <hugh/field/connection/manager.hpp>
#include <hugh/field/container.hpp>
#include <hugh/support/io_utils.hpp>

#define HUGH_USE_TRACE
#undef HUGH_USE_TRACE
#include <hugh/support/trace.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  // variables, internal

  // functions, internal

} // namespace {

namespace hugh {

  namespace field {

    // variables, exported

    // functions, exported

    container const&
    base::container() const
    {
      TRACE("hugh::field::base::container(get)");

      return container_;
    }

    std::string const&
    base::name() const
    {
      TRACE("hugh::field::base::name(get)");

      return name_;
    }

    support::clock::time_point const&
    base::last_change() const
    {
      TRACE("hugh::field::base::last_change(get)");

      return last_change_;
    }

    void
    base::touch()
    {
      TRACE("hugh::field::base::touch");

      changed();
    }

    /* virtual */ void
    base::print_on(std::ostream& os) const
    {
      TRACE_NEVER("hugh::field::base::print_on");

      using support::ostream::operator<<;

      boost::io::ios_all_saver const ias(os);

      os << '['
         << std::right << std::setw(19) << name_
         << '@'
         << std::hex << std::showbase << this
         << "->c@"
         << std::hex << std::showbase << &container_
         << ':'
         << std::dec << last_change_
         << ']';
    }

    /* explicit */
    base::base(container_type& a, std::string const& b)
      : container_  (a),
        name_       (b),
        last_change_(support::clock::now())
    {
      TRACE("hugh::field::base::base");

      if (name_.empty()) {
        throw std::logic_error("hugh::field::base::base: field names cannot be empty!");
      }

      container_.add(this);
    }

    /* virtual */
    base::~base()
    {
      TRACE("hugh::field::base::~base");

      connection::manager::instance->disconnect(this);

      container_.sub(this);
    }

    void
    base::changed()
    {
      TRACE("hugh::field::base::changed");

      last_change_ = support::clock::now();

      container_.changed(*this);

      notify();
    }

    void
    base::notify()
    {
      TRACE("hugh::field::base::notify");

      connection::manager::instance->update(this);
    }

  } // namespace field {

} // namespace hugh {
<commit_msg>cleanup: header inclusion<commit_after>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2016 University of Hull                                                          */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  hugh/field/base.cpp                                                             */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// include i/f header

#include "hugh/field/base.hpp"

// includes, system

#include <boost/io/ios_state.hpp> // boost::io::ios_all_saver
#include <iomanip>                // std::dec, std::hex, std::right, std::setw, std::showbase
#include <ostream>                // std::ostream
#include <stdexcept>              // std::logic_error

// includes, project

#include <hugh/field/connection/manager.hpp>
#include <hugh/field/container.hpp>
#include <hugh/support/io_utils.hpp>

#define HUGH_USE_TRACE
#undef HUGH_USE_TRACE
#include <hugh/support/trace.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  // variables, internal

  // functions, internal

} // namespace {

namespace hugh {

  namespace field {

    // variables, exported

    // functions, exported

    container const&
    base::container() const
    {
      TRACE("hugh::field::base::container(get)");

      return container_;
    }

    std::string const&
    base::name() const
    {
      TRACE("hugh::field::base::name(get)");

      return name_;
    }

    support::clock::time_point const&
    base::last_change() const
    {
      TRACE("hugh::field::base::last_change(get)");

      return last_change_;
    }

    void
    base::touch()
    {
      TRACE("hugh::field::base::touch");

      changed();
    }

    /* virtual */ void
    base::print_on(std::ostream& os) const
    {
      TRACE_NEVER("hugh::field::base::print_on");

      using support::ostream::operator<<;

      boost::io::ios_all_saver const ias(os);

      os << '['
         << std::right << std::setw(19) << name_
         << '@'
         << std::hex << std::showbase << this
         << "->c@"
         << std::hex << std::showbase << &container_
         << ':'
         << std::dec << last_change_
         << ']';
    }

    /* explicit */
    base::base(container_type& a, std::string const& b)
      : container_  (a),
        name_       (b),
        last_change_(support::clock::now())
    {
      TRACE("hugh::field::base::base");

      if (name_.empty()) {
        throw std::logic_error("hugh::field::base::base: field names cannot be empty!");
      }

      container_.add(this);
    }

    /* virtual */
    base::~base()
    {
      TRACE("hugh::field::base::~base");

      connection::manager::instance->disconnect(this);

      container_.sub(this);
    }

    void
    base::changed()
    {
      TRACE("hugh::field::base::changed");

      last_change_ = support::clock::now();

      container_.changed(*this);

      notify();
    }

    void
    base::notify()
    {
      TRACE("hugh::field::base::notify");

      connection::manager::instance->update(this);
    }

  } // namespace field {

} // namespace hugh {
<|endoftext|>