<commit_before>#include "broker.hpp"
#include "message.hpp"
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <unordered_map>

namespace {

bool revStrEquals(const std::string& str1, const std::string& str2) { //compare strings in reverse
    if(str1.length() != str2.length()) return false;
    for(int i = str1.length() - 1; i >= 0; --i)
        if(str1[i] != str2[i]) return false;
    return true;
}

bool equalOrPlus(const std::string& pat, const std::string& top) {
    return pat == "+" || revStrEquals(pat, top);
}
} //anonymous namespace

class Subscription {
public:

    Subscription(MqttSubscriber& subscriber, MqttSubscribe::Topic topic,
                 std::deque<std::string> topicParts):
        _subscriber(subscriber),
        _part(std::move(topicParts.back())),
        _topic(std::move(topic.topic)),
        _qos(topic.qos) {
    }

    void newMessage(std::string topic, std::vector<ubyte> payload) {
        _subscriber.newMessage(topic, payload);
    }

    bool isSubscriber(const MqttSubscriber& subscriber) const {
        return &_subscriber == &subscriber;
    }

    bool isSubscription(const MqttSubscriber& subscriber,
                        std::vector<std::string> topics) const {
        return isSubscriber(subscriber) && isTopic(topics);
    }

    bool isTopic(std::vector<std::string> topics) const {
        return std::find(topics.cbegin(), topics.cend(), _topic) == topics.cend();
    }

private:
    MqttSubscriber& _subscriber;
    std::string _part;
    std::string _topic;
    ubyte _qos;
};

struct SubscriptionTree {
public:

    void addSubscription(Subscription* s, std::deque<std::string> parts) {
        assert(parts.size());
        if(_useCache) _cache.clear(); //invalidate cache
        addSubscriptionImpl(s, parts, nullptr, _nodes);
    }

//     void removeSubscription(MqttSubscriber subscriber, ref Node*[string] nodes) {
//         if(_useCache) _cache = _cache.init; //invalidate cache
//         auto newnodes = nodes.dup;
//         foreach(n; newnodes) {
//             if(n.leaves) {
//                 n.leaves = std.algorithm.remove!(l => l.isSubscriber(subscriber))(n.leaves);
//                 if(n.leaves.empty && !n.branches.length) {
//                     removeNode(n.parent, n);
//                 }
//             } else {
//                 removeSubscription(subscriber, n.branches);
//             }
//         }
//     }

//     void removeSubscription(MqttSubscriber subscriber, in string[] topic, ref Node*[string] nodes) {
//         if(_useCache) _cache = _cache.init; //invalidate cache
//         auto newnodes = nodes.dup;
//         foreach(n; newnodes) {
//             if(n.leaves) {
//                 n.leaves = std.algorithm.remove!(l => l.isSubscription(subscriber, topic))(n.leaves);
//                 if(n.leaves.empty && !n.branches.length) {
//                     removeNode(n.parent, n);
//                 }
//             } else {
//                 removeSubscription(subscriber, topic, n.branches);
//             }
//         }
//     }

//     void removeNode(Node* parent, Node* child) {
//         if(parent) {
//             parent.branches.remove(child.part);
//         } else {
//             _nodes.remove(child.part);
//         }
//         if(parent && !parent.branches.length && parent.leaves.empty)
//             removeNode(parent.parent, parent);
//     }

//     void publish(in string topic, string[] topParts, in const(ubyte)[] payload) {
//         publish(topic, topParts, payload, _nodes);
//     }

//     void publish(in string topic, string[] topParts, in const(ubyte)[] payload,
//                  Node*[string] nodes) {
//         //check the cache first
//         if(_useCache && topic in _cache) {
//             foreach(s; _cache[topic]) s.newMessage(topic, payload);
//             return;
//         }

//         //not in the cache or not using the cache, do it the hard way
//         foreach(part; [topParts[0], "#", "+"]) {
//             if(part in nodes) {
//                 if(topParts.length == 1 && "#" in nodes[part].branches) {
//                     //So that "finance/#" matches finance
//                     publishLeaves(topic, payload, topParts, nodes[part].branches["#"].leaves);
//                 }
//                 publishLeaves(topic, payload, topParts, nodes[part].leaves);
//                 if(topParts.length > 1) {
//                     publish(topic, topParts[1..$], payload, nodes[part].branches);
//                 }
//             }
//         }
//     }

//     void publishLeaves(in string topic, in const(ubyte)[] payload,
//                        in string[] topParts,
//                        Subscription[] subscriptions) {
//         foreach(sub; subscriptions) {
//             if(topParts.length == 1 &&
//                equalOrPlus(sub._part, topParts[0])) {
//                 publishLeaf(sub, topic, payload);
//             }
//             else if(sub._part == "#") {
//                 publishLeaf(sub, topic, payload);
//             }
//         }
//     }

//     void publishLeaf(Subscription sub, in string topic, in const(ubyte)[] payload) {
//         sub.newMessage(topic, payload);
//         if(_useCache) _cache[topic] ~= sub;
//     }

    void useCache(bool u) { _useCache = u; }

private:
    struct Node {
        Node(std::string pt, Node* pr):part(pt), parent(pr) {}
        std::string part;
        Node* parent;
        std::unordered_map<std::string, Node*> branches;
        std::vector<Subscription*> leaves;
    };

    bool _useCache;
    std::unordered_map<std::string, Subscription*> _cache;
    std::unordered_map<std::string, Node*> _nodes;

    void addSubscriptionImpl(Subscription* s,
                             std::deque<std::string> parts,
                             Node* parent,
                             std::unordered_map<std::string, Node*> nodes) {
        auto part = parts.front();
        parts.pop_front();
        auto node = addOrFindNode(part, parent, nodes);
        if(!parts.size()) {
            node->leaves.emplace_back(s);
        } else {
            addSubscriptionImpl(s, parts, node, node->branches);
        }
    }

    Node* addOrFindNode(std::string part, Node* parent,
                        std::unordered_map<std::string, Node*> nodes) {
        if(nodes.count(part) && part == nodes[part]->part) {
            return nodes[part];
        }
        auto node = new Node(part, parent);
        nodes[part] = node;
        return node;
    }
};

class MqttBroker {
public:

    void subscribe(MqttSubscriber& subscriber, std::vector<std::string> topics) {
        std::vector<MqttSubscribe::Topic> newTopics;
        std::transform(topics.cbegin(), topics.cend(), std::back_inserter(newTopics),
                       [](std::string t) { return MqttSubscribe::Topic(t, 0); });
        subscribe(subscriber, newTopics);
    }

    void subscribe(MqttSubscriber& subscriber, std::vector<MqttSubscribe::Topic> topics) {
        for(const auto& t: topics) {
            std::deque<std::string> parts;
            boost::split(parts, t.topic, boost::is_any_of("/"));
            _subscriptions.addSubscription(new Subscription(subscriber, t, parts), parts);
        }
    }

    // void unsubscribe(MqttSubscriber& subscriber) {
    //     _subscriptions.removeSubscription(subscriber, _subscriptions._nodes);
    // }

    // void unsubscribe(MqttSubscriber& subscriber, std::vector<std::string> topics) {
    //     _subscriptions.removeSubscription(subscriber, topics, _subscriptions._nodes);
    // }

    // void publish(std::string topic, std::vector<ubyte> payload) {
    //     auto topParts = array(splitter(topic, "/"));
    //     publish(topic, topParts, payload);
    // }

    void useCache(bool u) { _subscriptions.useCache(u); }

private:

    SubscriptionTree _subscriptions;

    // void publish(std::string topic, std::vector<std::string> topParts,
    //              std::vector<ubyte> payload) {
    //     _subscriptions.publish(topic, topParts, payload);
    // }
};
<commit_msg>Uncommented removeNode<commit_after>#include "broker.hpp"
#include "message.hpp"
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <unordered_map>

namespace {

bool revStrEquals(const std::string& str1, const std::string& str2) { //compare strings in reverse
    if(str1.length() != str2.length()) return false;
    for(int i = str1.length() - 1; i >= 0; --i)
        if(str1[i] != str2[i]) return false;
    return true;
}

bool equalOrPlus(const std::string& pat, const std::string& top) {
    return pat == "+" || revStrEquals(pat, top);
}
} //anonymous namespace

class Subscription {
public:

    Subscription(MqttSubscriber& subscriber, MqttSubscribe::Topic topic,
                 std::deque<std::string> topicParts):
        _subscriber(subscriber),
        _part(std::move(topicParts.back())),
        _topic(std::move(topic.topic)),
        _qos(topic.qos) {
    }

    void newMessage(std::string topic, std::vector<ubyte> payload) {
        _subscriber.newMessage(topic, payload);
    }

    bool isSubscriber(const MqttSubscriber& subscriber) const {
        return &_subscriber == &subscriber;
    }

    bool isSubscription(const MqttSubscriber& subscriber,
                        std::vector<std::string> topics) const {
        return isSubscriber(subscriber) && isTopic(topics);
    }

    bool isTopic(std::vector<std::string> topics) const {
        return std::find(topics.cbegin(), topics.cend(), _topic) == topics.cend();
    }

private:
    MqttSubscriber& _subscriber;
    std::string _part;
    std::string _topic;
    ubyte _qos;
};

struct SubscriptionTree {
public:

    void addSubscription(Subscription* s, std::deque<std::string> parts) {
        assert(parts.size());
        clearCache();
        addSubscriptionImpl(s, parts, nullptr, _nodes);
    }

