<commit_before>#include "shell_manager.hh"

#include "context.hh"
#include "debug.hh"
#include "event_manager.hh"
#include "file.hh"

#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

namespace Kakoune
{

static const Regex env_var_regex(R"(\bkak_(\w+)\b)");

ShellManager::ShellManager()
{
    const char* path = getenv("PATH");
    String new_path;
    if (path)
        new_path = path + ":"_str;

    String kak_path = get_kak_binary_path();
    StringView kak_dir = kak_path.substr(0_byte, (int)kak_path.find_last_of('/'));
    new_path += kak_dir;
    setenv("PATH", new_path.c_str(), 1);
}

String ShellManager::eval(StringView cmdline, const Context& context,
                          memoryview<String> params,
                          const EnvVarMap& env_vars,
                          int* exit_status)
{
    return pipe("", cmdline, context, params, env_vars, exit_status);
}

String ShellManager::pipe(StringView input,
                          StringView cmdline, const Context& context,
                          memoryview<String> params,
                          const EnvVarMap& env_vars,
                          int* exit_status)
{
    int write_pipe[2]; // child stdin
    int read_pipe[2];  // child stdout
    int error_pipe[2]; // child stderr

    ::pipe(write_pipe);
    ::pipe(read_pipe);
    ::pipe(error_pipe);

    String output;
    if (pid_t pid = fork())
    {
        close(write_pipe[0]);
        close(read_pipe[1]);
        close(error_pipe[1]);

        write(write_pipe[1], input.data(), (int)input.length());
        close(write_pipe[1]);

        String error;
        {
            auto pipe_reader = [](String& output, bool& closed) {
                return [&output, &closed](FDWatcher& watcher, EventMode) {
                    if (closed)
                        return;
                    const int fd = watcher.fd();
                    char buffer[1024];
                    size_t size = read(fd, buffer, 1024);
                    if (size <= 0)
                    {
                        close(fd);
                        closed = true;
                    }
                    output += String(buffer, buffer+size);
                };
            };

            bool stdout_closed = false, stderr_closed = false;
            FDWatcher stdout_watcher{read_pipe[0], pipe_reader(output, stdout_closed)};
            FDWatcher stderr_watcher{error_pipe[0], pipe_reader(error, stderr_closed)};

            while (not stdout_closed or not stderr_closed)
                EventManager::instance().handle_next_events(EventMode::Urgent);
        }

        if (not error.empty())
            write_debug("shell stderr: <<<\n" + error + ">>>");

        waitpid(pid, exit_status, 0);
        if (exit_status)
        {
            if (WIFEXITED(*exit_status))
                *exit_status = WEXITSTATUS(*exit_status);
            else
                *exit_status = -1;
        }
    }
    else try
    {
        close(write_pipe[1]);
        close(read_pipe[0]);
        close(error_pipe[0]);

        dup2(read_pipe[1], 1); close(read_pipe[1]);
        dup2(error_pipe[1], 2); close(error_pipe[1]);
        dup2(write_pipe[0], 0); close(write_pipe[0]);

        RegexIterator<StringView::iterator> it(cmdline.begin(), cmdline.end(), env_var_regex);
        RegexIterator<StringView::iterator> end;

        while (it != end)
        {
            auto& match = *it;

            StringView name = StringView(match[1].first, match[1].second);
            kak_assert(name.length() > 0);

            auto local_var = env_vars.find(name);
            if (local_var != env_vars.end())
                setenv(("kak_" + name).c_str(), local_var->second.c_str(), 1);
            else
            {
                try
                {
                    String value = get_val(name, context);
                    setenv(("kak_"_str + name).c_str(), value.c_str(), 1);
                }
                catch (runtime_error&) {}
            }

            ++it;
        }
        const char* shell = "/bin/sh";
        auto cmdlinezstr = cmdline.zstr();
        std::vector<const char*> execparams = { shell, "-c", cmdlinezstr };
        if (not params.empty())
            execparams.push_back(shell);
        for (auto& param : params)
            execparams.push_back(param.c_str());
        execparams.push_back(nullptr);

        execvp(shell, (char* const*)execparams.data());
        exit(-1);
    }
    catch (...) { exit(-1); }
    return output;
}

void ShellManager::register_env_var(StringView regex,
                                    EnvVarRetriever retriever)
{
    m_env_vars.push_back({ Regex(regex.begin(), regex.end()), std::move(retriever) });
}

String ShellManager::get_val(StringView name, const Context& context) const
{
    auto env_var = std::find_if(
        m_env_vars.begin(), m_env_vars.end(),
        [&](const std::pair<Regex, EnvVarRetriever>& pair)
        { return regex_match(name.begin(), name.end(), pair.first); });

    if (env_var == m_env_vars.end())
        throw runtime_error("no such env var: " + name);
    return env_var->second(name, context);
}

}
<commit_msg>Handle SIGCHLD signals when piping<commit_after>#include "shell_manager.hh"

#include "context.hh"
#include "debug.hh"
#include "event_manager.hh"
#include "file.hh"

#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

namespace Kakoune
{

static const Regex env_var_regex(R"(\bkak_(\w+)\b)");

ShellManager::ShellManager()
{
    const char* path = getenv("PATH");
    String new_path;
    if (path)
        new_path = path + ":"_str;

    String kak_path = get_kak_binary_path();
    StringView kak_dir = kak_path.substr(0_byte, (int)kak_path.find_last_of('/'));
    new_path += kak_dir;
    setenv("PATH", new_path.c_str(), 1);
}

String ShellManager::eval(StringView cmdline, const Context& context,
                          memoryview<String> params,
                          const EnvVarMap& env_vars,
                          int* exit_status)
{
    return pipe("", cmdline, context, params, env_vars, exit_status);
}

String ShellManager::pipe(StringView input,
                          StringView cmdline, const Context& context,
                          memoryview<String> params,
                          const EnvVarMap& env_vars,
                          int* exit_status)
{
    int write_pipe[2]; // child stdin
    int read_pipe[2];  // child stdout
    int error_pipe[2]; // child stderr

    ::pipe(write_pipe);
    ::pipe(read_pipe);
    ::pipe(error_pipe);

    static sig_atomic_t exited; exited = 0;
    static sig_atomic_t sig_exit_status;
    signal(SIGCHLD, [](int) { wait(&sig_exit_status); exited = 1; });

    String output;
    if (pid_t pid = fork())
    {
        close(write_pipe[0]);
        close(read_pipe[1]);
        close(error_pipe[1]);

        write(write_pipe[1], input.data(), (int)input.length());
        close(write_pipe[1]);

        String error;
        {
            auto pipe_reader = [](String& output, bool& closed) {
                return [&output, &closed](FDWatcher& watcher, EventMode) {
                    if (closed)
                        return;
                    const int fd = watcher.fd();
                    char buffer[1024];
                    size_t size = read(fd, buffer, 1024);
                    if (size <= 0)
                    {
                        close(fd);
                        closed = true;
                    }
                    output += String(buffer, buffer+size);
                };
            };

            bool stdout_closed = false, stderr_closed = false;
            FDWatcher stdout_watcher{read_pipe[0], pipe_reader(output, stdout_closed)};
            FDWatcher stderr_watcher{error_pipe[0], pipe_reader(error, stderr_closed)};

            while (not stdout_closed or not stderr_closed)
                EventManager::instance().handle_next_events(EventMode::Urgent);
        }

        if (not error.empty())
            write_debug("shell stderr: <<<\n" + error + ">>>");

        signal(SIGCHLD, SIG_DFL);

        if (not exited)
            waitpid(pid, exit_status, 0);
        else if (exit_status)
            *exit_status = sig_exit_status;

        if (exit_status)
        {
            if (WIFEXITED(*exit_status))
                *exit_status = WEXITSTATUS(*exit_status);
            else
                *exit_status = -1;
        }
    }
    else try
    {
        close(write_pipe[1]);
        close(read_pipe[0]);
        close(error_pipe[0]);

        dup2(read_pipe[1], 1); close(read_pipe[1]);
        dup2(error_pipe[1], 2); close(error_pipe[1]);
        dup2(write_pipe[0], 0); close(write_pipe[0]);

        RegexIterator<StringView::iterator> it(cmdline.begin(), cmdline.end(), env_var_regex);
        RegexIterator<StringView::iterator> end;

        while (it != end)
        {
            auto& match = *it;

            StringView name = StringView(match[1].first, match[1].second);
            kak_assert(name.length() > 0);

            auto local_var = env_vars.find(name);
            if (local_var != env_vars.end())
                setenv(("kak_" + name).c_str(), local_var->second.c_str(), 1);
            else
            {
                try
                {
                    String value = get_val(name, context);
                    setenv(("kak_"_str + name).c_str(), value.c_str(), 1);
                }
                catch (runtime_error&) {}
            }

            ++it;
        }
        const char* shell = "/bin/sh";
        auto cmdlinezstr = cmdline.zstr();
        std::vector<const char*> execparams = { shell, "-c", cmdlinezstr };
        if (not params.empty())
            execparams.push_back(shell);
        for (auto& param : params)
            execparams.push_back(param.c_str());
        execparams.push_back(nullptr);

        execvp(shell, (char* const*)execparams.data());
        exit(-1);
    }
    catch (...) { exit(-1); }
    return output;
}

void ShellManager::register_env_var(StringView regex,
                                    EnvVarRetriever retriever)
{
    m_env_vars.push_back({ Regex(regex.begin(), regex.end()), std::move(retriever) });
}

String ShellManager::get_val(StringView name, const Context& context) const
{
    auto env_var = std::find_if(
        m_env_vars.begin(), m_env_vars.end(),
        [&](const std::pair<Regex, EnvVarRetriever>& pair)
        { return regex_match(name.begin(), name.end(), pair.first); });

    if (env_var == m_env_vars.end())
        throw runtime_error("no such env var: " + name);
    return env_var->second(name, context);
}

}
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <std_msgs/String.h>
#include <geometry_msgs/PointStamped.h>
#include <geometry_msgs/PoseStamped.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <actionlib/client/simple_action_client.h>
#include <tf/tf.h>
#include <tf/transform_listener.h>

#include <yaml-cpp/yaml.h>

#include <vector>
#include <fstream>
#include <string>

class WaypointsNavigation{
public:
    WaypointsNavigation() :
        has_activate_(false),
        move_base_action_("move_base", true),
        rate_(10)
    {
        while((move_base_action_.waitForServer(ros::Duration(1.0)) == false) && (ros::ok() == true))
        {
            ROS_INFO("Waiting...");
        }

        ros::NodeHandle private_nh("~");
        private_nh.param("robot_frame", robot_frame_, std::string("/base_link"));
        private_nh.param("world_frame", world_frame_, std::string("/map"));

        double max_update_rate;
        private_nh.param("max_update_rate", max_update_rate, 10.0);
        rate_ = ros::Rate(max_update_rate);
        std::string filename = "";
        private_nh.param("filename", filename, filename);
        if(filename != ""){
            ROS_INFO_STREAM("Read waypoints data from " << filename);
            readFile(filename);
        }
        for(int i=0; i < waypoints_.size(); i++){
            ROS_INFO_STREAM("waypoints \n" << waypoints_[i]);
        }
        ros::NodeHandle nh;

        syscommand_sub_ = nh.subscribe("syscommand", 1, &WaypointsNavigation::syscommandCallback, this);
    }

    void syscommandCallback(const std_msgs::String &msg){
        if(msg.data == "start"){
            has_activate_ = true;
        }
    }

