<commit_before>/*
 * Copyright (c) 2011-2014 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/client/zeromq_socket.hpp>

namespace libbitcoin {
namespace client {

BC_API zeromq_socket::~zeromq_socket()
{
    if (socket_)
        zmq_close(socket_);
}

BC_API zeromq_socket::zeromq_socket(void* context, int type)
  : socket_(nullptr)
{
    socket_ = zmq_socket(context, type);
    if (socket_)
    {
        // Do not wait for unsent messages when shutting down:
        int linger = 0;
        zmq_setsockopt(socket_, ZMQ_LINGER, &linger, sizeof(linger));
    }
}

BC_API bool zeromq_socket::connect(const std::string& address)
{
    return socket_ && 0 <= zmq_connect(socket_, address.c_str());
}

BC_API bool zeromq_socket::bind(const std::string& address)
{
    return socket_ && 0 <= zmq_bind(socket_, address.c_str());
}

BC_API zmq_pollitem_t zeromq_socket::pollitem()
{
    return zmq_pollitem_t
    {
        socket_, 0, ZMQ_POLLIN, 0
    };
}

BC_API bool zeromq_socket::forward(message_stream& dest)
{
    while (pending())
    {
        zmq_msg_t msg;
        zmq_msg_init(&msg);

        if (zmq_msg_recv(&msg, socket_, ZMQ_DONTWAIT) < 0)
            return false;

        const char* raw = reinterpret_cast<const char*>(zmq_msg_data(&msg));
        libbitcoin::data_chunk data(raw, raw + zmq_msg_size(&msg));
        dest.message(data, zmq_msg_more(&msg));
        zmq_msg_close(&msg);
    }
    return true;
}

BC_API bool zeromq_socket::forward(zeromq_socket& dest)
{
    while (pending())
    {
        zmq_msg_t msg;
        zmq_msg_init(&msg);

        if (zmq_msg_recv(&msg, socket_, ZMQ_DONTWAIT) < 0)
            return false;

        int flags = 0;
        if (zmq_msg_more(&msg))
            flags = ZMQ_SNDMORE;
        if (zmq_msg_send(&msg, dest.socket_, flags) < 0)
        {
            zmq_msg_close(&msg);
            return false;
        }

    }
    return true;
}

BC_API void zeromq_socket::message(const data_chunk& data, bool more)
{
    int flags = 0;
    if (more)
        flags = ZMQ_SNDMORE;
    // The message won't go through if this fails,
    // but we are prepared for that possibility anyhow:
    zmq_send(socket_, data.data(), data.size(), flags);
}

bool zeromq_socket::pending()
{
    int events = 0;
    size_t size = sizeof(events);
    if (zmq_getsockopt(socket_, ZMQ_EVENTS, &events, &size) < 0)
        return false;
    return events & ZMQ_POLLIN;
}

} // namespace client
} // namespace libbitcoin
<commit_msg>Assert that the socket is used correctly<commit_after>/*
 * Copyright (c) 2011-2014 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/client/zeromq_socket.hpp>

namespace libbitcoin {
namespace client {

BC_API zeromq_socket::~zeromq_socket()
{
    if (socket_)
        zmq_close(socket_);
}

BC_API zeromq_socket::zeromq_socket(void* context, int type)
  : socket_(nullptr)
{
    socket_ = zmq_socket(context, type);
    if (socket_)
    {
        // Do not wait for unsent messages when shutting down:
        int linger = 0;
        zmq_setsockopt(socket_, ZMQ_LINGER, &linger, sizeof(linger));
    }
}

BC_API bool zeromq_socket::connect(const std::string& address)
{
    return socket_ && 0 <= zmq_connect(socket_, address.c_str());
}

BC_API bool zeromq_socket::bind(const std::string& address)
{
    return socket_ && 0 <= zmq_bind(socket_, address.c_str());
}

BC_API zmq_pollitem_t zeromq_socket::pollitem()
{
    BITCOIN_ASSERT(socket_);

    return zmq_pollitem_t
    {
        socket_, 0, ZMQ_POLLIN, 0
    };
}

BC_API bool zeromq_socket::forward(message_stream& dest)
{
    BITCOIN_ASSERT(socket_);

    while (pending())
    {
        zmq_msg_t msg;
        zmq_msg_init(&msg);

        if (zmq_msg_recv(&msg, socket_, ZMQ_DONTWAIT) < 0)
            return false;

        const char* raw = reinterpret_cast<const char*>(zmq_msg_data(&msg));
        libbitcoin::data_chunk data(raw, raw + zmq_msg_size(&msg));
        dest.message(data, zmq_msg_more(&msg));
        zmq_msg_close(&msg);
    }
    return true;
}

BC_API bool zeromq_socket::forward(zeromq_socket& dest)
{
    BITCOIN_ASSERT(socket_);

    while (pending())
    {
        zmq_msg_t msg;
        zmq_msg_init(&msg);

        if (zmq_msg_recv(&msg, socket_, ZMQ_DONTWAIT) < 0)
            return false;

        int flags = 0;
        if (zmq_msg_more(&msg))
            flags = ZMQ_SNDMORE;
        if (zmq_msg_send(&msg, dest.socket_, flags) < 0)
        {
            zmq_msg_close(&msg);
            return false;
        }

    }
    return true;
}

BC_API void zeromq_socket::message(const data_chunk& data, bool more)
{
    BITCOIN_ASSERT(socket_);

    int flags = 0;
    if (more)
        flags = ZMQ_SNDMORE;
    // The message won't go through if this fails,
    // but we are prepared for that possibility anyhow:
    zmq_send(socket_, data.data(), data.size(), flags);
}

bool zeromq_socket::pending()
{
    int events = 0;
    size_t size = sizeof(events);
    if (zmq_getsockopt(socket_, ZMQ_EVENTS, &events, &size) < 0)
        return false;
    return events & ZMQ_POLLIN;
}

} // namespace client
} // namespace libbitcoin
<|endoftext|>


<commit_before>//
// Created by Scott Stark on 3/30/15.
//

#include <string.h>
#include <sys/sysinfo.h>
#include <sys/time.h>
#include "HealthStatus.h"

const string HealthStatus::statusPropertyNames[static_cast<unsigned int>(StatusProperties::N_STATUS_PROPERTIES)] = {
        string("ScannerID"),
        string("SystemTime"),
        string("Uptime"),
        string("Procs"),
        string("LoadAverage"),
        string("RawEventCount"),
        string("PublishEventCount"),
        string("HeartbeatCount"),
        string("HeartbeatRSSI"),
        string("EventsWindow"),
        string("MemTotal"),
        string("MemFree"),
        string("MemAvailable"),
        string("SwapTotal"),
        string("SwapFree"),
};

void HealthStatus::monitorStatus() {
    int statusInterval = statusInformation->getStatusInterval();
    const string& statusQueue = statusInformation->getStatusQueue();
    const string& scannerID = statusInformation->getScannerID();
    Properties statusProperties;
    const string& ScannerID = getStatusPropertyName(StatusProperties::ScannerID);
    const string& SystemTime = getStatusPropertyName(StatusProperties::SystemTime);
    const string& Uptime = getStatusPropertyName(StatusProperties::Uptime);
    const string& LoadAverage = getStatusPropertyName(StatusProperties::LoadAverage);
    const string& Procs = getStatusPropertyName(StatusProperties::Procs);
    const string& RawEventCount = getStatusPropertyName(StatusProperties::RawEventCount);
    const string& PublishEventCount = getStatusPropertyName(StatusProperties::PublishEventCount);
    const string& HeartbeatCount = getStatusPropertyName(StatusProperties::HeartbeatCount);
    const string& HeartbeatRSSI = getStatusPropertyName(StatusProperties::HeartbeatRSSI);
    const string& EventsWindow = getStatusPropertyName(StatusProperties::EventsWindow);
    const string& MemTotal = getStatusPropertyName(StatusProperties::MemTotal);
    const string& MemFree = getStatusPropertyName(StatusProperties::MemFree);
    const string& MemActive = getStatusPropertyName(StatusProperties::MemActive);
    const string& SwapTotal = getStatusPropertyName(StatusProperties::SwapTotal);
    const string& SwapFree = getStatusPropertyName(StatusProperties::SwapFree);
    struct timeval  tv;
    struct tm *tm;

    while(running) {
        // Wait for statusInterval before
        this_thread::sleep_for(chrono::seconds(statusInterval));

        statusProperties[ScannerID] = scannerID;

        // Time
        gettimeofday(&tv, nullptr);
        tm = localtime(&tv.tv_sec);
        char timestr[256];
        strftime(timestr, 128, "%F %T", tm);
        statusProperties[SystemTime] = timestr;
        printf("--- HealthStatus: %s\n", timestr);

        // Get the load average
        char tmp[128];
        readLoadAvg(tmp, sizeof(tmp));
        // Create the status message properties
        statusProperties[LoadAverage] = tmp;
        statusProperties[RawEventCount] = to_string(statusInformation->getRawEventCount());
        statusProperties[PublishEventCount] = to_string(statusInformation->getPublishEventCount());
        statusProperties[HeartbeatCount] = to_string(statusInformation->getHeartbeatCount());
        statusProperties[HeartbeatRSSI] = to_string(statusInformation->getHeartbeatRSSI());
        printf("RawEventCount: %d, PublishEventCount: %d, HeartbeatCount: %d, HeartbeatRSSI: %d\n",  statusInformation->getRawEventCount(),
               statusInformation->getPublishEventCount(), statusInformation->getHeartbeatCount(), statusInformation->getHeartbeatRSSI());

        // Events bucket info
        shared_ptr<EventsBucket> eventsBucket(statusInformation->getStatusWindow());
        vector<char> eventsBucketStr;
        eventsBucket->toSimpleString(eventsBucketStr);
        statusProperties[EventsWindow] = eventsBucketStr.data();

        // System uptime, load, procs, memory info
        struct sysinfo info;
        if(sysinfo(&info)) {
            perror("Failed to read sysinfo");
        } else {
            int mb = 1024*1024;
            int days = info.uptime / (24*3600);
            int hours = (info.uptime - days * 24*3600) / 3600;
            int minute = (info.uptime - days * 24*3600 - hours*3600) / 60;
            sprintf(tmp, "uptime: %ld, days:%d, hrs: %d, min: %d", info.uptime, days, hours, minute);
            statusProperties[Uptime] = tmp;
            printf("%s\n", tmp);
            sprintf(tmp, "%.2f, %.2f, %.2f", info.loads[0]/65536.0, info.loads[1]/65536.0, info.loads[2]/65536.0);
            printf("loadavg: %s\n", tmp);
            statusProperties[LoadAverage] = tmp;
            statusProperties[Procs] = to_string(info.procs);
            statusProperties[MemTotal] = to_string(info.totalram*info.mem_unit / mb);
            printf("MemTotal: %ld;  MemFree: %ld\n", info.totalram*info.mem_unit,  info.freeram*info.mem_unit);
            statusProperties[MemActive] = to_string((info.totalram - info.freeram)*info.mem_unit / mb);
            statusProperties[MemFree] = to_string(info.freeram*info.mem_unit / mb);
            statusProperties[SwapFree] = to_string(info.freeswap*info.mem_unit / mb);
            statusProperties[SwapTotal] = to_string(info.totalswap*info.mem_unit / mb);
        }
        fflush(stdout);

        // Publish the status
        try {
            publisher->publishProperties(statusQueue, statusProperties);
        } catch(exception& e) {
            fprintf(stderr, "Failed to send status, %s\n", e.what());
        }
    }
}

/** Begin monitoring in the background, sending status messages to the indicated queue via the publisher
*/
void HealthStatus::start(shared_ptr<MsgPublisher>& publisher, shared_ptr<StatusInformation>& statusInformation) {
    running = true;
    this->statusInformation = statusInformation;
    this->publisher = publisher;
    monitorThread.reset(new thread(&HealthStatus::monitorStatus, this));
}

