<commit_before>#include <mutex>
#include <unistd.h>
#include <functional>
#include <string.h>
#include <vector>
#include <string>
#include <algorithm>

#include "../../../src/contents.hh"
#include "../../../src/split.hh"
#include "../../../src/file_contents.hh"

namespace vick {
namespace shell_command {

class exec_shell_command_exception : public std::exception {
    std::string message;

public:
    exec_shell_command_exception(std::string message)
        : message(std::move(message)) {}
    virtual const char* what() const noexcept override {
        return message.c_str();
    }
};

void exec_shell_command(const std::string& cmd, std::string* out_,
                        std::string* err_) {
    *out_ = "";
    *err_ = "";

    int out[2], err[2];

    if (pipe(out) == -1)
        throw exec_shell_command_exception(
            "Couldn't open stdout pipe");
    if (pipe(err) == -1)
        throw exec_shell_command_exception(
            "Coudln't open stderr pipe");

    switch (fork()) {
        case -1:
            throw exec_shell_command_exception(
                "Forking error on stdout");
        case 0: {
            close(out[0]);
            close(err[0]);
            dup2(out[1], STDOUT_FILENO);
            dup2(err[1], STDERR_FILENO);
            system(cmd.c_str());
            _Exit(-1);
        }
        default: {
            close(out[1]);
            close(err[1]);
            char readbuffer[1024];
            memset(readbuffer, '\0', sizeof(readbuffer));
            int nbytes = sizeof(readbuffer) - 1;
            while (std::find(readbuffer, readbuffer + nbytes, EOF) ==
                       readbuffer + nbytes and
                   nbytes) {
                nbytes =
                    read(out[0], readbuffer, sizeof(readbuffer) - 1);
                readbuffer[nbytes] = 0;
                *out_ += readbuffer;
            }
            close(out[0]);

            memset(readbuffer, '\0', sizeof(readbuffer));
            nbytes = sizeof(readbuffer) - 1;
            while (std::find(readbuffer, readbuffer + nbytes, EOF) ==
                       readbuffer + nbytes and
                   nbytes) {
                nbytes =
                    read(err[0], readbuffer, sizeof(readbuffer) - 1);
                readbuffer[nbytes] = 0;
                *err_ += readbuffer;
            }
        }
    }
}

void exec_shell_command(const std::string& cmd, std::string* out_) {
    *out_ = "";

    int out[2];

    if (pipe(out) == -1) {
        throw exec_shell_command_exception(
            "Couldn't generate a pipe");
    }

    switch (fork()) {
        case -1:
            throw exec_shell_command_exception(
                "Couldn't fork the process");
        case 0: { // pump data into pipe
            close(out[0]);
            dup2(out[1], STDOUT_FILENO);
            dup2(out[1], STDERR_FILENO);
            std::vector<const char*> command = {"sh", "-c",
                                                cmd.c_str(), nullptr};
            execv("/bin/sh", const_cast<char* const*>(
                                 static_cast<const char* const*>(
                                     command.data())));
            _Exit(-1);
        }
        default: { // transfer pipe to param out_
            close(out[1]);
            char readbuffer[1024];
            memset(readbuffer, '\0', sizeof(readbuffer));
            int nbytes = sizeof(readbuffer) - 1;
            while (std::find(readbuffer, readbuffer + nbytes, EOF) ==
                       readbuffer + nbytes and
                   nbytes) {
                nbytes =
                    read(out[0], readbuffer, sizeof(readbuffer) - 1);
                readbuffer[nbytes] = 0;
                *out_ += std::string(readbuffer);
            }
        }
    }
}

void exec_shell_command(const std::string& cmd,
                        std::function<void(std::string)> out_,
                        size_t buffer_size) {
    int out[2];

    if (pipe(out) == -1) {
        throw exec_shell_command_exception(
            "Couldn't generate a pipe");
    }

    switch (fork()) {
        case -1:
            throw exec_shell_command_exception(
                "Couldn't fork the process");
        case 0: {
            close(out[0]);
            dup2(out[1], STDOUT_FILENO);
            dup2(out[1], STDERR_FILENO);
            const char* const args[] = {"/bin/sh", "-c", cmd.c_str(),
                                        nullptr};
            execv("/bin/sh", const_cast<char* const*>(args));
            _Exit(1);
        }
        default: {
            close(out[1]);
            char readbuffer[buffer_size];
            memset(readbuffer, 0, sizeof(readbuffer));
            int nbytes = buffer_size;
            bool cont = false;
            while (nbytes and
                   std::find(readbuffer, readbuffer + nbytes, EOF) ==
                       readbuffer + nbytes) {
                if (cont) {
                    out_(readbuffer);
                    cont = false;
                }

                nbytes = read(out[0], readbuffer, buffer_size);
                readbuffer[nbytes] = 0;

                if (readbuffer[0] == '\0')
                    cont = true;
                else
                    out_(readbuffer);
            }
        }
    }
}

void exec_shell_command(const std::string& cmd,
                        std::function<void(std::string)> out_,
                        std::function<void(std::string)> err_,
                        size_t buffer_size) {
    int out[2], err[2];

    if (pipe(out) == -1 or pipe(err) == -1) {
        throw exec_shell_command_exception(
            "Couldn't generate a pipe");
    }

    pid_t p_read, p_err;
    if ((p_read = fork()) == -1 or (p_err = fork()) == -1)
        throw exec_shell_command_exception(
            "Couldn't fork the process");
    if (not p_read and p_err)
        _Exit(-1);
    if (not p_read) {
        close(out[0]);
        dup2(out[1], STDOUT_FILENO);
        dup2(err[1], STDERR_FILENO);
        std::vector<const char*> command = {"sh", "-c", cmd.c_str(),
                                            nullptr};
        execv("/bin/sh",
              const_cast<char* const*>(
                  static_cast<const char* const*>(command.data())));
        _Exit(-1);
    } else if (p_err) {
        close(out[0]);
        close(out[1]);
        close(err[1]);
        char readbuffer[buffer_size + 1];
        memset(readbuffer, '\0', buffer_size);
        int nbytes = buffer_size;
        bool cont = false;
        while (nbytes and
               std::find(readbuffer, readbuffer + nbytes, EOF) ==
                   readbuffer + nbytes) {
            if (cont) {
                err_(readbuffer);
                cont = false;
            }

            nbytes = read(err[0], readbuffer, buffer_size);
            readbuffer[nbytes] = 0;
            if (readbuffer[0] == '\0')
                cont = true;
            else
                err_(readbuffer);
        }
    } else {
        close(out[1]);
        close(err[0]);
        close(err[1]);
        char readbuffer[buffer_size + 1];
        memset(readbuffer, '\0', buffer_size);
        int nbytes = buffer_size;
        bool cont = false;
        while (nbytes and
               std::find(readbuffer, readbuffer + nbytes, EOF) ==
                   readbuffer + nbytes) {
            if (cont) {
                out_(readbuffer);
                cont = false;
            }

            nbytes = read(out[0], readbuffer, buffer_size);
            readbuffer[nbytes] = 0;

            if (readbuffer[0] == '\0')
                cont = true;
            else
                out_(readbuffer);
        }
        _Exit(-1);
    }
}

void exec_shell_command(const std::string& cmd, contents& cont) {
    cont.cont.clear();
    cont.x = 0;
    cont.y = 0;
    std::mutex mut;
    bool pb_empty;
    exec_shell_command(cmd,
                       [&cont, &mut, &pb_empty](std::string str) {
                           std::lock_guard<std::mutex> _(mut);
                           if (pb_empty) {
                               pb_empty = false;
                               cont.cont.push_back("");
                           }

                           if ((str.empty()) or
                               (str.size() == 1 and str[0] == '\n'))
                               ;
                           else if (str.find('\n') ==
                                    std::string::npos) {
                               if (cont.cont.empty())
                                   cont.cont.push_back(str);
                               else
                                   cont.cont.back() += str;
                           } else {
                               std::vector<std::string> splitted =
                                   split(str, '\n');
                               auto itr = splitted.begin();
                               if (cont.cont.empty())
                                   cont.cont.push_back(*itr);
                               else
                                   cont.cont.back() += *itr;
                               ++itr;
                               bool contin = false;
                               for (auto end = splitted.end();
                                    itr != end; ++itr) {
                                   if (contin) {
                                       contin = false;
                                       cont.cont.push_back(*itr);
                                   }
                                   if (itr->empty()) {
                                       contin = true;
                                       continue;
                                   }
                                   cont.cont.push_back(*itr);
                               }
                           }

                           if (str.size() and
                               str[str.size() - 1] == '\n')
                               pb_empty = true;
                           print_contents(cont);
                       },
                       1024);
}
}
}
<commit_msg>vick-build allows for removal of noisy `../../../src/`s<commit_after>#include <mutex>
#include <unistd.h>
#include <functional>
#include <string.h>
#include <vector>
#include <string>
#include <algorithm>