    // void removeSubscription(MqttSubscriber& subscriber,
    //                         std::unordered_map<std::string, Node*>& nodes) {
    //     clearCache();
    //     decltype(nodes) newNodes;
    //     std::copy(nodes.cbegin(), nodes.cend(), std::back_inserter(newNodes));
    //     for(auto n: newnodes) {
    //         if(n->leaves) {
    //             std::remove_if(n->leaves.begin(), n->leaves.end(),
    //                            [](Subscription* l) { return l.isSubscriber(subscriber); });
    //             if(!n->leaves.size() && !n->branches.size()) {
    //                 removeNode(n->parent, n);
    //             }
    //         } else {
    //             removeSubscription(subscriber, n.branches);
    //         }
    //     }
    // }

//     void removeSubscription(MqttSubscriber subscriber, in string[] topic, ref Node*[string] nodes) {
//         clearCache();
//         auto newnodes = nodes.dup;
//         foreach(n; newnodes) {
//             if(n.leaves) {
//                 n.leaves = std.algorithm.remove!(l => l.isSubscription(subscriber, topic))(n.leaves);
//                 if(n.leaves.empty && !n.branches.length) {
//                     removeNode(n.parent, n);
//                 }
//             } else {
//                 removeSubscription(subscriber, topic, n.branches);
//             }
//         }
//     }

//     void publish(in string topic, string[] topParts, in const(ubyte)[] payload) {
//         publish(topic, topParts, payload, _nodes);
//     }

//     void publish(in string topic, string[] topParts, in const(ubyte)[] payload,
//                  Node*[string] nodes) {
//         //check the cache first
//         if(_useCache && topic in _cache) {
//             foreach(s; _cache[topic]) s.newMessage(topic, payload);
//             return;
//         }

//         //not in the cache or not using the cache, do it the hard way
//         foreach(part; [topParts[0], "#", "+"]) {
//             if(part in nodes) {
//                 if(topParts.length == 1 && "#" in nodes[part].branches) {
//                     //So that "finance/#" matches finance
//                     publishLeaves(topic, payload, topParts, nodes[part].branches["#"].leaves);
//                 }
//                 publishLeaves(topic, payload, topParts, nodes[part].leaves);
//                 if(topParts.length > 1) {
//                     publish(topic, topParts[1..$], payload, nodes[part].branches);
//                 }
//             }
//         }
//     }

//     void publishLeaves(in string topic, in const(ubyte)[] payload,
//                        in string[] topParts,
//                        Subscription[] subscriptions) {
//         foreach(sub; subscriptions) {
//             if(topParts.length == 1 &&
//                equalOrPlus(sub._part, topParts[0])) {
//                 publishLeaf(sub, topic, payload);
//             }
//             else if(sub._part == "#") {
//                 publishLeaf(sub, topic, payload);
//             }
//         }
//     }

//     void publishLeaf(Subscription sub, in string topic, in const(ubyte)[] payload) {
//         sub.newMessage(topic, payload);
//         if(_useCache) _cache[topic] ~= sub;
//     }

    void useCache(bool u) { _useCache = u; }

private:
    struct Node {
        Node(std::string pt, Node* pr):part(pt), parent(pr) {}
        std::string part;
        Node* parent;
        std::unordered_map<std::string, Node*> branches;
        std::vector<Subscription*> leaves;
    };

    bool _useCache;
    std::unordered_map<std::string, Subscription*> _cache;
    std::unordered_map<std::string, Node*> _nodes;

    void addSubscriptionImpl(Subscription* s,
                             std::deque<std::string> parts,
                             Node* parent,
                             std::unordered_map<std::string, Node*> nodes) {
        auto part = parts.front();
        parts.pop_front();
        auto node = addOrFindNode(part, parent, nodes);
        if(!parts.size()) {
            node->leaves.emplace_back(s);
        } else {
            addSubscriptionImpl(s, parts, node, node->branches);
        }
    }

    Node* addOrFindNode(std::string part, Node* parent,
                        std::unordered_map<std::string, Node*> nodes) {
        if(nodes.count(part) && part == nodes[part]->part) {
            return nodes[part];
        }
        auto node = new Node(part, parent);
        nodes[part] = node;
        return node;
    }

    void clearCache() {
        if(_useCache) _cache.clear();
    }

    void removeNode(Node* parent, Node* child) {
        if(parent) {
            parent->branches.erase(child->part);
        } else {
            _nodes.erase(child->part);
        }
        if(parent && !parent->branches.size() && !parent->leaves.size())
            removeNode(parent->parent, parent);
    }
};

class MqttBroker {
public:

    void subscribe(MqttSubscriber& subscriber, std::vector<std::string> topics) {
        std::vector<MqttSubscribe::Topic> newTopics;
        std::transform(topics.cbegin(), topics.cend(), std::back_inserter(newTopics),
                       [](std::string t) { return MqttSubscribe::Topic(t, 0); });
        subscribe(subscriber, newTopics);
    }

    void subscribe(MqttSubscriber& subscriber, std::vector<MqttSubscribe::Topic> topics) {
        for(const auto& t: topics) {
            std::deque<std::string> parts;
            boost::split(parts, t.topic, boost::is_any_of("/"));
            _subscriptions.addSubscription(new Subscription(subscriber, t, parts), parts);
        }
    }

    // void unsubscribe(MqttSubscriber& subscriber) {
    //     _subscriptions.removeSubscription(subscriber, _subscriptions._nodes);
    // }

    // void unsubscribe(MqttSubscriber& subscriber, std::vector<std::string> topics) {
    //     _subscriptions.removeSubscription(subscriber, topics, _subscriptions._nodes);
    // }

    // void publish(std::string topic, std::vector<ubyte> payload) {
    //     auto topParts = array(splitter(topic, "/"));
    //     publish(topic, topParts, payload);
    // }

    void useCache(bool u) { _subscriptions.useCache(u); }

private:

    SubscriptionTree _subscriptions;

    // void publish(std::string topic, std::vector<std::string> topParts,
    //              std::vector<ubyte> payload) {
    //     _subscriptions.publish(topic, topParts, payload);
    // }
};
<|endoftext|>


<commit_before>#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <cerrno>

/* Use the POSIX glob(3) function if available. On a native Windows port,
 * you'll need to make your own glob(3) implementation and define HAVE_GLOB, or
 * entirely reimplement ls.
 */
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif

#include "../interp.hxx"
#include "../command.hxx"
#include "../function.hxx"
#include "list.hxx"
#include "../common.hxx"

using namespace std;

namespace tglng {
#ifdef HAVE_GLOB
//Define glob parms which might not exist
#ifndef GLOB_BRACE
#  define GLOB_BRACE 0
#endif
#ifndef GLOB_TILDE
#  define GLOB_TILDE 0
#endif
  bool fs_ls(wstring* out, const wstring* in,
             Interpreter& interp, unsigned) {
    glob_t results;

    out->clear();

    //Transcode in[0] to a narrow string
    vector<char> pattern;
    if (!wstrtontbs(pattern, in[0])) {
      wcerr << L"Could not convert glob pattern to narrow string: "
            << *in << endl;
      return false;
    }

    //Perform the glob
    //If it fails, just return an empty list (*out is already empty);
    //otherwise, convert to a list.
    if (!glob(&pattern[0], GLOB_BRACE|GLOB_TILDE, NULL, &results)) {
      for (unsigned i = 0; i < results.gl_pathc; ++i) {
        wstring name;
        //Convert the filename back to a wide string
        if (!ntbstowstr(name, results.gl_pathv[i])) {
          //Print a warning about this one
          cerr << "WARN: Could not convert narrow filename to wide string: "
               << results.gl_pathv[i] << endl;
          continue;
        }

        //OK, add to the list
        list::lappend(*out, name);
      }

      globfree(&results);
    }

    return true;
  }

  static GlobalBinding<TFunctionParser<1,1,fs_ls> > _ls(L"ls");
#endif /* HAVE_GLOB */

  /**
   * Converts the given wstring to a char*, stored within dst. The actual size
   * of dst is not defined; rather, the only guarantee is that &dst[0] is a
   * valid NTBS.
   *
   * If successful, returns true; otherwise, prints a diagnostic and returns
   * false.
   */
  static bool wstrtofn(vector<char>& dst, const wstring& src) {
    bool success = wstrtontbs(dst, src);
    if (!success)
      wcerr << L"Could not convert filename to narrow string: "
            << src << endl;
    return success;
  }

  static void blitstr(wstring& dst, const wstring& src) {
    dst = src;
  }
  static void blitstr(wstring& dst, const string& src) {
    dst.resize(src.size());
    for (unsigned i = 0; i < src.size(); ++i)
      dst[i] = (wchar_t)(unsigned char)src[i];
  }
  static void blitstr(string& dst, const wstring& src) {
    dst.resize(src.size());
    for (unsigned i = 0; i < src.size(); ++i)
      dst[i] = (char)src[i];
  }

  template<typename Ifstream, typename String, bool Text>
  bool fs_read(wstring* out, const wstring* in,
               Interpreter& interp, unsigned) {
    vector<char> fname;
    if (!wstrtofn(fname, in[0]))
      return false;
    Ifstream input(&fname[0], Text? ios::in : ios::in | ios::binary);
    if (!input) {
      out[0].clear();
      out[1] = L"0";
      return true;
    }

    String str;
    static String eof((size_t)1, 4);
    getline(input, str, eof[0]);
    blitstr(out[0], str);

    if (!input.fail() && !input.eof())
      out[1] = L"1";
    else
      out[1] = L"0";

    return true;
  }

  static GlobalBinding<TFunctionParser<2,1,fs_read<wifstream, wstring, true> > >
  _read(L"read");
  static GlobalBinding<TFunctionParser<
                         2,1,fs_read<ifstream, string, false> > >
  _readBinary(L"read-binary");

  template<typename Ofstream, typename String, bool Text, bool Append>
  bool fs_write(wstring* out, const wstring* in,
                Interpreter& interp, unsigned) {
    vector<char> fname;
    String content;
    if (!wstrtofn(fname, in[0]))
      return false;

    blitstr(content, in[1]);

    ios_base::openmode mode = ios::out;
    if (!Text)
      mode |= ios::binary;
    if (Append)
      mode |= ios::app;
    else
      mode |= ios::trunc;

    Ofstream output(&fname[0], mode);
    if (!output) {
      out[0] = L"0";
      return true;
    }

    output << content;

    out[0] = output? L"1" : L"0";
    return true;
  }

  static GlobalBinding<TFunctionParser<1,2,fs_write<wofstream,
                                                    wstring,
                                                    true,
                                                    false> > >
  _write(L"write");
  static GlobalBinding<TFunctionParser<1,2,fs_write<wofstream,
                                                    wstring,
                                                    true,
                                                    true> > >
  _append(L"append");
  static GlobalBinding<TFunctionParser<1,2,fs_write<ofstream,
                                                    string,
                                                    false,
                                                    false> > >
  _writeBinary(L"write-binary");
  static GlobalBinding<TFunctionParser<1,2,fs_write<ofstream,
                                                    string,
                                                    false,
                                                    true> > >
  _appendBinary(L"append-binary");
}
<commit_msg>Fix read() always returning failure to status.<commit_after>#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <cerrno>