/**
 * Reset any counters
 */
void HealthStatus::reset() {

}
void HealthStatus::stop() {
    running = false;
    if(monitorThread->joinable())
        monitorThread->join();
}

void HealthStatus::readLoadAvg(char *buffer, int size) {
    FILE *loadavg = fopen ("/proc/loadavg", "r");
    if (loadavg == NULL) {
        perror ("Failed to open /proc/loadavg");
    }

    if (!fgets (buffer, size, loadavg)){
        perror ("Failed to read /proc/loadavg");
    }
    fclose(loadavg);
    // Replace trailing newline char with nil
    size_t length = strlen(buffer);
    buffer[length-1] = '\0';
}

void HealthStatus::readMeminfo(Properties& properties) {
    FILE *meminfo = fopen ("/proc/meminfo", "r");
    if (meminfo == NULL) {
        perror ("Failed to open /proc/meminfo");
    }

    char buffer[64];
    const string& MemTotal = getStatusPropertyName(StatusProperties::MemTotal);
    const string& MemFree = getStatusPropertyName(StatusProperties::MemFree);
    const string& MemAvailable = getStatusPropertyName(StatusProperties::MemActive);
    const string& SwapTotal = getStatusPropertyName(StatusProperties::SwapTotal);
    const string& SwapFree = getStatusPropertyName(StatusProperties::SwapFree);
    while(fgets (buffer, sizeof(buffer), meminfo)){
        // Replace trailing newline char with nil
        size_t length = strlen(buffer);
        buffer[length-1] = '\0';
        if(MemTotal.compare(0, MemTotal.size(), buffer, length))
            properties[MemTotal] = buffer;
        else if(MemFree.compare(0, MemFree.size(), buffer, length))
            properties[MemFree] = buffer;
        else if(MemAvailable.compare(0, MemAvailable.size(), buffer, length))
            properties[MemAvailable] = buffer;
        else if(SwapTotal.compare(0, SwapTotal.size(), buffer, length))
            properties[SwapTotal] = buffer;
        else if(SwapFree.compare(0, SwapFree.size(), buffer, length))
            properties[SwapFree] = buffer;
    }
    fclose(meminfo);

}
<commit_msg>Validate the the events bucket is not null<commit_after>//
// Created by Scott Stark on 3/30/15.
//

#include <string.h>
#include <sys/sysinfo.h>
#include <sys/time.h>
#include "HealthStatus.h"

const string HealthStatus::statusPropertyNames[static_cast<unsigned int>(StatusProperties::N_STATUS_PROPERTIES)] = {
        string("ScannerID"),
        string("SystemTime"),
        string("Uptime"),
        string("Procs"),
        string("LoadAverage"),
        string("RawEventCount"),
        string("PublishEventCount"),
        string("HeartbeatCount"),
        string("HeartbeatRSSI"),
        string("EventsWindow"),
        string("MemTotal"),
        string("MemFree"),
        string("MemAvailable"),
        string("SwapTotal"),
        string("SwapFree"),
};

void HealthStatus::monitorStatus() {
    int statusInterval = statusInformation->getStatusInterval();
    const string& statusQueue = statusInformation->getStatusQueue();
    const string& scannerID = statusInformation->getScannerID();
    Properties statusProperties;
    const string& ScannerID = getStatusPropertyName(StatusProperties::ScannerID);
    const string& SystemTime = getStatusPropertyName(StatusProperties::SystemTime);
    const string& Uptime = getStatusPropertyName(StatusProperties::Uptime);
    const string& LoadAverage = getStatusPropertyName(StatusProperties::LoadAverage);
    const string& Procs = getStatusPropertyName(StatusProperties::Procs);
    const string& RawEventCount = getStatusPropertyName(StatusProperties::RawEventCount);
    const string& PublishEventCount = getStatusPropertyName(StatusProperties::PublishEventCount);
    const string& HeartbeatCount = getStatusPropertyName(StatusProperties::HeartbeatCount);
    const string& HeartbeatRSSI = getStatusPropertyName(StatusProperties::HeartbeatRSSI);
    const string& EventsWindow = getStatusPropertyName(StatusProperties::EventsWindow);
    const string& MemTotal = getStatusPropertyName(StatusProperties::MemTotal);
    const string& MemFree = getStatusPropertyName(StatusProperties::MemFree);
    const string& MemActive = getStatusPropertyName(StatusProperties::MemActive);
    const string& SwapTotal = getStatusPropertyName(StatusProperties::SwapTotal);
    const string& SwapFree = getStatusPropertyName(StatusProperties::SwapFree);
    struct timeval  tv;
    struct tm *tm;

    while(running) {
        // Wait for statusInterval before
        this_thread::sleep_for(chrono::seconds(statusInterval));

        statusProperties[ScannerID] = scannerID;

        // Time
        gettimeofday(&tv, nullptr);
        tm = localtime(&tv.tv_sec);
        char timestr[256];
        strftime(timestr, 128, "%F %T", tm);
        statusProperties[SystemTime] = timestr;
        printf("--- HealthStatus: %s\n", timestr);

        // Get the load average
        char tmp[128];
        readLoadAvg(tmp, sizeof(tmp));
        // Create the status message properties
        statusProperties[LoadAverage] = tmp;
        statusProperties[RawEventCount] = to_string(statusInformation->getRawEventCount());
        statusProperties[PublishEventCount] = to_string(statusInformation->getPublishEventCount());
        statusProperties[HeartbeatCount] = to_string(statusInformation->getHeartbeatCount());
        statusProperties[HeartbeatRSSI] = to_string(statusInformation->getHeartbeatRSSI());
        printf("RawEventCount: %d, PublishEventCount: %d, HeartbeatCount: %d, HeartbeatRSSI: %d\n",  statusInformation->getRawEventCount(),
               statusInformation->getPublishEventCount(), statusInformation->getHeartbeatCount(), statusInformation->getHeartbeatRSSI());

        // Events bucket info
        shared_ptr<EventsBucket> eventsBucket(statusInformation->getStatusWindow());
        if(eventsBucket) {
            vector<char> eventsBucketStr;
            eventsBucket->toSimpleString(eventsBucketStr);
            statusProperties[EventsWindow] = eventsBucketStr.data();
        }

        // System uptime, load, procs, memory info
        struct sysinfo info;
        if(sysinfo(&info)) {
            perror("Failed to read sysinfo");
        } else {
            int mb = 1024*1024;
            int days = info.uptime / (24*3600);
            int hours = (info.uptime - days * 24*3600) / 3600;
            int minute = (info.uptime - days * 24*3600 - hours*3600) / 60;
            sprintf(tmp, "uptime: %ld, days:%d, hrs: %d, min: %d", info.uptime, days, hours, minute);
            statusProperties[Uptime] = tmp;
            printf("%s\n", tmp);
            sprintf(tmp, "%.2f, %.2f, %.2f", info.loads[0]/65536.0, info.loads[1]/65536.0, info.loads[2]/65536.0);
            printf("loadavg: %s\n", tmp);
            statusProperties[LoadAverage] = tmp;
            statusProperties[Procs] = to_string(info.procs);
            statusProperties[MemTotal] = to_string(info.totalram*info.mem_unit / mb);
            printf("MemTotal: %ld;  MemFree: %ld\n", info.totalram*info.mem_unit,  info.freeram*info.mem_unit);
            statusProperties[MemActive] = to_string((info.totalram - info.freeram)*info.mem_unit / mb);
            statusProperties[MemFree] = to_string(info.freeram*info.mem_unit / mb);
            statusProperties[SwapFree] = to_string(info.freeswap*info.mem_unit / mb);
            statusProperties[SwapTotal] = to_string(info.totalswap*info.mem_unit / mb);
        }
        fflush(stdout);

        // Publish the status
        try {
            publisher->publishProperties(statusQueue, statusProperties);
        } catch(exception& e) {
            fprintf(stderr, "Failed to send status, %s\n", e.what());
        }
    }
}

/** Begin monitoring in the background, sending status messages to the indicated queue via the publisher
*/
void HealthStatus::start(shared_ptr<MsgPublisher>& publisher, shared_ptr<StatusInformation>& statusInformation) {
    running = true;
    this->statusInformation = statusInformation;
    this->publisher = publisher;
    monitorThread.reset(new thread(&HealthStatus::monitorStatus, this));
}

/**
 * Reset any counters
 */
void HealthStatus::reset() {

}
void HealthStatus::stop() {
    running = false;
    if(monitorThread->joinable())
        monitorThread->join();
}

void HealthStatus::readLoadAvg(char *buffer, int size) {
    FILE *loadavg = fopen ("/proc/loadavg", "r");
    if (loadavg == NULL) {
        perror ("Failed to open /proc/loadavg");
    }

    if (!fgets (buffer, size, loadavg)){
        perror ("Failed to read /proc/loadavg");
    }
    fclose(loadavg);
    // Replace trailing newline char with nil
    size_t length = strlen(buffer);
    buffer[length-1] = '\0';
}

void HealthStatus::readMeminfo(Properties& properties) {
    FILE *meminfo = fopen ("/proc/meminfo", "r");
    if (meminfo == NULL) {
        perror ("Failed to open /proc/meminfo");
    }

    char buffer[64];
    const string& MemTotal = getStatusPropertyName(StatusProperties::MemTotal);
    const string& MemFree = getStatusPropertyName(StatusProperties::MemFree);
    const string& MemAvailable = getStatusPropertyName(StatusProperties::MemActive);
    const string& SwapTotal = getStatusPropertyName(StatusProperties::SwapTotal);
    const string& SwapFree = getStatusPropertyName(StatusProperties::SwapFree);
    while(fgets (buffer, sizeof(buffer), meminfo)){
        // Replace trailing newline char with nil
        size_t length = strlen(buffer);
        buffer[length-1] = '\0';
        if(MemTotal.compare(0, MemTotal.size(), buffer, length))
            properties[MemTotal] = buffer;
        else if(MemFree.compare(0, MemFree.size(), buffer, length))
            properties[MemFree] = buffer;
        else if(MemAvailable.compare(0, MemAvailable.size(), buffer, length))
            properties[MemAvailable] = buffer;
        else if(SwapTotal.compare(0, SwapTotal.size(), buffer, length))
            properties[SwapTotal] = buffer;
        else if(SwapFree.compare(0, SwapFree.size(), buffer, length))
            properties[SwapFree] = buffer;
    }
    fclose(meminfo);

}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_OBJECT_ACCESSOR_HPP
#define REALM_OBJECT_ACCESSOR_HPP

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