    bool readFile(const std::string &filename){
        waypoints_.clear();
        try{
            std::ifstream ifs(filename.c_str(), std::ifstream::in);
            if(ifs.good() == false){
                return false;
            }

            YAML::Node node;
            node = YAML::Load(ifs);
            const YAML::Node &wp_node_tmp = node["waypoints"];
            const YAML::Node *wp_node = wp_node_tmp ? &wp_node_tmp : NULL;
            if(wp_node != NULL){
                for(int i=0; i < wp_node->size(); i++){
                    geometry_msgs::PointStamped point;

                    point.point.x = (*wp_node)[i]["point"]["x"].as<double>();
                    point.point.y = (*wp_node)[i]["point"]["y"].as<double>();
                    point.point.z = (*wp_node)[i]["point"]["z"].as<double>();

                    waypoints_.push_back(point);

                }
            }else{
                return false;
            }

            const YAML::Node &fp_node_tmp = node["finish_pose"];
            const YAML::Node *fp_node = fp_node_tmp ? &fp_node_tmp : NULL;

            if(fp_node != NULL){
                finish_pose_.position.x = (*fp_node)["pose"]["position"]["x"].as<double>();
                finish_pose_.position.y = (*fp_node)["pose"]["position"]["y"].as<double>();
                finish_pose_.position.z = (*fp_node)["pose"]["position"]["z"].as<double>();

                finish_pose_.orientation.x = (*fp_node)["pose"]["orientation"]["x"].as<double>();
                finish_pose_.orientation.y = (*fp_node)["pose"]["orientation"]["y"].as<double>();
                finish_pose_.orientation.z = (*fp_node)["pose"]["orientation"]["z"].as<double>();
                finish_pose_.orientation.w = (*fp_node)["pose"]["orientation"]["w"].as<double>();
            }else{
                return false;
            }

        }catch(YAML::ParserException &e){
            return false;

        }catch(YAML::RepresentationException &e){
            return false;
        }

        return true;
    }

    bool shouldSendGoal(){
        bool ret = true;
        actionlib::SimpleClientGoalState state = move_base_action_.getState();
        if((state != actionlib::SimpleClientGoalState::ACTIVE) &&
           (state != actionlib::SimpleClientGoalState::PENDING) &&
           (state != actionlib::SimpleClientGoalState::RECALLED) &&
           (state != actionlib::SimpleClientGoalState::PREEMPTED))
        {
            ret = false;
        }

        if(waypoints_.empty()){
            ret = false;
        }

        return ret;
    }

    bool navigationFinished(){
        return move_base_action_.getState() == actionlib::SimpleClientGoalState::SUCCEEDED;
    }

    bool onNavigationPoint(const geometry_msgs::Point &dest, double dist_err = 0.5){
        tf::StampedTransform robot_gl;
        try{
            tf_listener_.lookupTransform(world_frame_, robot_frame_, ros::Time(0.0), robot_gl);
        }catch(tf::TransformException &e){
            ROS_WARN_STREAM("tf::TransformException: " << e.what());
        }
        const double wx = dest.x;
        const double wy = dest.y;
        const double rx = robot_gl.getOrigin().x();
        const double ry = robot_gl.getOrigin().y();
        const double dist = std::sqrt(std::pow(wx - rx, 2) + std::pow(wy - ry, 2));

        return dist < dist_err;
    }

    void sleep(){
        rate_.sleep();
        ros::spinOnce();
    }

    void startNavigationGL(const geometry_msgs::Point &dest){
        geometry_msgs::Pose pose;
        pose.position = dest;
        pose.orientation = tf::createQuaternionMsgFromYaw(0.0);
        startNavigationGL(pose);
    }

    void startNavigationGL(const geometry_msgs::Pose &dest){
        move_base_msgs::MoveBaseGoal move_base_goal;
        move_base_goal.target_pose.header.stamp = ros::Time::now();
        move_base_goal.target_pose.header.frame_id = world_frame_;
        move_base_goal.target_pose.pose.position = dest.position;
        move_base_goal.target_pose.pose.orientation = dest.orientation;

        move_base_action_.sendGoal(move_base_goal);
    }

    void run(){
        while(ros::ok()){
            if(has_activate_){
                for(int i=0; i < waypoints_.size(); i++){
                    ROS_INFO_STREAM("waypoint = " << waypoints_[i]);
                    if(!ros::ok()) break;

                    startNavigationGL(waypoints_[i].point);
                    while(!onNavigationPoint(waypoints_[i].point)) sleep();
                }
                waypoints_.clear();
                startNavigationGL(finish_pose_);
                while(!navigationFinished() && ros::ok()) sleep();
                has_activate_ = false;
            }

            sleep();
        }
    }

private:
    actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> move_base_action_;
    std::vector<geometry_msgs::PointStamped> waypoints_;
    geometry_msgs::Pose finish_pose_;
    bool has_activate_;
    std::string robot_frame_, world_frame_;
    tf::TransformListener tf_listener_;
    ros::Rate rate_;
    ros::Subscriber syscommand_sub_;
};

int main(int argc, char *argv[]){
    ros::init(argc, argv, ROS_PACKAGE_NAME);
    WaypointsNavigation w_nav;
    w_nav.run();

    return 0;
}
<commit_msg>Avoid error that the 'Aborting because a valid plan could not be found'<commit_after>#include <ros/ros.h>
#include <std_msgs/String.h>
#include <geometry_msgs/PointStamped.h>
#include <geometry_msgs/PoseStamped.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <actionlib/client/simple_action_client.h>
#include <tf/tf.h>
#include <tf/transform_listener.h>

#include <yaml-cpp/yaml.h>

#include <vector>
#include <fstream>
#include <string>

class WaypointsNavigation{
public:
    WaypointsNavigation() :
        has_activate_(false),
        move_base_action_("move_base", true),
        rate_(10)
    {
        while((move_base_action_.waitForServer(ros::Duration(1.0)) == false) && (ros::ok() == true))
        {
            ROS_INFO("Waiting...");
        }

        ros::NodeHandle private_nh("~");
        private_nh.param("robot_frame", robot_frame_, std::string("/base_link"));
        private_nh.param("world_frame", world_frame_, std::string("/map"));

        double max_update_rate;
        private_nh.param("max_update_rate", max_update_rate, 10.0);
        rate_ = ros::Rate(max_update_rate);
        std::string filename = "";
        private_nh.param("filename", filename, filename);
        if(filename != ""){
            ROS_INFO_STREAM("Read waypoints data from " << filename);
            readFile(filename);
        }
        for(int i=0; i < waypoints_.size(); i++){
            ROS_INFO_STREAM("waypoints \n" << waypoints_[i]);
        }
        ros::NodeHandle nh;

        syscommand_sub_ = nh.subscribe("syscommand", 1, &WaypointsNavigation::syscommandCallback, this);
    }

    void syscommandCallback(const std_msgs::String &msg){
        if(msg.data == "start"){
            has_activate_ = true;
        }
    }

    bool readFile(const std::string &filename){
        waypoints_.clear();
        try{
            std::ifstream ifs(filename.c_str(), std::ifstream::in);
            if(ifs.good() == false){
                return false;
            }

            YAML::Node node;
            node = YAML::Load(ifs);
            const YAML::Node &wp_node_tmp = node["waypoints"];
            const YAML::Node *wp_node = wp_node_tmp ? &wp_node_tmp : NULL;
            if(wp_node != NULL){
                for(int i=0; i < wp_node->size(); i++){
                    geometry_msgs::PointStamped point;

                    point.point.x = (*wp_node)[i]["point"]["x"].as<double>();
                    point.point.y = (*wp_node)[i]["point"]["y"].as<double>();
                    point.point.z = (*wp_node)[i]["point"]["z"].as<double>();

                    waypoints_.push_back(point);

                }
            }else{
                return false;
            }

            const YAML::Node &fp_node_tmp = node["finish_pose"];
            const YAML::Node *fp_node = fp_node_tmp ? &fp_node_tmp : NULL;

            if(fp_node != NULL){
                finish_pose_.position.x = (*fp_node)["pose"]["position"]["x"].as<double>();
                finish_pose_.position.y = (*fp_node)["pose"]["position"]["y"].as<double>();
                finish_pose_.position.z = (*fp_node)["pose"]["position"]["z"].as<double>();

                finish_pose_.orientation.x = (*fp_node)["pose"]["orientation"]["x"].as<double>();
                finish_pose_.orientation.y = (*fp_node)["pose"]["orientation"]["y"].as<double>();
                finish_pose_.orientation.z = (*fp_node)["pose"]["orientation"]["z"].as<double>();
                finish_pose_.orientation.w = (*fp_node)["pose"]["orientation"]["w"].as<double>();
            }else{
                return false;
            }

        }catch(YAML::ParserException &e){
            return false;

        }catch(YAML::RepresentationException &e){
            return false;
        }

        return true;
    }

    bool shouldSendGoal(){
        bool ret = true;
        actionlib::SimpleClientGoalState state = move_base_action_.getState();
        if((state != actionlib::SimpleClientGoalState::ACTIVE) &&
           (state != actionlib::SimpleClientGoalState::PENDING) &&
           (state != actionlib::SimpleClientGoalState::RECALLED) &&
           (state != actionlib::SimpleClientGoalState::PREEMPTED))
        {
            ret = false;
        }

        if(waypoints_.empty()){
            ret = false;
        }

        return ret;
    }

    bool navigationFinished(){
        return move_base_action_.getState() == actionlib::SimpleClientGoalState::SUCCEEDED;
    }

    bool onNavigationPoint(const geometry_msgs::Point &dest, double dist_err = 0.5){
        tf::StampedTransform robot_gl;
        try{
            tf_listener_.lookupTransform(world_frame_, robot_frame_, ros::Time(0.0), robot_gl);
        }catch(tf::TransformException &e){
            ROS_WARN_STREAM("tf::TransformException: " << e.what());
        }
        const double wx = dest.x;
        const double wy = dest.y;
        const double rx = robot_gl.getOrigin().x();
        const double ry = robot_gl.getOrigin().y();
        const double dist = std::sqrt(std::pow(wx - rx, 2) + std::pow(wy - ry, 2));

        return dist < dist_err;
    }

    void sleep(){
        rate_.sleep();
        ros::spinOnce();
    }

    void startNavigationGL(const geometry_msgs::Point &dest){
        geometry_msgs::Pose pose;
        pose.position = dest;
        pose.orientation = tf::createQuaternionMsgFromYaw(0.0);
        startNavigationGL(pose);
    }

    void startNavigationGL(const geometry_msgs::Pose &dest){
        move_base_msgs::MoveBaseGoal move_base_goal;
        move_base_goal.target_pose.header.stamp = ros::Time::now();
        move_base_goal.target_pose.header.frame_id = world_frame_;
        move_base_goal.target_pose.pose.position = dest.position;
        move_base_goal.target_pose.pose.orientation = dest.orientation;

        move_base_action_.sendGoal(move_base_goal);
    }

    void run(){
        while(ros::ok()){
            if(has_activate_){
                for(int i=0; i < waypoints_.size(); i++){
                    ROS_INFO_STREAM("waypoint = " << waypoints_[i]);
                    if(!ros::ok()) break;

                    startNavigationGL(waypoints_[i].point);
                    double start_nav_time = ros::Time::now().toSec();
                    while(!onNavigationPoint(waypoints_[i].point)){
                        if(ros::Time::now().toSec() - start_nav_time > 10.0){
                            ROS_INFO("Resend the navigation goal.");
                            startNavigationGL(waypoints_[i].point);
                            start_nav_time = ros::Time::now().toSec();
                        }
                        actionlib::SimpleClientGoalState state = move_base_action_.getState();
                        sleep();
                    }
                    ROS_INFO("waypoint goal");
                }
                ROS_INFO("waypoints clear");
                waypoints_.clear();
                startNavigationGL(finish_pose_);
                while(!navigationFinished() && ros::ok()) sleep();
                has_activate_ = false;
            }

            sleep();
        }
    }

private:
    actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> move_base_action_;
    std::vector<geometry_msgs::PointStamped> waypoints_;
    geometry_msgs::Pose finish_pose_;
    bool has_activate_;
    std::string robot_frame_, world_frame_;
    tf::TransformListener tf_listener_;
    ros::Rate rate_;
    ros::Subscriber syscommand_sub_;
};