#include "contents.hh"
#include "split.hh"
#include "file_contents.hh"

namespace vick {
namespace shell_command {

class exec_shell_command_exception : public std::exception {
    std::string message;

public:
    exec_shell_command_exception(std::string message)
        : message(std::move(message)) {}
    virtual const char* what() const noexcept override {
        return message.c_str();
    }
};

void exec_shell_command(const std::string& cmd, std::string* out_,
                        std::string* err_) {
    *out_ = "";
    *err_ = "";

    int out[2], err[2];

    if (pipe(out) == -1)
        throw exec_shell_command_exception(
            "Couldn't open stdout pipe");
    if (pipe(err) == -1)
        throw exec_shell_command_exception(
            "Coudln't open stderr pipe");

    switch (fork()) {
        case -1:
            throw exec_shell_command_exception(
                "Forking error on stdout");
        case 0: {
            close(out[0]);
            close(err[0]);
            dup2(out[1], STDOUT_FILENO);
            dup2(err[1], STDERR_FILENO);
            system(cmd.c_str());
            _Exit(-1);
        }
        default: {
            close(out[1]);
            close(err[1]);
            char readbuffer[1024];
            memset(readbuffer, '\0', sizeof(readbuffer));
            int nbytes = sizeof(readbuffer) - 1;
            while (std::find(readbuffer, readbuffer + nbytes, EOF) ==
                       readbuffer + nbytes and
                   nbytes) {
                nbytes =
                    read(out[0], readbuffer, sizeof(readbuffer) - 1);
                readbuffer[nbytes] = 0;
                *out_ += readbuffer;
            }
            close(out[0]);

            memset(readbuffer, '\0', sizeof(readbuffer));
            nbytes = sizeof(readbuffer) - 1;
            while (std::find(readbuffer, readbuffer + nbytes, EOF) ==
                       readbuffer + nbytes and
                   nbytes) {
                nbytes =
                    read(err[0], readbuffer, sizeof(readbuffer) - 1);
                readbuffer[nbytes] = 0;
                *err_ += readbuffer;
            }
        }
    }
}

void exec_shell_command(const std::string& cmd, std::string* out_) {
    *out_ = "";

    int out[2];

    if (pipe(out) == -1) {
        throw exec_shell_command_exception(
            "Couldn't generate a pipe");
    }

    switch (fork()) {
        case -1:
            throw exec_shell_command_exception(
                "Couldn't fork the process");
        case 0: { // pump data into pipe
            close(out[0]);
            dup2(out[1], STDOUT_FILENO);
            dup2(out[1], STDERR_FILENO);
            std::vector<const char*> command = {"sh", "-c",
                                                cmd.c_str(), nullptr};
            execv("/bin/sh", const_cast<char* const*>(
                                 static_cast<const char* const*>(
                                     command.data())));
            _Exit(-1);
        }
        default: { // transfer pipe to param out_
            close(out[1]);
            char readbuffer[1024];
            memset(readbuffer, '\0', sizeof(readbuffer));
            int nbytes = sizeof(readbuffer) - 1;
            while (std::find(readbuffer, readbuffer + nbytes, EOF) ==
                       readbuffer + nbytes and
                   nbytes) {
                nbytes =
                    read(out[0], readbuffer, sizeof(readbuffer) - 1);
                readbuffer[nbytes] = 0;
                *out_ += std::string(readbuffer);
            }
        }
    }
}

void exec_shell_command(const std::string& cmd,
                        std::function<void(std::string)> out_,
                        size_t buffer_size) {
    int out[2];

    if (pipe(out) == -1) {
        throw exec_shell_command_exception(
            "Couldn't generate a pipe");
    }

    switch (fork()) {
        case -1:
            throw exec_shell_command_exception(
                "Couldn't fork the process");
        case 0: {
            close(out[0]);
            dup2(out[1], STDOUT_FILENO);
            dup2(out[1], STDERR_FILENO);
            const char* const args[] = {"/bin/sh", "-c", cmd.c_str(),
                                        nullptr};
            execv("/bin/sh", const_cast<char* const*>(args));
            _Exit(1);
        }
        default: {
            close(out[1]);
            char readbuffer[buffer_size];
            memset(readbuffer, 0, sizeof(readbuffer));
            int nbytes = buffer_size;
            bool cont = false;
            while (nbytes and
                   std::find(readbuffer, readbuffer + nbytes, EOF) ==
                       readbuffer + nbytes) {
                if (cont) {
                    out_(readbuffer);
                    cont = false;
                }

                nbytes = read(out[0], readbuffer, buffer_size);
                readbuffer[nbytes] = 0;

                if (readbuffer[0] == '\0')
                    cont = true;
                else
                    out_(readbuffer);
            }
        }
    }
}

void exec_shell_command(const std::string& cmd,
                        std::function<void(std::string)> out_,
                        std::function<void(std::string)> err_,
                        size_t buffer_size) {
    int out[2], err[2];

    if (pipe(out) == -1 or pipe(err) == -1) {
        throw exec_shell_command_exception(
            "Couldn't generate a pipe");
    }

    pid_t p_read, p_err;
    if ((p_read = fork()) == -1 or (p_err = fork()) == -1)
        throw exec_shell_command_exception(
            "Couldn't fork the process");
    if (not p_read and p_err)
        _Exit(-1);
    if (not p_read) {
        close(out[0]);
        dup2(out[1], STDOUT_FILENO);
        dup2(err[1], STDERR_FILENO);
        std::vector<const char*> command = {"sh", "-c", cmd.c_str(),
                                            nullptr};
        execv("/bin/sh",
              const_cast<char* const*>(
                  static_cast<const char* const*>(command.data())));
        _Exit(-1);
    } else if (p_err) {
        close(out[0]);
        close(out[1]);
        close(err[1]);
        char readbuffer[buffer_size + 1];
        memset(readbuffer, '\0', buffer_size);
        int nbytes = buffer_size;
        bool cont = false;
        while (nbytes and
               std::find(readbuffer, readbuffer + nbytes, EOF) ==
                   readbuffer + nbytes) {
            if (cont) {
                err_(readbuffer);
                cont = false;
            }

            nbytes = read(err[0], readbuffer, buffer_size);
            readbuffer[nbytes] = 0;
            if (readbuffer[0] == '\0')
                cont = true;
            else
                err_(readbuffer);
        }
    } else {
        close(out[1]);
        close(err[0]);
        close(err[1]);
        char readbuffer[buffer_size + 1];
        memset(readbuffer, '\0', buffer_size);
        int nbytes = buffer_size;
        bool cont = false;
        while (nbytes and
               std::find(readbuffer, readbuffer + nbytes, EOF) ==
                   readbuffer + nbytes) {
            if (cont) {
                out_(readbuffer);
                cont = false;
            }

            nbytes = read(out[0], readbuffer, buffer_size);
            readbuffer[nbytes] = 0;

            if (readbuffer[0] == '\0')
                cont = true;
            else
                out_(readbuffer);
        }
        _Exit(-1);
    }
}

void exec_shell_command(const std::string& cmd, contents& cont) {
    cont.cont.clear();
    cont.x = 0;
    cont.y = 0;
    std::mutex mut;
    bool pb_empty;
    exec_shell_command(cmd,
                       [&cont, &mut, &pb_empty](std::string str) {
                           std::lock_guard<std::mutex> _(mut);
                           if (pb_empty) {
                               pb_empty = false;
                               cont.cont.push_back("");
                           }

                           if ((str.empty()) or
                               (str.size() == 1 and str[0] == '\n'))
                               ;
                           else if (str.find('\n') ==
                                    std::string::npos) {
                               if (cont.cont.empty())
                                   cont.cont.push_back(str);
                               else
                                   cont.cont.back() += str;
                           } else {
                               std::vector<std::string> splitted =
                                   split(str, '\n');
                               auto itr = splitted.begin();
                               if (cont.cont.empty())
                                   cont.cont.push_back(*itr);
                               else
                                   cont.cont.back() += *itr;
                               ++itr;
                               bool contin = false;
                               for (auto end = splitted.end();
                                    itr != end; ++itr) {
                                   if (contin) {
                                       contin = false;
                                       cont.cont.push_back(*itr);
                                   }
                                   if (itr->empty()) {
                                       contin = true;
                                       continue;
                                   }
                                   cont.cont.push_back(*itr);
                               }
                           }

                           if (str.size() and
                               str[str.size() - 1] == '\n')
                               pb_empty = true;
                           print_contents(cont);
                       },
                       1024);
}
}
}
<|endoftext|>


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