namespace realm {
    template<typename ValueType, typename ContextType>
    class NativeAccessor {
    public:
        //
        // Value converters - template specializations must be implemented for each platform
        //
        static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);

        static bool to_bool(ContextType ctx, ValueType &val);
        static long long to_long(ContextType ctx, ValueType &val);
        static float to_float(ContextType ctx, ValueType &val);
        static double to_double(ContextType ctx, ValueType &val);
        static std::string to_string(ContextType ctx, ValueType &val);
        static DateTime to_datetime(ContextType ctx, ValueType &val);

        static bool is_null(ContextType ctx, ValueType &val);

        // convert value to persisted object
        // for existing objects return the existing row index
        // for new/updated objects return the row index
        static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update);

        // array value acessors
        static size_t array_size(ContextType ctx, ValueType &val);
        static ValueType array_value_at_index(ContextType ctx, ValueType &val, size_t index);

        //
        // Deprecated
        //
        static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); }
    };

    class Object {
    public:
        Object(SharedRealm &r, ObjectSchema &s, Row o) : realm(r), object_schema(s), row(o) {}
        // FIXME - all should be const
        SharedRealm realm;
        ObjectSchema &object_schema;
        Row row;

        // property setter
        template<typename ValueType, typename ContextType>
        inline void set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update);

        // create an Object from a native representation
        template<typename ValueType, typename ContextType>
        static inline Object create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update);

    private:
        template<typename ValueType, typename ContextType>
        inline void set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update);
    };

    //
    // template method implementations
    //
    template <typename ValueType, typename ContextType>
    inline void Object::set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update)
    {
        Property *prop = object_schema.property_for_name(prop_name);
        if (!prop) {
            throw std::runtime_error("Setting invalid property '" + prop_name + "' on object '" + object_schema.name + "'.");
        }
        set_property_value_impl(ctx, *prop, value, try_update);
    };

    template <typename ValueType, typename ContextType>
    inline void Object::set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update)
    {
        using Accessor = NativeAccessor<ValueType, ContextType>;

        size_t column = property.table_column;
        switch (property.type) {
            case PropertyTypeBool:
                row.set_bool(column, Accessor::to_bool(ctx, value));
                break;
            case PropertyTypeInt:
                row.set_int(column, Accessor::to_long(ctx, value));
                break;
            case PropertyTypeFloat:
                row.set_float(column, Accessor::to_float(ctx, value));
                break;
            case PropertyTypeDouble:
                row.set_double(column, Accessor::to_double(ctx, value));
                break;
            case PropertyTypeString:
                row.set_string(column, Accessor::to_string(ctx, value));
                break;
            case PropertyTypeData:
                row.set_binary(column, BinaryData(Accessor::to_string(ctx, value)));
                break;
            case PropertyTypeAny:
                row.set_mixed(column, Accessor::to_mixed(ctx, value));
                break;
            case PropertyTypeDate:
                row.set_datetime(column, Accessor::to_datetime(ctx, value));
                break;
            case PropertyTypeObject: {
                if (Accessor::is_null(ctx, value)) {
                    row.nullify_link(column);
                }
                else {
                    row.set_link(column, Accessor::to_object_index(ctx, realm, value, property.object_type, try_update));
                }
                break;
            }
            case PropertyTypeArray: {
                realm::LinkViewRef link_view = row.get_linklist(column);
                link_view->clear();
                size_t count = Accessor::array_size(ctx, value);
                for (size_t i = 0; i < count; i++) {
                    ValueType element = Accessor::array_value_at_index(ctx, value, i);
                    link_view->add(Accessor::to_object_index(ctx, realm, element, property.object_type, try_update));
                }
                break;
            }
        }
    }

    template<typename ValueType, typename ContextType>
    inline Object Object::create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update)
    {
        using Accessor = NativeAccessor<ValueType, ContextType>;

        if (!realm->is_in_transaction()) {
            throw std::runtime_error("Can only create objects within a transaction.");
        }

        // get or create our accessor
        bool created;

        // try to get existing row if updating
        size_t row_index = realm::not_found;
        realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name);
        Property *primary_prop = object_schema.primary_key_property();
        if (primary_prop) {
            // search for existing object based on primary key type
            ValueType primary_value = Accessor::dict_value_for_key(ctx, value, object_schema.primary_key);
            if (primary_prop->type == PropertyTypeString) {
                row_index = table->find_first_string(primary_prop->table_column, Accessor::to_string(ctx, primary_value));
            }
            else {
                row_index = table->find_first_int(primary_prop->table_column, Accessor::to_long(ctx, primary_value));
            }

            if (!try_update && row_index != realm::not_found) {
                throw std::runtime_error("Attempting to create an object of type '" + object_schema.name + "' with an exising primary key value.");
            }
        }

        // if no existing, create row
        created = false;
        if (row_index == realm::not_found) {
            row_index = table->add_empty_row();
            created = true;
        }

        // populate
        Object object(realm, object_schema, table->get(row_index));
        for (Property &prop : object_schema.properties) {
            ValueType prop_value = Accessor::dict_value_for_key(ctx, value, prop.name);
            if (prop_value) {
                if (created || !prop.is_primary) {
                    object.set_property_value_impl(ctx, prop, prop_value, try_update);
                }
            }
            else if (created) {
                throw std::runtime_error("Missing property value for property " + prop.name);
            }
        }
        return object;
    }
}

#endif /* defined(REALM_OBJECT_ACCESSOR_HPP) */
<commit_msg>fix for partial update of string properties<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_OBJECT_ACCESSOR_HPP
#define REALM_OBJECT_ACCESSOR_HPP

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

namespace realm {
    template<typename ValueType, typename ContextType>
    class NativeAccessor {
    public:
        //
        // Value converters - template specializations must be implemented for each platform
        //
        static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
        static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);

        static bool to_bool(ContextType ctx, ValueType &val);
        static long long to_long(ContextType ctx, ValueType &val);
        static float to_float(ContextType ctx, ValueType &val);
        static double to_double(ContextType ctx, ValueType &val);
        static std::string to_string(ContextType ctx, ValueType &val);
        static DateTime to_datetime(ContextType ctx, ValueType &val);

        static bool is_null(ContextType ctx, ValueType &val);

        // convert value to persisted object
        // for existing objects return the existing row index
        // for new/updated objects return the row index
        static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update);

        // array value acessors
        static size_t array_size(ContextType ctx, ValueType &val);
        static ValueType array_value_at_index(ContextType ctx, ValueType &val, size_t index);

        //
        // Deprecated
        //
        static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); }
    };

    class Object {
    public:
        Object(SharedRealm &r, ObjectSchema &s, Row o) : realm(r), object_schema(s), row(o) {}
        // FIXME - all should be const
        SharedRealm realm;
        ObjectSchema &object_schema;
        Row row;

        // property setter
        template<typename ValueType, typename ContextType>
        inline void set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update);

        // create an Object from a native representation
        template<typename ValueType, typename ContextType>
        static inline Object create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update);

    private:
        template<typename ValueType, typename ContextType>
        inline void set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update);
    };

    //
    // template method implementations
    //
    template <typename ValueType, typename ContextType>
    inline void Object::set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update)
    {
        Property *prop = object_schema.property_for_name(prop_name);
        if (!prop) {
            throw std::runtime_error("Setting invalid property '" + prop_name + "' on object '" + object_schema.name + "'.");
        }
        set_property_value_impl(ctx, *prop, value, try_update);
    };

    template <typename ValueType, typename ContextType>
    inline void Object::set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update)
    {
        using Accessor = NativeAccessor<ValueType, ContextType>;

        size_t column = property.table_column;
        switch (property.type) {
            case PropertyTypeBool:
                row.set_bool(column, Accessor::to_bool(ctx, value));
                break;
            case PropertyTypeInt:
                row.set_int(column, Accessor::to_long(ctx, value));
                break;
            case PropertyTypeFloat:
                row.set_float(column, Accessor::to_float(ctx, value));
                break;
            case PropertyTypeDouble:
                row.set_double(column, Accessor::to_double(ctx, value));
                break;
            case PropertyTypeString:
                row.set_string(column, Accessor::to_string(ctx, value));
                break;
            case PropertyTypeData:
                row.set_binary(column, BinaryData(Accessor::to_string(ctx, value)));
                break;
            case PropertyTypeAny:
                row.set_mixed(column, Accessor::to_mixed(ctx, value));
                break;
            case PropertyTypeDate:
                row.set_datetime(column, Accessor::to_datetime(ctx, value));
                break;
            case PropertyTypeObject: {
                if (Accessor::is_null(ctx, value)) {
                    row.nullify_link(column);
                }
                else {
                    row.set_link(column, Accessor::to_object_index(ctx, realm, value, property.object_type, try_update));
                }
                break;
            }
            case PropertyTypeArray: {
                realm::LinkViewRef link_view = row.get_linklist(column);
                link_view->clear();
                size_t count = Accessor::array_size(ctx, value);
                for (size_t i = 0; i < count; i++) {
                    ValueType element = Accessor::array_value_at_index(ctx, value, i);
                    link_view->add(Accessor::to_object_index(ctx, realm, element, property.object_type, try_update));
                }
                break;
            }
        }
    }

    template<typename ValueType, typename ContextType>
    inline Object Object::create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update)
    {
        using Accessor = NativeAccessor<ValueType, ContextType>;

        if (!realm->is_in_transaction()) {
            throw std::runtime_error("Can only create objects within a transaction.");
        }

        // get or create our accessor
        bool created;

        // try to get existing row if updating
        size_t row_index = realm::not_found;
        realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name);
        Property *primary_prop = object_schema.primary_key_property();
        if (primary_prop) {
            // search for existing object based on primary key type
            ValueType primary_value = Accessor::dict_value_for_key(ctx, value, object_schema.primary_key);
            if (primary_prop->type == PropertyTypeString) {
                row_index = table->find_first_string(primary_prop->table_column, Accessor::to_string(ctx, primary_value));
            }
            else {
                row_index = table->find_first_int(primary_prop->table_column, Accessor::to_long(ctx, primary_value));
            }

            if (!try_update && row_index != realm::not_found) {
                throw std::runtime_error("Attempting to create an object of type '" + object_schema.name + "' with an exising primary key value.");
            }
        }

        // if no existing, create row
        created = false;
        if (row_index == realm::not_found) {
            row_index = table->add_empty_row();
            created = true;
        }

        // populate
        Object object(realm, object_schema, table->get(row_index));
        for (Property &prop : object_schema.properties) {
            if (Accessor::dict_has_value_for_key(ctx, value, prop.name)) {
                if (created || !prop.is_primary) {
                    ValueType prop_value = Accessor::dict_value_for_key(ctx, value, prop.name);
                    object.set_property_value_impl(ctx, prop, prop_value, try_update);
                }
            }
            else if (created) {
                throw std::runtime_error("Missing property value for property " + prop.name);
            }
        }
        return object;
    }
}