int main(int argc, char *argv[]){
    ros::init(argc, argv, ROS_PACKAGE_NAME);
    WaypointsNavigation w_nav;
    w_nav.run();

    return 0;
}
<|endoftext|>


<commit_before>//
//  trace.cpp
//  kuma
//
//  Created by Fengping Bao <jamol@live.com> on 11/12/14.
//  Copyright (c) 2014. All rights reserved.
//

#include "kmtrace.h"
#include "util.h"

#include <stdio.h>
#include <stdarg.h>
#include <thread>
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <chrono>

#ifdef KUMA_OS_WIN
# include <Windows.h>
#endif

KUMA_NS_BEGIN

#ifdef KUMA_OS_WIN
#define VSNPRINTF(d, dl, fmt, ...)    _vsnprintf_s(d, dl, _TRUNCATE, fmt, ##__VA_ARGS__)
#define LOCALTIME_R(timep, result) localtime_s(result, timep)
#else
#define VSNPRINTF   vsnprintf
#define LOCALTIME_R localtime_r
#endif

std::function<void(int, const char*)> trace_func;
void setTraceFunc(std::function<void(int, const char*)> func)
{
    trace_func = func;
}

void TracePrint(int level, const char* szMessage, ...)
{
    va_list VAList;
    char szMsgBuf[2048] = {0};
    va_start(VAList, szMessage);
    VSNPRINTF(szMsgBuf, sizeof(szMsgBuf)-1, szMessage, VAList);

    std::stringstream ss;

    auto now_p = std::chrono::system_clock::now();
    auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now_p.time_since_epoch());
    auto now_c = std::chrono::system_clock::to_time_t(now_p);
    struct tm tm_buf;
    LOCALTIME_R(&now_c, &tm_buf);
    ss << std::put_time(&tm_buf, "%F %T.");
    ss.width(3);
    ss.fill('0');
    ss << (now_ms.count()%1000);
    switch(level)
    {
        case KUMA_TRACE_LEVEL_INFO:
            ss << " INFO: ";
            break;
        case KUMA_TRACE_LEVEL_WARN:
            ss << " WARN: ";
            break;
        case KUMA_TRACE_LEVEL_ERROR:
            ss << " ERROR: ";
            break;
        case KUMA_TRACE_LEVEL_DEBUG:
            ss << " DEBUG: ";
            break;
        default:
            ss << " INFO: ";
            break;
    }
    ss << "[" << getCurrentThreadId() << "] " << szMsgBuf;
    if (trace_func) {
        trace_func(level, ss.str().c_str());
    } else {
#ifdef KUMA_OS_WIN
        OutputDebugString(ss.str().c_str());
#else
        printf("%s\n", ss.str().c_str());
#endif
    }
}

KUMA_NS_END
<commit_msg>remove date on log since most of log tool will print date automatically<commit_after>//
//  trace.cpp
//  kuma
//
//  Created by Fengping Bao <jamol@live.com> on 11/12/14.
//  Copyright (c) 2014. All rights reserved.
//

#include "kmtrace.h"
#include "util.h"

#include <stdio.h>
#include <stdarg.h>
#include <thread>
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <chrono>

#ifdef KUMA_OS_WIN
# include <Windows.h>
#endif

KUMA_NS_BEGIN

#ifdef KUMA_OS_WIN
#define VSNPRINTF(d, dl, fmt, ...)    _vsnprintf_s(d, dl, _TRUNCATE, fmt, ##__VA_ARGS__)
#define LOCALTIME_R(timep, result) localtime_s(result, timep)
#else
#define VSNPRINTF   vsnprintf
#define LOCALTIME_R localtime_r
#endif

std::function<void(int, const char*)> trace_func;
void setTraceFunc(std::function<void(int, const char*)> func)
{
    trace_func = func;
}

void TracePrint(int level, const char* szMessage, ...)
{
    va_list VAList;
    char szMsgBuf[2048] = {0};
    va_start(VAList, szMessage);
    VSNPRINTF(szMsgBuf, sizeof(szMsgBuf)-1, szMessage, VAList);

    std::stringstream ss;

    /*auto now_p = std::chrono::system_clock::now();
    auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now_p.time_since_epoch());
    auto now_c = std::chrono::system_clock::to_time_t(now_p);
    struct tm tm_buf;
    LOCALTIME_R(&now_c, &tm_buf);
    ss << std::put_time(&tm_buf, "%F %T.");
    ss.width(3);
    ss.fill('0');
    ss << (now_ms.count()%1000) << " ";*/
    switch(level)
    {
        case KUMA_TRACE_LEVEL_INFO:
            ss << "INFO: ";
            break;
        case KUMA_TRACE_LEVEL_WARN:
            ss << "WARN: ";
            break;
        case KUMA_TRACE_LEVEL_ERROR:
            ss << "ERROR: ";
            break;
        case KUMA_TRACE_LEVEL_DEBUG:
            ss << "DEBUG: ";
            break;
        default:
            ss << "INFO: ";
            break;
    }
    ss << "[" << getCurrentThreadId() << "] " << szMsgBuf;
    if (trace_func) {
        trace_func(level, ss.str().c_str());
    } else {
#ifdef KUMA_OS_WIN
        OutputDebugString(ss.str().c_str());
#else
        printf("%s\n", ss.str().c_str());
#endif
    }
}

KUMA_NS_END
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// libevent_server.cpp
//
// Identification: src/wire/libevent_server.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//
#include <fstream>
#include "wire/libevent_server.h"
#include "common/macros.h"
#include "common/init.h"
#include "common/config.h"
#include "common/thread_pool.h"
#include <fcntl.h>
#include <sys/socket.h>

namespace peloton {
namespace wire {

std::vector<std::unique_ptr<LibeventSocket>> &
LibeventServer::GetGlobalSocketList() {
  static std::vector<std::unique_ptr<LibeventSocket>>
      // 2 fd's per thread for pipe and 1 listening socket
      global_socket_list(FLAGS_max_connections +
                         QUERY_THREAD_COUNT * 2 + 1);
  return global_socket_list;
}

LibeventSocket *LibeventServer::GetConn(const int &connfd) {
  auto &global_socket_list = GetGlobalSocketList();
  return global_socket_list[connfd].get();
}

void LibeventServer::CreateNewConn(const int &connfd, short ev_flags,
                                   LibeventThread *thread,
                                   ConnState init_state) {
  auto &global_socket_list = GetGlobalSocketList();
  global_socket_list[connfd]
      .reset(new LibeventSocket(connfd, ev_flags, thread, init_state));
}

/**
 * Stop signal handling
 */
void Signal_Callback(UNUSED_ATTRIBUTE evutil_socket_t fd,
                     UNUSED_ATTRIBUTE short what, void *arg) {
  struct event_base *base = (event_base *)arg;
  LOG_INFO("stop");
  event_base_loopexit(base, NULL);
}

LibeventServer::LibeventServer() {
  struct event_base *base = event_base_new();
  struct event *evstop;

  // Create our event base
  if (!base) {
    LOG_INFO("Couldn't open event base");
    exit(EXIT_FAILURE);
  }
  // Add hang up signal event
  evstop = evsignal_new(base, SIGHUP, Signal_Callback, base);
  evsignal_add(evstop, NULL);

  // TODO: Make pool size a global
  std::shared_ptr<LibeventThread> master_thread(
      new LibeventMasterThread(QUERY_THREAD_COUNT, base));

  port_ = FLAGS_port;
  max_connections_ = FLAGS_max_connections;

  // For logging purposes
  //  event_enable_debug_mode();
  //  event_set_log_callback(LogCallback);

  // Commented because it's not in the libevent version we're using
  // When we upgrade this should be uncommented
  //  event_enable_debug_logging(EVENT_DBG_ALL);

  // Ignore the broken pipe signal
  // We don't want to exit on write when the client disconnects
  signal(SIGPIPE, SIG_IGN);

  if (FLAGS_socket_family == "AF_INET") {
    struct sockaddr_in sin;
    PL_MEMSET(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(port_);

    int listen_fd;

    listen_fd = socket(AF_INET, SOCK_STREAM, 0);

    if (listen_fd < 0) {
      LOG_ERROR("Failed to create listen socket");
      exit(EXIT_FAILURE);
    }

    int reuse = 1;
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));

    if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
      LOG_ERROR("Failed to bind");
      exit(EXIT_FAILURE);
    }

    int conn_backlog = 12;
    if (listen(listen_fd, conn_backlog) < 0) {
      LOG_ERROR("Failed to listen to socket");
      exit(EXIT_FAILURE);
    }

    LibeventServer::CreateNewConn(listen_fd, EV_READ | EV_PERSIST,
                                  master_thread.get(), CONN_LISTENING);

    event_base_dispatch(base);
    event_free(evstop);
    event_base_free(base);
  }

  // This socket family code is not implemented yet
  else {
    LOG_ERROR("Unsupported socket family");
    exit(1);
  }
}
}
}
<commit_msg>We now tell you what port the system failed to bind on in LibeventServer #350<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// libevent_server.cpp
//
// Identification: src/wire/libevent_server.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//
#include "wire/libevent_server.h"
#include <fcntl.h>
#include <inttypes.h>
#include <sys/socket.h>
#include <fstream>
#include "common/config.h"
#include "common/init.h"
#include "common/macros.h"
#include "common/thread_pool.h"

namespace peloton {
namespace wire {

std::vector<std::unique_ptr<LibeventSocket>>
    &LibeventServer::GetGlobalSocketList() {
  static std::vector<std::unique_ptr<LibeventSocket>>
      // 2 fd's per thread for pipe and 1 listening socket
      global_socket_list(FLAGS_max_connections + QUERY_THREAD_COUNT * 2 + 1);
  return global_socket_list;
}

LibeventSocket *LibeventServer::GetConn(const int &connfd) {
  auto &global_socket_list = GetGlobalSocketList();
  return global_socket_list[connfd].get();
}

void LibeventServer::CreateNewConn(const int &connfd, short ev_flags,
                                   LibeventThread *thread,
                                   ConnState init_state) {
  auto &global_socket_list = GetGlobalSocketList();
  global_socket_list[connfd].reset(
      new LibeventSocket(connfd, ev_flags, thread, init_state));
}

/**
 * Stop signal handling
 */
void Signal_Callback(UNUSED_ATTRIBUTE evutil_socket_t fd,
                     UNUSED_ATTRIBUTE short what, void *arg) {
  struct event_base *base = (event_base *)arg;
  LOG_INFO("stop");
  event_base_loopexit(base, NULL);
}

LibeventServer::LibeventServer() {
  struct event_base *base = event_base_new();
  struct event *evstop;

  // Create our event base
  if (!base) {
    LOG_INFO("Couldn't open event base");
    exit(EXIT_FAILURE);
  }
  // Add hang up signal event
  evstop = evsignal_new(base, SIGHUP, Signal_Callback, base);
  evsignal_add(evstop, NULL);

  // TODO: Make pool size a global
  std::shared_ptr<LibeventThread> master_thread(
      new LibeventMasterThread(QUERY_THREAD_COUNT, base));

  port_ = FLAGS_port;
  max_connections_ = FLAGS_max_connections;

  // For logging purposes
  //  event_enable_debug_mode();
  //  event_set_log_callback(LogCallback);

  // Commented because it's not in the libevent version we're using
  // When we upgrade this should be uncommented
  //  event_enable_debug_logging(EVENT_DBG_ALL);

  // Ignore the broken pipe signal
  // We don't want to exit on write when the client disconnects
  signal(SIGPIPE, SIG_IGN);

  if (FLAGS_socket_family == "AF_INET") {
    struct sockaddr_in sin;
    PL_MEMSET(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(port_);

    int listen_fd;

    listen_fd = socket(AF_INET, SOCK_STREAM, 0);

    if (listen_fd < 0) {
      LOG_ERROR("Failed to create listen socket");
      exit(EXIT_FAILURE);
    }

    int reuse = 1;
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));

    if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
      LOG_ERROR("Failed to bind socket to port %" PRIu64, port_);
      exit(EXIT_FAILURE);
    }