/* Use the POSIX glob(3) function if available. On a native Windows port,
 * you'll need to make your own glob(3) implementation and define HAVE_GLOB, or
 * entirely reimplement ls.
 */
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif

#include "../interp.hxx"
#include "../command.hxx"
#include "../function.hxx"
#include "list.hxx"
#include "../common.hxx"

using namespace std;

namespace tglng {
#ifdef HAVE_GLOB
//Define glob parms which might not exist
#ifndef GLOB_BRACE
#  define GLOB_BRACE 0
#endif
#ifndef GLOB_TILDE
#  define GLOB_TILDE 0
#endif
  bool fs_ls(wstring* out, const wstring* in,
             Interpreter& interp, unsigned) {
    glob_t results;

    out->clear();

    //Transcode in[0] to a narrow string
    vector<char> pattern;
    if (!wstrtontbs(pattern, in[0])) {
      wcerr << L"Could not convert glob pattern to narrow string: "
            << *in << endl;
      return false;
    }

    //Perform the glob
    //If it fails, just return an empty list (*out is already empty);
    //otherwise, convert to a list.
    if (!glob(&pattern[0], GLOB_BRACE|GLOB_TILDE, NULL, &results)) {
      for (unsigned i = 0; i < results.gl_pathc; ++i) {
        wstring name;
        //Convert the filename back to a wide string
        if (!ntbstowstr(name, results.gl_pathv[i])) {
          //Print a warning about this one
          cerr << "WARN: Could not convert narrow filename to wide string: "
               << results.gl_pathv[i] << endl;
          continue;
        }

        //OK, add to the list
        list::lappend(*out, name);
      }

      globfree(&results);
    }

    return true;
  }

  static GlobalBinding<TFunctionParser<1,1,fs_ls> > _ls(L"ls");
#endif /* HAVE_GLOB */

  /**
   * Converts the given wstring to a char*, stored within dst. The actual size
   * of dst is not defined; rather, the only guarantee is that &dst[0] is a
   * valid NTBS.
   *
   * If successful, returns true; otherwise, prints a diagnostic and returns
   * false.
   */
  static bool wstrtofn(vector<char>& dst, const wstring& src) {
    bool success = wstrtontbs(dst, src);
    if (!success)
      wcerr << L"Could not convert filename to narrow string: "
            << src << endl;
    return success;
  }

  static void blitstr(wstring& dst, const wstring& src) {
    dst = src;
  }
  static void blitstr(wstring& dst, const string& src) {
    dst.resize(src.size());
    for (unsigned i = 0; i < src.size(); ++i)
      dst[i] = (wchar_t)(unsigned char)src[i];
  }
  static void blitstr(string& dst, const wstring& src) {
    dst.resize(src.size());
    for (unsigned i = 0; i < src.size(); ++i)
      dst[i] = (char)src[i];
  }

  template<typename Ifstream, typename String, bool Text>
  bool fs_read(wstring* out, const wstring* in,
               Interpreter& interp, unsigned) {
    vector<char> fname;
    if (!wstrtofn(fname, in[0]))
      return false;
    Ifstream input(&fname[0], Text? ios::in : ios::in | ios::binary);
    if (!input) {
      out[0].clear();
      out[1] = L"0";
      return true;
    }

    String str;
    static String eof((size_t)1, 4);
    getline(input, str, eof[0]);
    blitstr(out[0], str);

    if (!input.fail())
      out[1] = L"1";
    else
      out[1] = L"0";

    return true;
  }

  static GlobalBinding<TFunctionParser<2,1,fs_read<wifstream, wstring, true> > >
  _read(L"read");
  static GlobalBinding<TFunctionParser<
                         2,1,fs_read<ifstream, string, false> > >
  _readBinary(L"read-binary");

  template<typename Ofstream, typename String, bool Text, bool Append>
  bool fs_write(wstring* out, const wstring* in,
                Interpreter& interp, unsigned) {
    vector<char> fname;
    String content;
    if (!wstrtofn(fname, in[0]))
      return false;

    blitstr(content, in[1]);

    ios_base::openmode mode = ios::out;
    if (!Text)
      mode |= ios::binary;
    if (Append)
      mode |= ios::app;
    else
      mode |= ios::trunc;

    Ofstream output(&fname[0], mode);
    if (!output) {
      out[0] = L"0";
      return true;
    }

    output << content;

    out[0] = output? L"1" : L"0";
    return true;
  }