#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

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

#include "base/inifile.hh"
#include "base/misc.hh"
#include "base/output.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "sim/eventq.hh"
#include "sim/serialize.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/sim_object.hh"

// For stat reset hack
#include "sim/stat_control.hh"

using namespace std;

extern SimObject *resolveSimObject(const string &);

//
// The base implementations use to_number for parsing and '<<' for
// displaying, suitable for integer types.
//
template <class T>
bool
parseParam(const string &s, T &value)
{
    return to_number(s, value);
}

template <class T>
void
showParam(ostream &os, const T &value)
{
    os << value;
}

//
// Template specializations:
// - char (8-bit integer)
// - floating-point types
// - bool
// - string
//

// Treat 8-bit ints (chars) as ints on output, not as chars
template <>
void
showParam(ostream &os, const char &value)
{
    os << (int)value;
}

template <>
void
showParam(ostream &os, const unsigned char &value)
{
    os << (unsigned int)value;
}

// Use sscanf() for FP types as to_number() only handles integers
template <>
bool
parseParam(const string &s, float &value)
{
    return (sscanf(s.c_str(), "%f", &value) == 1);
}

template <>
bool
parseParam(const string &s, double &value)
{
    return (sscanf(s.c_str(), "%lf", &value) == 1);
}

template <>
bool
parseParam(const string &s, bool &value)
{
    const string &ls = to_lower(s);

    if (ls == "true") {
        value = true;
        return true;
    }

    if (ls == "false") {
        value = false;
        return true;
    }

    return false;
}

// Display bools as strings
template <>
void
showParam(ostream &os, const bool &value)
{
    os << (value ? "true" : "false");
}

// String requires no processing to speak of
template <>
bool
parseParam(const string &s, string &value)
{
    value = s;
    return true;
}

int Serializable::ckptMaxCount = 0;
int Serializable::ckptCount = 0;
int Serializable::ckptPrevCount = -1;

void
Serializable::nameOut(ostream &os)
{
    os << "\n[" << name() << "]\n";
}

void
Serializable::nameOut(ostream &os, const string &_name)
{
    os << "\n[" << _name << "]\n";
}

template <class T>
void
paramOut(ostream &os, const string &name, const T &param)
{
    os << name << "=";
    showParam(os, param);
    os << "\n";
}

template <class T>
void
arrayParamOut(ostream &os, const string &name, const vector<T> &param)
{
    typename vector<T>::size_type size = param.size();
    os << name << "=";
    if (size > 0)
        showParam(os, param[0]);
    for (typename vector<T>::size_type i = 1; i < size; ++i) {
        os << " ";
        showParam(os, param[i]);
    }
    os << "\n";
}

template <class T>
void
paramIn(Checkpoint *cp, const string &section, const string &name, T &param)
{
    string str;
    if (!cp->find(section, name, str) || !parseParam(str, param)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }
}

template <class T>
bool
optParamIn(Checkpoint *cp, const string &section, const string &name, T &param)
{
    string str;
    if (!cp->find(section, name, str) || !parseParam(str, param)) {
        warn("optional parameter %s:%s not present\n", section, name);
        return false;
    } else {
        return true;
    }
}

template <class T>
void
arrayParamOut(ostream &os, const string &name, const T *param, unsigned size)
{
    os << name << "=";
    if (size > 0)
        showParam(os, param[0]);
    for (unsigned i = 1; i < size; ++i) {
        os << " ";
        showParam(os, param[i]);
    }
    os << "\n";
}

template <class T>
void
arrayParamIn(Checkpoint *cp, const string &section, const string &name,
             T *param, unsigned size)
{
    string str;
    if (!cp->find(section, name, str)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }

    // code below stolen from VectorParam<T>::parse().
    // it would be nice to unify these somehow...

    vector<string> tokens;

    tokenize(tokens, str, ' ');

    // Need this if we were doing a vector
    // value.resize(tokens.size());

    if (tokens.size() != size) {
        fatal("Array size mismatch on %s:%s'\n", section, name);
    }

    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
        // need to parse into local variable to handle vector<bool>,
        // for which operator[] returns a special reference class
        // that's not the same as 'bool&', (since it's a packed
        // vector)
        T scalar_value;
        if (!parseParam(tokens[i], scalar_value)) {
            string err("could not parse \"");

            err += str;
            err += "\"";

            fatal(err);
        }

        // assign parsed value to vector
        param[i] = scalar_value;
    }
}

template <class T>
void
arrayParamIn(Checkpoint *cp, const string &section,
             const string &name, vector<T> &param)
{
    string str;
    if (!cp->find(section, name, str)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }

    // code below stolen from VectorParam<T>::parse().
    // it would be nice to unify these somehow...

    vector<string> tokens;

    tokenize(tokens, str, ' ');

    // Need this if we were doing a vector
    // value.resize(tokens.size());

    param.resize(tokens.size());

    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
        // need to parse into local variable to handle vector<bool>,
        // for which operator[] returns a special reference class
        // that's not the same as 'bool&', (since it's a packed
        // vector)
        T scalar_value;
        if (!parseParam(tokens[i], scalar_value)) {
            string err("could not parse \"");

            err += str;
            err += "\"";

            fatal(err);
        }

        // assign parsed value to vector
        param[i] = scalar_value;
    }
}

void
objParamIn(Checkpoint *cp, const string &section,
           const string &name, SimObject * &param)
{
    if (!cp->findObj(section, name, param)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }
}

#define INSTANTIATE_PARAM_TEMPLATES(type)                               \
template void                                                           \
paramOut(ostream &os, const string &name, type const &param);           \
template void                                                           \
paramIn(Checkpoint *cp, const string &section,                          \
        const string &name, type & param);                              \
template bool                                                           \
optParamIn(Checkpoint *cp, const string &section,                       \
        const string &name, type & param);                              \
template void                                                           \
arrayParamOut(ostream &os, const string &name,                          \
              type const *param, unsigned size);                        \
template void                                                           \
arrayParamIn(Checkpoint *cp, const string &section,                     \
             const string &name, type *param, unsigned size);           \
template void                                                           \
arrayParamOut(ostream &os, const string &name,                          \
              const vector<type> &param);                               \
template void                                                           \
arrayParamIn(Checkpoint *cp, const string &section,                     \
             const string &name, vector<type> &param);

INSTANTIATE_PARAM_TEMPLATES(signed char)
INSTANTIATE_PARAM_TEMPLATES(unsigned char)
INSTANTIATE_PARAM_TEMPLATES(signed short)
INSTANTIATE_PARAM_TEMPLATES(unsigned short)
INSTANTIATE_PARAM_TEMPLATES(signed int)
INSTANTIATE_PARAM_TEMPLATES(unsigned int)
INSTANTIATE_PARAM_TEMPLATES(signed long)
INSTANTIATE_PARAM_TEMPLATES(unsigned long)
INSTANTIATE_PARAM_TEMPLATES(signed long long)
INSTANTIATE_PARAM_TEMPLATES(unsigned long long)
INSTANTIATE_PARAM_TEMPLATES(bool)
INSTANTIATE_PARAM_TEMPLATES(float)
INSTANTIATE_PARAM_TEMPLATES(double)
INSTANTIATE_PARAM_TEMPLATES(string)

/////////////////////////////

/// Container for serializing global variables (not associated with
/// any serialized object).
class Globals : public Serializable
{
  public:
    const string name() const;
    void serialize(ostream &os);
    void unserialize(Checkpoint *cp);
};

/// The one and only instance of the Globals class.
Globals globals;

const string
Globals::name() const
{
    return "Globals";
}

void
Globals::serialize(ostream &os)
{
    nameOut(os);
    SERIALIZE_SCALAR(curTick);

    nameOut(os, "MainEventQueue");
    mainEventQueue.serialize(os);
}

void
Globals::unserialize(Checkpoint *cp)
{
    const string &section = name();
    UNSERIALIZE_SCALAR(curTick);

    mainEventQueue.unserialize(cp, "MainEventQueue");
}

Serializable::Serializable()
{
}

Serializable::~Serializable()
{
}

void
Serializable::serialize(ostream &os)
{
}

void
Serializable::unserialize(Checkpoint *cp, const string &section)
{
}