    int conn_backlog = 12;
    if (listen(listen_fd, conn_backlog) < 0) {
      LOG_ERROR("Failed to listen to socket");
      exit(EXIT_FAILURE);
    }

    LibeventServer::CreateNewConn(listen_fd, EV_READ | EV_PERSIST,
                                  master_thread.get(), CONN_LISTENING);

    event_base_dispatch(base);
    event_free(evstop);
    event_base_free(base);
  }

  // This socket family code is not implemented yet
  else {
    LOG_ERROR("Unsupported socket family");
    exit(1);
  }
}
}
}
<|endoftext|>


<commit_before>/*
 * v8cgi main file. Loosely based on V8's "shell" sample app.
 */

#define _STRING(x) #x
#define STRING(x) _STRING(x)

#include <sstream>
#include <stdlib.h>
#include <v8.h>
#include <map>

#ifdef FASTCGI
#  include <fcgi_stdio.h>
#endif

#include "js_system.h"
#include "js_io.h"
#include "js_socket.h"
#include "js_common.h"
#include "js_macros.h"
#include "js_cache.h"

#ifndef windows
#   include <dlfcn.h>
#else
#   include <windows.h>
#   define dlsym(x,y) (void*)GetProcAddress((HMODULE)x,y)
#endif

// chdir()
#ifndef HAVE_CHDIR
#	include <direct.h>
#	define chdir(name) _chdir(name)
#endif

// getcwd()
#ifndef HAVE_GETCWD
#	include <direct.h>
#	define getcwd(name, bytes) _getcwd(name, bytes)
#endif

v8::Handle<v8::Array> __onexit; /* what to do on exit */
const char * cfgfile = NULL; /* config file */
const char * execfile = NULL; /* command-line specified file */
Cache cache;

int total = 0; /* fcgi debug */

void js_error(const char * message) {
	int cgi = 0;
	v8::Local<v8::Function> fun;
	v8::Local<v8::Value> context = v8::Context::GetCurrent()->Global()->Get(JS_STR("response"));
	if (context->IsObject()) {
		v8::Local<v8::Value> print = context->ToObject()->Get(JS_STR("error"));
		if (print->IsObject()) {
			fun = v8::Local<v8::Function>::Cast(print);
			cgi = 1;
		}
	}
	if (!cgi) {
		context = v8::Context::GetCurrent()->Global()->Get(JS_STR("System"));
		fun = v8::Local<v8::Function>::Cast(context->ToObject()->Get(JS_STR("stdout")));
	}

	v8::Handle<v8::Value> data[1];
	data[0] = JS_STR(message);
	fun->Call(context->ToObject(), 1, data);
}

void js_exception(v8::TryCatch* try_catch) {
	v8::HandleScope handle_scope;
	v8::String::Utf8Value exception(try_catch->Exception());
	v8::Handle<v8::Message> message = try_catch->Message();
	std::string msgstring = "";
	std::stringstream ss;

	if (message.IsEmpty()) {
		msgstring += *exception;
		msgstring += "\n";
	} else {
		v8::String::Utf8Value filename(message->GetScriptResourceName());
		int linenum = message->GetLineNumber();
		msgstring += *filename;
		msgstring += ":";
		ss << linenum;
		msgstring += ss.str();
		msgstring += ": ";
		msgstring += *exception;
		msgstring += "\n";
	}

	js_error(msgstring.c_str());
}

v8::Handle<v8::String> js_read(const char* name) {
	std::string n = name;
	std::string source = cache.getJS(n);
	return JS_STR(source.c_str());
}

int js_execute(const char * str, bool change) {
	v8::HandleScope handle_scope;
	v8::TryCatch try_catch;
	v8::Handle<v8::String> name = JS_STR(str);
	v8::Handle<v8::String> source = js_read(str);

	if (source.IsEmpty()) {
		std::string s = "Error reading '";
		s += str;
		s += "'\n";
		js_error(s.c_str());
		return 1;
	}

	v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
	if (script.IsEmpty()) {
		js_exception(&try_catch);
		return 1;
	} else {
		std::string oldcwd = getcwd(NULL, 0);
		std::string newcwd = str;
		size_t pos = newcwd.find_last_of('/');
		if (pos == std::string::npos) { pos = newcwd.find_last_of('\\'); }
		if (pos != std::string::npos && change) {
			newcwd.erase(pos, newcwd.length()-pos);
    		chdir(newcwd.c_str());
		}

		v8::Handle<v8::Value> result = script->Run();

		if (change) { chdir(oldcwd.c_str()); }
		if (result.IsEmpty()) {
			js_exception(&try_catch);
			return 1;
		}
	}
	return 0;
}

int js_library(char * name) {
	v8::HandleScope handle_scope;
	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Value> prefix = config->ToObject()->Get(JS_STR("libraryPath"));
	v8::String::Utf8Value pfx(prefix);
	std::string path = "";
	std::string error;

	path += *pfx;
	path += "/";
	path += name;

	if (path.find(".so") != std::string::npos || path.find(".dll") != std::string::npos) {
		void * handle = cache.getHandle(path);
		if (handle == NULL) {
			error = "Cannot load shared library '";
			error += path;
			error += "'\n";
			js_error(error.c_str());
			return 1;
		}

		void (*func) (v8::Handle<v8::Object>);
		func = reinterpret_cast<void (*)(v8::Handle<v8::Object>)>(dlsym(handle, "init"));
		if (!func) {
			error = "Cannot initialize shared library '";
			error += path;
			error += "'\n";
			js_error(error.c_str());
			return 1;
		}

		func(v8::Context::GetCurrent()->Global());
		return 0;
	} else {
		return js_execute(path.c_str(), false);
	}
}

int js_autoload() {
	v8::HandleScope handle_scope;
	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Array> list = v8::Handle<v8::Array>::Cast(config->ToObject()->Get(JS_STR("libraryAutoload")));
	int cnt = list->Length();
	for (int i=0;i<cnt;i++) {
		v8::Handle<v8::Value> item = list->Get(JS_INT(i));
		v8::String::Utf8Value name(item);
		if (js_library(*name)) { return 1; }
	}
	return 0;
}

v8::Handle<v8::Value> _include(const v8::Arguments& args) {
	bool ok = true;
	int result;
	for (int i = 0; i < args.Length(); i++) {
		v8::HandleScope handle_scope;
		v8::String::Utf8Value file(args[i]);
		result = js_execute(*file, true);
		if (result != 0) { ok = false; }
	}
	return JS_BOOL(ok);
}

v8::Handle<v8::Value> _library(const v8::Arguments & args) {
	v8::HandleScope handle_scope;
	bool ok = true;
	int result;

	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Value> prefix = config->ToObject()->Get(JS_STR("libraryPath"));
	v8::String::Utf8Value pfx(prefix);

	for (int i = 0; i < args.Length(); i++) {
		v8::HandleScope handle_scope;
		v8::String::Utf8Value file(args[i]);
		result = js_library(*file);
		if (result != 0) { ok = false; }
	}
	return JS_BOOL(ok);
}

v8::Handle<v8::Value> _onexit(const v8::Arguments& args) {
	__onexit->Set(JS_INT(__onexit->Length()), args[0]);
	return v8::Undefined();
}

void main_terminate() {
}

void main_finish() {
	v8::HandleScope handle_scope;
	uint32_t max = __onexit->Length();
	v8::Handle<v8::Function> fun;
	for (unsigned int i=0;i<max;i++) {
		fun = v8::Handle<v8::Function>::Cast(__onexit->Get(JS_INT(i)));
		fun->Call(v8::Context::GetCurrent()->Global(), 0, NULL);
	}
}

int main_execute() {
	v8::HandleScope handle_scope;
	const char * name = execfile;

	if (name == NULL) { // try the PATH_TRANSLATED env var
		v8::Handle<v8::Value> sys = v8::Context::GetCurrent()->Global()->Get(JS_STR("System"));
		v8::Handle<v8::Value> env = sys->ToObject()->Get(JS_STR("env"));
		v8::Handle<v8::Value> pt = env->ToObject()->Get(JS_STR("PATH_TRANSLATED"));
		if (pt->IsString()) {
			v8::String::Utf8Value jsname(pt);
			name = *jsname;
		}
	}

	if (name == NULL) {
		js_error("Nothing to do.\n");
		return 1;
	} else {
		return js_execute(name, true);
	}

}

int main_prepare(char ** envp) {
	__onexit = v8::Array::New();
	v8::Handle<v8::Object> g = v8::Context::GetCurrent()->Global();
	g->Set(JS_STR("library"), v8::FunctionTemplate::New(_library)->GetFunction());
	g->Set(JS_STR("include"), v8::FunctionTemplate::New(_include)->GetFunction());
	g->Set(JS_STR("onexit"), v8::FunctionTemplate::New(_onexit)->GetFunction());
	g->Set(JS_STR("total"), JS_INT(total++));
	g->Set(JS_STR("global"), g);
	g->Set(JS_STR("Config"), v8::Object::New());

	setup_system(envp, g);
	setup_io(g);
	setup_socket(g);

	if (js_execute(cfgfile, false)) {
		js_error("Cannot load configuration, quitting...\n");
		return 1;
	}

	if (js_autoload()) {
		js_error("Cannot load default libraries, quitting...\n");
		return 1;
	}

	return 0;
}

int main_initialize(int argc, char ** argv) {
	v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
	cfgfile = STRING(CONFIG_PATH);

	int argptr = 0;
	for (int i = 1; i < argc; i++) {
		const char* str = argv[i];
		argptr = i;
		if (strcmp(str, "-c") == 0 && i + 1 < argc) {
			cfgfile = argv[i+1];
			argptr = 0;
			i++;
		}
	}

	if (argptr) { execfile = argv[argptr]; }

	FILE* file = fopen(cfgfile, "rb");
	if (file == NULL) {
		printf("Invalid configuration file.\n");
		return 1;
	}
	fclose(file);
	return 0;
}

int main_cycle(char ** envp) {
	int result = 0;
	v8::HandleScope handle_scope;
	v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
	v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
	v8::Context::Scope context_scope(context);

	result = main_prepare(envp);
	if (result == 0) {
		result = main_execute();
	}
	main_finish();
	return result;
}

int main(int argc, char ** argv, char ** envp) {
	int result = 0;
	result = main_initialize(argc, argv);
	if (result) { exit(1); }

#ifdef FASTCGI
	while(FCGI_Accept() >= 0) {
#endif

	result = main_cycle(envp);

#ifdef FASTCGI
	FCGI_SetExitStatus(result);
#endif

#ifdef FASTCGI
	}
#endif

	main_terminate();
	return result;
}
<commit_msg>main code cleanup<commit_after>/*
 * v8cgi main file. Loosely based on V8's "shell" sample app.
 */

#define _STRING(x) #x
#define STRING(x) _STRING(x)

#include <sstream>
#include <stdlib.h>
#include <v8.h>
#include <map>

#ifdef FASTCGI
#  include <fcgi_stdio.h>
#endif

#include "js_system.h"
#include "js_io.h"
#include "js_socket.h"
#include "js_common.h"
#include "js_macros.h"
#include "js_cache.h"

#ifndef windows
#   include <dlfcn.h>
#else
#   include <windows.h>
#   define dlsym(x,y) (void*)GetProcAddress((HMODULE)x,y)
#endif

// chdir()
#ifndef HAVE_CHDIR
#	include <direct.h>
#	define chdir(name) _chdir(name)
#endif

// getcwd()
#ifndef HAVE_GETCWD
#	include <direct.h>
#	define getcwd(name, bytes) _getcwd(name, bytes)
#endif

v8::Handle<v8::Array> __onexit; /* what to do on exit */
const char * cfgfile = NULL; /* config file */
const char * execfile = NULL; /* command-line specified file */
Cache cache;