  static GlobalBinding<TFunctionParser<1,2,fs_write<wofstream,
                                                    wstring,
                                                    true,
                                                    false> > >
  _write(L"write");
  static GlobalBinding<TFunctionParser<1,2,fs_write<wofstream,
                                                    wstring,
                                                    true,
                                                    true> > >
  _append(L"append");
  static GlobalBinding<TFunctionParser<1,2,fs_write<ofstream,
                                                    string,
                                                    false,
                                                    false> > >
  _writeBinary(L"write-binary");
  static GlobalBinding<TFunctionParser<1,2,fs_write<ofstream,
                                                    string,
                                                    false,
                                                    true> > >
  _appendBinary(L"append-binary");
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012, Dennis Hedback
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "common.hpp"

#include <iostream>
#include <vector>

struct Counter {
    Set::const_iterator begin;
    Set::const_iterator end;
    Set::const_iterator current;
};

typedef std::vector<Counter> Counters;

void init_counters(Counters &ctrs, Generator &gen)
{
    for (Generator::const_iterator set = gen.begin(); set != gen.end(); set++)
    {
        Counter ctr = {
            set->begin(),
            set->end(),
            set->begin()
        };
        ctrs.push_back(ctr);
    }
}

void populate_tuple(Tuple &tup, Counters &ctrs)
{
    for(Counters::const_iterator ctr = ctrs.begin(); ctr != ctrs.end(); ctr++)
    {
        tup.push_back(*(ctr->current));
    }
}

int increment_counters(Counters &ctrs)
{
    for (Counters::iterator ctr = ctrs.begin(); ; )
    {
        (ctr->current)++;
        if (ctr->current == ctr->end)
        {
            if (ctr+1 == ctrs.end())
            {
                return 1;
            }
            else
            {
                ctr->current = ctr->begin;
                ctr++;
            }
        }
        else
        {
            break;
        }
    }
    return 0;
}

void print_tuple(Tuple &tup)
{
    for (Tuple::const_iterator ti = tup.begin(); ti != tup.end(); ti++)
    {
        std::cout << *ti;

        if (++ti != tup.end())
            std::cout << ',';

        ti--;
    }

    std::cout << '\n';
}

void cartesian_product(Generator &gen, Product &prod, bool print)
{
    Counters ctrs;

    init_counters(ctrs, gen);

    while (true)
    {
        Tuple tup;

        populate_tuple(tup, ctrs);

        if (print)
            print_tuple(tup);
        else
            prod.insert(tup);

        if (increment_counters(ctrs) != 0)
            return;
    }
}

<commit_msg>Abolished the use of push_back to speed up the quotient executable.<commit_after>/*
 * Copyright (c) 2012, Dennis Hedback
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "common.hpp"

#include <iostream>
#include <vector>

struct Counter {
    Set::const_iterator begin;
    Set::const_iterator end;
    Set::const_iterator current;
};

typedef std::vector<Counter> Counters;

void init_counters(Counters &ctrs, Generator &gen)
{
    Counter tpl;
    ctrs = Counters(gen.size(), tpl);

    unsigned int i = 0;
    for (Generator::const_iterator set = gen.begin(); set != gen.end(); set++, i++)
    {
        ctrs[i].begin = set->begin();
        ctrs[i].end = set->end();
        ctrs[i].current = ctrs[i].begin;
    }
}

void populate_tuple(Tuple &tup, Counters &ctrs)
{
    for(Counters::const_iterator ctr = ctrs.begin(); ctr != ctrs.end(); ctr++)
    {
        tup.push_back(*(ctr->current));
    }
}

int increment_counters(Counters &ctrs)
{
    for (Counters::iterator ctr = ctrs.begin(); ; )
    {
        (ctr->current)++;
        if (ctr->current == ctr->end)
        {
            if (ctr+1 == ctrs.end())
            {
                return 1;
            }
            else
            {
                ctr->current = ctr->begin;
                ctr++;
            }
        }
        else
        {
            break;
        }
    }
    return 0;
}

void print_tuple(Tuple &tup)
{
    for (Tuple::const_iterator ti = tup.begin(); ti != tup.end(); ti++)
    {
        std::cout << *ti;

        if (++ti != tup.end())
            std::cout << ',';

        ti--;
    }

    std::cout << '\n';
}

void cartesian_product(Generator &gen, Product &prod, bool print)
{
    Counters ctrs;

    init_counters(ctrs, gen);

    while (true)
    {
        Tuple tup;

        populate_tuple(tup, ctrs);

        if (print)
            print_tuple(tup);
        else
            prod.insert(tup);

        if (increment_counters(ctrs) != 0)
            return;
    }
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011, Peter Thorson. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the WebSocket++ Project nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef WEBSOCKET_CONSTANTS_HPP
#define WEBSOCKET_CONSTANTS_HPP

#ifndef __STDC_LIMIT_MACROS
  #define __STDC_LIMIT_MACROS
#endif
#include <stdint.h>

#include <exception>
#include <string>
#include <vector>

#include <boost/shared_ptr.hpp>

// Defaults
namespace websocketpp {
    typedef std::vector<unsigned char> binary_string;
    typedef boost::shared_ptr<binary_string> binary_string_ptr;

    typedef std::string utf8_string;
    typedef boost::shared_ptr<utf8_string> utf8_string_ptr;

    const uint64_t DEFAULT_MAX_MESSAGE_SIZE = 0xFFFFFF; // ~16MB

    const uint16_t DEFAULT_PORT = 80;
    const uint16_t DEFAULT_SECURE_PORT = 443;

    inline uint16_t default_port(bool secure) {
        return (secure ? DEFAULT_SECURE_PORT : DEFAULT_PORT);
    }

    namespace session {
        namespace state {
            enum value {
                CONNECTING = 0,
                OPEN = 1,
                CLOSING = 2,
                CLOSED = 3
            };
        }
    }

    namespace close {
    namespace status {
        enum value {
            INVALID_END = 999,
            NORMAL = 1000,
            GOING_AWAY = 1001,
            PROTOCOL_ERROR = 1002,
            UNSUPPORTED_DATA = 1003,
            RSV_ADHOC_1 = 1004,
            NO_STATUS = 1005,
            ABNORMAL_CLOSE = 1006,
            INVALID_PAYLOAD = 1007,
            POLICY_VIOLATION = 1008,
            MESSAGE_TOO_BIG = 1009,
            EXTENSION_REQUIRE = 1010,
            INTERNAL_ENDPOINT_ERROR = 1011,
            RSV_START = 1012,
            RSV_END = 2999,
            INVALID_START = 5000
        };

        inline bool reserved(value s) {
            return ((s >= RSV_START && s <= RSV_END) ||
                    s == RSV_ADHOC_1);
        }

        inline bool invalid(value s) {
            return ((s <= INVALID_END || s >= INVALID_START) ||
                    s == NO_STATUS ||
                    s == ABNORMAL_CLOSE);
        }

        // TODO functions for application ranges?
    } // namespace status
    } // namespace close

    namespace frame {
        // Opcodes are 4 bits
        // See spec section 5.2
        namespace opcode {
            enum value {
                CONTINUATION = 0x0,
                TEXT = 0x1,
                BINARY = 0x2,
                RSV3 = 0x3,
                RSV4 = 0x4,
                RSV5 = 0x5,
                RSV6 = 0x6,
                RSV7 = 0x7,
                CLOSE = 0x8,
                PING = 0x9,
                PONG = 0xA,
                CONTROL_RSVB = 0xB,
                CONTROL_RSVC = 0xC,
                CONTROL_RSVD = 0xD,
                CONTROL_RSVE = 0xE,
                CONTROL_RSVF = 0xF,
            };

            inline bool reserved(value v) {
                return (v >= RSV3 && v <= RSV7) ||
                (v >= CONTROL_RSVB && v <= CONTROL_RSVF);
            }

            inline bool invalid(value v) {
                return (v > 0xF || v < 0);
            }

            inline bool is_control(value v) {
                return v >= 0x8;
            }
        }

        namespace limits {
            static const uint8_t PAYLOAD_SIZE_BASIC = 125;
            static const uint16_t PAYLOAD_SIZE_EXTENDED = 0xFFFF; // 2^16, 65535
            static const uint64_t PAYLOAD_SIZE_JUMBO = 0x7FFFFFFFFFFFFFFF;//2^63
        }
    } // namespace frame

    // exception class for errors that should be propogated back to the user.
    namespace error {
        enum value {
            GENERIC = 0,
            // send attempted when endpoint write queue was full
            SEND_QUEUE_FULL = 1,
            PAYLOAD_VIOLATION = 2,
            ENDPOINT_UNSECURE = 3,
            ENDPOINT_UNAVAILABLE = 4
        };
    }

    class exception : public std::exception {
    public:
        exception(const std::string& msg,
                  error::value code = error::GENERIC)
        : m_msg(msg),m_code(code) {}
        ~exception() throw() {}

        virtual const char* what() const throw() {
            return m_msg.c_str();
        }

        error::value code() const throw() {
            return m_code;
        }

        std::string m_msg;
        error::value m_code;
    };
}

#endif // WEBSOCKET_CONSTANTS_HPP
<commit_msg>adds SIZE_MAX definition<commit_after>/*
 * Copyright (c) 2011, Peter Thorson. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the WebSocket++ Project nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef WEBSOCKET_CONSTANTS_HPP
#define WEBSOCKET_CONSTANTS_HPP

#ifndef __STDC_LIMIT_MACROS
  #define __STDC_LIMIT_MACROS
#endif
#include <stdint.h>

// SIZE_MAX appears to be a compiler thing not an OS header thing.
// make sure it is defined.
#ifndef SIZE_MAX
    #define SIZE_MAX ((size_t)(-1))
#endif

#include <exception>
#include <string>
#include <vector>

#include <boost/shared_ptr.hpp>

// Defaults
namespace websocketpp {
    typedef std::vector<unsigned char> binary_string;
    typedef boost::shared_ptr<binary_string> binary_string_ptr;

    typedef std::string utf8_string;
    typedef boost::shared_ptr<utf8_string> utf8_string_ptr;

    const uint64_t DEFAULT_MAX_MESSAGE_SIZE = 0xFFFFFF; // ~16MB

    const uint16_t DEFAULT_PORT = 80;
    const uint16_t DEFAULT_SECURE_PORT = 443;

    inline uint16_t default_port(bool secure) {
        return (secure ? DEFAULT_SECURE_PORT : DEFAULT_PORT);
    }

    namespace session {
        namespace state {
            enum value {
                CONNECTING = 0,
                OPEN = 1,
                CLOSING = 2,
                CLOSED = 3
            };
        }
    }

    namespace close {
    namespace status {
        enum value {
            INVALID_END = 999,
            NORMAL = 1000,
            GOING_AWAY = 1001,
            PROTOCOL_ERROR = 1002,
            UNSUPPORTED_DATA = 1003,
            RSV_ADHOC_1 = 1004,
            NO_STATUS = 1005,
            ABNORMAL_CLOSE = 1006,
            INVALID_PAYLOAD = 1007,
            POLICY_VIOLATION = 1008,
            MESSAGE_TOO_BIG = 1009,
            EXTENSION_REQUIRE = 1010,
            INTERNAL_ENDPOINT_ERROR = 1011,
            RSV_START = 1012,
            RSV_END = 2999,
            INVALID_START = 5000
        };

        inline bool reserved(value s) {
            return ((s >= RSV_START && s <= RSV_END) ||
                    s == RSV_ADHOC_1);
        }

        inline bool invalid(value s) {
            return ((s <= INVALID_END || s >= INVALID_START) ||
                    s == NO_STATUS ||
                    s == ABNORMAL_CLOSE);
        }

        // TODO functions for application ranges?
    } // namespace status
    } // namespace close

    namespace frame {
        // Opcodes are 4 bits
        // See spec section 5.2
        namespace opcode {
            enum value {
                CONTINUATION = 0x0,
                TEXT = 0x1,
                BINARY = 0x2,
                RSV3 = 0x3,
                RSV4 = 0x4,
                RSV5 = 0x5,
                RSV6 = 0x6,
                RSV7 = 0x7,
                CLOSE = 0x8,
                PING = 0x9,
                PONG = 0xA,
                CONTROL_RSVB = 0xB,
                CONTROL_RSVC = 0xC,
                CONTROL_RSVD = 0xD,
                CONTROL_RSVE = 0xE,
                CONTROL_RSVF = 0xF,
            };

            inline bool reserved(value v) {
                return (v >= RSV3 && v <= RSV7) ||
                (v >= CONTROL_RSVB && v <= CONTROL_RSVF);
            }

            inline bool invalid(value v) {
                return (v > 0xF || v < 0);
            }

            inline bool is_control(value v) {
                return v >= 0x8;
            }
        }

        namespace limits {
            static const uint8_t PAYLOAD_SIZE_BASIC = 125;
            static const uint16_t PAYLOAD_SIZE_EXTENDED = 0xFFFF; // 2^16, 65535
            static const uint64_t PAYLOAD_SIZE_JUMBO = 0x7FFFFFFFFFFFFFFF;//2^63
        }
    } // namespace frame

    // exception class for errors that should be propogated back to the user.
    namespace error {
        enum value {
            GENERIC = 0,
            // send attempted when endpoint write queue was full
            SEND_QUEUE_FULL = 1,
            PAYLOAD_VIOLATION = 2,
            ENDPOINT_UNSECURE = 3,
            ENDPOINT_UNAVAILABLE = 4
        };
    }

    class exception : public std::exception {
    public:
        exception(const std::string& msg,
                  error::value code = error::GENERIC)
        : m_msg(msg),m_code(code) {}
        ~exception() throw() {}

        virtual const char* what() const throw() {
            return m_msg.c_str();
        }

        error::value code() const throw() {
            return m_code;
        }

        std::string m_msg;
        error::value m_code;
    };
}

#endif // WEBSOCKET_CONSTANTS_HPP
<|endoftext|>


<commit_before>/*
* This file is part of the QPackageKit project
* Copyright (C) 2008 Adrien Bustany <madcat@mymadcat.com>
* Copyright (C) 2010-2011 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/

#include <QtSql>
#include <QDebug>

#include "daemon.h"
#include "daemonprivate.h"
#include "daemonproxy.h"

#include "common.h"

using namespace PackageKit;

Daemon* Daemon::m_global = 0;

Daemon* Daemon::global()
{
    if(!m_global) {
        m_global = new Daemon(qApp);
    }

    return m_global;
}

Daemon::Daemon(QObject *parent) :
    QObject(parent),
    d_ptr(new DaemonPrivate(this))
{
    Q_D(Daemon);
    d->daemon = new ::DaemonProxy(QLatin1String(PK_NAME),
                                  QLatin1String(PK_PATH),
                                  QDBusConnection::systemBus(),
                                  this);

    connect(d->daemon, SIGNAL(Changed()),
            this, SIGNAL(changed()));
    connect(d->daemon, SIGNAL(RepoListChanged()),
            this, SIGNAL(repoListChanged()));
    connect(d->daemon, SIGNAL(RestartSchedule()),
            this, SIGNAL(restartScheduled()));
    connect(d->daemon, SIGNAL(TransactionListChanged(QStringList)),
            this, SIGNAL(transactionListChanged(QStringList)));
    connect(d->daemon, SIGNAL(UpdatesChanged()),
            this, SIGNAL(updatesChanged()));

    // Set up database for desktop files
    QSqlDatabase db;
    db = QSqlDatabase::addDatabase("QSQLITE", PK_DESKTOP_DEFAULT_DATABASE);
    db.setDatabaseName(PK_DESKTOP_DEFAULT_DATABASE);
    if (!db.open()) {
        qDebug() << "Failed to initialize the desktop files database";
    }
}

Daemon::~Daemon()
{
}

Transaction::Roles Daemon::actions()
{
    Q_D(const Daemon);
    return d->daemon->roles();
}

QString Daemon::backendName()
{
    Q_D(const Daemon);
    return d->daemon->backendName();
}

QString Daemon::backendDescription()
{
    Q_D(const Daemon);
    return d->daemon->backendDescription();
}

QString Daemon::backendAuthor()
{
    Q_D(const Daemon);
    return d->daemon->backendAuthor();
}

Transaction::Filters Daemon::filters()
{
    Q_D(const Daemon);
    return static_cast<Transaction::Filters>(d->daemon->filters());
}

Transaction::Groups Daemon::groups()
{
    Q_D(const Daemon);
    return static_cast<Transaction::Groups>(d->daemon->groups());
}

bool Daemon::locked()
{
    Q_D(const Daemon);
    return d->daemon->locked();
}

QStringList Daemon::mimeTypes()
{
    Q_D(const Daemon);
    return d->daemon->mimeTypes();
}

Daemon::Network Daemon::networkState()
{
    Q_D(const Daemon);
    return static_cast<Daemon::Network>(d->daemon->networkState());
}

QString Daemon::distroID()
{
    Q_D(const Daemon);
    return d->daemon->distroId();
}

Daemon::Authorize Daemon::canAuthorize(const QString &actionId)
{
    Q_D(const Daemon);
    uint ret;
    ret = d->daemon->CanAuthorize(actionId);
    return static_cast<Daemon::Authorize>(ret);
}

QDBusObjectPath Daemon::getTid()
{
    Q_D(const Daemon);
    return d->daemon->CreateTransaction();
}

uint Daemon::getTimeSinceAction(Transaction::Role role)
{
    Q_D(const Daemon);
    return d->daemon->GetTimeSinceAction(role);
}

QList<QDBusObjectPath> Daemon::getTransactionList()
{
    Q_D(const Daemon);
    return d->daemon->GetTransactionList();
}

QList<Transaction*> Daemon::getTransactionObjects(QObject *parent)
{
    Q_D(Daemon);
    return d->transactions(getTransactionList(), parent);
}

void Daemon::setHints(const QStringList &hints)
{
    Q_D(Daemon);
    d->hints = hints;
}

void Daemon::setHints(const QString &hints)
{
    Q_D(Daemon);
    d->hints = QStringList() << hints;
}

QStringList Daemon::hints()
{
    Q_D(const Daemon);
    return d->hints;
}

Transaction::InternalError Daemon::setProxy(const QString& http_proxy, const QString& https_proxy, const QString& ftp_proxy, const QString& socks_proxy, const QString& no_proxy, const QString& pac)
{
    Q_D(const Daemon);
    QDBusPendingReply<> r = d->daemon->SetProxy(http_proxy, https_proxy, ftp_proxy, socks_proxy, no_proxy, pac);
    r.waitForFinished();
    if (r.isError ()) {
        return Transaction::parseError(r.error().name());
    } else {
        return Transaction::InternalErrorNone;
    }
}

void Daemon::stateHasChanged(const QString& reason)
{
    Q_D(const Daemon);
    d->daemon->StateHasChanged(reason);
}

void Daemon::suggestDaemonQuit()
{
    Q_D(const Daemon);
    d->daemon->SuggestDaemonQuit();
}

uint Daemon::versionMajor()
{
    Q_D(const Daemon);
    return d->daemon->versionMajor();
}

uint Daemon::versionMinor()
{
    Q_D(const Daemon);
    return d->daemon->versionMinor();
}

uint Daemon::versionMicro()
{
    Q_D(const Daemon);
    return d->daemon->versionMicro();
}

QString Daemon::packageName(const QString &packageID)
{
    return packageID.section(QLatin1Char(';'), 0, 0);
}

QString Daemon::packageVersion(const QString &packageID)
{
    return packageID.section(QLatin1Char(';'), 1, 1);
}

QString Daemon::packageArch(const QString &packageID)
{
    return packageID.section(QLatin1Char(';'), 2, 2);
}

QString Daemon::packageData(const QString &packageID)
{
    return packageID.section(QLatin1Char(';'), 3, 3);
}

QString Daemon::packageIcon(const QString &packageID)
{
    return Transaction::packageIcon(packageID);
}

#include "daemon.moc"
<commit_msg>Make sure we waitForFinishe() when getting the TransactionList Trying to fix kde BUG:286500<commit_after>/*
* This file is part of the QPackageKit project
* Copyright (C) 2008 Adrien Bustany <madcat@mymadcat.com>
* Copyright (C) 2010-2011 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/

#include <QtSql>
#include <QDebug>

#include "daemon.h"
#include "daemonprivate.h"
#include "daemonproxy.h"

#include "common.h"

using namespace PackageKit;

Daemon* Daemon::m_global = 0;

Daemon* Daemon::global()
{
    if(!m_global) {
        m_global = new Daemon(qApp);
    }

    return m_global;
}

Daemon::Daemon(QObject *parent) :
    QObject(parent),
    d_ptr(new DaemonPrivate(this))
{
    Q_D(Daemon);
    d->daemon = new ::DaemonProxy(QLatin1String(PK_NAME),
                                  QLatin1String(PK_PATH),
                                  QDBusConnection::systemBus(),
                                  this);

    connect(d->daemon, SIGNAL(Changed()),
            this, SIGNAL(changed()));
    connect(d->daemon, SIGNAL(RepoListChanged()),
            this, SIGNAL(repoListChanged()));
    connect(d->daemon, SIGNAL(RestartSchedule()),
            this, SIGNAL(restartScheduled()));
    connect(d->daemon, SIGNAL(TransactionListChanged(QStringList)),
            this, SIGNAL(transactionListChanged(QStringList)));
    connect(d->daemon, SIGNAL(UpdatesChanged()),
            this, SIGNAL(updatesChanged()));

    // Set up database for desktop files
    QSqlDatabase db;
    db = QSqlDatabase::addDatabase("QSQLITE", PK_DESKTOP_DEFAULT_DATABASE);
    db.setDatabaseName(PK_DESKTOP_DEFAULT_DATABASE);
    if (!db.open()) {
        qDebug() << "Failed to initialize the desktop files database";
    }
}

Daemon::~Daemon()
{
}

Transaction::Roles Daemon::actions()
{
    Q_D(const Daemon);
    return d->daemon->roles();
}

QString Daemon::backendName()
{
    Q_D(const Daemon);
    return d->daemon->backendName();
}

QString Daemon::backendDescription()
{
    Q_D(const Daemon);
    return d->daemon->backendDescription();
}

QString Daemon::backendAuthor()
{
    Q_D(const Daemon);
    return d->daemon->backendAuthor();
}

Transaction::Filters Daemon::filters()
{
    Q_D(const Daemon);
    return static_cast<Transaction::Filters>(d->daemon->filters());
}

Transaction::Groups Daemon::groups()
{
    Q_D(const Daemon);
    return static_cast<Transaction::Groups>(d->daemon->groups());
}

bool Daemon::locked()
{
    Q_D(const Daemon);
    return d->daemon->locked();
}

QStringList Daemon::mimeTypes()
{
    Q_D(const Daemon);
    return d->daemon->mimeTypes();
}

Daemon::Network Daemon::networkState()
{
    Q_D(const Daemon);
    return static_cast<Daemon::Network>(d->daemon->networkState());
}

QString Daemon::distroID()
{
    Q_D(const Daemon);
    return d->daemon->distroId();
}

Daemon::Authorize Daemon::canAuthorize(const QString &actionId)
{
    Q_D(const Daemon);
    uint ret;
    ret = d->daemon->CanAuthorize(actionId);
    return static_cast<Daemon::Authorize>(ret);
}

QDBusObjectPath Daemon::getTid()
{
    Q_D(const Daemon);
    return d->daemon->CreateTransaction();
}

uint Daemon::getTimeSinceAction(Transaction::Role role)
{
    Q_D(const Daemon);
    return d->daemon->GetTimeSinceAction(role);
}

QList<QDBusObjectPath> Daemon::getTransactionList()
{
    Q_D(const Daemon);
    QDBusPendingReply<QList<QDBusObjectPath> > reply = d->daemon->GetTransactionList();
    if (reply.isValid()) {
        return reply.value();
    }
    return QList<QDBusObjectPath>();
}

QList<Transaction*> Daemon::getTransactionObjects(QObject *parent)
{
    Q_D(Daemon);
    return d->transactions(getTransactionList(), parent);
}

void Daemon::setHints(const QStringList &hints)
{
    Q_D(Daemon);
    d->hints = hints;
}

void Daemon::setHints(const QString &hints)
{
    Q_D(Daemon);
    d->hints = QStringList() << hints;
}

QStringList Daemon::hints()
{
    Q_D(const Daemon);
    return d->hints;
}

Transaction::InternalError Daemon::setProxy(const QString& http_proxy, const QString& https_proxy, const QString& ftp_proxy, const QString& socks_proxy, const QString& no_proxy, const QString& pac)
{
    Q_D(const Daemon);
    QDBusPendingReply<> r = d->daemon->SetProxy(http_proxy, https_proxy, ftp_proxy, socks_proxy, no_proxy, pac);
    r.waitForFinished();
    if (r.isError ()) {
        return Transaction::parseError(r.error().name());
    } else {
        return Transaction::InternalErrorNone;
    }
}

void Daemon::stateHasChanged(const QString& reason)
{
    Q_D(const Daemon);
    d->daemon->StateHasChanged(reason);
}

void Daemon::suggestDaemonQuit()
{
    Q_D(const Daemon);
    d->daemon->SuggestDaemonQuit();
}

uint Daemon::versionMajor()
{
    Q_D(const Daemon);
    return d->daemon->versionMajor();
}

uint Daemon::versionMinor()
{
    Q_D(const Daemon);
    return d->daemon->versionMinor();
}

uint Daemon::versionMicro()
{
    Q_D(const Daemon);
    return d->daemon->versionMicro();
}

QString Daemon::packageName(const QString &packageID)
{
    return packageID.section(QLatin1Char(';'), 0, 0);
}

QString Daemon::packageVersion(const QString &packageID)
{
    return packageID.section(QLatin1Char(';'), 1, 1);
}

QString Daemon::packageArch(const QString &packageID)
{
    return packageID.section(QLatin1Char(';'), 2, 2);
}

QString Daemon::packageData(const QString &packageID)
{
    return packageID.section(QLatin1Char(';'), 3, 3);
}

QString Daemon::packageIcon(const QString &packageID)
{
    return Transaction::packageIcon(packageID);
}

#include "daemon.moc"
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2015 John Connor (BM-NC49AxAjcqVcF5jNPu85Rb8MJ2d9JqZt)
 *
 * This file is part of vanillacoin.
 *
 * vanillacoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#if (defined _MSC_VER)
#ifndef S_IRUSR
#define S_IRUSR 0400
#define S_IWUSR 0200
#endif // S_IRUSR
#else
#include <sys/stat.h>
#endif // _MSC_VER

#include <cassert>
#include <sstream>

#include <coin/db_env.hpp>
#include <coin/globals.hpp>
#include <coin/logger.hpp>
#include <coin/utility.hpp>

using namespace coin;

db_env::db_env()
    : m_DbEnv(DB_CXX_NO_EXCEPTIONS)
    , state_(state_closed)
{
    // ...
}

db_env::~db_env()
{
    close_DbEnv();
}

bool db_env::open(const std::string & data_path)
{
    if (state_ == state_closed)
    {
        filesystem::create_path(data_path);

        auto log_path = data_path + "/database";

        filesystem::create_path(log_path);

        auto errfile_path = data_path + "/db.log";

        std::int32_t flags =
            DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
            DB_INIT_TXN | DB_THREAD | DB_RECOVER
        ;

        auto cache = 25;

        std::lock_guard<std::recursive_mutex> l1(m_mutex_DbEnv);

        m_DbEnv.set_lg_dir(log_path.c_str());
        m_DbEnv.set_cachesize(cache / 1024, (cache % 1024) * 1048576, 1);
        m_DbEnv.set_lg_bsize(1048576);
        m_DbEnv.set_lg_max(10485760);
        m_DbEnv.set_lk_max_locks(10000);
        m_DbEnv.set_lk_max_objects(10000);
        m_DbEnv.set_errfile(fopen(errfile_path.c_str(), "a"));
        m_DbEnv.set_flags(DB_AUTO_COMMIT, 1);
        m_DbEnv.set_flags(DB_TXN_WRITE_NOSYNC, 1);

        auto ret = m_DbEnv.open(data_path.c_str(), flags, S_IRUSR | S_IWUSR);

        if (ret != 0)
        {
            log_error(
                "Database environment open failed, error = " <<
                DbEnv::strerror(ret) << "."
            );
        }
        else
        {
            state_ = state_opened;
        }

        return ret == 0;
    }
    else if (state_ == state_opened)
    {
        return true;
    }

    return false;
}

void db_env::close_DbEnv()
{
    if (state_ == state_opened)
    {
        state_ = state_closed;

        std::lock_guard<std::recursive_mutex> l1(m_mutex_DbEnv);

        auto ret = m_DbEnv.close(0);

        if (ret != 0)
        {
            log_error(
                "Database environment closed failed, error = " <<
                DbEnv::strerror(ret) << "."
            );
        }

        std::string data_path = filesystem::data_path();

        DbEnv(0).remove(data_path.c_str(), 0);
    }
}

void db_env::close_Db(const std::string & file_name)
{
    std::lock_guard<std::recursive_mutex> l1(mutex_m_Dbs_);

    auto & ptr_Db = m_Dbs[file_name];

    if (ptr_Db)
    {
        ptr_Db->close(0);

        delete ptr_Db, ptr_Db = 0;
    }
}

bool db_env::remove_Db(const std::string & file_name)
{
    this->close_Db(file_name);

    std::lock_guard<std::recursive_mutex> l1(m_mutex_DbEnv);

    int ret = m_DbEnv.dbremove(0, file_name.c_str(), 0, DB_AUTO_COMMIT);

    return ret == 0;
}

bool db_env::verify(const std::string & file_name)
{
    std::lock_guard<std::recursive_mutex> l1(mutex_file_use_counts_);

    assert(m_file_use_counts.count(file_name) == 0);

    std::lock_guard<std::recursive_mutex> l2(m_mutex_DbEnv);

    Db db(&m_DbEnv, 0);

    auto result = db.verify(file_name.c_str(), 0, 0, 0);

    return result == 0;
}

bool db_env::salvage(
    const std::string & file_name, const bool & aggressive,
    std::vector< std::pair< std::vector<std::uint8_t>,
    std::vector<std::uint8_t> > > & result
    )
{
    std::lock_guard<std::recursive_mutex> l1(mutex_file_use_counts_);

    assert(m_file_use_counts.count(file_name) == 0);

    std::lock_guard<std::recursive_mutex> l2(m_mutex_DbEnv);

    std::uint32_t flags = DB_SALVAGE;

    if (aggressive)
    {
        flags |= DB_AGGRESSIVE;
    }

    std::stringstream dump;

    Db db(&m_DbEnv, 0);

    int ret = db.verify(file_name.c_str(), 0, &dump, flags);

    if (ret != 0)
    {
        log_error("Database environment salvage failed.");

        return false;
    }

    std::string line;

    while (dump.eof() == false && line != "HEADER=END")
    {
        getline(dump, line);
    }

    std::string key, value;

    while (dump.eof() == false && key != "DATA=END")
    {
        getline(dump, key);

        if (key != "DATA=END")
        {
            getline(dump, value);

            result.push_back(
                std::make_pair(utility::from_hex(key),
                utility::from_hex(value))
            );
        }
    }

    return ret == 0;
}

void db_env::checkpoint_lsn(const std::string & file_name)
{
    std::lock_guard<std::recursive_mutex> l2(m_mutex_DbEnv);

    m_DbEnv.txn_checkpoint(0, 0, 0);

    m_DbEnv.lsn_reset(file_name.c_str(), 0);
}

void db_env::flush()
{
    if (state_ == state_opened)
    {
        globals::instance().io_service().post(globals::instance().strand().wrap(
            [this]()
        {
            std::lock_guard<std::recursive_mutex> l1(mutex_file_use_counts_);

            auto it = m_file_use_counts.begin();

            while (it != m_file_use_counts.end())
            {
                auto file_name = it->first;

                auto reference_count = it->second;

                log_debug(
                    "Db Env " << file_name << ", reference count = " <<
                    reference_count << "."
                );

                if (reference_count == 0)
                {
                    /**
                     * Move the log data to the dat file.
                     */
                    close_Db(file_name);