void
Serializable::serializeAll(const string &cpt_dir)
{
    setCheckpointDir(cpt_dir);
    string dir = Checkpoint::dir();
    if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
            fatal("couldn't mkdir %s\n", dir);

    string cpt_file = dir + Checkpoint::baseFilename;
    ofstream outstream(cpt_file.c_str());
    time_t t = time(NULL);
    if (!outstream.is_open())
        fatal("Unable to open file %s for writing\n", cpt_file.c_str());
    outstream << "## checkpoint generated: " << ctime(&t);

    globals.serialize(outstream);
    SimObject::serializeAll(outstream);
}

void
Serializable::unserializeAll(const string &cpt_dir)
{
    setCheckpointDir(cpt_dir);
    string dir = Checkpoint::dir();
    string cpt_file = dir + Checkpoint::baseFilename;
    string section = "";

    DPRINTFR(Config, "Loading checkpoint dir '%s'\n",
             dir);
    Checkpoint *cp = new Checkpoint(dir, section);
    unserializeGlobals(cp);
    SimObject::unserializeAll(cp);
}

void
Serializable::unserializeGlobals(Checkpoint *cp)
{
    globals.unserialize(cp);
}

const char *Checkpoint::baseFilename = "m5.cpt";

static string checkpointDirBase;

void
setCheckpointDir(const string &name)
{
    checkpointDirBase = name;
    if (checkpointDirBase[checkpointDirBase.size() - 1] != '/')
        checkpointDirBase += "/";
}

string
Checkpoint::dir()
{
    // use csprintf to insert curTick into directory name if it
    // appears to have a format placeholder in it.
    return (checkpointDirBase.find("%") != string::npos) ?
        csprintf(checkpointDirBase, curTick) : checkpointDirBase;
}

void
debug_serialize(const string &cpt_dir)
{
    Serializable::serializeAll(cpt_dir);
}

////////////////////////////////////////////////////////////////////////
//
// SerializableClass member definitions
//
////////////////////////////////////////////////////////////////////////

// Map of class names to SerializableBuilder creation functions.
// Need to make this a pointer so we can force initialization on the
// first reference; otherwise, some SerializableClass constructors
// may be invoked before the classMap constructor.
map<string, SerializableClass::CreateFunc> *SerializableClass::classMap = 0;

// SerializableClass constructor: add mapping to classMap
SerializableClass::SerializableClass(const string &className,
                                     CreateFunc createFunc)
{
    if (classMap == NULL)
        classMap = new map<string, SerializableClass::CreateFunc>();

    if ((*classMap)[className])
        fatal("Error: simulation object class %s redefined\n", className);

    // add className --> createFunc to class map
    (*classMap)[className] = createFunc;
}

//
//
Serializable *
SerializableClass::createObject(Checkpoint *cp, const string &section)
{
    string className;

    if (!cp->find(section, "type", className)) {
        fatal("Serializable::create: no 'type' entry in section '%s'.\n",
              section);
    }

    CreateFunc createFunc = (*classMap)[className];

    if (createFunc == NULL) {
        fatal("Serializable::create: no create function for class '%s'.\n",
              className);
    }

    Serializable *object = createFunc(cp, section);

    assert(object != NULL);

    return object;
}

Serializable *
Serializable::create(Checkpoint *cp, const string &section)
{
    Serializable *object = SerializableClass::createObject(cp, section);
    object->unserialize(cp, section);
    return object;
}

Checkpoint::Checkpoint(const string &cpt_dir, const string &path)
    : db(new IniFile), basePath(path), cptDir(cpt_dir)
{
    string filename = cpt_dir + "/" + Checkpoint::baseFilename;
    if (!db->load(filename)) {
        fatal("Can't load checkpoint file '%s'\n", filename);
    }
}

bool
Checkpoint::find(const string &section, const string &entry, string &value)
{
    return db->find(section, entry, value);
}

bool
Checkpoint::findObj(const string &section, const string &entry,
                    SimObject *&value)
{
    string path;

    if (!db->find(section, entry, path))
        return false;

    value = resolveSimObject(path);
    return true;
}

bool
Checkpoint::sectionExists(const string &section)
{
    return db->sectionExists(section);
}
<commit_msg>checkpointing: fix minor bug Somehow we now need to explicitly specialize on 'signed char' and not just 'char' to catch cases like int8_t<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Erik Hallnor
 *          Steve Reinhardt
 */

#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

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

#include "base/inifile.hh"
#include "base/misc.hh"
#include "base/output.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "sim/eventq.hh"
#include "sim/serialize.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/sim_object.hh"

// For stat reset hack
#include "sim/stat_control.hh"

using namespace std;

extern SimObject *resolveSimObject(const string &);

//
// The base implementations use to_number for parsing and '<<' for
// displaying, suitable for integer types.
//
template <class T>
bool
parseParam(const string &s, T &value)
{
    return to_number(s, value);
}

template <class T>
void
showParam(ostream &os, const T &value)
{
    os << value;
}

//
// Template specializations:
// - char (8-bit integer)
// - floating-point types
// - bool
// - string
//

// Treat 8-bit ints (chars) as ints on output, not as chars
template <>
void
showParam(ostream &os, const signed char &value)
{
    os << (int)value;
}

template <>
void
showParam(ostream &os, const unsigned char &value)
{
    os << (unsigned int)value;
}

// Use sscanf() for FP types as to_number() only handles integers
template <>
bool
parseParam(const string &s, float &value)
{
    return (sscanf(s.c_str(), "%f", &value) == 1);
}

template <>
bool
parseParam(const string &s, double &value)
{
    return (sscanf(s.c_str(), "%lf", &value) == 1);
}

template <>
bool
parseParam(const string &s, bool &value)
{
    const string &ls = to_lower(s);

    if (ls == "true") {
        value = true;
        return true;
    }

    if (ls == "false") {
        value = false;
        return true;
    }

    return false;
}

// Display bools as strings
template <>
void
showParam(ostream &os, const bool &value)
{
    os << (value ? "true" : "false");
}

// String requires no processing to speak of
template <>
bool
parseParam(const string &s, string &value)
{
    value = s;
    return true;
}

int Serializable::ckptMaxCount = 0;
int Serializable::ckptCount = 0;
int Serializable::ckptPrevCount = -1;

void
Serializable::nameOut(ostream &os)
{
    os << "\n[" << name() << "]\n";
}

void
Serializable::nameOut(ostream &os, const string &_name)
{
    os << "\n[" << _name << "]\n";
}

template <class T>
void
paramOut(ostream &os, const string &name, const T &param)
{
    os << name << "=";
    showParam(os, param);
    os << "\n";
}

template <class T>
void
arrayParamOut(ostream &os, const string &name, const vector<T> &param)
{
    typename vector<T>::size_type size = param.size();
    os << name << "=";
    if (size > 0)
        showParam(os, param[0]);
    for (typename vector<T>::size_type i = 1; i < size; ++i) {
        os << " ";
        showParam(os, param[i]);
    }
    os << "\n";
}

template <class T>
void
paramIn(Checkpoint *cp, const string &section, const string &name, T &param)
{
    string str;
    if (!cp->find(section, name, str) || !parseParam(str, param)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }
}

template <class T>
bool
optParamIn(Checkpoint *cp, const string &section, const string &name, T &param)
{
    string str;
    if (!cp->find(section, name, str) || !parseParam(str, param)) {
        warn("optional parameter %s:%s not present\n", section, name);
        return false;
    } else {
        return true;
    }
}

template <class T>
void
arrayParamOut(ostream &os, const string &name, const T *param, unsigned size)
{
    os << name << "=";
    if (size > 0)
        showParam(os, param[0]);
    for (unsigned i = 1; i < size; ++i) {
        os << " ";
        showParam(os, param[i]);
    }
    os << "\n";
}

template <class T>
void
arrayParamIn(Checkpoint *cp, const string &section, const string &name,
             T *param, unsigned size)
{
    string str;
    if (!cp->find(section, name, str)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }

    // code below stolen from VectorParam<T>::parse().
    // it would be nice to unify these somehow...

    vector<string> tokens;

    tokenize(tokens, str, ' ');

    // Need this if we were doing a vector
    // value.resize(tokens.size());

    if (tokens.size() != size) {
        fatal("Array size mismatch on %s:%s'\n", section, name);
    }

    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
        // need to parse into local variable to handle vector<bool>,
        // for which operator[] returns a special reference class
        // that's not the same as 'bool&', (since it's a packed
        // vector)
        T scalar_value;
        if (!parseParam(tokens[i], scalar_value)) {
            string err("could not parse \"");

            err += str;
            err += "\"";

            fatal(err);
        }

        // assign parsed value to vector
        param[i] = scalar_value;
    }
}