#endif /* defined(REALM_OBJECT_ACCESSOR_HPP) */
<|endoftext|>


<commit_before>

/*
题意：

一条直线有N个村庄，要建p个邮局，使距离和最小。

思路：
明显dp：先处理各个区间的最短的距离（打表）。
dis[i][j]=dis[i][j-1]+x[j]-x[(i+j)/2]; （村庄位置为x[i]）
dp[i][j]为i个村庄j个邮局的最短距离。
dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][i])

*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <cstring>
#include <string>
#include <vector>
#include <iomanip>
#include <cmath>
#include <list>
#include <bitset>

using namespace std;

#define ll long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1

typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, double>pdd;

const double eps = 1e-6;
const ll  LINF = 0x3f3f3f3f3f3f3f3fLL;
const int INF = 0x3f3f3f3f;
const double FINF = 1e18;

#define x first
#define y second

#define REP(i,j,k) for(int i =(j);i<=(k);i++)
#define REPD(i,j,k) for(int i =(j);i>=(k);i--)
#define print(x) cout<<(x)<<endl;
#define IOS ios::sync_with_stdio(0);cin.tie(0);

int dp[500][35]={0};
int dis[500][500]={0};
int x[500];

int v,p,i,j,k;

void printarray2(int* a,int len1,int len2){

	REP(i,0,len1-1){
		REP(j,0,len2-1){
			cout<<(a+i*len2+j);
		}
		cout<<endl;
	}
}
void Init(){

	scanf("%d%d",&v,&p);
	REP(i,1,v)
		scanf("%d",&x[i]);

	return ;
}

void Solve(){
	REP(i,1,v)
        REP(j,i+1,v)
            dis[i][j]=dis[i][j-1]+x[j]-x[(i+j)/2];
 	printarray2((int *) dis,v+1,v+1);
    REP(i,1,v)
    {
        dp[i][i]=0;
        dp[i][1]=dis[1][i]; //只有一个邮局
    }

    REP(j,2,p)
        REP(i,j+1,v)
        {
        	dp[i][j]=INF;
            REP(k,j-1,i-1)
            {
                dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][i]);
            }
        }

    print(dp[v][p]);

	return ;
}

int main(){
#ifdef LOCAL
	freopen("poj1160.in","r",stdin);
#endif

	Init(),Solve();
	return 0;
}<commit_msg>update poj1160<commit_after>

/*
题意：

一条直线有N个村庄，要建p个邮局，使距离和最小。

思路：
明显dp：先处理各个区间的最短的距离（打表）。
dis[i][j]=dis[i][j-1]+x[j]-x[(i+j)/2]; （村庄位置为x[i]）
dp[i][j]为i个村庄j个邮局的最短距离。
dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][i])

*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <cstring>
#include <string>
#include <vector>
#include <iomanip>
#include <cmath>
#include <list>
#include <bitset>

using namespace std;

#define ll long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1

typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, double>pdd;

const double eps = 1e-6;
const ll  LINF = 0x3f3f3f3f3f3f3f3fLL;
const int INF = 0x3f3f3f3f;
const double FINF = 1e18;

#define x first
#define y second

#define REP(i,j,k) for(int i =(j);i<=(k);i++)
#define REPD(i,j,k) for(int i =(j);i>=(k);i--)
#define print(x) cout<<(x)<<endl;
#define IOS ios::sync_with_stdio(0);cin.tie(0);

int dp[500][35]={0};
int dis[500][500]={0};
int x[500];

int v,p,i,j,k;

void printarray2(int* a,int len1,int len2){

	REP(i,0,len1-1){
		REP(j,0,len2-1){
			cout<<(a+i*len2+j);
		}
		cout<<endl;
	}
}
void Init(){

	scanf("%d%d",&v,&p);
	REP(i,1,v)
		scanf("%d",&x[i]);

	return ;
}

void Solve(){
	REP(i,1,v)
        REP(j,i+1,v)
            dis[i][j]=dis[i][j-1]+x[j]-x[(i+j)/2];
 	printarray2((int *) dis,v+1,v+1);
 	cout<<dis[2][2];
    REP(i,1,v)
    {
        dp[i][i]=0;
        dp[i][1]=dis[1][i]; //只有一个邮局
    }

    REP(j,2,p)
        REP(i,j+1,v)
        {
        	dp[i][j]=INF;
            REP(k,j-1,i-1)
            {
                dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][i]);
            }
        }

    print(dp[v][p]);

	return ;
}

int main(){
#ifdef LOCAL
	freopen("poj1160.in","r",stdin);
#endif

	Init(),Solve();
	return 0;
}<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
 *
 * This 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.  See file COPYING.
 *
 * Simple little program to let you:
 * 1) View the layout information on a file or directory,
 * 2) Modify the layout information on an empty file,
 * 3) Modify the default layout on a directory
 */

#include <iostream>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include "client/ioctl.h"

using namespace std;

#define CMD_SHOW_LAYOUT 1
#define CMD_SHOW_LOC    2
#define CMD_SET_LAYOUT  3

void usage();
int init_options(int argc, char **argv, int *fd, char **path, int *cmd,
                 int *stripe_unit, int *stripe_count,
                 int *object_size, int *pool, int* osd, int *file_offset, bool *dir);
int get_layout(int fd, struct ceph_ioctl_layout *layout);
int get_location(int fd, struct ceph_ioctl_dataloc *location);

int main (int argc, char **argv) {
  int fd = 0;
  int err = 0;
  struct ceph_ioctl_layout layout;
  struct ceph_ioctl_dataloc location;
  char *path = 0;
  int cmd = 0;
  int stripe_unit = 0;
  int stripe_count = 0;
  int object_size = 0;
  int pool = 0;
  int osd = 0;
  int file_offset = 0;
  bool dir = false;

  if (init_options(argc, argv, &fd, &path, &cmd, &stripe_unit, &stripe_count,
                   &object_size, &pool, &osd, &file_offset, &dir)){
    usage();
    return 0;
  }

  if (CMD_SHOW_LAYOUT == cmd) {
    struct ceph_ioctl_layout layout;
    memset(&layout, 0, sizeof(layout));
    err = ioctl(fd, CEPH_IOC_GET_LAYOUT, (unsigned long)&layout);
    if (err) {
      cerr << "Error getting layout: "
	   << (err == -1 ? strerror(errno) : strerror(-err)) << endl;
      return 1;
    }
    if (layout.stripe_unit == 0) {
      cerr << "layout not specified" << endl;
    } else {
      cout << "layout.data_pool:     " << layout.data_pool << endl;
      cout << "layout.object_size:   " << layout.object_size << endl;
      cout << "layout.stripe_unit:   " << layout.stripe_unit << endl;
      cout << "layout.stripe_count:  " << layout.stripe_count << endl;
      cout << "layout.preferred_osd: " << layout.preferred_osd << endl;
    }
  } else if (CMD_SHOW_LOC == cmd) {
    struct ceph_ioctl_dataloc location;
    location.file_offset = file_offset;
    err = ioctl(fd, CEPH_IOC_GET_DATALOC, (unsigned long)&location);
    if (err) {
      cerr << "Error getting location: "
	   << (err == -1 ? strerror(errno) : strerror(-err)) << endl;
      return 1;
    }
    cout << "location.file_offset:  " << location.file_offset << endl;
    cout << "location.object_offset:" << location.object_offset << endl;
    cout << "location.object_no:    " << location.object_no << endl;
    cout << "location.object_size:  " << location.object_size << endl;
    cout << "location.object_name:  " << location.object_name << endl;
    cout << "location.block_offset: " << location.block_offset << endl;
    cout << "location.block_size:   " << location.block_size << endl;
    cout << "location.osd:          " << location.osd << endl;
//    cout << "osd address:           " << location.osd_addr << endl;
  } else if (CMD_SET_LAYOUT == cmd) {
    struct ceph_ioctl_layout layout;
    memset(&layout, 0, sizeof(layout));
    int ioctl_num = (dir ? CEPH_IOC_SET_LAYOUT_POLICY : CEPH_IOC_SET_LAYOUT);
    layout.data_pool = pool;
    layout.object_size = object_size;
    layout.preferred_osd = osd;
    layout.stripe_count = stripe_count;
    layout.stripe_unit = stripe_unit;
    err = ioctl(fd, ioctl_num, (unsigned long)&layout);
    if (err) {
      cerr << "Error setting layout: "
	   << (err == -1 ? strerror(errno) : strerror(-err)) << endl;
      return 1;
    }
  } else {
    cerr << "unknown cmd somehow set!" << endl;
    usage();
    return 1;
  }

  return 0;
}

void usage() {
  cerr << "usage: cephfs path command [options]*" << endl;
  cerr << "Commands:" << endl;
  cerr << "   show_layout    -- view the layout information on a file or dir" << endl;
  cerr << "   set_layout     -- set the layout on an empty file,\n"
       << "                     or the default layout on a directory" << endl;
  cerr << "   show_location  -- view the location information on a file" << endl;
  cerr << "Options:" << endl;
  cerr << "   Useful for setting layouts:" << endl;
  cerr << "   --stripe_unit, -u:  set the size of each stripe" << endl;
  cerr << "   --stripe_count, -c: set the number of stripes per object" << endl;
  cerr << "   --object_size, -s:  set the size of the objects to stripe across" << endl;
  cerr << "   --pool, -p:         set the pool to use" << endl;
  cerr << "   --osd, -o:          set the preferred osd to use as primary" << endl;
  cerr << endl;
  cerr << "   Useful for getting location data:" << endl;
  cerr << "   --offset, -l:       the offset to retrieve location data for" << endl;
  cerr << endl;
}