                    log_debug("Db Env checkpoint " << file_name << ".");

                    std::lock_guard<std::recursive_mutex> l2(m_mutex_DbEnv);

                    m_DbEnv.txn_checkpoint(0, 0, 0);

                    static bool detach_db = true;

                    if (
                        utility::is_chain_file(file_name) == false || detach_db
                        )
                    {
                        log_debug("Db Env detach " << file_name << ".");

                        m_DbEnv.lsn_reset(file_name.c_str(), 0);
                    }

                    log_debug("Db Env closed " << file_name << ".");

                    m_file_use_counts.erase(it++);
                }
                else
                {
                    it++;
                }
            }

            if (globals::instance().state() > globals::state_started)
            {
                if (m_file_use_counts.empty())
                {
                    char ** list;

                    std::lock_guard<std::recursive_mutex> l3(m_mutex_DbEnv);

                    m_DbEnv.log_archive(&list, DB_ARCH_REMOVE);

                    close_DbEnv();
                }
            }
        }));
    }
}

DbEnv & db_env::get_DbEnv()
{
    std::lock_guard<std::recursive_mutex> l1(m_mutex_DbEnv);

    return m_DbEnv;
}

std::map<std::string, std::uint32_t> & db_env::file_use_counts()
{
    std::lock_guard<std::recursive_mutex> l1(mutex_file_use_counts_);

    return m_file_use_counts;
}