template <class T>
void
arrayParamIn(Checkpoint *cp, const string &section,
             const string &name, vector<T> &param)
{
    string str;
    if (!cp->find(section, name, str)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }

    // code below stolen from VectorParam<T>::parse().
    // it would be nice to unify these somehow...

    vector<string> tokens;

    tokenize(tokens, str, ' ');

    // Need this if we were doing a vector
    // value.resize(tokens.size());

    param.resize(tokens.size());

    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
        // need to parse into local variable to handle vector<bool>,
        // for which operator[] returns a special reference class
        // that's not the same as 'bool&', (since it's a packed
        // vector)
        T scalar_value;
        if (!parseParam(tokens[i], scalar_value)) {
            string err("could not parse \"");

            err += str;
            err += "\"";

            fatal(err);
        }

        // assign parsed value to vector
        param[i] = scalar_value;
    }
}

void
objParamIn(Checkpoint *cp, const string &section,
           const string &name, SimObject * &param)
{
    if (!cp->findObj(section, name, param)) {
        fatal("Can't unserialize '%s:%s'\n", section, name);
    }
}

#define INSTANTIATE_PARAM_TEMPLATES(type)                               \
template void                                                           \
paramOut(ostream &os, const string &name, type const &param);           \
template void                                                           \
paramIn(Checkpoint *cp, const string &section,                          \
        const string &name, type & param);                              \
template bool                                                           \
optParamIn(Checkpoint *cp, const string &section,                       \
        const string &name, type & param);                              \
template void                                                           \
arrayParamOut(ostream &os, const string &name,                          \
              type const *param, unsigned size);                        \
template void                                                           \
arrayParamIn(Checkpoint *cp, const string &section,                     \
             const string &name, type *param, unsigned size);           \
template void                                                           \
arrayParamOut(ostream &os, const string &name,                          \
              const vector<type> &param);                               \
template void                                                           \
arrayParamIn(Checkpoint *cp, const string &section,                     \
             const string &name, vector<type> &param);

INSTANTIATE_PARAM_TEMPLATES(signed char)
INSTANTIATE_PARAM_TEMPLATES(unsigned char)
INSTANTIATE_PARAM_TEMPLATES(signed short)
INSTANTIATE_PARAM_TEMPLATES(unsigned short)
INSTANTIATE_PARAM_TEMPLATES(signed int)
INSTANTIATE_PARAM_TEMPLATES(unsigned int)
INSTANTIATE_PARAM_TEMPLATES(signed long)
INSTANTIATE_PARAM_TEMPLATES(unsigned long)
INSTANTIATE_PARAM_TEMPLATES(signed long long)
INSTANTIATE_PARAM_TEMPLATES(unsigned long long)
INSTANTIATE_PARAM_TEMPLATES(bool)
INSTANTIATE_PARAM_TEMPLATES(float)
INSTANTIATE_PARAM_TEMPLATES(double)
INSTANTIATE_PARAM_TEMPLATES(string)

/////////////////////////////

/// Container for serializing global variables (not associated with
/// any serialized object).
class Globals : public Serializable
{
  public:
    const string name() const;
    void serialize(ostream &os);
    void unserialize(Checkpoint *cp);
};

/// The one and only instance of the Globals class.
Globals globals;

const string
Globals::name() const
{
    return "Globals";
}

void
Globals::serialize(ostream &os)
{
    nameOut(os);
    SERIALIZE_SCALAR(curTick);

    nameOut(os, "MainEventQueue");
    mainEventQueue.serialize(os);
}

void
Globals::unserialize(Checkpoint *cp)
{
    const string &section = name();
    UNSERIALIZE_SCALAR(curTick);

    mainEventQueue.unserialize(cp, "MainEventQueue");
}

Serializable::Serializable()
{
}

Serializable::~Serializable()
{
}

void
Serializable::serialize(ostream &os)
{
}

void
Serializable::unserialize(Checkpoint *cp, const string &section)
{
}

void
Serializable::serializeAll(const string &cpt_dir)
{
    setCheckpointDir(cpt_dir);
    string dir = Checkpoint::dir();
    if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
            fatal("couldn't mkdir %s\n", dir);

    string cpt_file = dir + Checkpoint::baseFilename;
    ofstream outstream(cpt_file.c_str());
    time_t t = time(NULL);
    if (!outstream.is_open())
        fatal("Unable to open file %s for writing\n", cpt_file.c_str());
    outstream << "## checkpoint generated: " << ctime(&t);

    globals.serialize(outstream);
    SimObject::serializeAll(outstream);
}

void
Serializable::unserializeAll(const string &cpt_dir)
{
    setCheckpointDir(cpt_dir);
    string dir = Checkpoint::dir();
    string cpt_file = dir + Checkpoint::baseFilename;
    string section = "";

    DPRINTFR(Config, "Loading checkpoint dir '%s'\n",
             dir);
    Checkpoint *cp = new Checkpoint(dir, section);
    unserializeGlobals(cp);
    SimObject::unserializeAll(cp);
}

void
Serializable::unserializeGlobals(Checkpoint *cp)
{
    globals.unserialize(cp);
}

const char *Checkpoint::baseFilename = "m5.cpt";

static string checkpointDirBase;

void
setCheckpointDir(const string &name)
{
    checkpointDirBase = name;
    if (checkpointDirBase[checkpointDirBase.size() - 1] != '/')
        checkpointDirBase += "/";
}

string
Checkpoint::dir()
{
    // use csprintf to insert curTick into directory name if it
    // appears to have a format placeholder in it.
    return (checkpointDirBase.find("%") != string::npos) ?
        csprintf(checkpointDirBase, curTick) : checkpointDirBase;
}

void
debug_serialize(const string &cpt_dir)
{
    Serializable::serializeAll(cpt_dir);
}

////////////////////////////////////////////////////////////////////////
//
// SerializableClass member definitions
//
////////////////////////////////////////////////////////////////////////

// Map of class names to SerializableBuilder creation functions.
// Need to make this a pointer so we can force initialization on the
// first reference; otherwise, some SerializableClass constructors
// may be invoked before the classMap constructor.
map<string, SerializableClass::CreateFunc> *SerializableClass::classMap = 0;

// SerializableClass constructor: add mapping to classMap
SerializableClass::SerializableClass(const string &className,
                                     CreateFunc createFunc)
{
    if (classMap == NULL)
        classMap = new map<string, SerializableClass::CreateFunc>();

    if ((*classMap)[className])
        fatal("Error: simulation object class %s redefined\n", className);

    // add className --> createFunc to class map
    (*classMap)[className] = createFunc;
}

//
//
Serializable *
SerializableClass::createObject(Checkpoint *cp, const string &section)
{
    string className;

    if (!cp->find(section, "type", className)) {
        fatal("Serializable::create: no 'type' entry in section '%s'.\n",
              section);
    }

    CreateFunc createFunc = (*classMap)[className];

    if (createFunc == NULL) {
        fatal("Serializable::create: no create function for class '%s'.\n",
              className);
    }

    Serializable *object = createFunc(cp, section);

    assert(object != NULL);

    return object;
}

Serializable *
Serializable::create(Checkpoint *cp, const string &section)
{
    Serializable *object = SerializableClass::createObject(cp, section);
    object->unserialize(cp, section);
    return object;
}

Checkpoint::Checkpoint(const string &cpt_dir, const string &path)
    : db(new IniFile), basePath(path), cptDir(cpt_dir)
{
    string filename = cpt_dir + "/" + Checkpoint::baseFilename;
    if (!db->load(filename)) {
        fatal("Can't load checkpoint file '%s'\n", filename);
    }
}

bool
Checkpoint::find(const string &section, const string &entry, string &value)
{
    return db->find(section, entry, value);
}

bool
Checkpoint::findObj(const string &section, const string &entry,
                    SimObject *&value)
{
    string path;

    if (!db->find(section, entry, path))
        return false;

    value = resolveSimObject(path);
    return true;
}

bool
Checkpoint::sectionExists(const string &section)
{
    return db->sectionExists(section);
}
<|endoftext|>


<commit_before>#include "SimpleMemory.hh"