int total = 0; /* fcgi debug */

void js_error(const char * message) {
	int cgi = 0;
	v8::Local<v8::Function> fun;
	v8::Local<v8::Value> context = v8::Context::GetCurrent()->Global()->Get(JS_STR("response"));
	if (context->IsObject()) {
		v8::Local<v8::Value> print = context->ToObject()->Get(JS_STR("error"));
		if (print->IsObject()) {
			fun = v8::Local<v8::Function>::Cast(print);
			cgi = 1;
		}
	}
	if (!cgi) {
		context = v8::Context::GetCurrent()->Global()->Get(JS_STR("System"));
		fun = v8::Local<v8::Function>::Cast(context->ToObject()->Get(JS_STR("stdout")));
	}

	v8::Handle<v8::Value> data[1];
	data[0] = JS_STR(message);
	fun->Call(context->ToObject(), 1, data);
}

void js_exception(v8::TryCatch* try_catch) {
	v8::HandleScope handle_scope;
	v8::String::Utf8Value exception(try_catch->Exception());
	v8::Handle<v8::Message> message = try_catch->Message();
	std::string msgstring = "";
	std::stringstream ss;

	if (message.IsEmpty()) {
		msgstring += *exception;
		msgstring += "\n";
	} else {
		v8::String::Utf8Value filename(message->GetScriptResourceName());
		int linenum = message->GetLineNumber();
		msgstring += *filename;
		msgstring += ":";
		ss << linenum;
		msgstring += ss.str();
		msgstring += ": ";
		msgstring += *exception;
		msgstring += "\n";
	}

	js_error(msgstring.c_str());
}

v8::Handle<v8::String> js_read(const char* name) {
	std::string n = name;
	std::string source = cache.getJS(n);
	return JS_STR(source.c_str());
}

int js_execute(const char * str, bool change) {
	v8::HandleScope handle_scope;
	v8::TryCatch try_catch;
	v8::Handle<v8::String> name = JS_STR(str);
	v8::Handle<v8::String> source = js_read(str);

	if (source.IsEmpty()) {
		std::string s = "Error reading '";
		s += str;
		s += "'\n";
		js_error(s.c_str());
		return 1;
	}

	v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
	if (script.IsEmpty()) {
		js_exception(&try_catch);
		return 1;
	} else {
		std::string oldcwd = getcwd(NULL, 0);
		std::string newcwd = str;
		size_t pos = newcwd.find_last_of('/');
		if (pos == std::string::npos) { pos = newcwd.find_last_of('\\'); }
		if (pos != std::string::npos && change) {
			newcwd.erase(pos, newcwd.length()-pos);
    		chdir(newcwd.c_str());
		}

		v8::Handle<v8::Value> result = script->Run();

		if (change) { chdir(oldcwd.c_str()); }
		if (result.IsEmpty()) {
			js_exception(&try_catch);
			return 1;
		}
	}
	return 0;
}

int js_library(char * name) {
	v8::HandleScope handle_scope;
	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Value> prefix = config->ToObject()->Get(JS_STR("libraryPath"));
	v8::String::Utf8Value pfx(prefix);
	std::string path = "";
	std::string error;

	path += *pfx;
	path += "/";
	path += name;

	if (path.find(".so") != std::string::npos || path.find(".dll") != std::string::npos) {
		void * handle = cache.getHandle(path);
		if (handle == NULL) {
			error = "Cannot load shared library '";
			error += path;
			error += "'\n";
			js_error(error.c_str());
			return 1;
		}

		void (*func) (v8::Handle<v8::Object>);
		func = reinterpret_cast<void (*)(v8::Handle<v8::Object>)>(dlsym(handle, "init"));
		if (!func) {
			error = "Cannot initialize shared library '";
			error += path;
			error += "'\n";
			js_error(error.c_str());
			return 1;
		}

		func(v8::Context::GetCurrent()->Global());
		return 0;
	} else {
		return js_execute(path.c_str(), false);
	}
}

int js_autoload() {
	v8::HandleScope handle_scope;
	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Array> list = v8::Handle<v8::Array>::Cast(config->ToObject()->Get(JS_STR("libraryAutoload")));
	int cnt = list->Length();
	for (int i=0;i<cnt;i++) {
		v8::Handle<v8::Value> item = list->Get(JS_INT(i));
		v8::String::Utf8Value name(item);
		if (js_library(*name)) { return 1; }
	}
	return 0;
}

JS_METHOD(_include) {
	bool ok = true;
	int result;
	for (int i = 0; i < args.Length(); i++) {
		v8::HandleScope handle_scope;
		v8::String::Utf8Value file(args[i]);
		result = js_execute(*file, true);
		if (result != 0) { ok = false; }
	}
	return JS_BOOL(ok);
}

JS_METHOD(_library) {
	v8::HandleScope handle_scope;
	bool ok = true;
	int result;

	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Value> prefix = config->ToObject()->Get(JS_STR("libraryPath"));
	v8::String::Utf8Value pfx(prefix);

	for (int i = 0; i < args.Length(); i++) {
		v8::HandleScope handle_scope;
		v8::String::Utf8Value file(args[i]);
		result = js_library(*file);
		if (result != 0) { ok = false; }
	}
	return JS_BOOL(ok);
}

JS_METHOD(_onexit) {
	__onexit->Set(JS_INT(__onexit->Length()), args[0]);
	return v8::Undefined();
}

void main_terminate() {
}

void main_finish() {
	v8::HandleScope handle_scope;
	uint32_t max = __onexit->Length();
	v8::Handle<v8::Function> fun;
	for (unsigned int i=0;i<max;i++) {
		fun = v8::Handle<v8::Function>::Cast(__onexit->Get(JS_INT(i)));
		fun->Call(v8::Context::GetCurrent()->Global(), 0, NULL);
	}
}

int main_execute() {
	v8::HandleScope handle_scope;
	const char * name = execfile;

	if (name == NULL) { // try the PATH_TRANSLATED env var
		v8::Handle<v8::Value> sys = v8::Context::GetCurrent()->Global()->Get(JS_STR("System"));
		v8::Handle<v8::Value> env = sys->ToObject()->Get(JS_STR("env"));
		v8::Handle<v8::Value> pt = env->ToObject()->Get(JS_STR("PATH_TRANSLATED"));
		if (pt->IsString()) {
			v8::String::Utf8Value jsname(pt);
			name = *jsname;
		}
	}

	if (name == NULL) {
		js_error("Nothing to do.\n");
		return 1;
	} else {
		return js_execute(name, true);
	}

}

int main_prepare(char ** envp) {
	__onexit = v8::Array::New();
	v8::Handle<v8::Object> g = v8::Context::GetCurrent()->Global();
	g->Set(JS_STR("library"), v8::FunctionTemplate::New(_library)->GetFunction());
	g->Set(JS_STR("include"), v8::FunctionTemplate::New(_include)->GetFunction());
	g->Set(JS_STR("onexit"), v8::FunctionTemplate::New(_onexit)->GetFunction());
	g->Set(JS_STR("total"), JS_INT(total++));
	g->Set(JS_STR("global"), g);
	g->Set(JS_STR("Config"), v8::Object::New());

	setup_system(envp, g);
	setup_io(g);
	setup_socket(g);

	if (js_execute(cfgfile, false)) {
		js_error("Cannot load configuration, quitting...\n");
		return 1;
	}

	if (js_autoload()) {
		js_error("Cannot load default libraries, quitting...\n");
		return 1;
	}

	return 0;
}

int main_initialize(int argc, char ** argv) {
	v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
	cfgfile = STRING(CONFIG_PATH);

	int argptr = 0;
	for (int i = 1; i < argc; i++) {
		const char* str = argv[i];
		argptr = i;
		if (strcmp(str, "-c") == 0 && i + 1 < argc) {
			cfgfile = argv[i+1];
			argptr = 0;
			i++;
		}
	}

	if (argptr) { execfile = argv[argptr]; }

	FILE* file = fopen(cfgfile, "rb");
	if (file == NULL) {
		printf("Invalid configuration file.\n");
		return 1;
	}
	fclose(file);
	return 0;
}

int main_cycle(char ** envp) {
	int result = 0;
	v8::HandleScope handle_scope;
	v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
	v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
	v8::Context::Scope context_scope(context);

	result = main_prepare(envp);
	if (result == 0) {
		result = main_execute();
	}
	main_finish();
	return result;
}

int main(int argc, char ** argv, char ** envp) {
	int result = 0;
	result = main_initialize(argc, argv);
	if (result) { exit(1); }

#ifdef FASTCGI
	while(FCGI_Accept() >= 0) {
#endif

	result = main_cycle(envp);

#ifdef FASTCGI
	FCGI_SetExitStatus(result);
#endif

#ifdef FASTCGI
	}
#endif

	main_terminate();
	return result;
}
<|endoftext|>


<commit_before>/*
 * IceWM
 *
 * Copyright (C) 1997-2001 Marko Macek
 */
#include "config.h"
#include "yfull.h"
#include "ypixbuf.h"
#include "ypaint.h"
#include "yicon.h"
#include "yapp.h"
#include "sysdep.h"
#include "prefs.h"
#include "yprefs.h"
#include "wmprog.h" // !!! remove this

#include "intl.h"

#ifndef LITE

static bool didInit = false;
static ref<YResourcePaths> iconPaths;

void initIcons() {
    if (!didInit) {
        didInit = true;
        iconPaths = YResourcePaths::subdirs("icons/");
    }
}

YIcon::YIcon(upath filename):
    fSmall(null), fLarge(null), fHuge(null),
    loadedS(false), loadedL(false), loadedH(false),
    fPath(filename), fCached(false)
{
}

YIcon::YIcon(ref<YImage> small, ref<YImage> large, ref<YImage> huge) :
    fSmall(small), fLarge(large), fHuge(huge),
    loadedS(small != null), loadedL(large != null), loadedH(huge != null),
    fPath(NULL), fCached(false)
{
}

YIcon::~YIcon() {
    fHuge = null;
    fLarge = null;
    fSmall = null;
}

static upath joinPath(upath dir, upath name) {
    if (dir == null)
        return name;

    if (name.isAbsolute())
        return name;

    return dir.relative(name);
}

upath YIcon::findIcon(upath dir, upath base, unsigned size) {
    char icons_size[1024];
    upath fullpath;

    fullpath = joinPath(dir, base);
    if (fullpath.fileExists())
        return fullpath;

    sprintf(icons_size, "%s_%dx%d.xpm", cstring(base.path()).c_str(), size, size);
    fullpath = joinPath(dir, icons_size);
    if (fullpath.fileExists())
        return fullpath;

    fullpath = joinPath(dir, base.addExtension("xpm"));
    if (fullpath.fileExists())
        return fullpath;

    fullpath = joinPath(dir, base.addExtension("png"));
    if (fullpath.fileExists())
        return fullpath;

    return 0;
}

upath YIcon::findIcon(int size) {
    cstring cs(fPath.path());
    initIcons();

    if (iconPath != 0 && iconPath[0] != 0) {
        for (char const *p = iconPath, *q = iconPath; *q; q = p) {
            while (*p && *p != PATHSEP) p++;

            unsigned len(p - q);
            if (*p) ++p;

            upath path = upath(newstr(q, len));

            upath fullpath = findIcon(path.path(), fPath, size);
            if (fullpath != null) {
                return fullpath;
            }
        }
    }

    for (int i = 0; i < iconPaths->getCount(); i++) {
        upath path = iconPaths->getPath(i)->joinPath(upath("/icons/"));
        upath fullpath = findIcon(path.path(), fPath, size);
        if (fullpath != null)
            return fullpath;
    }

    MSG(("Icon \"%s\" not found.", cs.c_str()));

    return null;
}