int init_options(int argc, char **argv, int *fd, char **path, int *cmd,
                 int *stripe_unit, int *stripe_count,
                 int *object_size, int *pool, int* osd, int *file_offset,
                 bool *dir) {
  // look through the options, make sure they're valid,
  // and set the variables from them
  int i = 3;
  struct stat stat_field;

  if (argc < 3) {
    cerr << "not enough parameters!" << endl;
    return 1;
  }

  *path = argv[1];

  *fd = open(argv[1], O_RDONLY);
  if (*fd < 0) {
    cerr << "error opening path: " << strerror(*fd) << endl;
  }

  if (!strcmp(argv[2], "show_layout")) {
    *cmd = CMD_SHOW_LAYOUT;
    if (argc > 4)
      return 1;
  } else if (!strcmp(argv[2], "set_layout")) {
    *cmd = CMD_SET_LAYOUT;
  } else if (!strcmp(argv[2], "show_location")){
    *cmd = CMD_SHOW_LOC;
  } else {
    cerr << "invalid command" << endl;
    return 1;
  }

  // okay, fill in options
  while (i < argc) {
    if (i == argc-1) {
      // there's an option without an associated value!
      cerr << "not all options are paired with a value!" << endl;
      return 1;
    }

    if (!strcmp(argv[i], "--stripe_unit") || argv[i][1] == 'u') {
      if (*cmd != CMD_SET_LAYOUT) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *stripe_unit = atoi(argv[i+1]);
      if (!*stripe_unit) {
        cerr << "invalid value for stripe unit" << endl;
        return 1;
      }
    } else if (!strcmp(argv[i], "--stripe_count") || argv[i][1] == 'c') {
      if (*cmd != CMD_SET_LAYOUT) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *stripe_count = atoi(argv[i+1]);
      if (!*stripe_count) {
        cerr << "invalid value for stripe count" << endl;
        return 1;
      }
    } else if (!strcmp(argv[i], "--object_size") || argv[i][1] == 's') {
      if (*cmd != CMD_SET_LAYOUT) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *object_size = atoi(argv[i+1]);
      if (!*object_size) {
        cerr << "invalid value for object size" << endl;
        return 1;
      }
    } else if (!strcmp(argv[i], "--pool") || argv[i][1] == 'p') {
      if (*cmd != CMD_SET_LAYOUT) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *pool= atoi(argv[i+1]);
      if (!*pool) {
        cerr << "invalid value for pool" << endl;
        return 1;
      }
    } else if (!strcmp(argv[i], "--osd") || argv[i][1] == 'o') {
      if (*cmd != CMD_SET_LAYOUT) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *osd = atoi(argv[i+1]);
      if (!*osd) {
        cerr << "invalid value for osd" << endl;
        return 1;
      }
    } else if (!strcmp(argv[i], "--offset") || argv[i][1] == 'l') {
      if (*cmd != CMD_SHOW_LOC) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *file_offset = atoi(argv[i+1]);
      if (!*file_offset) {
        cerr << "invalid value for offset" << endl;
        return 1;
      }
    }
    i += 2;
  }

  fstat (*fd, &stat_field);
  if (S_ISREG(stat_field.st_mode)) { // open read-write to set layout
    close(*fd);
    *fd = open(argv[1], O_RDWR);
    if (*fd < 0) {
      cerr << "error opening file" << endl;
      return 1;
    }
  } else {
    *dir = true;
  }

  return 0;
}
<commit_msg>cephfs: remove unused variables<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
 *
 * This 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.  See file COPYING.
 *
 * Simple little program to let you:
 * 1) View the layout information on a file or directory,
 * 2) Modify the layout information on an empty file,
 * 3) Modify the default layout on a directory
 */

#include <iostream>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include "client/ioctl.h"

using namespace std;

#define CMD_SHOW_LAYOUT 1
#define CMD_SHOW_LOC    2
#define CMD_SET_LAYOUT  3

void usage();
int init_options(int argc, char **argv, int *fd, char **path, int *cmd,
                 int *stripe_unit, int *stripe_count,
                 int *object_size, int *pool, int* osd, int *file_offset, bool *dir);
int get_layout(int fd, struct ceph_ioctl_layout *layout);
int get_location(int fd, struct ceph_ioctl_dataloc *location);

int main (int argc, char **argv) {
  int fd = 0;
  int err = 0;
  char *path = 0;
  int cmd = 0;
  int stripe_unit = 0;
  int stripe_count = 0;
  int object_size = 0;
  int pool = 0;
  int osd = 0;
  int file_offset = 0;
  bool dir = false;

  if (init_options(argc, argv, &fd, &path, &cmd, &stripe_unit, &stripe_count,
                   &object_size, &pool, &osd, &file_offset, &dir)){
    usage();
    return 0;
  }

  if (CMD_SHOW_LAYOUT == cmd) {
    struct ceph_ioctl_layout layout;
    memset(&layout, 0, sizeof(layout));
    err = ioctl(fd, CEPH_IOC_GET_LAYOUT, (unsigned long)&layout);
    if (err) {
      cerr << "Error getting layout: "
	   << (err == -1 ? strerror(errno) : strerror(-err)) << endl;
      return 1;
    }
    if (layout.stripe_unit == 0) {
      cerr << "layout not specified" << endl;
    } else {
      cout << "layout.data_pool:     " << layout.data_pool << endl;
      cout << "layout.object_size:   " << layout.object_size << endl;
      cout << "layout.stripe_unit:   " << layout.stripe_unit << endl;
      cout << "layout.stripe_count:  " << layout.stripe_count << endl;
      cout << "layout.preferred_osd: " << layout.preferred_osd << endl;
    }
  } else if (CMD_SHOW_LOC == cmd) {
    struct ceph_ioctl_dataloc location;
    location.file_offset = file_offset;
    err = ioctl(fd, CEPH_IOC_GET_DATALOC, (unsigned long)&location);
    if (err) {
      cerr << "Error getting location: "
	   << (err == -1 ? strerror(errno) : strerror(-err)) << endl;
      return 1;
    }
    cout << "location.file_offset:  " << location.file_offset << endl;
    cout << "location.object_offset:" << location.object_offset << endl;
    cout << "location.object_no:    " << location.object_no << endl;
    cout << "location.object_size:  " << location.object_size << endl;
    cout << "location.object_name:  " << location.object_name << endl;
    cout << "location.block_offset: " << location.block_offset << endl;
    cout << "location.block_size:   " << location.block_size << endl;
    cout << "location.osd:          " << location.osd << endl;
//    cout << "osd address:           " << location.osd_addr << endl;
  } else if (CMD_SET_LAYOUT == cmd) {
    struct ceph_ioctl_layout layout;
    memset(&layout, 0, sizeof(layout));
    int ioctl_num = (dir ? CEPH_IOC_SET_LAYOUT_POLICY : CEPH_IOC_SET_LAYOUT);
    layout.data_pool = pool;
    layout.object_size = object_size;
    layout.preferred_osd = osd;
    layout.stripe_count = stripe_count;
    layout.stripe_unit = stripe_unit;
    err = ioctl(fd, ioctl_num, (unsigned long)&layout);
    if (err) {
      cerr << "Error setting layout: "
	   << (err == -1 ? strerror(errno) : strerror(-err)) << endl;
      return 1;
    }
  } else {
    cerr << "unknown cmd somehow set!" << endl;
    usage();
    return 1;
  }

  return 0;
}

void usage() {
  cerr << "usage: cephfs path command [options]*" << endl;
  cerr << "Commands:" << endl;
  cerr << "   show_layout    -- view the layout information on a file or dir" << endl;
  cerr << "   set_layout     -- set the layout on an empty file,\n"
       << "                     or the default layout on a directory" << endl;
  cerr << "   show_location  -- view the location information on a file" << endl;
  cerr << "Options:" << endl;
  cerr << "   Useful for setting layouts:" << endl;
  cerr << "   --stripe_unit, -u:  set the size of each stripe" << endl;
  cerr << "   --stripe_count, -c: set the number of stripes per object" << endl;
  cerr << "   --object_size, -s:  set the size of the objects to stripe across" << endl;
  cerr << "   --pool, -p:         set the pool to use" << endl;
  cerr << "   --osd, -o:          set the preferred osd to use as primary" << endl;
  cerr << endl;
  cerr << "   Useful for getting location data:" << endl;
  cerr << "   --offset, -l:       the offset to retrieve location data for" << endl;
  cerr << endl;
}