std::map<std::string, Db *> & db_env::Dbs()
{
    std::lock_guard<std::recursive_mutex> l1(mutex_m_Dbs_);

    return m_Dbs;
}

std::recursive_mutex & db_env::mutex_DbEnv()
{
    return m_mutex_DbEnv;
}

DbTxn * db_env::txn_begin(int flags)
{
    DbTxn * ptr = 0;

    std::lock_guard<std::recursive_mutex> l1(m_mutex_DbEnv);

    int ret = m_DbEnv.txn_begin(0, &ptr, flags);

    if (ret == ENOMEM)
    {
        log_debug("Database environment txn_begin failed, ENOMEM.");

        return 0;
    }
    else if (ret != 0)
    {
        return 0;
    }

    return ptr;
}
<commit_msg>Fixes for Android + Berkley DB<commit_after>/*
 * Copyright (c) 2013-2015 John Connor (BM-NC49AxAjcqVcF5jNPu85Rb8MJ2d9JqZt)
 *
 * This file is part of vanillacoin.
 *
 * vanillacoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#if (defined _MSC_VER)
#ifndef S_IRUSR
#define S_IRUSR 0400
#define S_IWUSR 0200
#endif // S_IRUSR
#else
#include <sys/stat.h>
#endif // _MSC_VER

#include <cassert>
#include <sstream>

#include <coin/db_env.hpp>
#include <coin/globals.hpp>
#include <coin/logger.hpp>
#include <coin/utility.hpp>

using namespace coin;

db_env::db_env()
    : m_DbEnv(DB_CXX_NO_EXCEPTIONS)
    , state_(state_closed)
{
    // ...
}

db_env::~db_env()
{
    close_DbEnv();
}

bool db_env::open(const std::string & data_path)
{
    if (state_ == state_closed)
    {
        filesystem::create_path(data_path);

        auto log_path = data_path + "database";

        log_info("Database environment log path = " << log_path << ".");

        filesystem::create_path(log_path);

        auto errfile_path = data_path + "db.log";

        log_info("Database environment err path = " << errfile_path << ".");

        std::int32_t flags =
            DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
            DB_INIT_TXN | DB_THREAD | DB_RECOVER
        ;

        auto cache = 25;

        std::lock_guard<std::recursive_mutex> l1(m_mutex_DbEnv);

        m_DbEnv.set_lg_dir(log_path.c_str());
        m_DbEnv.set_cachesize(cache / 1024, (cache % 1024) * 1048576, 1);
        m_DbEnv.set_lg_bsize(1048576);
        m_DbEnv.set_lg_max(10485760);
        m_DbEnv.set_lk_max_locks(10000);
        m_DbEnv.set_lk_max_objects(10000);
        m_DbEnv.set_errfile(fopen(errfile_path.c_str(), "a"));
        m_DbEnv.set_flags(DB_AUTO_COMMIT, 1);
        m_DbEnv.set_flags(DB_TXN_WRITE_NOSYNC, 1);

        auto ret = m_DbEnv.open(data_path.c_str(), flags, S_IRUSR | S_IWUSR);

        if (ret != 0)
        {
            log_error(
                "Database environment open failed, error = " <<
                DbEnv::strerror(ret) << "."
            );
        }
        else
        {
            state_ = state_opened;
        }

        return ret == 0;
    }
    else if (state_ == state_opened)
    {
        return true;
    }

    return false;
}

void db_env::close_DbEnv()
{
    if (state_ == state_opened)
    {
        state_ = state_closed;

        std::lock_guard<std::recursive_mutex> l1(m_mutex_DbEnv);

        auto ret = m_DbEnv.close(0);

        if (ret != 0)
        {
            log_error(
                "Database environment closed failed, error = " <<
                DbEnv::strerror(ret) << "."
            );
        }

        std::string data_path = filesystem::data_path();

        DbEnv(0).remove(data_path.c_str(), 0);
    }
}

void db_env::close_Db(const std::string & file_name)
{
    std::lock_guard<std::recursive_mutex> l1(mutex_m_Dbs_);

    auto & ptr_Db = m_Dbs[file_name];

    if (ptr_Db)
    {
        ptr_Db->close(0);

        delete ptr_Db, ptr_Db = 0;
    }
}

bool db_env::remove_Db(const std::string & file_name)
{
    this->close_Db(file_name);

    std::lock_guard<std::recursive_mutex> l1(m_mutex_DbEnv);

    int ret = m_DbEnv.dbremove(0, file_name.c_str(), 0, DB_AUTO_COMMIT);

    return ret == 0;
}

bool db_env::verify(const std::string & file_name)
{
    std::lock_guard<std::recursive_mutex> l1(mutex_file_use_counts_);

    assert(m_file_use_counts.count(file_name) == 0);

    std::lock_guard<std::recursive_mutex> l2(m_mutex_DbEnv);

    Db db(&m_DbEnv, 0);

    auto result = db.verify(file_name.c_str(), 0, 0, 0);

    return result == 0;
}

bool db_env::salvage(
    const std::string & file_name, const bool & aggressive,
    std::vector< std::pair< std::vector<std::uint8_t>,
    std::vector<std::uint8_t> > > & result
    )
{
    std::lock_guard<std::recursive_mutex> l1(mutex_file_use_counts_);

    assert(m_file_use_counts.count(file_name) == 0);

    std::lock_guard<std::recursive_mutex> l2(m_mutex_DbEnv);

    std::uint32_t flags = DB_SALVAGE;

    if (aggressive)
    {
        flags |= DB_AGGRESSIVE;
    }

    std::stringstream dump;

    Db db(&m_DbEnv, 0);

    int ret = db.verify(file_name.c_str(), 0, &dump, flags);

    if (ret != 0)
    {
        log_error("Database environment salvage failed.");

        return false;
    }

    std::string line;

    while (dump.eof() == false && line != "HEADER=END")
    {
        getline(dump, line);
    }

    std::string key, value;

    while (dump.eof() == false && key != "DATA=END")
    {
        getline(dump, key);

        if (key != "DATA=END")
        {
            getline(dump, value);

            result.push_back(
                std::make_pair(utility::from_hex(key),
                utility::from_hex(value))
            );
        }
    }

    return ret == 0;
}

void db_env::checkpoint_lsn(const std::string & file_name)
{
    std::lock_guard<std::recursive_mutex> l2(m_mutex_DbEnv);

    m_DbEnv.txn_checkpoint(0, 0, 0);

    m_DbEnv.lsn_reset(file_name.c_str(), 0);
}

void db_env::flush()
{
    if (state_ == state_opened)
    {
        globals::instance().io_service().post(globals::instance().strand().wrap(
            [this]()
        {
            std::lock_guard<std::recursive_mutex> l1(mutex_file_use_counts_);

            auto it = m_file_use_counts.begin();

            while (it != m_file_use_counts.end())
            {
                auto file_name = it->first;

                auto reference_count = it->second;

                log_debug(
                    "Db Env " << file_name << ", reference count = " <<
                    reference_count << "."
                );

                if (reference_count == 0)
                {
                    /**
                     * Move the log data to the dat file.
                     */
                    close_Db(file_name);

                    log_debug("Db Env checkpoint " << file_name << ".");

                    std::lock_guard<std::recursive_mutex> l2(m_mutex_DbEnv);

                    m_DbEnv.txn_checkpoint(0, 0, 0);

                    static bool detach_db = true;

                    if (
                        utility::is_chain_file(file_name) == false || detach_db
                        )
                    {
                        log_debug("Db Env detach " << file_name << ".");

                        m_DbEnv.lsn_reset(file_name.c_str(), 0);
                    }

                    log_debug("Db Env closed " << file_name << ".");

                    m_file_use_counts.erase(it++);
                }
                else
                {
                    it++;
                }
            }

            if (globals::instance().state() > globals::state_started)
            {
                if (m_file_use_counts.empty())
                {
                    char ** list;

                    std::lock_guard<std::recursive_mutex> l3(m_mutex_DbEnv);

                    m_DbEnv.log_archive(&list, DB_ARCH_REMOVE);

                    close_DbEnv();
                }
            }
        }));
    }
}