SimpleMemory::SimpleMemory(AstraNetworkAPI *NI,double access_latency,double npu_access_bw_GB,double nic_access_bw_GB){
        this->last_request_serviced=0;
        this->request_count=0;
        this->NI=NI;
        this->access_latency=access_latency;
        this->npu_access_bw_GB=npu_access_bw_GB;
        this->nic_access_bw_GB=nic_access_bw_GB;
}
void SimpleMemory::set_network_api(AstraNetworkAPI *astraNetworkApi){
    this->NI=astraNetworkApi;
}
uint64_t SimpleMemory::npu_mem_read(uint64_t size){
    request_count++;
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/npu_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    //std::cout<<"node id: "<<NI->sim_comm_get_rank()<<", access latency: "<<(uint64_t)(offset)
             //<<", current delay: "<<delay<<", total requests: "<<request_count<<std::endl;
    return (uint64_t)(offset);

}
uint64_t SimpleMemory::SimpleMemory::npu_mem_write(uint64_t size){
    request_count++;
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/npu_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    //std::cout<<"node id: "<<NI->sim_comm_get_rank()<<", access latency: "<<(uint64_t)(offset)
             //<<", current delay: "<<delay<<", total requests: "<<request_count<<std::endl;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::nic_mem_read(uint64_t size){
    request_count++;
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/nic_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    //std::cout<<"node id: "<<NI->sim_comm_get_rank()<<", access latency: "<<(uint64_t)(offset)
    //<<", current delay: "<<delay<<", total requests: "<<request_count<<std::endl;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::nic_mem_write(uint64_t size){
    request_count++;
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/nic_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    //std::cout<<"node id: "<<NI->sim_comm_get_rank()<<", access latency: "<<(uint64_t)(offset)
             //<<", current delay: "<<delay<<", total requests: "<<request_count<<std::endl;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::mem_read(uint64_t size){
    return nic_mem_read(size);
}
uint64_t SimpleMemory::mem_write(uint64_t size){
    return nic_mem_write(size);
}<commit_msg>updated<commit_after>#include "SimpleMemory.hh"

SimpleMemory::SimpleMemory(AstraNetworkAPI *NI,double access_latency,double npu_access_bw_GB,double nic_access_bw_GB){
        this->last_request_serviced=0;
        this->request_count=0;
        this->NI=NI;
        this->access_latency=access_latency;
        this->npu_access_bw_GB=npu_access_bw_GB;
        this->nic_access_bw_GB=nic_access_bw_GB;
}
void SimpleMemory::set_network_api(AstraNetworkAPI *astraNetworkApi){
    this->NI=astraNetworkApi;
}
uint64_t SimpleMemory::npu_mem_read(uint64_t size){
    request_count++;
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/npu_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    //std::cout<<"node id: "<<NI->sim_comm_get_rank()<<", bytes: "<<size<<", access latency: "<<(uint64_t)(offset)
             //<<", current delay: "<<delay<<", total requests: "<<request_count<<std::endl;
    return (uint64_t)(offset);

}
uint64_t SimpleMemory::SimpleMemory::npu_mem_write(uint64_t size){
    request_count++;
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/npu_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    //std::cout<<"node id: "<<NI->sim_comm_get_rank()<<", bytes: "<<size<<", access latency: "<<(uint64_t)(offset)
             //<<", current delay: "<<delay<<", total requests: "<<request_count<<std::endl;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::nic_mem_read(uint64_t size){
    request_count++;
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/nic_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    //std::cout<<"node id: "<<NI->sim_comm_get_rank()<<", bytes: "<<size<<", access latency: "<<(uint64_t)(offset)
             //<<", current delay: "<<delay<<", total requests: "<<request_count<<std::endl;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::nic_mem_write(uint64_t size){
    request_count++;
    timespec_t time=NI->sim_get_time();
    double time_ns=time.time_val;
    double delay=access_latency+(size/nic_access_bw_GB);
    double max=last_request_serviced;
    if(max<time_ns){
        max=time_ns;
    }
    double offset=(max+delay)-time_ns;
    this->last_request_serviced=max+delay;
    //std::cout<<"node id: "<<NI->sim_comm_get_rank()<<", bytes: "<<size<<", access latency: "<<(uint64_t)(offset)
             //<<", current delay: "<<delay<<", total requests: "<<request_count<<std::endl;
    return (uint64_t)(offset);
}
uint64_t SimpleMemory::mem_read(uint64_t size){
    return nic_mem_read(size);
}
uint64_t SimpleMemory::mem_write(uint64_t size){
    return nic_mem_write(size);
}<|endoftext|>