int init_options(int argc, char **argv, int *fd, char **path, int *cmd,
                 int *stripe_unit, int *stripe_count,
                 int *object_size, int *pool, int* osd, int *file_offset,
                 bool *dir) {
  // look through the options, make sure they're valid,
  // and set the variables from them
  int i = 3;
  struct stat stat_field;

  if (argc < 3) {
    cerr << "not enough parameters!" << endl;
    return 1;
  }

  *path = argv[1];

  *fd = open(argv[1], O_RDONLY);
  if (*fd < 0) {
    cerr << "error opening path: " << strerror(*fd) << endl;
  }

  if (!strcmp(argv[2], "show_layout")) {
    *cmd = CMD_SHOW_LAYOUT;
    if (argc > 4)
      return 1;
  } else if (!strcmp(argv[2], "set_layout")) {
    *cmd = CMD_SET_LAYOUT;
  } else if (!strcmp(argv[2], "show_location")){
    *cmd = CMD_SHOW_LOC;
  } else {
    cerr << "invalid command" << endl;
    return 1;
  }

  // okay, fill in options
  while (i < argc) {
    if (i == argc-1) {
      // there's an option without an associated value!
      cerr << "not all options are paired with a value!" << endl;
      return 1;
    }

    if (!strcmp(argv[i], "--stripe_unit") || argv[i][1] == 'u') {
      if (*cmd != CMD_SET_LAYOUT) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *stripe_unit = atoi(argv[i+1]);
      if (!*stripe_unit) {
        cerr << "invalid value for stripe unit" << endl;
        return 1;
      }
    } else if (!strcmp(argv[i], "--stripe_count") || argv[i][1] == 'c') {
      if (*cmd != CMD_SET_LAYOUT) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *stripe_count = atoi(argv[i+1]);
      if (!*stripe_count) {
        cerr << "invalid value for stripe count" << endl;
        return 1;
      }
    } else if (!strcmp(argv[i], "--object_size") || argv[i][1] == 's') {
      if (*cmd != CMD_SET_LAYOUT) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *object_size = atoi(argv[i+1]);
      if (!*object_size) {
        cerr << "invalid value for object size" << endl;
        return 1;
      }
    } else if (!strcmp(argv[i], "--pool") || argv[i][1] == 'p') {
      if (*cmd != CMD_SET_LAYOUT) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *pool= atoi(argv[i+1]);
      if (!*pool) {
        cerr << "invalid value for pool" << endl;
        return 1;
      }
    } else if (!strcmp(argv[i], "--osd") || argv[i][1] == 'o') {
      if (*cmd != CMD_SET_LAYOUT) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *osd = atoi(argv[i+1]);
      if (!*osd) {
        cerr << "invalid value for osd" << endl;
        return 1;
      }
    } else if (!strcmp(argv[i], "--offset") || argv[i][1] == 'l') {
      if (*cmd != CMD_SHOW_LOC) {
        cerr << "Invalid option for command!" << endl;
        return 1;
      }
      *file_offset = atoi(argv[i+1]);
      if (!*file_offset) {
        cerr << "invalid value for offset" << endl;
        return 1;
      }
    }
    i += 2;
  }

  fstat (*fd, &stat_field);
  if (S_ISREG(stat_field.st_mode)) { // open read-write to set layout
    close(*fd);
    *fd = open(argv[1], O_RDWR);
    if (*fd < 0) {
      cerr << "error opening file" << endl;
      return 1;
    }
  } else {
    *dir = true;
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
FAST corner detection from scratch
by Sammy Hasan
2017
*/

# include <opencv2/opencv.hpp>
# include <iostream>
# include <vector>

using namespace std;
using namespace cv;

bool isCorner(Mat,int,vector<int>* ,vector<int>* ,int );
void circle_vals(int,vector<int>*,vector<int>*);

/* MAIN ()*/
int main(){

  int window_size = 7; // 7x7
  int intensity_thr = 42;
  int contig = 9; // min number of required contigous pixels for a corner

  vector<int>* ixX_s = new vector<int>();
  vector<int>* ixY_s = new vector<int>();

  circle_vals(window_size);
  // vectors are now populated

  Mat image,grey_image,roi;
  image = imread("./image.jpg",CV_U8C1);

  // convert to greyscale
  cvColor(image,grey_image,CV_BGR2GRAY);

  // slide over the input image
  for(int x=0;x<grey_image.rows-window_size;x++){
    for(int y=0;y<grey_image.cols-window_size;y++){
      roi = grey_image(Rect(x,y,window_size,window_size))
      if (isCorner(roi,intensity_thr,pixels,contig)){
        circle(image,Point(x+window_size/2-1,y+window_size/2-1),4,Scalar(136,50,203),2);
      }
    }
  }

  namedWindow("Original",WIDOW_AUTOSIZE);
  imshow("Original",image);

  waitKey(0);

  return 0;
}

bool isCorner(Mat window,int thr,vector<int>* pix_x,vector<int>* pix_y,int cont_N){

  // check if pixel intenisties are larger than thr from centre intenisty
  int cntr_pix_I = window.at<int>(window/2,window/2);
  int pix_I = 0;
  int x,y;

  vector<bool> thr_test = new vector<bool>();

  for (int v=0;v<pix_x->size()<v++){
    x = pix_x(v);
    y = pix_y(v);

    pix_I = window.at<int>(x,y);
    thr_test.push_back(abs(pix_I-cntr_pix_I) >= thr);
  }

  // thr_test now populated using threshold test

  // quick check (1,9),(5,13) points for edge
  // (1,9)
  if (thr_test(0) && thr_test(9)){
    // (5,13)
    if(thr_test(4) && thr_test(12)){

      // perform full check with contingency
      // looping over thr_test
      bool cached = thr_test(0);
      int cont_count = 0;
      for(int l=1;l<thr_test.size();l++){
        if(thr_test(l) == cached){
          cont_count++;
        }else{
          cont_count = 0;
          cached = thr_test(l);
        }
      }
      return cont_count >= cont_N;

    }

  }else{
    return false;
  }
  return false;

}

void circle_vals(int mask_dim,vector<int>* ixX_s,vector<int>* ixY_s){

  Mat mask = Mat::zeros(mask_dim+2,mask_dim+2,CV_8UC1); // +2: padding on each side
  int midPt = mask_dim/2;
  circle(mask,Point(midPt,midPt),midPt,Scalar(255),1);
  mask.at<int>(1,midPt-1) = 0; // directs the search
  // starting at mid of top row, pixel 1:
  // indeces start from 0,
  int x_row = 1;
  int y_col = midPt;

  int brk_flag = 0;
  int inc = 0;
  while(inc<(mask_dim+1)*2) // while white pixels havent been all counted
  {

    mask.at<int>(x_row,y_col) = 0; // done with element
    ixX_s->push_back(x_row-1);
    ixY_s->push_back(y_col-1);

    brk_flag = 0;
    for(int xp = -1;xp<2;xp++){
      for(int yp = -1;yp<2;yp++){
        if(mask.at<int>(x_row+xp,y_col+yp) == 255){
          x_row += xp;
          y_col += yp;
          brk_flag = 1;
          break;

        }
      }
      // break from second for loop
      if (brk_flag == 1)
        break;
    }

    inc++;
  }

  ixX_s->push_back(0);
  ixY_s->push_back(midPt-2); // -2 =  for padding (-1) + last pixel in loop (-1)

}
<commit_msg>'working' version<commit_after>/*
FAST corner detection from scratch
by Sammy Hasan
2017
*/

# include <opencv2/opencv.hpp>
# include <iostream>
# include <vector>
# include <string>

using namespace std;
using namespace cv;

bool isCorner(Mat,int,vector<int>* ,vector<int>* ,int );
void circle_vals(int,vector<int>*,vector<int>*);

void debug(String text){
  cerr << text << endl;
}

/* MAIN ()*/
int main(int argc,char** argv){

  int window_size = 7; // 7x7
  int intensity_thr = atoi(argv[1]);
  cout << "intensity_thr: " << intensity_thr << endl;
  int contig = 12; // min number of required contigous pixels for a corner

  vector<int>* ixX_s = new vector<int>();
  vector<int>* ixY_s = new vector<int>();

  circle_vals(window_size,ixX_s,ixY_s);
  // vectors are now populated

  Mat grey_image,roi;
  grey_image = imread("./image2.jpg",CV_LOAD_IMAGE_GRAYSCALE); // also converts to grey scale

  // slide over the input image
  for(int x=0;x<grey_image.cols-window_size;x++){
    for(int y=0;y<grey_image.rows-window_size;y++){
      roi = grey_image(Rect(x,y,window_size,window_size));

      // check if corner exists:
      if (isCorner(roi,intensity_thr,ixX_s,ixY_s,contig)){
        circle(grey_image,Point(x+window_size/2-1,y+window_size/2-1),4,255,1);
      }

    }
  }

  namedWindow("Original",WINDOW_AUTOSIZE);
  imshow("Original",grey_image);

  waitKey(0);

  return 0;
}

bool isCorner(const Mat window,int thr,vector<int>* pix_x,vector<int>* pix_y,int cont_N){

  // check if pixel intenisties are larger than thr from centre intenisty
  int cntr_pix_I = window.at<uchar>(window.rows/2,window.cols/2);
  int pix_I = 0;
  int x,y;

  vector<bool> thr_test;

  for (int v=0;v<pix_x->size();v++){
    x = pix_x->at(v);
    y = pix_y->at(v);

    pix_I = (int)window.at<uchar>(x,y);
    thr_test.push_back(abs(pix_I-cntr_pix_I) >= thr);
  }

  // thr_test now populated using threshold test

  // quick check (1,9),(5,13) points for edge
  // (1,9)
  if (thr_test.at(0) && thr_test.at(9)){
    // (5,13)
    if(thr_test.at(4) && thr_test.at(12)){
      // perform full check with contingency
      // looping over thr_test
      bool cached = thr_test.at(0);
      int cont_count = 0;
      for(int l=1;l<thr_test.size();l++){
        if(thr_test.at(l) == cached){
          cont_count++;
        }else{
          cont_count = 0;
          cached = thr_test.at(l);
        }
      }
      return cont_count >= cont_N;

    }

  }else{
    return false;
  }
  return false;

}

void circle_vals(int mask_dim,vector<int>* ixX_s,vector<int>* ixY_s){

  Mat mask = Mat::zeros(mask_dim+2,mask_dim+2,CV_8UC1); // +2: padding on each side
  int midPt = mask_dim/2;
  circle(mask,Point(midPt,midPt),midPt,Scalar(255),1);
  mask.at<uchar>(1,midPt-1) = 0; // directs the search
  // starting at mid of top row, pixel 1:
  // indeces start from 0,
  int x_row = 1;
  int y_col = midPt;

  int brk_flag = 0;
  int inc = 0;
  while(inc<(mask_dim+1)*2) // while white pixels havent been all counted
  {

    mask.at<int>(x_row,y_col) = 0; // done with element
    ixX_s->push_back(x_row-1);
    ixY_s->push_back(y_col-1);

    brk_flag = 0;
    for(int xp = -1;xp<2;xp++){
      for(int yp = -1;yp<2;yp++){
        if((int)mask.at<uchar>(x_row+xp,y_col+yp) == 255){
          x_row += xp;
          y_col += yp;
          brk_flag = 1;
          break;

        }
      }
      // break from second for loop
      if (brk_flag == 1)
        break;
    }

    inc++;
  }

  ixX_s->push_back(0);
  ixY_s->push_back(midPt-2); // -2 =  for padding (-1) + last pixel in loop (-1)

}
<|endoftext|>


<commit_before>/* client.cc - gpgex assuan client implementation
   Copyright (C) 2007, 2008, 2013, 2014 g10 Code GmbH

   This file is part of GpgEX.

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

   GpgEX 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 program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301, USA.  */

#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <vector>
#include <string>
#include <stdexcept>

using std::vector;
using std::string;

#include <winsock2.h>
#include <windows.h>

#include <assuan.h>

#include "main.h"
#include "registry.h"
#include "exechelp.h"

#include "client.h"

static inline char *
_gpgex_stpcpy (char *a, const char *b)
{
  while (*b)
    *a++ = *b++;
  *a = 0;
  return a;
}
#define stpcpy(a,b) _gpgex_stpcpy ((a), (b))

static const char *
default_socket_name (void)
{
  static string name;

  if (name.size () == 0)
    {
      char *dir = NULL;

      dir = default_homedir ();
      if (dir)
	{
	  try { name = ((string) dir) + "\\S.uiserver"; } catch (...) {}
	  free ((void *) dir);
	}
    }

  return name.c_str ();
}

/* Return the name of the default UI server.  This name is used to
   auto start an UI server if an initial connect failed.  */
static const char *
default_uiserver_cmdline (void)
{
  static char *name;

  if (!name)
    {
      const char *dir;
      char *uiserver, *p;
      int extra_arglen = 0;

      dir = gpgex_server::root_dir;
      if (!dir)
        return NULL;

      uiserver = read_w32_registry_string (NULL, REGKEY, "UI Server");
      if (!uiserver)
        {
          uiserver = strdup ("kleopatra.exe");
          if (!uiserver)
            return NULL;
          extra_arglen = 9; /* Space required for " --daemon".  */
        }

      name = (char*)malloc (strlen (dir) + strlen (uiserver) + extra_arglen +2);
      if (!name)
        {
          free (uiserver);
          return NULL;
        }
      strcpy (stpcpy (stpcpy (name, dir), "\\"), uiserver);
      for (p = name; *p; p++)
        if (*p == '/')
          *p = '\\';
      free (uiserver);
      gpgex_server::ui_server = "Kleopatra";
      if (extra_arglen && access (name, F_OK))
        {
          /* Kleopatra is not installed: Try GPA instead but if it is
             also not available return the Kleopatra filename.  */
          const char gpaserver[] = "gpa.exe";
          char *name2;

          name2 = (char*)malloc (strlen (dir) + strlen (gpaserver)
                                 + extra_arglen+2);
          if (name2)
            {
              strcpy (stpcpy (stpcpy (name2, dir), "\\"), gpaserver);
              for (p = name2; *p; p++)
                if (*p == '/')
                  *p = '\\';
              if (access (name2, F_OK ))
                free (name2);
              else
                {
                  free (name);
                  name = name2;
                  gpgex_server::ui_server = "GPA";
                }
            }
        }

      /* Append the --daemon arg unless the server name has been taken
         from the Registry.  */
      if (name && extra_arglen)
        strcat (name, " --daemon");
      else
        gpgex_server::ui_server = NULL;
    }

  return name;
}

#define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))

/* Percent-escape the string STR by replacing colons with '%3a'.  If
   EXTRA is not NULL all characters in it are also escaped. */
static char *
percent_escape (const char *str, const char *extra)
{
  int i, j;
  char *ptr;

  if (!str)
    return NULL;

  for (i=j=0; str[i]; i++)
    if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
      j++;
  ptr = (char *) malloc (i + 2 * j + 1);
  i = 0;
  while (*str)
    {
      /* FIXME: Work around a bug in Kleo.  */
      if (*str == ':')
	{
	  ptr[i++] = '%';
	  ptr[i++] = '3';
	  ptr[i++] = 'a';
	}
      else
    if (*str == '%')
	{
	  ptr[i++] = '%';
	  ptr[i++] = '2';
	  ptr[i++] = '5';
	}
      else if (extra && strchr (extra, *str))
        {
	  ptr[i++] = '%';
          ptr[i++] = tohex_lower ((*str >> 4) & 15);
          ptr[i++] = tohex_lower (*str & 15);
        }
      else
	ptr[i++] = *str;
      str++;
    }
  ptr[i] = '\0';

  return ptr;
}

static string
escape (string str)
{
  char *arg_esc = percent_escape (str.c_str (), "+= ");

  if (arg_esc == NULL)
    throw std::bad_alloc ();

  string res = arg_esc;
  free (arg_esc);

  return res;
}

/* Send options to the UI server and return the server's PID.  */
static gpg_error_t
send_one_option (assuan_context_t ctx, const char *name, const char *value)
{
  gpg_error_t err;
  char buffer[1024];

  if (! value || ! *value)
    err = 0;  /* Avoid sending empty strings.  */
  else
    {
      snprintf (buffer, sizeof (buffer), "OPTION %s=%s", name, value);
      err = assuan_transact (ctx, buffer, NULL, NULL, NULL, NULL, NULL, NULL);
    }

  return err;
}

static gpg_error_t
getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
{
  pid_t *pid = (pid_t *) opaque;

  *pid = (pid_t) strtoul ((char *) buffer, NULL, 10);

  return 0;
}

static gpg_error_t
send_options (assuan_context_t ctx, HWND hwnd, pid_t *r_pid)
{
  gpg_error_t rc = 0;
  char numbuf[50];

  TRACE_BEG (DEBUG_ASSUAN, "client_t::send_options", ctx);

  *r_pid = (pid_t) (-1);
  rc = assuan_transact (ctx, "GETINFO pid", getinfo_pid_cb, r_pid,
			NULL, NULL, NULL, NULL);
  if (! rc && *r_pid == (pid_t) (-1))
    {
      (void) TRACE_LOG ("server did not return a PID");
      rc = gpg_error (GPG_ERR_ASSUAN_SERVER_FAULT);
    }

  if (! rc && *r_pid != (pid_t) (-1)
      && ! AllowSetForegroundWindow (*r_pid))
    {
      (void) TRACE_LOG ("AllowSetForegroundWindow (%u) failed");
      TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ()));

      /* Ignore the error, though.  */
    }

  if (! rc && hwnd)
    {
      /* We hope that HWND is limited to 32 bit.  If not a 32 bit
         UI-server would not be able to do anything with this
         window-id.  */
      uintptr_t tmp = (uintptr_t)hwnd;

      if (tmp & ~0xffffffff)
        {
          /* HWND fits into 32 bit - send it. */
          snprintf (numbuf, sizeof (numbuf), "%lx", (unsigned long)tmp);
          rc = send_one_option (ctx, "window-id", numbuf);
        }
    }

  return TRACE_GPGERR (rc);
}