DbEnv & db_env::get_DbEnv()
{
    std::lock_guard<std::recursive_mutex> l1(m_mutex_DbEnv);

    return m_DbEnv;
}

std::map<std::string, std::uint32_t> & db_env::file_use_counts()
{
    std::lock_guard<std::recursive_mutex> l1(mutex_file_use_counts_);

    return m_file_use_counts;
}

std::map<std::string, Db *> & db_env::Dbs()
{
    std::lock_guard<std::recursive_mutex> l1(mutex_m_Dbs_);

    return m_Dbs;
}

std::recursive_mutex & db_env::mutex_DbEnv()
{
    return m_mutex_DbEnv;
}

DbTxn * db_env::txn_begin(int flags)
{
    DbTxn * ptr = 0;

    std::lock_guard<std::recursive_mutex> l1(m_mutex_DbEnv);

    int ret = m_DbEnv.txn_begin(0, &ptr, flags);

    if (ret == ENOMEM)
    {
        log_debug("Database environment txn_begin failed, ENOMEM.");

        return 0;
    }
    else if (ret != 0)
    {
        return 0;
    }

    return ptr;
}
<|endoftext|>


<commit_before>/* Linguagens de Programação 2017.1
 * Autorship: Daniel Barbosa and Erick Silva
 *
 * Implementation of the List ADT using doubly linked list
*/

// Quick compilation
// g++ src/driver.cpp -o bin/list -I include -Wall -std=c++11

#include <iostream>
#include <cassert>

#include "list.h"

using namespace ls;

template <typename T>
void print( list<T> & v )
{
	typename list<T>::const_iterator b_it = v.begin();
	typename list<T>::const_iterator e_it = v.end();

	std::cout << "[ ";
	for ( /*empty*/; b_it != e_it; ++b_it )
		std::cout << *b_it << " ";
	std::cout << "]\n";
}

int main()
{
	// Teste construtor vazio. //
	list<int> listaVazia;
	std::cout << "Lista Vazia" << std::endl;
	print( listaVazia );

    // Criando nova lista vazia
    list<int> listaInteiros = { 2 , 5 , 7 , 8 , 9 , 11 , 15 };

    return 0;
}<commit_msg>insignificant change<commit_after>/* Linguagens de Programação 2017.1
 * Autorship: Daniel Barbosa and Erick Silva
 *
 * Implementation of the List ADT using doubly linked list
*/

// Quick compilation
// g++ src/driver.cpp -o bin/list -I include -Wall -std=c++11

#include <iostream>
#include <cassert>

#include "list.h"

using namespace ls;

template <typename T>
void print( list<T> & v )
{
	typename list<T>::const_iterator b_it = v.begin();
	typename list<T>::const_iterator e_it = v.end();

	std::cout << "[ ";
	for ( /* EMPTY */; b_it != e_it; ++b_it )
		std::cout << *b_it << " ";
	std::cout << "]\n";
}

int main()
{
	// Teste construtor vazio. //
	list<int> listaVazia;
	std::cout << "Lista Vazia" << std::endl;
	print( listaVazia );

    // Criando nova lista vazia
    list<int> listaInteiros = { 2 , 5 , 7 , 8 , 9 , 11 , 15 };

    return 0;
}<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>

#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#include "RCSwitch.h"

namespace {

const std::size_t UNIX_PATH_MAX = 108;
const std::size_t gpio_pin = 2;

//Buffers
char write_buffer[4096];
char receive_buffer[4096];

bool revoke_root(){
    if (getuid() == 0) {
        if (setgid(1000) != 0){
            std::cout << "asgard:dht11: setgid: Unable to drop group privileges: " << strerror(errno) << std::endl;
            return false;
        }

        if (setuid(1000) != 0){
            std::cout << "asgard:dht11: setgid: Unable to drop user privileges: " << strerror(errno) << std::endl;
            return false;
        }
    }

    if (setuid(0) != -1){
        std::cout << "asgard:dht11: managed to regain root privileges, exiting..." << std::endl;
        return false;
    }

    return true;
}

void decode_wt450(unsigned long data, int socket_fd, int temperature_sensor, int humidity_sensor){
    int house=(data>>28) & (0x0f);
    byte station=((data>>26) & (0x03))+1;
    int humidity=(data>>16)&(0xff);
    double temperature=((data>>8) & (0xff));
    temperature = temperature - 50;
    byte tempfraction=(data>>4) & (0x0f);

    double tempdecimal=((tempfraction>>3 & 1) * 0.5) + ((tempfraction>>2 & 1) * 0.25) + ((tempfraction>>1 & 1) * 0.125) + ((tempfraction & 1) * 0.0625);
    temperature=temperature+tempdecimal;
    temperature=(int)(temperature*10);
    temperature=temperature/10;

    //Note: House and station can be used to distinguish between different weather stations
    (void) house;
    (void) station;

    //Send the humidity to the server
    auto nbytes = snprintf(write_buffer, 4096, "DATA %d %d", humidity_sensor, humidity);
    write(socket_fd, write_buffer, nbytes);

    sleep(1);

    //Send the temperature to the server
    nbytes = snprintf(write_buffer, 4096, "DATA %d %f", temperature_sensor, temperature);
    write(socket_fd, write_buffer, nbytes);
}

void read_data(RCSwitch& rc_switch, int socket_fd, int rf_button_1, int temperature_sensor, int humidity_sensor){
    if (rc_switch.available()) {
        int value = rc_switch.getReceivedValue();

        if (value) {
            if((rc_switch.getReceivedProtocol() == 1 || rc_switch.getReceivedProtocol() == 2) && rc_switch.getReceivedValue() == 1135920){
                //Send the event to the server
                auto nbytes = snprintf(write_buffer, 4096, "EVENT %d 1", rf_button_1);
                write(socket_fd, write_buffer, nbytes);
            } else if(rc_switch.getReceivedProtocol() == 5){
                unsigned long value = rc_switch.getReceivedValue();
                decode_wt450(value, socket_fd, temperature_sensor, humidity_sensor);
            } else {
                printf("asgard:rf:received unknown value: %lu\n", rc_switch.getReceivedValue());
                printf("asgard:rf:received unknown protocol: %i\n", rc_switch.getReceivedProtocol());
            }
        } else {
            printf("asgard:rf:received unknown encoding\n");
        }

        rc_switch.resetAvailable();
    }
}

} //end of anonymous namespace