ref<YImage> YIcon::loadIcon(int size) {
    ref<YImage> icon;

    if (fPath != null) {
        upath fullPath;
        upath loadPath;

        if (fPath.isAbsolute() && fPath.fileExists()) {
            loadPath = fPath;
        } else {
            fullPath = findIcon(size);
            if (fullPath != null) {
                loadPath = fullPath;
            } else if (size != hugeSize() && (fullPath = findIcon(hugeSize())) != null) {
                loadPath = fullPath;
            } else if (size != largeSize() && (fullPath = findIcon(largeSize())) != null) {
                loadPath = fullPath;
            } else if (size != smallSize() && (fullPath = findIcon(smallSize())) != null) {
                loadPath = fullPath;
            }
        }
        if (loadPath != null) {
            cstring cs(loadPath.path());
            icon = YImage::load(cs.c_str());
            if (icon == null)
                warn(_("Out of memory for pixmap \"%s\""), cs.c_str());
        }
    }
#if 1
    if (icon != null) {
        icon = icon->scale(size, size);
    }
#endif
    return icon;
}

ref<YImage> YIcon::huge() {
    if (fHuge == null && !loadedH) {
        fHuge = loadIcon(hugeSize());
        loadedH = true;

	if (fHuge == null && large() != null)
            fHuge = large()->scale(hugeSize(), hugeSize());

	if (fHuge == null && small() != null)
            fHuge = small()->scale(hugeSize(), hugeSize());
    }

    return fHuge;
}

ref<YImage> YIcon::large() {
    if (fLarge == null && !loadedL) {
        fLarge = loadIcon(largeSize());
        loadedL = true;

	if (fLarge == null && huge() != null)
            fLarge = huge()->scale(largeSize(), largeSize());

	if (fLarge == null && small() != null)
	    fLarge = small()->scale(largeSize(), largeSize());
    }

    return fLarge;
}

ref<YImage> YIcon::small() {
    if (fSmall == null && !loadedS) {
        fSmall = loadIcon(smallSize());
        loadedS = true;

        if (fSmall == null && large() != null)
            fSmall = large()->scale(smallSize(), smallSize());
	if (fSmall == null && huge() != null)
            fSmall = huge()->scale(smallSize(), smallSize());
    }

    return fSmall;
}

ref<YImage> YIcon::getScaledIcon(int size) {
    ref<YImage> base = null;

#if 1
    if (size == smallSize())
        base = small();
    else if (size == largeSize())
        base = large();
    else if (size == hugeSize())
        base = huge();
#endif

    if (base == null)
        base = huge();
    if (base == null)
        base = large();
    if (base == null)
        base = small();

    if (base != null) {
        ref<YImage> img = base->scale(size, size);
        return img;
    }
    return base;
}

static YRefArray<YIcon> iconCache;

void YIcon::removeFromCache() {
    int n = cacheFind(iconName());
    if (n >= 0) {
        fPath = null;
        iconCache.remove(n);
    }
}

int YIcon::cacheFind(upath name) {
    int l, r, m;

    l = 0;
    r = iconCache.getCount();
    while (l < r) {
        m = (l + r) / 2;
        ref<YIcon> found = iconCache.getItem(m);
        int cmp = name.path().compareTo(found->iconName().path());
        if (cmp == 0) {
            return m;
        } else if (cmp < 0)
            r = m;
        else
            l = m + 1;
    }
    return -(l + 1);
}

ref<YIcon> YIcon::getIcon(const char *name) {
    int n = cacheFind(name);
    if (n >= 0)
        return iconCache.getItem(n);

    ref<YIcon>newicon;
    newicon.init(new YIcon(name));
    if (newicon != null) {
        newicon->setCached(true);
        iconCache.insert(-n - 1, newicon);
    }
    return getIcon(name);
}

void YIcon::freeIcons() {
    while (iconCache.getCount() > 0)
        iconCache.getItem(0)->removeFromCache();
}

int YIcon::smallSize() {
    return smallIconSize;
}

int YIcon::largeSize() {
    return largeIconSize;
}

int YIcon::hugeSize() {
    return hugeIconSize;
}

void YIcon::draw(Graphics &g, int x, int y, int size) {
    ref<YImage> image = getScaledIcon(size);
    if (image != null) {
        if (!doubleBuffer) {
            g.drawImage(image, x, y);
        } else {
            g.compositeImage(image, 0, 0, size, size, x, y);
        }
    }
}

#endif
<commit_msg>fix icon search (.xpm .png)<commit_after>/*
 * IceWM
 *
 * Copyright (C) 1997-2001 Marko Macek
 */
#include "config.h"
#include "yfull.h"
#include "ypixbuf.h"
#include "ypaint.h"
#include "yicon.h"
#include "yapp.h"
#include "sysdep.h"
#include "prefs.h"
#include "yprefs.h"
#include "wmprog.h" // !!! remove this

#include "intl.h"

#ifndef LITE

static bool didInit = false;
static ref<YResourcePaths> iconPaths;

void initIcons() {
    if (!didInit) {
        didInit = true;
        iconPaths = YResourcePaths::subdirs("icons/");
    }
}

YIcon::YIcon(upath filename):
    fSmall(null), fLarge(null), fHuge(null),
    loadedS(false), loadedL(false), loadedH(false),
    fPath(filename), fCached(false)
{
}

YIcon::YIcon(ref<YImage> small, ref<YImage> large, ref<YImage> huge) :
    fSmall(small), fLarge(large), fHuge(huge),
    loadedS(small != null), loadedL(large != null), loadedH(huge != null),
    fPath(NULL), fCached(false)
{
}

YIcon::~YIcon() {
    fHuge = null;
    fLarge = null;
    fSmall = null;
}

static upath joinPath(upath dir, upath name) {
    if (dir == null)
        return name;

    if (name.isAbsolute())
        return name;

    return dir.relative(name);
}

upath YIcon::findIcon(upath dir, upath base, unsigned size) {
    char icons_size[1024];
    upath fullpath;

    fullpath = joinPath(dir, base);
    if (fullpath.fileExists())
        return fullpath;

    sprintf(icons_size, "%s_%dx%d.xpm", cstring(base.path()).c_str(), size, size);
    fullpath = joinPath(dir, icons_size);
    if (fullpath.fileExists())
        return fullpath;

    fullpath = joinPath(dir, base.addExtension(".xpm"));
    if (fullpath.fileExists())
        return fullpath;

    fullpath = joinPath(dir, base.addExtension(".png"));
    if (fullpath.fileExists())
        return fullpath;

    return 0;
}

upath YIcon::findIcon(int size) {
    cstring cs(fPath.path());
    initIcons();

    if (iconPath != 0 && iconPath[0] != 0) {
        for (char const *p = iconPath, *q = iconPath; *q; q = p) {
            while (*p && *p != PATHSEP) p++;

            unsigned len(p - q);
            if (*p) ++p;

            upath path = upath(newstr(q, len));

            upath fullpath = findIcon(path.path(), fPath, size);
            if (fullpath != null) {
                return fullpath;
            }
        }
    }

    for (int i = 0; i < iconPaths->getCount(); i++) {
        upath path = iconPaths->getPath(i)->joinPath(upath("/icons/"));
        upath fullpath = findIcon(path.path(), fPath, size);
        if (fullpath != null)
            return fullpath;
    }

    MSG(("Icon \"%s\" not found.", cs.c_str()));

    return null;
}

ref<YImage> YIcon::loadIcon(int size) {
    ref<YImage> icon;

    if (fPath != null) {
        upath fullPath;
        upath loadPath;

        if (fPath.isAbsolute() && fPath.fileExists()) {
            loadPath = fPath;
        } else {
            fullPath = findIcon(size);
            if (fullPath != null) {
                loadPath = fullPath;
            } else if (size != hugeSize() && (fullPath = findIcon(hugeSize())) != null) {
                loadPath = fullPath;
            } else if (size != largeSize() && (fullPath = findIcon(largeSize())) != null) {
                loadPath = fullPath;
            } else if (size != smallSize() && (fullPath = findIcon(smallSize())) != null) {
                loadPath = fullPath;
            }
        }
        if (loadPath != null) {
            cstring cs(loadPath.path());
            icon = YImage::load(cs.c_str());
            if (icon == null)
                warn(_("Out of memory for pixmap \"%s\""), cs.c_str());
        }
    }
#if 1
    if (icon != null) {
        icon = icon->scale(size, size);
    }
#endif
    return icon;
}

ref<YImage> YIcon::huge() {
    if (fHuge == null && !loadedH) {
        fHuge = loadIcon(hugeSize());
        loadedH = true;

	if (fHuge == null && large() != null)
            fHuge = large()->scale(hugeSize(), hugeSize());

	if (fHuge == null && small() != null)
            fHuge = small()->scale(hugeSize(), hugeSize());
    }

    return fHuge;
}

ref<YImage> YIcon::large() {
    if (fLarge == null && !loadedL) {
        fLarge = loadIcon(largeSize());
        loadedL = true;

	if (fLarge == null && huge() != null)
            fLarge = huge()->scale(largeSize(), largeSize());

	if (fLarge == null && small() != null)
	    fLarge = small()->scale(largeSize(), largeSize());
    }

    return fLarge;
}

ref<YImage> YIcon::small() {
    if (fSmall == null && !loadedS) {
        fSmall = loadIcon(smallSize());
        loadedS = true;

        if (fSmall == null && large() != null)
            fSmall = large()->scale(smallSize(), smallSize());
	if (fSmall == null && huge() != null)
            fSmall = huge()->scale(smallSize(), smallSize());
    }

    return fSmall;
}

ref<YImage> YIcon::getScaledIcon(int size) {
    ref<YImage> base = null;

#if 1
    if (size == smallSize())
        base = small();
    else if (size == largeSize())
        base = large();
    else if (size == hugeSize())
        base = huge();
#endif

    if (base == null)
        base = huge();
    if (base == null)
        base = large();
    if (base == null)
        base = small();

    if (base != null) {
        ref<YImage> img = base->scale(size, size);
        return img;
    }
    return base;
}

static YRefArray<YIcon> iconCache;

void YIcon::removeFromCache() {
    int n = cacheFind(iconName());
    if (n >= 0) {
        fPath = null;
        iconCache.remove(n);
    }
}

int YIcon::cacheFind(upath name) {
    int l, r, m;

    l = 0;
    r = iconCache.getCount();
    while (l < r) {
        m = (l + r) / 2;
        ref<YIcon> found = iconCache.getItem(m);
        int cmp = name.path().compareTo(found->iconName().path());
        if (cmp == 0) {
            return m;
        } else if (cmp < 0)
            r = m;
        else
            l = m + 1;
    }
    return -(l + 1);
}

ref<YIcon> YIcon::getIcon(const char *name) {
    int n = cacheFind(name);
    if (n >= 0)
        return iconCache.getItem(n);

    ref<YIcon>newicon;
    newicon.init(new YIcon(name));
    if (newicon != null) {
        newicon->setCached(true);
        iconCache.insert(-n - 1, newicon);
    }
    return getIcon(name);
}

void YIcon::freeIcons() {
    while (iconCache.getCount() > 0)
        iconCache.getItem(0)->removeFromCache();
}

int YIcon::smallSize() {
    return smallIconSize;
}

int YIcon::largeSize() {
    return largeIconSize;
}

int YIcon::hugeSize() {
    return hugeIconSize;
}

void YIcon::draw(Graphics &g, int x, int y, int size) {
    ref<YImage> image = getScaledIcon(size);
    if (image != null) {
        if (!doubleBuffer) {
            g.drawImage(image, x, y);
        } else {
            g.compositeImage(image, 0, 0, size, size, x, y);
        }
    }
}

#endif
<|endoftext|>


<commit_before>#include "get.h"