static gpg_error_t
uiserver_connect (assuan_context_t *ctx, HWND hwnd)
{
  gpg_error_t rc;
  const char *socket_name = NULL;
  pid_t pid;
  lock_spawn_t lock;

  TRACE_BEG (DEBUG_ASSUAN, "client_t::uiserver_connect", ctx);

  socket_name = default_socket_name ();
  if (! socket_name || ! *socket_name)
    {
      (void) TRACE_LOG ("invalid socket name");
      return TRACE_GPGERR (gpg_error (GPG_ERR_INV_ARG));
    }

  (void) TRACE_LOG1 ("socket name: %s", socket_name);
  rc = assuan_new (ctx);
  if (rc)
    {
      (void) TRACE_LOG ("could not allocate context");
      return TRACE_GPGERR (rc);
    }

  rc = assuan_socket_connect (*ctx, socket_name, -1, 0);
  if (rc)
    {
      int count;

      (void) TRACE_LOG ("UI server not running, starting it");

      /* Now try to connect again with the spawn lock taken.  */
      if (!(rc = gpgex_lock_spawning (&lock))
          && assuan_socket_connect (*ctx, socket_name, -1, 0))
        {
          rc = gpgex_spawn_detached (default_uiserver_cmdline ());
          if (!rc)
            {
              /* Give it a bit of time to start up and try a couple of
                 times.  */
              for (count = 0; count < 10; count++)
                {
                  Sleep (1000);
                  rc = assuan_socket_connect (*ctx, socket_name, -1, 0);
                  if (!rc)
                    break;
                }
            }

        }
      gpgex_unlock_spawning (&lock);
    }

  if (! rc)
    {
      if (debug_flags & DEBUG_ASSUAN)
	assuan_set_log_stream (*ctx, debug_file);

      rc = send_options (*ctx, hwnd, &pid);
      if (rc)
	{
	  assuan_release (*ctx);
	  *ctx = NULL;
	}
    }

  return TRACE_GPGERR (rc);
}

bool
client_t::call_assuan (const char *cmd, vector<string> &filenames)
{
  int rc = 0;
  int connect_failed = 0;

  assuan_context_t ctx = NULL;
  string msg;

  TRACE_BEG2 (DEBUG_ASSUAN, "client_t::call_assuan", this,
	      "%s on %u files", cmd, filenames.size ());

  rc = uiserver_connect (&ctx, this->window);
  if (rc)
    {
      connect_failed = 1;
      goto leave;
    }

  try
    {
      /* Set the input files.  We don't specify the output files.  */
      for (unsigned int i = 0; i < filenames.size (); i++)
	{
	  msg = "FILE " + escape (filenames[i]);

	  (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ());

	  rc = assuan_transact (ctx, msg.c_str (),
				NULL, NULL, NULL, NULL, NULL, NULL);
	  if (rc)
	    goto leave;
	}

      /* Set the --nohup option, so that the operation continues and
	 completes in the background.  */
      msg = ((string) cmd) + " --nohup";
      (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ());
      rc = assuan_transact (ctx, msg.c_str (),
			    NULL, NULL, NULL, NULL, NULL, NULL);
    }
  catch (std::bad_alloc)
    {
      rc = gpg_error (GPG_ERR_ENOMEM);
    }
  catch (...)
    {
      rc = gpg_error (GPG_ERR_GENERAL);
    }

  /* Fall-through.  */
 leave:
  TRACE_GPGERR (rc);
  if (ctx)
    assuan_release (ctx);
  if (rc)
    {
      char buf[256];

      if (connect_failed)
        snprintf (buf, sizeof (buf),
                  _("Can not connect to the GnuPG user interface%s%s%s:\r\n%s"),
                  gpgex_server::ui_server? " (":"",
                  gpgex_server::ui_server? gpgex_server::ui_server:"",
                  gpgex_server::ui_server? ")":"",
                  gpg_strerror (rc));
      else
        snprintf (buf, sizeof (buf),
                  _("Error returned by the GnuPG user interface%s%s%s:\r\n%s"),
                  gpgex_server::ui_server? " (":"",
                  gpgex_server::ui_server? gpgex_server::ui_server:"",
                  gpgex_server::ui_server? ")":"",
                  gpg_strerror (rc));
      MessageBox (this->window, buf, "GpgEX", MB_ICONINFORMATION);
    }

  return rc ? false : true;
}

void
client_t::decrypt_verify (vector<string> &filenames)
{
  this->call_assuan ("DECRYPT_VERIFY_FILES", filenames);
}

void
client_t::verify (vector<string> &filenames)
{
  this->call_assuan ("VERIFY_FILES", filenames);
}

void
client_t::decrypt (vector<string> &filenames)
{
  this->call_assuan ("DECRYPT_FILES", filenames);
}

void
client_t::sign_encrypt (vector<string> &filenames)
{
  this->call_assuan ("ENCRYPT_SIGN_FILES", filenames);
}

void
client_t::encrypt (vector<string> &filenames)
{
  this->call_assuan ("ENCRYPT_FILES", filenames);
}

void
client_t::sign (vector<string> &filenames)
{
  this->call_assuan ("SIGN_FILES", filenames);
}

void
client_t::import (vector<string> &filenames)
{
  this->call_assuan ("IMPORT_FILES", filenames);
}

void
client_t::create_checksums (vector<string> &filenames)
{
  this->call_assuan ("CHECKSUM_CREATE_FILES", filenames);
}

void
client_t::verify_checksums (vector<string> &filenames)
{
  this->call_assuan ("CHECKSUM_VERIFY_FILES", filenames);
}
<commit_msg>Start launch-gpa to avoid pop up console windows.<commit_after>/* client.cc - gpgex assuan client implementation
   Copyright (C) 2007, 2008, 2013, 2014 g10 Code GmbH

   This file is part of GpgEX.

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

   GpgEX 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 program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301, USA.  */

#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <vector>
#include <string>
#include <stdexcept>

using std::vector;
using std::string;

#include <winsock2.h>
#include <windows.h>

#include <assuan.h>

#include "main.h"
#include "registry.h"
#include "exechelp.h"

#include "client.h"

static inline char *
_gpgex_stpcpy (char *a, const char *b)
{
  while (*b)
    *a++ = *b++;
  *a = 0;
  return a;
}
#define stpcpy(a,b) _gpgex_stpcpy ((a), (b))

static const char *
default_socket_name (void)
{
  static string name;

  if (name.size () == 0)
    {
      char *dir = NULL;

      dir = default_homedir ();
      if (dir)
	{
	  try { name = ((string) dir) + "\\S.uiserver"; } catch (...) {}
	  free ((void *) dir);
	}
    }

  return name.c_str ();
}

/* Return the name of the default UI server.  This name is used to
   auto start an UI server if an initial connect failed.  */