int main(){
    RCSwitch rc_switch;

    //Run the wiringPi setup (as root)
    wiringPiSetup();

    rc_switch = RCSwitch();
    rc_switch.enableReceive(gpio_pin);

    //Drop root privileges and run as pi:pi again
    if(!revoke_root()){
       std::cout << "asgard:rf: unable to revoke root privileges, exiting..." << std::endl;
       return 1;
    }

    //Open the socket
    auto socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
    if(socket_fd < 0){
        std::cout << "asgard:rf: socket() failed" << std::endl;
        return 1;
    }

    //Init the address
    struct sockaddr_un address;
    memset(&address, 0, sizeof(struct sockaddr_un));
    address.sun_family = AF_UNIX;
    snprintf(address.sun_path, UNIX_PATH_MAX, "/tmp/asgard_socket");

    //Connect to the server
    if(connect(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0){
        std::cout << "asgard:rf: connect() failed" << std::endl;
        return 1;
    }

    //Register the actuator
    auto nbytes = snprintf(write_buffer, 4096, "REG_ACTUATOR rf_button_1");
    write(socket_fd, write_buffer, nbytes);

    //Get the response from the server
    nbytes = read(socket_fd, receive_buffer, 4096);

    if(!nbytes){
        std::cout << "asgard:ir: failed to register actuator" << std::endl;
        return 1;
    }

    receive_buffer[nbytes] = 0;

    //Parse the actuator id
    int rf_button_1 = atoi(receive_buffer);
    std::cout << "remote actuator: " << rf_button_1 << std::endl;

    nbytes = snprintf(write_buffer, 4096, "REG_SENSOR TEMPERATURE rf_weather_1");
    write(socket_fd, write_buffer, nbytes);

    nbytes = read(socket_fd, receive_buffer, 4096);

    if(!nbytes){
        std::cout << "asgard:dht11: failed to register temperature sensor" << std::endl;
        return 1;
    }

    receive_buffer[nbytes] = 0;

    int temperature_sensor = atoi(receive_buffer);

    std::cout << "Temperature sensor: " << temperature_sensor << std::endl;

    nbytes = snprintf(write_buffer, 4096, "REG_SENSOR HUMIDITY rf_weather_1");
    write(socket_fd, write_buffer, nbytes);

    nbytes = read(socket_fd, receive_buffer, 4096);

    if(!nbytes){
        std::cout << "asgard:dht11: failed to register humidity sensor" << std::endl;
        return 1;
    }

    receive_buffer[nbytes] = 0;

    int humidity_sensor = atoi(receive_buffer);

    std::cout << "Humidity sensor: " << humidity_sensor << std::endl;

    //wait for events
    while(true) {
        read_data(rc_switch, socket_fd, rf_button_1, temperature_sensor, humidity_sensor);

        //wait for 10 time units
        delay(10);
    }

    //Close the socket
    close(socket_fd);

    return 0;
}
<commit_msg>remove delay<commit_after>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>

#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#include "RCSwitch.h"

namespace {

const std::size_t UNIX_PATH_MAX = 108;
const std::size_t gpio_pin = 2;

//Buffers
char write_buffer[4096];
char receive_buffer[4096];

bool revoke_root(){
    if (getuid() == 0) {
        if (setgid(1000) != 0){
            std::cout << "asgard:dht11: setgid: Unable to drop group privileges: " << strerror(errno) << std::endl;
            return false;
        }

        if (setuid(1000) != 0){
            std::cout << "asgard:dht11: setgid: Unable to drop user privileges: " << strerror(errno) << std::endl;
            return false;
        }
    }

    if (setuid(0) != -1){
        std::cout << "asgard:dht11: managed to regain root privileges, exiting..." << std::endl;
        return false;
    }

    return true;
}

void decode_wt450(unsigned long data, int socket_fd, int temperature_sensor, int humidity_sensor){
    int house=(data>>28) & (0x0f);
    byte station=((data>>26) & (0x03))+1;
    int humidity=(data>>16)&(0xff);
    double temperature=((data>>8) & (0xff));
    temperature = temperature - 50;
    byte tempfraction=(data>>4) & (0x0f);

    double tempdecimal=((tempfraction>>3 & 1) * 0.5) + ((tempfraction>>2 & 1) * 0.25) + ((tempfraction>>1 & 1) * 0.125) + ((tempfraction & 1) * 0.0625);
    temperature=temperature+tempdecimal;
    temperature=(int)(temperature*10);
    temperature=temperature/10;

    //Note: House and station can be used to distinguish between different weather stations
    (void) house;
    (void) station;

    //Send the humidity to the server
    auto nbytes = snprintf(write_buffer, 4096, "DATA %d %d", humidity_sensor, humidity);
    write(socket_fd, write_buffer, nbytes);

    //Send the temperature to the server
    nbytes = snprintf(write_buffer, 4096, "DATA %d %f", temperature_sensor, temperature);
    write(socket_fd, write_buffer, nbytes);
}

void read_data(RCSwitch& rc_switch, int socket_fd, int rf_button_1, int temperature_sensor, int humidity_sensor){
    if (rc_switch.available()) {
        int value = rc_switch.getReceivedValue();

        if (value) {
            if((rc_switch.getReceivedProtocol() == 1 || rc_switch.getReceivedProtocol() == 2) && rc_switch.getReceivedValue() == 1135920){
                //Send the event to the server
                auto nbytes = snprintf(write_buffer, 4096, "EVENT %d 1", rf_button_1);
                write(socket_fd, write_buffer, nbytes);
            } else if(rc_switch.getReceivedProtocol() == 5){
                unsigned long value = rc_switch.getReceivedValue();
                decode_wt450(value, socket_fd, temperature_sensor, humidity_sensor);
            } else {
                printf("asgard:rf:received unknown value: %lu\n", rc_switch.getReceivedValue());
                printf("asgard:rf:received unknown protocol: %i\n", rc_switch.getReceivedProtocol());
            }
        } else {
            printf("asgard:rf:received unknown encoding\n");
        }

        rc_switch.resetAvailable();
    }
}

} //end of anonymous namespace

int main(){
    RCSwitch rc_switch;

    //Run the wiringPi setup (as root)
    wiringPiSetup();

    rc_switch = RCSwitch();
    rc_switch.enableReceive(gpio_pin);

    //Drop root privileges and run as pi:pi again
    if(!revoke_root()){
       std::cout << "asgard:rf: unable to revoke root privileges, exiting..." << std::endl;
       return 1;
    }

    //Open the socket
    auto socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
    if(socket_fd < 0){
        std::cout << "asgard:rf: socket() failed" << std::endl;
        return 1;
    }

    //Init the address
    struct sockaddr_un address;
    memset(&address, 0, sizeof(struct sockaddr_un));
    address.sun_family = AF_UNIX;
    snprintf(address.sun_path, UNIX_PATH_MAX, "/tmp/asgard_socket");

    //Connect to the server
    if(connect(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0){
        std::cout << "asgard:rf: connect() failed" << std::endl;
        return 1;
    }

    //Register the actuator
    auto nbytes = snprintf(write_buffer, 4096, "REG_ACTUATOR rf_button_1");
    write(socket_fd, write_buffer, nbytes);

    //Get the response from the server
    nbytes = read(socket_fd, receive_buffer, 4096);

    if(!nbytes){
        std::cout << "asgard:ir: failed to register actuator" << std::endl;
        return 1;
    }

    receive_buffer[nbytes] = 0;

    //Parse the actuator id
    int rf_button_1 = atoi(receive_buffer);
    std::cout << "remote actuator: " << rf_button_1 << std::endl;

    nbytes = snprintf(write_buffer, 4096, "REG_SENSOR TEMPERATURE rf_weather_1");
    write(socket_fd, write_buffer, nbytes);

    nbytes = read(socket_fd, receive_buffer, 4096);

    if(!nbytes){
        std::cout << "asgard:dht11: failed to register temperature sensor" << std::endl;
        return 1;
    }

    receive_buffer[nbytes] = 0;

    int temperature_sensor = atoi(receive_buffer);

    std::cout << "Temperature sensor: " << temperature_sensor << std::endl;

    nbytes = snprintf(write_buffer, 4096, "REG_SENSOR HUMIDITY rf_weather_1");
    write(socket_fd, write_buffer, nbytes);

    nbytes = read(socket_fd, receive_buffer, 4096);

    if(!nbytes){
        std::cout << "asgard:dht11: failed to register humidity sensor" << std::endl;
        return 1;
    }

    receive_buffer[nbytes] = 0;

    int humidity_sensor = atoi(receive_buffer);

    std::cout << "Humidity sensor: " << humidity_sensor << std::endl;

    //wait for events
    while(true) {
        read_data(rc_switch, socket_fd, rf_button_1, temperature_sensor, humidity_sensor);

        //wait for 10 time units
        delay(10);
    }

    //Close the socket
    close(socket_fd);

    return 0;
}
<|endoftext|>