<commit_before>/* -*- mode: c++; c-basic-offset:4 -*-
    dialogs/lookupcertificatesdialog.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2008 Klarälvdalens Datakonsult AB

    Kleopatra is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Kleopatra 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
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include <config-kleopatra.h>

#include "lookupcertificatesdialog.h"

#include "ui_lookupcertificatesdialog.h"

#include <models/keylistmodel.h>
#include <models/keylistsortfilterproxymodel.h>

#include <utils/headerview.h>
#include <utils/stl_util.h>

#include <gpgme++/key.h>

#include <KLineEdit>
#include <KLocale>

#include <QTreeView>
#include <QLayout>
#include <QPushButton>
#include <QHeaderView>
#include <QLabel>

#include <boost/bind.hpp>

#include <cassert>

static const bool ALLOW_MULTI_SELECTION = false;
static const bool ALLOW_MULTI_PROTOCOL  = false;

using namespace Kleo;
using namespace Kleo::Dialogs;
using namespace GpgME;
using namespace boost;

static const int minimalSearchTextLength = 2; // ### TODO: make that KIOSK-able

static const QHeaderView::ResizeMode resize_modes[AbstractKeyListModel::NumColumns] = {
    QHeaderView::Stretch,          // Name
    QHeaderView::Stretch, // EMail
    QHeaderView::Fixed, // Valid From
    QHeaderView::Fixed, // Valid Until
    QHeaderView::Fixed, // Details
    QHeaderView::Fixed, // Fingerprint
};

static void adjust_header( HeaderView * hv ) {
    for ( int i = 0, end = AbstractKeyListModel::NumColumns ; i < end ; ++i )
        hv->setSectionResizeMode( i, resize_modes[i] );
}

class LookupCertificatesDialog::Private {
    friend class ::Kleo::Dialogs::LookupCertificatesDialog;
    LookupCertificatesDialog * const q;
public:
    explicit Private( LookupCertificatesDialog * qq );
    ~Private();

private:
    void slotSelectionChanged() {
        enableDisableWidgets();
    }
    void slotSearchTextChanged() {
        enableDisableWidgets();
    }
    void slotSearchClicked() {
        emit q->searchTextChanged( ui.findED->text() );
    }
    void slotDetailsClicked() {
        assert( q->selectedCertificates().size() == 1 );
        emit q->detailsRequested( q->selectedCertificates().front() );
    }
    void slotSaveAsClicked() {
        emit q->saveAsRequested( q->selectedCertificates() );
    }

    void enableDisableWidgets();

    QString searchText() const { return ui.findED->text().trimmed(); }
    QModelIndexList selectedIndexes() const {
        if ( const QItemSelectionModel * const sm = ui.resultTV->selectionModel() )
            return sm->selectedRows();
        else
            return QModelIndexList();
    }
private:
    AbstractKeyListModel * model;
    KeyListSortFilterProxyModel proxy;
    bool passive;

    struct Ui : Ui_LookupCertificatesDialog {

        explicit Ui( LookupCertificatesDialog * q )
            : Ui_LookupCertificatesDialog()
        {
            setupUi( q );

            saveAsPB->hide(); // ### not yet implemented in LookupCertificatesCommand

            if ( !ALLOW_MULTI_SELECTION ) {
                resultTV->setSelectionMode( QAbstractItemView::SingleSelection );
                selectAllPB->hide();
                deselectAllPB->hide();
            }

            findED->setClearButtonShown( true );

            importPB()->setText( i18n("Import") );
            importPB()->setEnabled( false );

            HeaderView * hv = new HeaderView( Qt::Horizontal );
            KDAB_SET_OBJECT_NAME( hv );
            resultTV->setHeader( hv );
            adjust_header( hv );

            connect( resultTV,   SIGNAL(doubleClicked(QModelIndex)),
                     importPB(), SLOT(animateClick()) );

            findED->setFocus();
        }

        QPushButton * importPB() const { return buttonBox->button( QDialogButtonBox::Save ); }
        QPushButton * closePB()  const { return buttonBox->button( QDialogButtonBox::Close ); }
    } ui;
};

LookupCertificatesDialog::Private::Private( LookupCertificatesDialog * qq )
    : q( qq ),
      model( AbstractKeyListModel::createFlatKeyListModel() ),
      proxy(),
      passive( false ),
      ui( q )
{
    KDAB_SET_OBJECT_NAME( model );
    KDAB_SET_OBJECT_NAME( proxy );

    proxy.setSourceModel( model );
    ui.resultTV->setModel( &proxy );

    connect( ui.resultTV->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
             q, SLOT(slotSelectionChanged()) );
}

LookupCertificatesDialog::Private::~Private() {}

LookupCertificatesDialog::LookupCertificatesDialog( QWidget * p, Qt::WindowFlags f )
    : QDialog( p, f ), d( new Private( this ) )
{

}

LookupCertificatesDialog::~LookupCertificatesDialog() {}

void LookupCertificatesDialog::setCertificates( const std::vector<Key> & certs ) {
    d->model->setKeys( certs );
}

std::vector<Key> LookupCertificatesDialog::selectedCertificates() const {
    return d->proxy.keys( d->selectedIndexes() );
}

void LookupCertificatesDialog::setPassive( bool on ) {
    if ( d->passive == on )
        return;
    d->passive = on;
    d->enableDisableWidgets();
}

bool LookupCertificatesDialog::isPassive() const {
    return d->passive;
}

void LookupCertificatesDialog::accept() {
    assert( !d->selectedIndexes().empty() );
    emit importRequested( selectedCertificates() );
    QDialog::accept();
}

void LookupCertificatesDialog::Private::enableDisableWidgets() {
    // enable/disable everything except 'close', based on passive:
    Q_FOREACH( QObject * const o, q->children() )
        if ( QWidget * const w = qobject_cast<QWidget*>( o ) )
            w->setDisabled( passive && w != ui.closePB() && w != ui.buttonBox );

    if ( passive )
        return;

    ui.findPB->setEnabled( searchText().length() > minimalSearchTextLength );

    const std::vector<Key> selection = q->selectedCertificates();

    ui.detailsPB->setEnabled(   selection.size() == 1 );
    ui.saveAsPB->setEnabled(    selection.size() == 1 );
    if ( ALLOW_MULTI_SELECTION ) {
        // this is commented out until such a time as we know how to
        // import more than one key in one go.
        ui.importPB()->setEnabled( !selection.empty() &&
                                   ALLOW_MULTI_PROTOCOL ||
                                   // suppress mixed imports:
                                   kdtools::all( selection, bind( &Key::protocol, _1 ) == selection.front().protocol() ) );
    } else {
        ui.importPB()->setEnabled(  selection.size() == 1 );
    }
    ui.importPB()->setDefault( false ); // otherwise Import becomes default button if enabled and return triggers both a search and accept()
}

#include "moc_lookupcertificatesdialog.cpp"

<commit_msg>Adjust the column sizes to contents when keys have been received.<commit_after>/* -*- mode: c++; c-basic-offset:4 -*-
    dialogs/lookupcertificatesdialog.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2008 Klarälvdalens Datakonsult AB

    Kleopatra is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Kleopatra 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
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include <config-kleopatra.h>

#include "lookupcertificatesdialog.h"

#include "ui_lookupcertificatesdialog.h"

#include <models/keylistmodel.h>
#include <models/keylistsortfilterproxymodel.h>

#include <utils/headerview.h>
#include <utils/stl_util.h>

#include <gpgme++/key.h>

#include <KLineEdit>
#include <KLocale>

#include <QTreeView>
#include <QLayout>
#include <QPushButton>
#include <QHeaderView>
#include <QLabel>

#include <boost/bind.hpp>

#include <cassert>

static const bool ALLOW_MULTI_SELECTION = false;
static const bool ALLOW_MULTI_PROTOCOL  = false;

using namespace Kleo;
using namespace Kleo::Dialogs;
using namespace GpgME;
using namespace boost;

static const int minimalSearchTextLength = 2; // ### TODO: make that KIOSK-able

class LookupCertificatesDialog::Private {
    friend class ::Kleo::Dialogs::LookupCertificatesDialog;
    LookupCertificatesDialog * const q;
public:
    explicit Private( LookupCertificatesDialog * qq );
    ~Private();

private:
    void slotSelectionChanged() {
        enableDisableWidgets();
    }
    void slotSearchTextChanged() {
        enableDisableWidgets();
    }
    void slotSearchClicked() {
        emit q->searchTextChanged( ui.findED->text() );
    }
    void slotDetailsClicked() {
        assert( q->selectedCertificates().size() == 1 );
        emit q->detailsRequested( q->selectedCertificates().front() );
    }
    void slotSaveAsClicked() {
        emit q->saveAsRequested( q->selectedCertificates() );
    }

    void enableDisableWidgets();

    QString searchText() const { return ui.findED->text().trimmed(); }
    QModelIndexList selectedIndexes() const {
        if ( const QItemSelectionModel * const sm = ui.resultTV->selectionModel() )
            return sm->selectedRows();
        else
            return QModelIndexList();
    }
private:
    AbstractKeyListModel * model;
    KeyListSortFilterProxyModel proxy;
    bool passive;

    struct Ui : Ui_LookupCertificatesDialog {

        explicit Ui( LookupCertificatesDialog * q )
            : Ui_LookupCertificatesDialog()
        {
            setupUi( q );

            saveAsPB->hide(); // ### not yet implemented in LookupCertificatesCommand

            if ( !ALLOW_MULTI_SELECTION ) {
                resultTV->setSelectionMode( QAbstractItemView::SingleSelection );
                selectAllPB->hide();
                deselectAllPB->hide();
            }

            findED->setClearButtonShown( true );

            importPB()->setText( i18n("Import") );
            importPB()->setEnabled( false );

            HeaderView * hv = new HeaderView( Qt::Horizontal );
            KDAB_SET_OBJECT_NAME( hv );
            resultTV->setHeader( hv );

            connect( resultTV,   SIGNAL(doubleClicked(QModelIndex)),
                     importPB(), SLOT(animateClick()) );

            findED->setFocus();
        }

        QPushButton * importPB() const { return buttonBox->button( QDialogButtonBox::Save ); }
        QPushButton * closePB()  const { return buttonBox->button( QDialogButtonBox::Close ); }
    } ui;
};

LookupCertificatesDialog::Private::Private( LookupCertificatesDialog * qq )
    : q( qq ),
      model( AbstractKeyListModel::createFlatKeyListModel() ),
      proxy(),
      passive( false ),
      ui( q )
{
    KDAB_SET_OBJECT_NAME( model );
    KDAB_SET_OBJECT_NAME( proxy );

    proxy.setSourceModel( model );
    ui.resultTV->setModel( &proxy );

    connect( ui.resultTV->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
             q, SLOT(slotSelectionChanged()) );
}

LookupCertificatesDialog::Private::~Private() {}

LookupCertificatesDialog::LookupCertificatesDialog( QWidget * p, Qt::WindowFlags f )
    : QDialog( p, f ), d( new Private( this ) )
{

}

LookupCertificatesDialog::~LookupCertificatesDialog() {}

void LookupCertificatesDialog::setCertificates( const std::vector<Key> & certs ) {
    d->model->setKeys( certs );
    d->ui.resultTV->header()->resizeSections( QHeaderView::ResizeToContents );
}

std::vector<Key> LookupCertificatesDialog::selectedCertificates() const {
    return d->proxy.keys( d->selectedIndexes() );
}

void LookupCertificatesDialog::setPassive( bool on ) {
    if ( d->passive == on )
        return;
    d->passive = on;
    d->enableDisableWidgets();
}

bool LookupCertificatesDialog::isPassive() const {
    return d->passive;
}

void LookupCertificatesDialog::accept() {
    assert( !d->selectedIndexes().empty() );
    emit importRequested( selectedCertificates() );
    QDialog::accept();
}

void LookupCertificatesDialog::Private::enableDisableWidgets() {
    // enable/disable everything except 'close', based on passive:
    Q_FOREACH( QObject * const o, q->children() )
        if ( QWidget * const w = qobject_cast<QWidget*>( o ) )
            w->setDisabled( passive && w != ui.closePB() && w != ui.buttonBox );

    if ( passive )
        return;

    ui.findPB->setEnabled( searchText().length() > minimalSearchTextLength );

    const std::vector<Key> selection = q->selectedCertificates();

    ui.detailsPB->setEnabled(   selection.size() == 1 );
    ui.saveAsPB->setEnabled(    selection.size() == 1 );
    if ( ALLOW_MULTI_SELECTION ) {
        // this is commented out until such a time as we know how to
        // import more than one key in one go.
        ui.importPB()->setEnabled( !selection.empty() &&
                                   ALLOW_MULTI_PROTOCOL ||
                                   // suppress mixed imports:
                                   kdtools::all( selection, bind( &Key::protocol, _1 ) == selection.front().protocol() ) );
    } else {
        ui.importPB()->setEnabled(  selection.size() == 1 );
    }
    ui.importPB()->setDefault( false ); // otherwise Import becomes default button if enabled and return triggers both a search and accept()
}

#include "moc_lookupcertificatesdialog.cpp"

<|endoftext|>


<commit_before>/* -*- mode: c++; c-basic-offset:4 -*-
    uiserver/signencryptfilescommand.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2007 Klarälvdalens Datakonsult AB

    Kleopatra is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Kleopatra 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
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include <config-kleopatra.h>

#include "signencryptfilescommand.h"

#include <crypto/signencryptfilescontroller.h>

#include <utils/exception.h>

#include <KLocale>

using namespace Kleo;
using namespace Kleo::Crypto;
using namespace boost;

class SignEncryptFilesCommand::Private : public QObject {
    Q_OBJECT
private:
    friend class ::Kleo::SignEncryptFilesCommand;
    SignEncryptFilesCommand * const q;
public:
    explicit Private( SignEncryptFilesCommand * qq )
        : q( qq ),
          controller()
    {

    }

private:
    void checkForErrors() const;

private Q_SLOTS:
    void slotDone();
    void slotError( int, const QString & );

private:
    shared_ptr<SignEncryptFilesController> controller;
};

SignEncryptFilesCommand::SignEncryptFilesCommand()
    : AssuanCommandMixin<SignEncryptFilesCommand>(), d( new Private( this ) )
{

}

SignEncryptFilesCommand::~SignEncryptFilesCommand() {}

void SignEncryptFilesCommand::Private::checkForErrors() const {

    if ( !q->numFiles() )
        throw Exception( makeError( GPG_ERR_ASS_NO_INPUT ),
                         i18n("At least one FILE must be present") );

    if ( !q->senders().empty() )
        throw Exception( makeError( GPG_ERR_CONFLICT ),
                         i18n( "%1 is a filemanager mode command, "
                               "connection seems to be in email mode (%2 present)",
                               QString::fromLatin1( q->name() ), QLatin1String("SENDER") ) );
    if ( !q->recipients().empty() )
        throw Exception( makeError( GPG_ERR_CONFLICT ),
                         i18n( "%1 is a filemanager mode command, "
                               "connection seems to be in email mode (%2 present)",
                               QString::fromLatin1( q->name() ), QLatin1String("RECIPIENT") ) );

    if ( !q->inputs().empty() )
        throw Exception( makeError( GPG_ERR_CONFLICT ),
                         i18n( "%1 is a filemanager mode command, "
                               "connection seems to be in email mode (%2 present)",
                               QString::fromLatin1( q->name() ), QLatin1String("INPUT") ) );
    if ( !q->outputs().empty() )
        throw Exception( makeError( GPG_ERR_CONFLICT ),
                         i18n( "%1 is a filemanager mode command, "
                               "connection seems to be in email mode (%2 present)",
                               QString::fromLatin1( q->name() ), QLatin1String("OUTPUT") ) );
    if ( !q->messages().empty() )
        throw Exception( makeError( GPG_ERR_CONFLICT ),
                         i18n( "%1 is a filemanager mode command, "
                               "connection seems to be in email mode (%2 present)",
                               QString::fromLatin1( q->name() ), QLatin1String("MESSAGE") ) );
}

int SignEncryptFilesCommand::doStart() {

    d->checkForErrors();

    d->controller.reset( new SignEncryptFilesController( shared_from_this() ) );

    d->controller->setProtocol( checkProtocol( FileManager ) );
    d->controller->setOperationMode( operation() );
    d->controller->setFiles( fileNames() );

    QObject::connect( d->controller.get(), SIGNAL(done()), d.get(), SLOT(slotDone()), Qt::QueuedConnection );
    QObject::connect( d->controller.get(), SIGNAL(error(int,QString)), d.get(), SLOT(slotError(int,QString)), Qt::QueuedConnection );

    d->controller->start();

    return 0;
}

void SignEncryptFilesCommand::Private::slotDone() {
    q->done();
}

void SignEncryptFilesCommand::Private::slotError( int err, const QString & details ) {
    q->done( err, details );
}

void SignEncryptFilesCommand::doCanceled() {
    if ( d->controller )
        d->controller->cancel();
}

#include "signencryptfilescommand.moc"

<commit_msg>SignEncryptFilesCommand: teach the uiserver the --archive option which requests to create an archive of the selected files before signing/encrypting<commit_after>/* -*- mode: c++; c-basic-offset:4 -*-
    uiserver/signencryptfilescommand.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2007 Klarälvdalens Datakonsult AB

    Kleopatra is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Kleopatra 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
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include <config-kleopatra.h>

#include "signencryptfilescommand.h"

#include <crypto/signencryptfilescontroller.h>

#include <utils/exception.h>

#include <KLocale>

using namespace Kleo;
using namespace Kleo::Crypto;
using namespace boost;

class SignEncryptFilesCommand::Private : public QObject {
    Q_OBJECT
private:
    friend class ::Kleo::SignEncryptFilesCommand;
    SignEncryptFilesCommand * const q;
public:
    explicit Private( SignEncryptFilesCommand * qq )
        : q( qq ),
          controller()
    {

    }

private:
    void checkForErrors() const;

private Q_SLOTS:
    void slotDone();
    void slotError( int, const QString & );

private:
    shared_ptr<SignEncryptFilesController> controller;
};

SignEncryptFilesCommand::SignEncryptFilesCommand()
    : AssuanCommandMixin<SignEncryptFilesCommand>(), d( new Private( this ) )
{

}

SignEncryptFilesCommand::~SignEncryptFilesCommand() {}

void SignEncryptFilesCommand::Private::checkForErrors() const {

    if ( !q->numFiles() )
        throw Exception( makeError( GPG_ERR_ASS_NO_INPUT ),
                         i18n("At least one FILE must be present") );

    if ( !q->senders().empty() )
        throw Exception( makeError( GPG_ERR_CONFLICT ),
                         i18n( "%1 is a filemanager mode command, "
                               "connection seems to be in email mode (%2 present)",
                               QString::fromLatin1( q->name() ), QLatin1String("SENDER") ) );
    if ( !q->recipients().empty() )
        throw Exception( makeError( GPG_ERR_CONFLICT ),
                         i18n( "%1 is a filemanager mode command, "
                               "connection seems to be in email mode (%2 present)",
                               QString::fromLatin1( q->name() ), QLatin1String("RECIPIENT") ) );

    if ( !q->inputs().empty() )
        throw Exception( makeError( GPG_ERR_CONFLICT ),
                         i18n( "%1 is a filemanager mode command, "
                               "connection seems to be in email mode (%2 present)",
                               QString::fromLatin1( q->name() ), QLatin1String("INPUT") ) );
    if ( !q->outputs().empty() )
        throw Exception( makeError( GPG_ERR_CONFLICT ),
                         i18n( "%1 is a filemanager mode command, "
                               "connection seems to be in email mode (%2 present)",
                               QString::fromLatin1( q->name() ), QLatin1String("OUTPUT") ) );
    if ( !q->messages().empty() )
        throw Exception( makeError( GPG_ERR_CONFLICT ),
                         i18n( "%1 is a filemanager mode command, "
                               "connection seems to be in email mode (%2 present)",
                               QString::fromLatin1( q->name() ), QLatin1String("MESSAGE") ) );
}

int SignEncryptFilesCommand::doStart() {

    d->checkForErrors();

    d->controller.reset( new SignEncryptFilesController( shared_from_this() ) );

    d->controller->setProtocol( checkProtocol( FileManager ) );

    unsigned int op = operation();
    if ( hasOption( "archive" ) )
        op |= SignEncryptFilesController::ArchiveForced;
    else
        op |= SignEncryptFilesController::ArchiveAllowed;
    d->controller->setOperationMode( op );
    d->controller->setFiles( fileNames() );

    QObject::connect( d->controller.get(), SIGNAL(done()), d.get(), SLOT(slotDone()), Qt::QueuedConnection );
    QObject::connect( d->controller.get(), SIGNAL(error(int,QString)), d.get(), SLOT(slotError(int,QString)), Qt::QueuedConnection );

    d->controller->start();

    return 0;
}

void SignEncryptFilesCommand::Private::slotDone() {
    q->done();
}

void SignEncryptFilesCommand::Private::slotError( int err, const QString & details ) {
    q->done( err, details );
}

void SignEncryptFilesCommand::doCanceled() {
    if ( d->controller )
        d->controller->cancel();
}

#include "signencryptfilescommand.moc"

<|endoftext|>