void tags(std::string location, std::string cover_folder, Library *library) {
  Local<Object> record = Nan::New<Object>();

  TagLib::FileRef f(location.c_str());
  TagLib::Tag *tag = f.tag();
  TagLib::AudioProperties *properties = f.audioProperties();

  TagLib::String title  = tag->title();
  TagLib::String artist = tag->artist();
  TagLib::String album  = tag->album();
  TagLib::String genre  = tag->genre();

  // Set the default title based on the file's location
  // if there's no tags for the file.
  if (!title.length()) {
    std::string::size_type slash  = location.rfind('/');
    std::string::size_type dot    = location.rfind('.');

    std::string default_title = location.substr(slash+1, dot - slash - 1);

    for (std::string::iterator it = default_title.begin(); it != default_title.end(); it++)
      title += *it;
  }

  record->Set(string("title"),    string(title.toCString(true)));
  record->Set(string("artist"),   string(artist.toCString(true)));
  record->Set(string("genre"),    string(genre.toCString(true)));
  record->Set(string("id"),       string(location));
  record->Set(string("track"),    Nan::New(tag->track()));
  record->Set(string("duration"), Nan::New(properties->length()));

  if (cover_folder.length())
    extractPicture(location, cover_folder, title, album, artist, record);

  if (album.length())
    library->AddTrack(artist.toCString(true), album.toCString(true), record);
  else
    library->AddSingle(artist.toCString(true), record);
}

void inline extractPicture(std::string location,  std::string cover_folder,
                           TagLib::String title,  TagLib::String album,
                           TagLib::String artist, Local<Object> record) {
  std::string extension = location.substr(location.length() - 3, 3);

  if (extension == "mp3")
    mp3Picture(location, cover_folder, record);
  else if (extension == "m4a")
    mp4Picture(location, cover_folder, record);
}

void mp3Picture(std::string location, std::string cover_folder, Local<Object> record) {
  TagLib::MPEG::File mp3_file(location.c_str());
  TagLib::ID3v2::Tag *mp3_tag = mp3_file.ID3v2Tag(true);
  TagLib::ID3v2::FrameList pictures = mp3_tag->frameList("APIC");

  if (pictures.isEmpty())
    return;

  TagLib::ID3v2::AttachedPictureFrame *picture_frame = static_cast<TagLib::ID3v2::AttachedPictureFrame *> (*pictures.begin());;

  unsigned int checksum = picture_frame->picture().checksum();

  std::stringstream path_stream;

  path_stream << cover_folder;
  path_stream << "/";
  path_stream << checksum;

  std::string img_path = path_stream.str();

  if (picture_frame->mimeType() == "image/png")
    img_path.append(".png");
  else
    img_path.append(".jpg");

  if (!exist(img_path)) {
    size_t image_size = picture_frame->picture().size();
    const char *data  = picture_frame->picture().data();
    FILE *cover_file  = fopen(img_path.c_str(), "wb");

    fwrite(data, image_size, 1, cover_file);
    fclose(cover_file);
  }

  record->Set(string("icon"), string(img_path));
}

void mp4Picture(std::string location, std::string cover_folder, Local<Object> record) {
  TagLib::MP4::File mp4_file(location.c_str());
  TagLib::MP4::Tag *mp4_tag = mp4_file.tag();

  if (!mp4_tag->contains("covr"))
    return;

  TagLib::MP4::CoverArtList covert_art_list = mp4_tag->item("covr").toCoverArtList();

  if (covert_art_list.isEmpty())
    return;

  TagLib::MP4::CoverArt cover_art = covert_art_list[0];

  unsigned int checksum = cover_art.data().checksum();

  std::stringstream path_stream;

  path_stream << cover_folder;
  path_stream << "/";
  path_stream << checksum;

  std::string img_path = path_stream.str();

  img_path.append(".jpg");

  if (!exist(img_path)) {
    size_t image_size = cover_art.data().size();
    const char *data  = cover_art.data().data();
    FILE *cover_file  = fopen(img_path.c_str(), "wb");

    fwrite(data, image_size, 1, cover_file);
    fclose(cover_file);
  }

  record->Set(string("icon"), string(img_path));
}
<commit_msg>Remove an extra semi-colon<commit_after>#include "get.h"

void tags(std::string location, std::string cover_folder, Library *library) {
  Local<Object> record = Nan::New<Object>();

  TagLib::FileRef f(location.c_str());
  TagLib::Tag *tag = f.tag();
  TagLib::AudioProperties *properties = f.audioProperties();

  TagLib::String title  = tag->title();
  TagLib::String artist = tag->artist();
  TagLib::String album  = tag->album();
  TagLib::String genre  = tag->genre();

  // Set the default title based on the file's location
  // if there's no tags for the file.
  if (!title.length()) {
    std::string::size_type slash  = location.rfind('/');
    std::string::size_type dot    = location.rfind('.');

    std::string default_title = location.substr(slash+1, dot - slash - 1);

    for (std::string::iterator it = default_title.begin(); it != default_title.end(); it++)
      title += *it;
  }

  record->Set(string("title"),    string(title.toCString(true)));
  record->Set(string("artist"),   string(artist.toCString(true)));
  record->Set(string("genre"),    string(genre.toCString(true)));
  record->Set(string("id"),       string(location));
  record->Set(string("track"),    Nan::New(tag->track()));
  record->Set(string("duration"), Nan::New(properties->length()));

  if (cover_folder.length())
    extractPicture(location, cover_folder, title, album, artist, record);

  if (album.length())
    library->AddTrack(artist.toCString(true), album.toCString(true), record);
  else
    library->AddSingle(artist.toCString(true), record);
}

void inline extractPicture(std::string location,  std::string cover_folder,
                           TagLib::String title,  TagLib::String album,
                           TagLib::String artist, Local<Object> record) {
  std::string extension = location.substr(location.length() - 3, 3);

  if (extension == "mp3")
    mp3Picture(location, cover_folder, record);
  else if (extension == "m4a")
    mp4Picture(location, cover_folder, record);
}

void mp3Picture(std::string location, std::string cover_folder, Local<Object> record) {
  TagLib::MPEG::File mp3_file(location.c_str());
  TagLib::ID3v2::Tag *mp3_tag = mp3_file.ID3v2Tag(true);
  TagLib::ID3v2::FrameList pictures = mp3_tag->frameList("APIC");

  if (pictures.isEmpty())
    return;

  TagLib::ID3v2::AttachedPictureFrame *picture_frame = static_cast<TagLib::ID3v2::AttachedPictureFrame *> (*pictures.begin());

  unsigned int checksum = picture_frame->picture().checksum();

  std::stringstream path_stream;

  path_stream << cover_folder;
  path_stream << "/";
  path_stream << checksum;

  std::string img_path = path_stream.str();

  if (picture_frame->mimeType() == "image/png")
    img_path.append(".png");
  else
    img_path.append(".jpg");

  if (!exist(img_path)) {
    size_t image_size = picture_frame->picture().size();
    const char *data  = picture_frame->picture().data();
    FILE *cover_file  = fopen(img_path.c_str(), "wb");

    fwrite(data, image_size, 1, cover_file);
    fclose(cover_file);
  }

  record->Set(string("icon"), string(img_path));
}