static const char *
default_uiserver_cmdline (void)
{
  static char *name;

  if (!name)
    {
      const char *dir;
      char *uiserver, *p;
      int extra_arglen = 0;

      dir = gpgex_server::root_dir;
      if (!dir)
        return NULL;

      uiserver = read_w32_registry_string (NULL, REGKEY, "UI Server");
      if (!uiserver)
        {
          uiserver = strdup ("kleopatra.exe");
          if (!uiserver)
            return NULL;
          extra_arglen = 9; /* Space required for " --daemon".  */
        }

      name = (char*)malloc (strlen (dir) + strlen (uiserver) + extra_arglen +2);
      if (!name)
        {
          free (uiserver);
          return NULL;
        }
      strcpy (stpcpy (stpcpy (name, dir), "\\"), uiserver);
      for (p = name; *p; p++)
        if (*p == '/')
          *p = '\\';
      free (uiserver);
      gpgex_server::ui_server = "Kleopatra";
      if (extra_arglen && access (name, F_OK))
        {
          /* Kleopatra is not installed: Try GPA instead but if it is
             also not available return the Kleopatra filename.  */
          const char gpaserver[] = "launch-gpa.exe";
          char *name2;

          name2 = (char*)malloc (strlen (dir) + strlen (gpaserver)
                                 + extra_arglen+2);
          if (name2)
            {
              strcpy (stpcpy (stpcpy (name2, dir), "\\"), gpaserver);
              for (p = name2; *p; p++)
                if (*p == '/')
                  *p = '\\';
              if (access (name2, F_OK ))
                free (name2);
              else
                {
                  free (name);
                  name = name2;
                  gpgex_server::ui_server = "GPA";
                }
            }
        }

      /* Append the --daemon arg unless the server name has been taken
         from the Registry.  */
      if (name && extra_arglen)
        strcat (name, " --daemon");
      else
        gpgex_server::ui_server = NULL;
    }

  return name;
}

#define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))

/* Percent-escape the string STR by replacing colons with '%3a'.  If
   EXTRA is not NULL all characters in it are also escaped. */
static char *
percent_escape (const char *str, const char *extra)
{
  int i, j;
  char *ptr;

  if (!str)
    return NULL;

  for (i=j=0; str[i]; i++)
    if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
      j++;
  ptr = (char *) malloc (i + 2 * j + 1);
  i = 0;
  while (*str)
    {
      /* FIXME: Work around a bug in Kleo.  */
      if (*str == ':')
	{
	  ptr[i++] = '%';
	  ptr[i++] = '3';
	  ptr[i++] = 'a';
	}
      else
    if (*str == '%')
	{
	  ptr[i++] = '%';
	  ptr[i++] = '2';
	  ptr[i++] = '5';
	}
      else if (extra && strchr (extra, *str))
        {
	  ptr[i++] = '%';
          ptr[i++] = tohex_lower ((*str >> 4) & 15);
          ptr[i++] = tohex_lower (*str & 15);
        }
      else
	ptr[i++] = *str;
      str++;
    }
  ptr[i] = '\0';

  return ptr;
}

static string
escape (string str)
{
  char *arg_esc = percent_escape (str.c_str (), "+= ");

  if (arg_esc == NULL)
    throw std::bad_alloc ();

  string res = arg_esc;
  free (arg_esc);

  return res;
}

/* Send options to the UI server and return the server's PID.  */
static gpg_error_t
send_one_option (assuan_context_t ctx, const char *name, const char *value)
{
  gpg_error_t err;
  char buffer[1024];

  if (! value || ! *value)
    err = 0;  /* Avoid sending empty strings.  */
  else
    {
      snprintf (buffer, sizeof (buffer), "OPTION %s=%s", name, value);
      err = assuan_transact (ctx, buffer, NULL, NULL, NULL, NULL, NULL, NULL);
    }

  return err;
}

static gpg_error_t
getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
{
  pid_t *pid = (pid_t *) opaque;

  *pid = (pid_t) strtoul ((char *) buffer, NULL, 10);

  return 0;
}

static gpg_error_t
send_options (assuan_context_t ctx, HWND hwnd, pid_t *r_pid)
{
  gpg_error_t rc = 0;
  char numbuf[50];

  TRACE_BEG (DEBUG_ASSUAN, "client_t::send_options", ctx);

  *r_pid = (pid_t) (-1);
  rc = assuan_transact (ctx, "GETINFO pid", getinfo_pid_cb, r_pid,
			NULL, NULL, NULL, NULL);
  if (! rc && *r_pid == (pid_t) (-1))
    {
      (void) TRACE_LOG ("server did not return a PID");
      rc = gpg_error (GPG_ERR_ASSUAN_SERVER_FAULT);
    }

  if (! rc && *r_pid != (pid_t) (-1)
      && ! AllowSetForegroundWindow (*r_pid))
    {
      (void) TRACE_LOG ("AllowSetForegroundWindow (%u) failed");
      TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ()));

      /* Ignore the error, though.  */
    }

  if (! rc && hwnd)
    {
      /* We hope that HWND is limited to 32 bit.  If not a 32 bit
         UI-server would not be able to do anything with this
         window-id.  */
      uintptr_t tmp = (uintptr_t)hwnd;

      if (tmp & ~0xffffffff)
        {
          /* HWND fits into 32 bit - send it. */
          snprintf (numbuf, sizeof (numbuf), "%lx", (unsigned long)tmp);
          rc = send_one_option (ctx, "window-id", numbuf);
        }
    }

  return TRACE_GPGERR (rc);
}

static gpg_error_t
uiserver_connect (assuan_context_t *ctx, HWND hwnd)
{
  gpg_error_t rc;
  const char *socket_name = NULL;
  pid_t pid;
  lock_spawn_t lock;

  TRACE_BEG (DEBUG_ASSUAN, "client_t::uiserver_connect", ctx);

  socket_name = default_socket_name ();
  if (! socket_name || ! *socket_name)
    {
      (void) TRACE_LOG ("invalid socket name");
      return TRACE_GPGERR (gpg_error (GPG_ERR_INV_ARG));
    }

  (void) TRACE_LOG1 ("socket name: %s", socket_name);
  rc = assuan_new (ctx);
  if (rc)
    {
      (void) TRACE_LOG ("could not allocate context");
      return TRACE_GPGERR (rc);
    }

  rc = assuan_socket_connect (*ctx, socket_name, -1, 0);
  if (rc)
    {
      int count;

      (void) TRACE_LOG ("UI server not running, starting it");

      /* Now try to connect again with the spawn lock taken.  */
      if (!(rc = gpgex_lock_spawning (&lock))
          && assuan_socket_connect (*ctx, socket_name, -1, 0))
        {
          rc = gpgex_spawn_detached (default_uiserver_cmdline ());
          if (!rc)
            {
              /* Give it a bit of time to start up and try a couple of
                 times.  */
              for (count = 0; count < 10; count++)
                {
                  Sleep (1000);
                  rc = assuan_socket_connect (*ctx, socket_name, -1, 0);
                  if (!rc)
                    break;
                }
            }

        }
      gpgex_unlock_spawning (&lock);
    }

  if (! rc)
    {
      if (debug_flags & DEBUG_ASSUAN)
	assuan_set_log_stream (*ctx, debug_file);

      rc = send_options (*ctx, hwnd, &pid);
      if (rc)
	{
	  assuan_release (*ctx);
	  *ctx = NULL;
	}
    }

  return TRACE_GPGERR (rc);
}

bool
client_t::call_assuan (const char *cmd, vector<string> &filenames)
{
  int rc = 0;
  int connect_failed = 0;

  assuan_context_t ctx = NULL;
  string msg;

  TRACE_BEG2 (DEBUG_ASSUAN, "client_t::call_assuan", this,
	      "%s on %u files", cmd, filenames.size ());

  rc = uiserver_connect (&ctx, this->window);
  if (rc)
    {
      connect_failed = 1;
      goto leave;
    }

  try
    {
      /* Set the input files.  We don't specify the output files.  */
      for (unsigned int i = 0; i < filenames.size (); i++)
	{
	  msg = "FILE " + escape (filenames[i]);

	  (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ());

	  rc = assuan_transact (ctx, msg.c_str (),
				NULL, NULL, NULL, NULL, NULL, NULL);
	  if (rc)
	    goto leave;
	}

      /* Set the --nohup option, so that the operation continues and
	 completes in the background.  */
      msg = ((string) cmd) + " --nohup";
      (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ());
      rc = assuan_transact (ctx, msg.c_str (),
			    NULL, NULL, NULL, NULL, NULL, NULL);
    }
  catch (std::bad_alloc)
    {
      rc = gpg_error (GPG_ERR_ENOMEM);
    }
  catch (...)
    {
      rc = gpg_error (GPG_ERR_GENERAL);
    }

  /* Fall-through.  */
 leave:
  TRACE_GPGERR (rc);
  if (ctx)
    assuan_release (ctx);
  if (rc)
    {
      char buf[256];

      if (connect_failed)
        snprintf (buf, sizeof (buf),
                  _("Can not connect to the GnuPG user interface%s%s%s:\r\n%s"),
                  gpgex_server::ui_server? " (":"",
                  gpgex_server::ui_server? gpgex_server::ui_server:"",
                  gpgex_server::ui_server? ")":"",
                  gpg_strerror (rc));
      else
        snprintf (buf, sizeof (buf),
                  _("Error returned by the GnuPG user interface%s%s%s:\r\n%s"),
                  gpgex_server::ui_server? " (":"",
                  gpgex_server::ui_server? gpgex_server::ui_server:"",
                  gpgex_server::ui_server? ")":"",
                  gpg_strerror (rc));
      MessageBox (this->window, buf, "GpgEX", MB_ICONINFORMATION);
    }

  return rc ? false : true;
}

void
client_t::decrypt_verify (vector<string> &filenames)
{
  this->call_assuan ("DECRYPT_VERIFY_FILES", filenames);
}

void
client_t::verify (vector<string> &filenames)
{
  this->call_assuan ("VERIFY_FILES", filenames);
}

void
client_t::decrypt (vector<string> &filenames)
{
  this->call_assuan ("DECRYPT_FILES", filenames);
}

void
client_t::sign_encrypt (vector<string> &filenames)
{
  this->call_assuan ("ENCRYPT_SIGN_FILES", filenames);
}

void
client_t::encrypt (vector<string> &filenames)
{
  this->call_assuan ("ENCRYPT_FILES", filenames);
}

void
client_t::sign (vector<string> &filenames)
{
  this->call_assuan ("SIGN_FILES", filenames);
}

void
client_t::import (vector<string> &filenames)
{
  this->call_assuan ("IMPORT_FILES", filenames);
}

void
client_t::create_checksums (vector<string> &filenames)
{
  this->call_assuan ("CHECKSUM_CREATE_FILES", filenames);
}

void
client_t::verify_checksums (vector<string> &filenames)
{
  this->call_assuan ("CHECKSUM_VERIFY_FILES", filenames);
}
<|endoftext|>