void mp4Picture(std::string location, std::string cover_folder, Local<Object> record) {
  TagLib::MP4::File mp4_file(location.c_str());
  TagLib::MP4::Tag *mp4_tag = mp4_file.tag();

  if (!mp4_tag->contains("covr"))
    return;

  TagLib::MP4::CoverArtList covert_art_list = mp4_tag->item("covr").toCoverArtList();

  if (covert_art_list.isEmpty())
    return;

  TagLib::MP4::CoverArt cover_art = covert_art_list[0];

  unsigned int checksum = cover_art.data().checksum();

  std::stringstream path_stream;

  path_stream << cover_folder;
  path_stream << "/";
  path_stream << checksum;

  std::string img_path = path_stream.str();

  img_path.append(".jpg");

  if (!exist(img_path)) {
    size_t image_size = cover_art.data().size();
    const char *data  = cover_art.data().data();
    FILE *cover_file  = fopen(img_path.c_str(), "wb");

    fwrite(data, image_size, 1, cover_file);
    fclose(cover_file);
  }

  record->Set(string("icon"), string(img_path));
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008, 2009 Nokia Corporation.
 *
 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include "context.h"
#include "logging.h"
#include "manager.h"
#include "manageradaptor.h"
#include "sconnect.h"
#include "loggingfeatures.h"

using namespace ContextProvider;

/*!
    \class Context

    \brief The main class used to provide context data.

    Typically, to provide some keys you would:

    \code
    QStringList keys;
    keys.append("Some.Key1");
    keys.append("Some.Key2");

    Context::initService(QDBusConnection::SessionBus, "org.test.somename", keys);
    Context someKey1("Some.Key1");
    Context someKey2("Some.Key2");
    // Do something with someKey1, someKey2...
    \endcode

    \c Context::initService initializes a new bus connection with a specified service name
    and creates a Manager object on it. The clients obtain Subscriber objects through this
    Manager.

    For each service there is one Manager object.
*/

QHash<QString, Manager*> Context::busesToManagers;
QHash<QString, QDBusConnection*> Context::busesToConnections;
QHash<QString, Manager*> Context::keysToManagers;

/// Constructor. This creates a new context property that should
/// be used to provide/set values and get notified about subscribers appearing.
Context::Context(const QString &k, QObject* parent)
    : QObject(parent), key(k)
{
    contextDebug() << F_CONTEXT << "Creating new Context for key:" << key;

    manager = keysToManagers.value(key);
    if (manager == NULL) {
        contextCritical() << key << "is currently not provided by any service";
        return;
    }

    sconnect(manager, SIGNAL(firstSubscriberAppeared(const QString&)),
             this, SLOT(onManagerFirstSubscriberAppeared(const QString&)));

    sconnect(manager, SIGNAL(lastSubscriberDisappeared(const QString&)),
             this, SLOT(onManagerLastSubscriberDisappeared(const QString&)));
}

/// Checks if a Context is valid (can be set/get/manipulated), prints an error message if not.
/// Returns true if the Context is valid. False otherwise. Helper for the Context::set
/// and Context::get familly of functions.
bool Context::keyCheck() const
{
    if (manager == NULL) {
        contextWarning() << "Trying to manipulate an invalid key:" << key;
        return false;
    } else
        return true;
}

/// Returns true if the key is valid.
bool Context::isValid() const
{
    return (manager != NULL);
}

/// Returns true if the key is set (it's value is determined).
bool Context::isSet() const
{
    if (! keyCheck())
        return false;

    return (manager->getKeyValue(key) != QVariant());
}

/// Returns the name of the key this Context represents.
QString Context::getKey() const
{
    return key;
}

/// Unsets the key value. The key value becomes undetermined.
void Context::unset()
{
    if (! keyCheck())
        return;

    manager->setKeyValue(key, QVariant());
}

/// Sets the key value to QVariant \a v.
void Context::set(const QVariant &v)
{
    if (! keyCheck())
        return;

    manager->setKeyValue(key, v);
}

/// Returns the current value of the key. The returned QVariant is invalid
/// if the key value is undetermined or the Context is invalid.
QVariant Context::get()
{
    if (! keyCheck())
        return QVariant();

    return manager->getKeyValue(key);
}

/// Called by Manager when first subscriber appears. Delegated if
/// this concerns us.
void Context::onManagerFirstSubscriberAppeared(const QString &key)
{
    if (key == this->key) {
        contextDebug() << F_SIGNALS << F_CONTEXT << "First subscriber appeared for key:" << key;
        emit firstSubscriberAppeared(key);
    }
}

/// Called by Manager when last subscriber disappears. Delegate if
/// this concerns us.
void Context::onManagerLastSubscriberDisappeared(const QString &key)
{
    if (key == this->key) {
        contextDebug() << F_SIGNALS << F_CONTEXT << "Last subscriber disappeared for key:" << key;
        emit lastSubscriberDisappeared(key);
    }
}

/// Destructor.
Context::~Context()
{
    contextDebug() << F_CONTEXT << F_DESTROY << "Destroying Context for key:" << key;
}

/// Initialize a new service on a bus \a busType with service name \a busName and a given
/// set of \a keys. This is the main method used to setup/bootstrap the keys that
/// we want to provide.
/// Returns true if service was registered, false otherwise.
bool Context::initService(QDBusConnection::BusType busType, const QString &busName, const QStringList &keys)
{
    contextDebug() << F_CONTEXT << "Initializing service for bus:" << busName;

    // Basic sanity check
    if (busesToManagers.contains(busName)) {
        contextCritical() << busName << "service is already registered";
        return false;
    }

    QDBusConnection *connection = new QDBusConnection(QDBusConnection::connectToBus(busType, busName));

    Manager *manager = new Manager(keys);
    ManagerAdaptor *managerAdaptor = new ManagerAdaptor(manager, connection);

    // Register service
    if (! connection->registerService(busName)) {
        contextCritical() << "Failed to register service with name" << busName;
        return false;
    }

    // Register object
    if (managerAdaptor && !connection->registerObject("/org/freedesktop/ContextKit/Manager", manager)) {
        contextCritical() << "Failed to register the Manager object for" << busName;
        return false;
    }

    busesToManagers.insert(busName, manager);
    busesToConnections.insert(busName, connection);

    // Add a mapping for all the keys -> manager
    foreach(QString key, keys) {
        if (keysToManagers.contains(key)) {
            contextCritical() << key << "is already provided by another manager/service!";
            return false;
        } else {
            keysToManagers.insert(key, manager);
        }
    }

    return true;
}

/// Stops the previously started (with initService) service with the given \a busName.
void Context::stopService(const QString &busName)
{
    contextDebug() << F_CONTEXT << "Stopping service for bus:" << busName;

    // Basic sanity check
    if (! busesToManagers.contains(busName)) {
        contextCritical() << busName << "service is not started!";
        return;
    }

    // The manager...
    Manager *manager = busesToManagers.value(busName);

    // Remove all key mappings
    foreach(QString key, QStringList(manager->getKeys())) {
        keysToManagers.remove(key);
    }

    // The connection...
    QDBusConnection *connection = busesToConnections.value(busName);

    // Unregister
    connection->unregisterObject("/org/freedesktop/ContextKit/Manager");
    connection->unregisterService(busName);

    // Remove the remaining mappings
    busesToManagers.remove(busName);
    busesToConnections.remove(busName);

    // Dealloc
    delete manager;
    delete connection;
}

<commit_msg>Updating the documentation about Context objects.<commit_after>/*
 * Copyright (C) 2008, 2009 Nokia Corporation.
 *
 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include "context.h"
#include "logging.h"
#include "manager.h"
#include "manageradaptor.h"
#include "sconnect.h"
#include "loggingfeatures.h"

using namespace ContextProvider;

/*!
    \class Context

    \brief The main class used to provide context data.

    Typically, to provide some keys you would:

    \code
    QStringList keys;
    keys.append("Some.Key1");
    keys.append("Some.Key2");

    Context::initService(QDBusConnection::SessionBus, "org.test.somename", keys);
    Context someKey1("Some.Key1");
    Context someKey2("Some.Key2");
    // Do something with someKey1, someKey2...
    \endcode

    \c Context::initService initializes a new bus connection with a specified service name
    and creates a Manager object on it. The clients obtain Subscriber objects through this
    Manager.

    The Context objects are proxy interfaces to actual keys. It's recommended that you create
    Context objects to represent keys and keep them around in your class/object. Remember that
    once the Context object is destroyed, it will not fire the proper signals about
    subscription status changing.

    For each service there is one Manager object.
*/

QHash<QString, Manager*> Context::busesToManagers;
QHash<QString, QDBusConnection*> Context::busesToConnections;
QHash<QString, Manager*> Context::keysToManagers;

/// Constructor. This creates a new context property that should
/// be used to provide/set values and get notified about subscribers appearing.
Context::Context(const QString &k, QObject* parent)
    : QObject(parent), key(k)
{
    contextDebug() << F_CONTEXT << "Creating new Context for key:" << key;

    manager = keysToManagers.value(key);
    if (manager == NULL) {
        contextCritical() << key << "is currently not provided by any service";
        return;
    }

    sconnect(manager, SIGNAL(firstSubscriberAppeared(const QString&)),
             this, SLOT(onManagerFirstSubscriberAppeared(const QString&)));

    sconnect(manager, SIGNAL(lastSubscriberDisappeared(const QString&)),
             this, SLOT(onManagerLastSubscriberDisappeared(const QString&)));
}

/// Checks if a Context is valid (can be set/get/manipulated), prints an error message if not.
/// Returns true if the Context is valid. False otherwise. Helper for the Context::set
/// and Context::get familly of functions.
bool Context::keyCheck() const
{
    if (manager == NULL) {
        contextWarning() << "Trying to manipulate an invalid key:" << key;
        return false;
    } else
        return true;
}

/// Returns true if the key is valid.
bool Context::isValid() const
{
    return (manager != NULL);
}

/// Returns true if the key is set (it's value is determined).
bool Context::isSet() const
{
    if (! keyCheck())
        return false;

    return (manager->getKeyValue(key) != QVariant());
}

/// Returns the name of the key this Context represents.
QString Context::getKey() const
{
    return key;
}

/// Unsets the key value. The key value becomes undetermined.
void Context::unset()
{
    if (! keyCheck())
        return;

    manager->setKeyValue(key, QVariant());
}

/// Sets the key value to QVariant \a v.
void Context::set(const QVariant &v)
{
    if (! keyCheck())
        return;

    manager->setKeyValue(key, v);
}

/// Returns the current value of the key. The returned QVariant is invalid
/// if the key value is undetermined or the Context is invalid.
QVariant Context::get()
{
    if (! keyCheck())
        return QVariant();

    return manager->getKeyValue(key);
}

/// Called by Manager when first subscriber appears. Delegated if
/// this concerns us.
void Context::onManagerFirstSubscriberAppeared(const QString &key)
{
    if (key == this->key) {
        contextDebug() << F_SIGNALS << F_CONTEXT << "First subscriber appeared for key:" << key;
        emit firstSubscriberAppeared(key);
    }
}

/// Called by Manager when last subscriber disappears. Delegate if
/// this concerns us.
void Context::onManagerLastSubscriberDisappeared(const QString &key)
{
    if (key == this->key) {
        contextDebug() << F_SIGNALS << F_CONTEXT << "Last subscriber disappeared for key:" << key;
        emit lastSubscriberDisappeared(key);
    }
}

/// Destructor.
Context::~Context()
{
    contextDebug() << F_CONTEXT << F_DESTROY << "Destroying Context for key:" << key;
}

/// Initialize a new service on a bus \a busType with service name \a busName and a given
/// set of \a keys. This is the main method used to setup/bootstrap the keys that
/// we want to provide.
/// Returns true if service was registered, false otherwise.
bool Context::initService(QDBusConnection::BusType busType, const QString &busName, const QStringList &keys)
{
    contextDebug() << F_CONTEXT << "Initializing service for bus:" << busName;

    // Basic sanity check
    if (busesToManagers.contains(busName)) {
        contextCritical() << busName << "service is already registered";
        return false;
    }

    QDBusConnection *connection = new QDBusConnection(QDBusConnection::connectToBus(busType, busName));

    Manager *manager = new Manager(keys);
    ManagerAdaptor *managerAdaptor = new ManagerAdaptor(manager, connection);

    // Register service
    if (! connection->registerService(busName)) {
        contextCritical() << "Failed to register service with name" << busName;
        return false;
    }

    // Register object
    if (managerAdaptor && !connection->registerObject("/org/freedesktop/ContextKit/Manager", manager)) {
        contextCritical() << "Failed to register the Manager object for" << busName;
        return false;
    }

    busesToManagers.insert(busName, manager);
    busesToConnections.insert(busName, connection);

    // Add a mapping for all the keys -> manager
    foreach(QString key, keys) {
        if (keysToManagers.contains(key)) {
            contextCritical() << key << "is already provided by another manager/service!";
            return false;
        } else {
            keysToManagers.insert(key, manager);
        }
    }

    return true;
}

/// Stops the previously started (with initService) service with the given \a busName.
void Context::stopService(const QString &busName)
{
    contextDebug() << F_CONTEXT << "Stopping service for bus:" << busName;

    // Basic sanity check
    if (! busesToManagers.contains(busName)) {
        contextCritical() << busName << "service is not started!";
        return;
    }

    // The manager...
    Manager *manager = busesToManagers.value(busName);

    // Remove all key mappings
    foreach(QString key, QStringList(manager->getKeys())) {
        keysToManagers.remove(key);
    }

    // The connection...
    QDBusConnection *connection = busesToConnections.value(busName);

    // Unregister
    connection->unregisterObject("/org/freedesktop/ContextKit/Manager");
    connection->unregisterService(busName);

    // Remove the remaining mappings
    busesToManagers.remove(busName);
    busesToConnections.remove(busName);

    // Dealloc
    delete manager;
    delete connection;
}

<|endoftext|>


<commit_before>#include "flag.h"

#include <cassert>
#include <limits>
#include <sstream>

using namespace dariadb::compression::v2;

FlagCompressor::FlagCompressor(const ByteBuffer_Ptr &bw_)
    : BaseCompressor(bw_){
	_is_first = true;
}

bool FlagCompressor::append(dariadb::Flag v) {
	static_assert(sizeof(dariadb::Flag) == 4, "Flag no x32 value");
	if (_is_first) {
		_first = v;
		_is_first = false;
		return true;
	}
	//TODO calc size before write for better space usage.
	if (bw->free_size() < 8) {
		return false;
	}
	// LEB128
	auto x = v;
	do {

		auto sub_res = x & 0x7fU;
		if (x >>= 7)
			sub_res |= 0x80U;
		bw->write<uint8_t>(sub_res);
	} while (x);

	return true;
}

FlagDeCompressor::FlagDeCompressor(const ByteBuffer_Ptr &bw_, dariadb::Flag first):BaseCompressor(bw_)
{
	_first = first;
	_is_first = true;;
}

dariadb::Flag FlagDeCompressor::read() {
  static_assert(sizeof(dariadb::Flag) == 4, "Flag no x32 value");
 /* if (_is_first) {
	  _is_first = false;
	  return _first;
  }*/
  dariadb::Flag result(0);

  size_t bytes = 0;
  while (true) {
	  auto readed = bw->read<uint8_t>();
	  result |= (readed & 0x7fULL) << (7 * bytes++);
	  if (!(readed & 0x80U))
		  break;
  }
  return result;
}
<commit_msg>leb128 refact.<commit_after>#include "flag.h"

#include <cassert>
#include <limits>
#include <sstream>

using namespace dariadb::compression::v2;

FlagCompressor::FlagCompressor(const ByteBuffer_Ptr &bw_)
    : BaseCompressor(bw_) {
  _is_first = true;
}

bool FlagCompressor::append(dariadb::Flag v) {
  static_assert(sizeof(dariadb::Flag) == 4, "Flag no x32 value");
  if (_is_first) {
    _first = v;
    _is_first = false;
    return true;
  }

  // LEB128
  auto x = v;
  do {
    if (bw->free_size() < 1) {
      return false;
    }
    auto sub_res = x & 0x7fU;
    if (x >>= 7)
      sub_res |= 0x80U;
    bw->write<uint8_t>(sub_res);
  } while (x);

  return true;
}

FlagDeCompressor::FlagDeCompressor(const ByteBuffer_Ptr &bw_,
                                   dariadb::Flag first)
    : BaseCompressor(bw_) {
  _first = first;
  _is_first = true;
  ;
}

dariadb::Flag FlagDeCompressor::read() {
  static_assert(sizeof(dariadb::Flag) == 4, "Flag no x32 value");
  dariadb::Flag result(0);

  size_t bytes = 0;
  while (true) {
    auto readed = bw->read<uint8_t>();
    result |= (readed & 0x7fULL) << (7 * bytes++);
    if (!(readed & 0x80U))
      break;
  }
  return result;
}
<|endoftext|>