<commit_before>// Copyright (c) 2011, Cornell University
// 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 HyperDex 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.

#define __STDC_LIMIT_MACROS

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

// C
#include <stdint.h>

// STL
#include <list>
#include <stdexcept>

// Google Log
#include <glog/logging.h>

// HyperDex
#include "hyperdex/hyperdex/coordinatorlink.h"

// HyperDaemon
#include "hyperdaemon/logical.h"

using hyperdex::configuration;
using hyperdex::coordinatorlink;
using hyperdex::entityid;
using hyperdex::instance;
using hyperdex::network_msgtype;
using hyperdex::regionid;

//////////////////////////////// Early Messages ////////////////////////////////

class hyperdaemon::logical::early_message
{
    public:
        early_message();
        early_message(uint64_t v,
                      const po6::net::location& l,
                      std::auto_ptr<e::buffer> m);
        ~early_message() throw ();

    public:
        uint64_t config_version;
        po6::net::location loc;
        std::auto_ptr<e::buffer> msg;
};

hyperdaemon :: logical :: early_message :: early_message()
    : config_version(0)
    , loc()
    , msg()
{
}

hyperdaemon :: logical :: early_message :: early_message(uint64_t v,
                                                         const po6::net::location& l,
                                                         std::auto_ptr<e::buffer> m)
    : config_version(v)
    , loc(l)
    , msg(m)
{
}

hyperdaemon :: logical :: early_message :: ~early_message() throw ()
{
}

///////////////////////////////// Public Class /////////////////////////////////

hyperdaemon :: logical :: logical(coordinatorlink* cl, const po6::net::ipaddr& ip,
                                  in_port_t incoming, in_port_t outgoing, size_t num_threads)
    : m_cl(cl)
    , m_us()
    , m_config()
    , m_early_messages()
    , m_client_nums()
    , m_client_locs()
    , m_client_counter(0)
    , m_physical(ip, incoming, outgoing, true, num_threads)
{
    assert(m_physical.inbound().address == m_physical.outbound().address);
    m_us.address = m_physical.inbound().address;
    m_us.inbound_port = m_physical.inbound().port;
    m_us.outbound_port = m_physical.outbound().port;
    m_us.inbound_version = 0;
    m_us.outbound_version = 0;
}

hyperdaemon :: logical :: ~logical() throw ()
{
}

typedef std::map<hyperdex::entityid, hyperdex::instance>::iterator mapiter;

size_t
hyperdaemon :: logical :: header_size() const
{
    return sizeof(uint8_t) + m_physical.header_size() + sizeof(uint64_t) + 2 * sizeof(uint16_t) + 2 * entityid::SERIALIZEDSIZE;
}

void
hyperdaemon :: logical :: prepare(const configuration&, const hyperdex::instance&)
{
    // Do nothing.
}

void
hyperdaemon :: logical :: reconfigure(const configuration& newconfig,
                                      const hyperdex::instance& newinst)
{
    m_config = newconfig;
    m_us = newinst;

    e::lockfree_fifo<early_message> ems;
    early_message em;

    while (m_early_messages.pop(&em))
    {
        if (em.config_version <= m_config.version())
        {
            m_physical.deliver(em.loc, em.msg);
        }
        else
        {
            ems.push(em);
        }
    }

    while (ems.pop(&em))
    {
        m_early_messages.push(em);
    }
}

void
hyperdaemon :: logical :: cleanup(const configuration&, const hyperdex::instance&)
{
    // Do nothing.
}

bool
hyperdaemon :: logical :: send(const hyperdex::entityid& from,
                               const hyperdex::entityid& to,
                               const network_msgtype msg_type,
                               std::auto_ptr<e::buffer> msg)
{
#ifdef HD_LOG_ALL_MESSAGES
    LOG(INFO) << "SEND " << from << "->" << to << " " << msg_type << " " << msg->hex();
#endif
    instance src;
    instance dst;

    // If we are sending as a transfer-recipient
    if (from.space == hyperdex::configuration::TRANSFERSPACE)
    {
        src = m_config.instancefortransfer(from.subspace);
    }
    else
    {
        src = m_config.instancefor(from);
    }

    // If we are sending to a client
    if (to.space == hyperdex::configuration::CLIENTSPACE)
    {
        po6::net::location loc;

        if (!m_client_locs.lookup(to.mask, &loc))
        {
            return false;
        }

        dst.address = loc.address;
        dst.inbound_port = loc.port;
        dst.inbound_version = 1;
    }
    else if (to.space == hyperdex::configuration::TRANSFERSPACE)
    {
        dst = m_config.instancefortransfer(to.subspace);
    }
    else
    {
        dst = m_config.instancefor(to);
    }

    if (src != m_us || dst == instance())
    {
        return false;
    }

    uint8_t mt = static_cast<uint8_t>(msg_type);
    assert(msg->capacity() >= header_size());
    msg->pack_at(m_physical.header_size())
        << mt << m_config.version() << src.outbound_version << dst.inbound_version << from << to;

    if (dst == m_us)
    {
        m_physical.deliver(po6::net::location(m_us.address, m_us.outbound_port), msg);
    }
    else
    {
        po6::net::location loc(dst.address, dst.inbound_port);

        switch (m_physical.send(loc, msg))
        {
            case physical::SUCCESS:
            case physical::QUEUED:
                break;
            case physical::CONNECTFAIL:
                handle_connectfail(loc);
                return false;
            case physical::DISCONNECT:
                handle_disconnect(loc);
                return false;
            case physical::SHUTDOWN:
                LOG(ERROR) << "physical::recv unexpectedly returned SHUTDOWN.";
                return false;
            case physical::LOGICERROR:
                LOG(ERROR) << "physical::recv unexpectedly returned LOGICERROR.";
                return false;
            default:
                LOG(ERROR) << "physical::recv unexpectedly returned unknown state.";
                return false;
        }
    }

    return true;
}

bool
hyperdaemon :: logical :: recv(hyperdex::entityid* from,
                               hyperdex::entityid* to,
                               network_msgtype* msg_type,
                               std::auto_ptr<e::buffer>* msg)
{
    po6::net::location loc;
    bool fromvalid = false;
    bool tovalid = false;
    instance frominst;
    instance toinst;
    uint16_t fromver = 0;
    uint16_t tover = 0;

    // Read messages from the network until we get one which meets the following
    // constraints:
    //  - We have a mapping for the source entityid.
    //  - We have a mapping for the destination entityid.
    //  - We have a mapping for the source entityid which corresponds to the
    //    underlying network location and version number of this message.
    //  - The destination entityid maps to our network location.
    //  - The message is to the correct version of our port bindings.
    while (true)
    {
        switch(m_physical.recv(&loc, msg))
        {
            case physical::SHUTDOWN:
                return false;
            case physical::SUCCESS:
                break;
            case physical::DISCONNECT:
                handle_disconnect(loc);
                continue;
            case physical::CONNECTFAIL:
                handle_connectfail(loc);
                continue;
            case physical::QUEUED:
                LOG(ERROR) << "physical::recv unexpectedly returned QUEUED.";
                continue;
            case physical::LOGICERROR:
                LOG(ERROR) << "physical::recv unexpectedly returned LOGICERROR.";
                continue;
            default:
                LOG(ERROR) << "physical::recv unexpectedly returned unknown state.";
                continue;
        }

        if ((*msg)->size() < header_size())
        {
            LOG(WARNING) << "dropping message that is too small to parse: " << (*msg)->hex();
            continue;
        }

        // This should not throw thanks to the size check above.
        uint8_t mt;
        uint64_t version;
        (*msg)->unpack_from(sizeof(uint32_t))
            >> mt >> version >> fromver >> tover >> *from >> *to;
        *msg_type = static_cast<network_msgtype>(mt);

        // Checkout the sender
        if (from->space == hyperdex::configuration::CLIENTSPACE)
        {
            po6::net::location expected_loc;

            if (m_client_locs.lookup(from->mask, &expected_loc))
            {
                if (expected_loc != loc)
                {
                    continue;
                }
            }
            else
            {
                if (from->mask != 0)
                {
                    continue;
                }

                uint64_t client_num;

                if (!m_client_nums.lookup(loc, &client_num))
                {
                    client_num = __sync_add_and_fetch(&m_client_counter, 1);
                    m_client_locs.insert(client_num, loc);
                    m_client_nums.insert(loc, client_num);
                }

                from->mask = client_num;
            }

            frominst.address = loc.address;
            frominst.outbound_port = loc.port;
            frominst.outbound_version = fromver;
            fromvalid = true;
        }
        else if (from->space == hyperdex::configuration::TRANSFERSPACE)
        {
            frominst = m_config.instancefortransfer(from->subspace);
            fromvalid = frominst != instance();
        }
        else
        {
            frominst = m_config.instancefor(*from);
            fromvalid = frominst != instance();
        }

        // Checkout the receiver
        if (to->space == hyperdex::configuration::TRANSFERSPACE)
        {
            toinst = m_config.instancefortransfer(to->subspace);
            tovalid = toinst != instance();
        }
        else
        {
            toinst = m_config.instancefor(*to);
            tovalid = toinst != instance();
        }

        if (fromvalid && // Try again because we don't know the source.
            tovalid && // Try again because we don't know the destination.
            frominst.address == loc.address && // Try again because the sender isn't who it should be.
            frominst.outbound_port == loc.port && // Try again because the sender isn't who it should be.
            frominst.outbound_version == fromver && // Try again because an older sender is sending the message.
            toinst == m_us && // Try again because we don't believe ourselves to be the dest entity.
            m_us.inbound_version == tover) // Try again because it is to an older version of us.
        {
            break;
        }

        // Shove the message back at the client so it fails with a reconfigure.
        if (from->space == hyperdex::configuration::CLIENTSPACE)
        {
            mt = static_cast<uint8_t>(hyperdex::CONFIGMISMATCH);
            (*msg)->pack_at(sizeof(uint32_t))
                << mt << tover << fromver << *to << *from;
            m_physical.send(loc, *msg);
        }
        // Otherwise, it's an early arrival.  We should postpone it, because it
        // could become valid in the future.
        else if (version > m_config.version())
        {
            early_message em(version, loc, *msg);
            assert(em.msg.get());
            m_early_messages.push(em);
            continue;
        }
    }

#ifdef HD_LOG_ALL_MESSAGES
    LOG(INFO) << "RECV " << *from << "->" << *to << " " << *msg_type << " " << (*msg)->hex();
#endif
    return true;
}

void
hyperdaemon :: logical :: handle_connectfail(const po6::net::location& loc)
{
    if (m_client_nums.contains(loc))
    {
        uint64_t client_num = 0;
        m_client_nums.lookup(loc, &client_num);
        m_client_nums.remove(loc);
        m_client_locs.remove(client_num);
    }
    else
    {
        switch (m_cl->warn_location(loc))
        {
            case hyperdex::coordinatorlink::SUCCESS:
                break;
            case hyperdex::coordinatorlink::SHUTDOWN:
                LOG(WARNING) << "Could not report connection failure to " << loc << ":  error(SHUTDOWN)";
                break;
            case hyperdex::coordinatorlink::CONNECTFAIL:
                LOG(WARNING) << "Could not report connection failure to " << loc << ":  error(CONNECTFAIL)";
                break;
            case hyperdex::coordinatorlink::DISCONNECT:
                LOG(WARNING) << "Could not report connection failure to " << loc << ":  error(DISCONNECT)";
                break;
            case hyperdex::coordinatorlink::LOGICERROR:
                LOG(WARNING) << "Could not report connection failure to " << loc << ":  error(LOGICERROR)";
                break;
            default:
                LOG(WARNING) << "Could not report connection failure to " << loc << ":  error unknown";
                break;
        }
    }
}

void
hyperdaemon :: logical :: handle_disconnect(const po6::net::location& loc)
{
    if (m_client_nums.contains(loc))
    {
        uint64_t client_num = 0;
        m_client_nums.lookup(loc, &client_num);
        m_client_nums.remove(loc);
        m_client_locs.remove(client_num);
    }
    else
    {
        switch (m_cl->fail_location(loc))
        {
            case hyperdex::coordinatorlink::SUCCESS:
                break;
            case hyperdex::coordinatorlink::SHUTDOWN:
                LOG(WARNING) << "Could not report disconnect from " << loc << ":  error(SHUTDOWN)";
                break;
            case hyperdex::coordinatorlink::CONNECTFAIL:
                LOG(WARNING) << "Could not report disconnect from " << loc << ":  error(CONNECTFAIL)";
                break;
            case hyperdex::coordinatorlink::DISCONNECT:
                LOG(WARNING) << "Could not report disconnect from " << loc << ":  error(DISCONNECT)";
                break;
            case hyperdex::coordinatorlink::LOGICERROR:
                LOG(WARNING) << "Could not report disconnect from " << loc << ":  error(LOGICERROR)";
                break;
            default:
                LOG(WARNING) << "Could not report disconnect from " << loc << ":  error unknown";
                break;
        }
    }
}
<commit_msg>Pack the config version when sending CONFIGMISMATCH<commit_after>// Copyright (c) 2011, Cornell University
// 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 HyperDex 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.

#define __STDC_LIMIT_MACROS

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

// C
#include <stdint.h>

// STL
#include <list>
#include <stdexcept>

// Google Log
#include <glog/logging.h>

// HyperDex
#include "hyperdex/hyperdex/coordinatorlink.h"

// HyperDaemon
#include "hyperdaemon/logical.h"

using hyperdex::configuration;
using hyperdex::coordinatorlink;
using hyperdex::entityid;
using hyperdex::instance;
using hyperdex::network_msgtype;
using hyperdex::regionid;

//////////////////////////////// Early Messages ////////////////////////////////

class hyperdaemon::logical::early_message
{
    public:
        early_message();
        early_message(uint64_t v,
                      const po6::net::location& l,
                      std::auto_ptr<e::buffer> m);
        ~early_message() throw ();

    public:
        uint64_t config_version;
        po6::net::location loc;
        std::auto_ptr<e::buffer> msg;
};

hyperdaemon :: logical :: early_message :: early_message()
    : config_version(0)
    , loc()
    , msg()
{
}

hyperdaemon :: logical :: early_message :: early_message(uint64_t v,
                                                         const po6::net::location& l,
                                                         std::auto_ptr<e::buffer> m)
    : config_version(v)
    , loc(l)
    , msg(m)
{
}

hyperdaemon :: logical :: early_message :: ~early_message() throw ()
{
}

///////////////////////////////// Public Class /////////////////////////////////

hyperdaemon :: logical :: logical(coordinatorlink* cl, const po6::net::ipaddr& ip,
                                  in_port_t incoming, in_port_t outgoing, size_t num_threads)
    : m_cl(cl)
    , m_us()
    , m_config()
    , m_early_messages()
    , m_client_nums()
    , m_client_locs()
    , m_client_counter(0)
    , m_physical(ip, incoming, outgoing, true, num_threads)
{
    assert(m_physical.inbound().address == m_physical.outbound().address);
    m_us.address = m_physical.inbound().address;
    m_us.inbound_port = m_physical.inbound().port;
    m_us.outbound_port = m_physical.outbound().port;
    m_us.inbound_version = 0;
    m_us.outbound_version = 0;
}

hyperdaemon :: logical :: ~logical() throw ()
{
}

typedef std::map<hyperdex::entityid, hyperdex::instance>::iterator mapiter;

size_t
hyperdaemon :: logical :: header_size() const
{
    return sizeof(uint8_t) + m_physical.header_size() + sizeof(uint64_t) + 2 * sizeof(uint16_t) + 2 * entityid::SERIALIZEDSIZE;
}

void
hyperdaemon :: logical :: prepare(const configuration&, const hyperdex::instance&)
{
    // Do nothing.
}

void
hyperdaemon :: logical :: reconfigure(const configuration& newconfig,
                                      const hyperdex::instance& newinst)
{
    m_config = newconfig;
    m_us = newinst;

    e::lockfree_fifo<early_message> ems;
    early_message em;

    while (m_early_messages.pop(&em))
    {
        if (em.config_version <= m_config.version())
        {
            m_physical.deliver(em.loc, em.msg);
        }
        else
        {
            ems.push(em);
        }
    }

    while (ems.pop(&em))
    {
        m_early_messages.push(em);
    }
}

void
hyperdaemon :: logical :: cleanup(const configuration&, const hyperdex::instance&)
{
    // Do nothing.
}

bool
hyperdaemon :: logical :: send(const hyperdex::entityid& from,
                               const hyperdex::entityid& to,
                               const network_msgtype msg_type,
                               std::auto_ptr<e::buffer> msg)
{
#ifdef HD_LOG_ALL_MESSAGES
    LOG(INFO) << "SEND " << from << "->" << to << " " << msg_type << " " << msg->hex();
#endif
    instance src;
    instance dst;

    // If we are sending as a transfer-recipient
    if (from.space == hyperdex::configuration::TRANSFERSPACE)
    {
        src = m_config.instancefortransfer(from.subspace);
    }
    else
    {
        src = m_config.instancefor(from);
    }

    // If we are sending to a client
    if (to.space == hyperdex::configuration::CLIENTSPACE)
    {
        po6::net::location loc;

        if (!m_client_locs.lookup(to.mask, &loc))
        {
            return false;
        }

        dst.address = loc.address;
        dst.inbound_port = loc.port;
        dst.inbound_version = 1;
    }
    else if (to.space == hyperdex::configuration::TRANSFERSPACE)
    {
        dst = m_config.instancefortransfer(to.subspace);
    }
    else
    {
        dst = m_config.instancefor(to);
    }

    if (src != m_us || dst == instance())
    {
        return false;
    }

    uint8_t mt = static_cast<uint8_t>(msg_type);
    assert(msg->capacity() >= header_size());
    msg->pack_at(m_physical.header_size())
        << mt << m_config.version() << src.outbound_version << dst.inbound_version << from << to;

    if (dst == m_us)
    {
        m_physical.deliver(po6::net::location(m_us.address, m_us.outbound_port), msg);
    }
    else
    {
        po6::net::location loc(dst.address, dst.inbound_port);

        switch (m_physical.send(loc, msg))
        {
            case physical::SUCCESS:
            case physical::QUEUED:
                break;
            case physical::CONNECTFAIL:
                handle_connectfail(loc);
                return false;
            case physical::DISCONNECT:
                handle_disconnect(loc);
                return false;
            case physical::SHUTDOWN:
                LOG(ERROR) << "physical::recv unexpectedly returned SHUTDOWN.";
                return false;
            case physical::LOGICERROR:
                LOG(ERROR) << "physical::recv unexpectedly returned LOGICERROR.";
                return false;
            default:
                LOG(ERROR) << "physical::recv unexpectedly returned unknown state.";
                return false;
        }
    }

    return true;
}

bool
hyperdaemon :: logical :: recv(hyperdex::entityid* from,
                               hyperdex::entityid* to,
                               network_msgtype* msg_type,
                               std::auto_ptr<e::buffer>* msg)
{
    po6::net::location loc;
    bool fromvalid = false;
    bool tovalid = false;
    instance frominst;
    instance toinst;
    uint16_t fromver = 0;
    uint16_t tover = 0;

    // Read messages from the network until we get one which meets the following
    // constraints:
    //  - We have a mapping for the source entityid.
    //  - We have a mapping for the destination entityid.
    //  - We have a mapping for the source entityid which corresponds to the
    //    underlying network location and version number of this message.
    //  - The destination entityid maps to our network location.
    //  - The message is to the correct version of our port bindings.
    while (true)
    {
        switch(m_physical.recv(&loc, msg))
        {
            case physical::SHUTDOWN:
                return false;
            case physical::SUCCESS:
                break;
            case physical::DISCONNECT:
                handle_disconnect(loc);
                continue;
            case physical::CONNECTFAIL:
                handle_connectfail(loc);
                continue;
            case physical::QUEUED:
                LOG(ERROR) << "physical::recv unexpectedly returned QUEUED.";
                continue;
            case physical::LOGICERROR:
                LOG(ERROR) << "physical::recv unexpectedly returned LOGICERROR.";
                continue;
            default:
                LOG(ERROR) << "physical::recv unexpectedly returned unknown state.";
                continue;
        }

        if ((*msg)->size() < header_size())
        {
            LOG(WARNING) << "dropping message that is too small to parse: " << (*msg)->hex();
            continue;
        }

        // This should not throw thanks to the size check above.
        uint8_t mt;
        uint64_t version;
        (*msg)->unpack_from(sizeof(uint32_t))
            >> mt >> version >> fromver >> tover >> *from >> *to;
        *msg_type = static_cast<network_msgtype>(mt);

        // Checkout the sender
        if (from->space == hyperdex::configuration::CLIENTSPACE)
        {
            po6::net::location expected_loc;

            if (m_client_locs.lookup(from->mask, &expected_loc))
            {
                if (expected_loc != loc)
                {
                    continue;
                }
            }
            else
            {
                if (from->mask != 0)
                {
                    continue;
                }

                uint64_t client_num;

                if (!m_client_nums.lookup(loc, &client_num))
                {
                    client_num = __sync_add_and_fetch(&m_client_counter, 1);
                    m_client_locs.insert(client_num, loc);
                    m_client_nums.insert(loc, client_num);
                }

                from->mask = client_num;
            }

            frominst.address = loc.address;
            frominst.outbound_port = loc.port;
            frominst.outbound_version = fromver;
            fromvalid = true;
        }
        else if (from->space == hyperdex::configuration::TRANSFERSPACE)
        {
            frominst = m_config.instancefortransfer(from->subspace);
            fromvalid = frominst != instance();
        }
        else
        {
            frominst = m_config.instancefor(*from);
            fromvalid = frominst != instance();
        }

        // Checkout the receiver
        if (to->space == hyperdex::configuration::TRANSFERSPACE)
        {
            toinst = m_config.instancefortransfer(to->subspace);
            tovalid = toinst != instance();
        }
        else
        {
            toinst = m_config.instancefor(*to);
            tovalid = toinst != instance();
        }

        if (fromvalid && // Try again because we don't know the source.
            tovalid && // Try again because we don't know the destination.
            frominst.address == loc.address && // Try again because the sender isn't who it should be.
            frominst.outbound_port == loc.port && // Try again because the sender isn't who it should be.
            frominst.outbound_version == fromver && // Try again because an older sender is sending the message.
            toinst == m_us && // Try again because we don't believe ourselves to be the dest entity.
            m_us.inbound_version == tover) // Try again because it is to an older version of us.
        {
            break;
        }

        // Shove the message back at the client so it fails with a reconfigure.
        if (from->space == hyperdex::configuration::CLIENTSPACE)
        {
            mt = static_cast<uint8_t>(hyperdex::CONFIGMISMATCH);
            (*msg)->pack_at(sizeof(uint32_t))
                << mt << m_config.version() << tover << fromver << *to << *from;
            m_physical.send(loc, *msg);
        }
        // Otherwise, it's an early arrival.  We should postpone it, because it
        // could become valid in the future.
        else if (version > m_config.version())
        {
            early_message em(version, loc, *msg);
            assert(em.msg.get());
            m_early_messages.push(em);
            continue;
        }
    }

#ifdef HD_LOG_ALL_MESSAGES
    LOG(INFO) << "RECV " << *from << "->" << *to << " " << *msg_type << " " << (*msg)->hex();
#endif
    return true;
}

void
hyperdaemon :: logical :: handle_connectfail(const po6::net::location& loc)
{
    if (m_client_nums.contains(loc))
    {
        uint64_t client_num = 0;
        m_client_nums.lookup(loc, &client_num);
        m_client_nums.remove(loc);
        m_client_locs.remove(client_num);
    }
    else
    {
        switch (m_cl->warn_location(loc))
        {
            case hyperdex::coordinatorlink::SUCCESS:
                break;
            case hyperdex::coordinatorlink::SHUTDOWN:
                LOG(WARNING) << "Could not report connection failure to " << loc << ":  error(SHUTDOWN)";
                break;
            case hyperdex::coordinatorlink::CONNECTFAIL:
                LOG(WARNING) << "Could not report connection failure to " << loc << ":  error(CONNECTFAIL)";
                break;
            case hyperdex::coordinatorlink::DISCONNECT:
                LOG(WARNING) << "Could not report connection failure to " << loc << ":  error(DISCONNECT)";
                break;
            case hyperdex::coordinatorlink::LOGICERROR:
                LOG(WARNING) << "Could not report connection failure to " << loc << ":  error(LOGICERROR)";
                break;
            default:
                LOG(WARNING) << "Could not report connection failure to " << loc << ":  error unknown";
                break;
        }
    }
}

void
hyperdaemon :: logical :: handle_disconnect(const po6::net::location& loc)
{
    if (m_client_nums.contains(loc))
    {
        uint64_t client_num = 0;
        m_client_nums.lookup(loc, &client_num);
        m_client_nums.remove(loc);
        m_client_locs.remove(client_num);
    }
    else
    {
        switch (m_cl->fail_location(loc))
        {
            case hyperdex::coordinatorlink::SUCCESS:
                break;
            case hyperdex::coordinatorlink::SHUTDOWN:
                LOG(WARNING) << "Could not report disconnect from " << loc << ":  error(SHUTDOWN)";
                break;
            case hyperdex::coordinatorlink::CONNECTFAIL:
                LOG(WARNING) << "Could not report disconnect from " << loc << ":  error(CONNECTFAIL)";
                break;
            case hyperdex::coordinatorlink::DISCONNECT:
                LOG(WARNING) << "Could not report disconnect from " << loc << ":  error(DISCONNECT)";
                break;
            case hyperdex::coordinatorlink::LOGICERROR:
                LOG(WARNING) << "Could not report disconnect from " << loc << ":  error(LOGICERROR)";
                break;
            default:
                LOG(WARNING) << "Could not report disconnect from " << loc << ":  error unknown";
                break;
        }
    }
}
<|endoftext|>


<commit_before>// @(#)root/utils:$Id$
// Author: Fons Rademakers   05/12/2003

/*************************************************************************
 * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

// This program generates a map between class name and shared library.
// Its output is in TEnv format.
// Usage: rlibmap [-f] [-o <mapfile>] -l <sofile> -d <depsofiles>
//                 -c <linkdeffiles>
// -f: output full library path name (not needed when ROOT library
//     search path is used)
// -o: write output to specified file, otherwise to stdout
// -r: replace existing entries in the specified file
// -l: library containing the classes in the specified linkdef files
// -d: libraries on which the -l library depends
// -c: linkdef files containing the list of classes defined in the -l library

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string>
#include <string.h>
#include <vector>
#ifndef WIN32
#   include <unistd.h>
#else
#   define ssize_t int
#   include <io.h>
#   include <sys/types.h>
#endif

#ifdef __APPLE__
#include <AvailabilityMacros.h>
#endif
#if (defined(__FreeBSD__) && (__FreeBSD__ < 4)) || defined(__OpenBSD__) || \
    (defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_10_3) || \
     (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3)))
#include <sys/file.h>
#define lockf(fd, op, sz)   flock((fd), (op))
#ifndef F_LOCK
#define F_LOCK             (LOCK_EX | LOCK_NB)
#endif
#ifndef F_ULOCK
#define F_ULOCK             LOCK_UN
#endif
#endif

#if defined(__CYGWIN__) && defined(__GNUC__)
#define F_LOCK F_WRLCK
#define F_ULOCK F_UNLCK
static int fcntl_lockf(int fd, int op, off_t off)
{
   flock fl;
   fl.l_whence = SEEK_SET;
   fl.l_start  = off;
   fl.l_len    = 0;       // whole file
   fl.l_pid    = getpid();
   fl.l_type   = op;
   return fcntl(fd, F_SETLK, &fl);
}
#define lockf fcntl_lockf
#endif

const char *usage = "Usage: %s [-f] [<-r|-o> <mapfile>] -l <sofile> -d <depsofiles> -c <linkdeffiles>\n";

namespace std {}
using namespace std;

#ifdef WIN32
#include <windows.h>
#include <errno.h>

#define ftruncate(fd, size)  win32_ftruncate(fd, size)

//______________________________________________________________________________
int win32_ftruncate(int fd, ssize_t size)
{
   HANDLE hfile;
   int curpos;

   if (fd < 0) return -1;

   hfile = (HANDLE) _get_osfhandle(fd);
   curpos = ::SetFilePointer(hfile, 0, 0, FILE_CURRENT);
   if (curpos == 0xFFFFFFFF ||
       ::SetFilePointer(hfile, size, 0, FILE_BEGIN) == 0xFFFFFFFF ||
       !::SetEndOfFile(hfile)) {
         int error = ::GetLastError();

      switch (error) {
         case ERROR_INVALID_HANDLE:
            errno = EBADF;
            break;
         default:
            errno = EIO;
         break;
      }
      return -1;
   }
   return 0;
}

#endif // WIN32

//______________________________________________________________________________
char *Compress(const char *str)
{
   // Remove all blanks from the string str. The returned string has to be
   // deleted by the user.

   if (!str) return 0;

   const char *p = str;
   // allocate 20 extra characters in case of eg, vector<vector<T>>
   char *s, *s1 = new char[strlen(str)+20];
   s = s1;

   while (*p) {
      if (*p != ' ')
         *s++ = *p;
      p++;
   }
   *s = '\0';

   return s1;
}

//______________________________________________________________________________
void UnCompressTemplate(char*& str)
{
   // Replace ">>" by "> >" except for operator>>.
   // str might be changed; the old string gets deleted in here.

   // Even handles cases like "A<B<operator>>()>>::operator >>()".

   char* pos = strstr(str, ">>");
   char* fixed = 0;
   int countgtgt = 0;
   while (pos) {
      // first run: just count, so we can allocate space for fixed
      ++countgtgt;
      pos = strstr(pos+1, ">>");
   }
   if (!countgtgt)
      return;
   pos = strstr(str, ">>");
   while (pos && pos > str) {
      bool isop = false;
      // check that it's not op>>:
      if (pos - str >= 8) {
         char* posop = pos - 1;
         // remove spaces in front of ">>":
         while (posop >= str && *posop == ' ')
            --posop;
         if (!strncmp("operator", posop - 7, 8)) {
            // it is an operator!
            isop = true;
         }
      }
      if (!isop) {
         // not an operator; we need to add a space.
         if (!fixed) {
            fixed = new char[strlen(str) + countgtgt + 1];
            strcpy(fixed, str);
         }
         fixed[pos - str + 1] = ' ';
         strcpy(fixed + (pos - str) + 2, pos + 1);
      }
      pos = strstr(pos + 1, ">>");
   }
   delete [] str;
   str = fixed;
}

//______________________________________________________________________________
int RemoveLib(const string &solib, bool fullpath, FILE *fp)
{
   // Remove entries from the map file for the specified solib.

   fseek(fp, 0, SEEK_SET);

   // get file size
   struct stat sbuf;
   fstat(fileno(fp), &sbuf);
   size_t siz = sbuf.st_size;

   if (!siz) return 0;

   const char *libbase = solib.c_str();
   if (!fullpath) {
      if ((libbase = strrchr(libbase, '/')))
         libbase++;
   }

   // read file and remove lines matching specified libs
   char *fbuf = new char[siz+1];
   char *fptr = fbuf;

   while (fgets(fptr, 1+siz - size_t(fptr-fbuf), fp)) {

      char *line = new char[strlen(fptr)+1];
      strcpy(line, fptr);
      strtok(line, " ");
      char *lib = strtok(0, " \n");
      if (lib && strcmp(lib, libbase)) {
         fptr += strlen(fptr);
         if (*(fptr-1) != '\n') {
            *fptr = '\n';
            fptr++;
         }
      }
      delete [] line;

      // fgets() should return 0 in this case but doesn't
      if ( (siz - size_t(fptr - fbuf)) <= 0)
         break;
   }

   ftruncate(fileno(fp), 0);

   // write remaining lines back
   if (fptr != fbuf) {
      fseek(fp, 0, SEEK_SET);
      fwrite(fbuf, 1, size_t(fptr-fbuf), fp);
   }

   delete [] fbuf;

   fseek(fp, 0, SEEK_END);

   return 0;
}

//______________________________________________________________________________
int LibMap(const string &solib, const vector<string> &solibdeps,
           const vector<string> &linkdefs, bool fullpath, FILE *fp)
{
   // Write libmap. Returns -1 in case of error.

   vector<string> classes;

   vector<string>::const_iterator lk;
   for (lk = linkdefs.begin(); lk != linkdefs.end(); lk++) {
      const char *linkdef = lk->c_str();
      FILE *lfp;
      char pragma[1024];
      if ((lfp = fopen(linkdef, "r"))) {
         while (fgets(pragma, 1024, lfp)) {
            if (strcmp(strtok(pragma, " "), "#pragma")) continue;
            const char* linkOrCreate = strtok(0, " ");
            bool pragmaLink = (!strcmp(linkOrCreate, "link") &&
                               !strcmp(strtok(0, " "), "C++"));
            bool pragmaCreate = false;
            // disabled for now, until we find a way to load cintdlls without
            // LD_LIBRARY_PATH nor G__p_class_autoloading / TAppication.
            // (!strcmp(linkOrCreate, "create") &&
            //!strcmp(strtok(0," "), "TClass"));

            if (pragmaLink || pragmaCreate) {
               const char *type = pragmaLink ? strtok(0, " ") : "class";
               if (!strncmp(type, "option=", 7) || !strncmp(type, "options=", 8)) {
                  if (strstr(type, "nomap"))
                     continue;
                  type = strtok(0, " ");
               }
               //the following statement had to be commented. Currently CINT
               //cannot autoload when executing a typedef (must be fixed!!!)
               //if (!strncmp(type, "class", 5) || !strcmp(type, "typedef")) {
               // handles class, class+protected and class+private
               if (!strncmp(type, "class", 5)) {
                  char *cls = strtok(0, "-!+;");
                  // just in case remove trailing space and tab
                  while (*cls == ' ') cls++;
                  int len = strlen(cls) - 1;
                  while (cls[len] == ' ' || cls[len] == '\t')
                     cls[len--] = '\0';
                  //no space between tmpl arguments allowed
                  cls = Compress(cls);
                  // except for A<B<C> >!
                  UnCompressTemplate(cls);

                  // don't include "vector<string>" and "std::pair<" classes
                  if (!strncmp(cls, "vector<string>", 14) ||
                      !strncmp(cls, "std::pair<", 10))
                     continue;

                  // replace "::" by "@@" since TEnv uses ":" as delimeter
                  char *s = cls;
                  while (*s) {
                     if (*s == ':')
                        *s = '@';
                     else if (*s == ' ')
                        *s = '-';
                     s++;
                  }
                  classes.push_back(cls);
               }
            }
         }
         fclose(lfp);
      } else {
         fprintf(stderr, "cannot open linkdef file %s\n", linkdef);
      }
   }

   const char *libbase = solib.c_str();
   if (!fullpath) {
      if ((libbase = strrchr(libbase, '/')))
         libbase++;
      else libbase = solib.c_str();
   }

   vector<string>::const_iterator it;
   for (it = classes.begin(); it != classes.end(); it++) {
      fprintf(fp, "Library.%-35s %s", ((*it)+":").c_str(), libbase);

      if (solibdeps.size() > 0) {
         vector<string>::const_iterator depit;
         for (depit = solibdeps.begin(); depit != solibdeps.end(); depit++) {
            const char *deplib = depit->c_str();
            if (!fullpath) {
               if ((deplib = strrchr(deplib, '/')))
                  deplib++;
               else deplib = depit->c_str();
            }
            fprintf(fp, " %s", deplib);
         }
      }
      fprintf(fp, "\n");
   }

   return 0;
}

//______________________________________________________________________________
int main(int argc, char **argv)
{
   string         solib;
   vector<string> solibdeps;
   vector<string> linkdefs;
   bool fullpath = false;
   bool replace  = false;
   FILE *fp      = stdout;

   if (argc > 1) {
      int ic = 1;
      if (!strcmp(argv[ic], "-?") || !strcmp(argv[ic], "-h")) {
         fprintf(stderr, usage, argv[0]);
         return 1;
      }
      if (!strcmp(argv[ic], "-f")) {
         fullpath = true;
         ic++;
      }
      if (!strcmp(argv[ic], "-o")) {
         ic++;
         fp = fopen(argv[ic], "w");
         if (!fp) {
            fprintf(stderr, "cannot open output file %s\n", argv[ic]);
            return 1;
         }
         ic++;
      }
      if (!strcmp(argv[ic], "-r")) {
         replace = true;
         ic++;
         fp = fopen(argv[ic], "a+");
         if (!fp) {
            fprintf(stderr, "cannot open output file %s\n", argv[ic]);
            return 1;
         }
         ic++;
      }
      if (!strcmp(argv[ic], "-l")) {
         ic++;
         solib = argv[ic];
#ifdef __APPLE__
         string::size_type i = solib.find(".dylib");
         if (i != string::npos)
            solib.replace(i, 6, ".so");
#endif
         ic++;
      }
      if (!strcmp(argv[ic], "-d")) {
         ic++;
         for (int i = ic; i < argc && argv[i][0] != '-'; i++) {
            string dl = argv[i];
#ifdef __APPLE__
            string::size_type j = dl.find(".dylib");
            if (j != string::npos)
               dl.replace(j, 6, ".so");
#endif
            solibdeps.push_back(dl);
            ic++;
         }
      }
      if (!strcmp(argv[ic], "-c")) {
         ic++;
         for (int i = ic; i < argc; i++) {
            linkdefs.push_back(argv[i]);
            ic++;
         }
      }
   } else {
      fprintf(stderr, usage, argv[0]);
      return 1;
   }

   if (replace) {
#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && \
    !defined(__OpenBSD__)
      // lock file
      if (lockf(fileno(fp), F_LOCK, (off_t)1) == -1) {
         fprintf(stderr, "rlibmap: locking failed, don't use gmake -j\n");
      }
#endif

      // remove entries for solib to be processed
      RemoveLib(solib, fullpath, fp);
   }

   LibMap(solib, solibdeps, linkdefs, fullpath, fp);

   if (replace) {
#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && \
    !defined(__OpenBSD__)
      // remove lock
      lseek(fileno(fp), 0, SEEK_SET);
      if (lockf(fileno(fp), F_ULOCK, (off_t)1) == -1) {
         //fprintf(stderr, "rlibmap: error unlocking output file\n");
      }
#endif
   }

   if (fp != stdout)
      fclose(fp);

   return 0;
}
<commit_msg>white space.<commit_after>// @(#)root/utils:$Id$
// Author: Fons Rademakers   05/12/2003

/*************************************************************************
 * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

// This program generates a map between class name and shared library.
// Its output is in TEnv format.
// Usage: rlibmap [-f] [-o <mapfile>] -l <sofile> -d <depsofiles>
//                 -c <linkdeffiles>
// -f: output full library path name (not needed when ROOT library
//     search path is used)
// -o: write output to specified file, otherwise to stdout
// -r: replace existing entries in the specified file
// -l: library containing the classes in the specified linkdef files
// -d: libraries on which the -l library depends
// -c: linkdef files containing the list of classes defined in the -l library

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string>
#include <string.h>
#include <vector>
#ifndef WIN32
#   include <unistd.h>
#else
#   define ssize_t int
#   include <io.h>
#   include <sys/types.h>
#endif

#ifdef __APPLE__
#include <AvailabilityMacros.h>
#endif
#if (defined(__FreeBSD__) && (__FreeBSD__ < 4)) || defined(__OpenBSD__) || \
    (defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_10_3) || \
     (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3)))
#include <sys/file.h>
#define lockf(fd, op, sz)   flock((fd), (op))
#ifndef F_LOCK
#define F_LOCK             (LOCK_EX | LOCK_NB)
#endif
#ifndef F_ULOCK
#define F_ULOCK             LOCK_UN
#endif
#endif

#if defined(__CYGWIN__) && defined(__GNUC__)
#define F_LOCK F_WRLCK
#define F_ULOCK F_UNLCK
static int fcntl_lockf(int fd, int op, off_t off)
{
   flock fl;
   fl.l_whence = SEEK_SET;
   fl.l_start  = off;
   fl.l_len    = 0;       // whole file
   fl.l_pid    = getpid();
   fl.l_type   = op;
   return fcntl(fd, F_SETLK, &fl);
}
#define lockf fcntl_lockf
#endif

const char *usage = "Usage: %s [-f] [<-r|-o> <mapfile>] -l <sofile> -d <depsofiles> -c <linkdeffiles>\n";

namespace std {}
using namespace std;

#ifdef WIN32
#include <windows.h>
#include <errno.h>

#define ftruncate(fd, size)  win32_ftruncate(fd, size)

//______________________________________________________________________________
int win32_ftruncate(int fd, ssize_t size)
{
   HANDLE hfile;
   int curpos;

   if (fd < 0) return -1;

   hfile = (HANDLE) _get_osfhandle(fd);
   curpos = ::SetFilePointer(hfile, 0, 0, FILE_CURRENT);
   if (curpos == 0xFFFFFFFF ||
       ::SetFilePointer(hfile, size, 0, FILE_BEGIN) == 0xFFFFFFFF ||
       !::SetEndOfFile(hfile)) {
         int error = ::GetLastError();

      switch (error) {
         case ERROR_INVALID_HANDLE:
            errno = EBADF;
            break;
         default:
            errno = EIO;
         break;
      }
      return -1;
   }
   return 0;
}

#endif // WIN32

//______________________________________________________________________________
char *Compress(const char *str)
{
   // Remove all blanks from the string str. The returned string has to be
   // deleted by the user.

   if (!str) return 0;

   const char *p = str;
   // allocate 20 extra characters in case of eg, vector<vector<T>>
   char *s, *s1 = new char[strlen(str)+20];
   s = s1;

   while (*p) {
      if (*p != ' ')
         *s++ = *p;
      p++;
   }
   *s = '\0';

   return s1;
}

//______________________________________________________________________________
void UnCompressTemplate(char*& str)
{
   // Replace ">>" by "> >" except for operator>>.
   // str might be changed; the old string gets deleted in here.

   // Even handles cases like "A<B<operator>>()>>::operator >>()".

   char* pos = strstr(str, ">>");
   char* fixed = 0;
   int countgtgt = 0;
   while (pos) {
      // first run: just count, so we can allocate space for fixed
      ++countgtgt;
      pos = strstr(pos+1, ">>");
   }
   if (!countgtgt)
      return;
   pos = strstr(str, ">>");
   while (pos && pos > str) {
      bool isop = false;
      // check that it's not op>>:
      if (pos - str >= 8) {
         char* posop = pos - 1;
         // remove spaces in front of ">>":
         while (posop >= str && *posop == ' ')
            --posop;
         if (!strncmp("operator", posop - 7, 8)) {
            // it is an operator!
            isop = true;
         }
      }
      if (!isop) {
         // not an operator; we need to add a space.
         if (!fixed) {
            fixed = new char[strlen(str) + countgtgt + 1];
            strcpy(fixed, str);
         }
         fixed[pos - str + 1] = ' ';
         strcpy(fixed + (pos - str) + 2, pos + 1);
      }
      pos = strstr(pos + 1, ">>");
   }
   delete [] str;
   str = fixed;
}

//______________________________________________________________________________
int RemoveLib(const string &solib, bool fullpath, FILE *fp)
{
   // Remove entries from the map file for the specified solib.

   fseek(fp, 0, SEEK_SET);

   // get file size
   struct stat sbuf;
   fstat(fileno(fp), &sbuf);
   size_t siz = sbuf.st_size;

   if (!siz) return 0;

   const char *libbase = solib.c_str();
   if (!fullpath) {
      if ((libbase = strrchr(libbase, '/')))
         libbase++;
   }

   // read file and remove lines matching specified libs
   char *fbuf = new char[siz+1];
   char *fptr = fbuf;

   while (fgets(fptr, 1+siz - size_t(fptr-fbuf), fp)) {

      char *line = new char[strlen(fptr)+1];
      strcpy(line, fptr);
      strtok(line, " ");
      char *lib = strtok(0, " \n");
      if (lib && strcmp(lib, libbase)) {
         fptr += strlen(fptr);
         if (*(fptr-1) != '\n') {
            *fptr = '\n';
            fptr++;
         }
      }
      delete [] line;

      // fgets() should return 0 in this case but doesn't
      if ( (siz - size_t(fptr - fbuf)) <= 0)
         break;
   }

   ftruncate(fileno(fp), 0);

   // write remaining lines back
   if (fptr != fbuf) {
      fseek(fp, 0, SEEK_SET);
      fwrite(fbuf, 1, size_t(fptr-fbuf), fp);
   }

   delete [] fbuf;

   fseek(fp, 0, SEEK_END);

   return 0;
}

//______________________________________________________________________________
int LibMap(const string &solib, const vector<string> &solibdeps,
           const vector<string> &linkdefs, bool fullpath, FILE *fp)
{
   // Write libmap. Returns -1 in case of error.

   vector<string> classes;

   vector<string>::const_iterator lk;
   for (lk = linkdefs.begin(); lk != linkdefs.end(); lk++) {
      const char *linkdef = lk->c_str();
      FILE *lfp;
      char pragma[1024];
      if ((lfp = fopen(linkdef, "r"))) {
         while (fgets(pragma, 1024, lfp)) {
            if (strcmp(strtok(pragma, " "), "#pragma")) continue;
            const char* linkOrCreate = strtok(0, " ");
            bool pragmaLink = (!strcmp(linkOrCreate, "link") &&
                               !strcmp(strtok(0, " "), "C++"));
            bool pragmaCreate = false;
            // disabled for now, until we find a way to load cintdlls without
            // LD_LIBRARY_PATH nor G__p_class_autoloading / TAppication.
            // (!strcmp(linkOrCreate, "create") &&
            //!strcmp(strtok(0," "), "TClass"));

            if (pragmaLink || pragmaCreate) {
               const char *type = pragmaLink ? strtok(0, " ") : "class";
               if (!strncmp(type, "option=", 7) || !strncmp(type, "options=", 8)) {
                  if (strstr(type, "nomap"))
                     continue;
                  type = strtok(0, " ");
               }
               //the following statement had to be commented. Currently CINT
               //cannot autoload when executing a typedef (must be fixed!!!)
               //if (!strncmp(type, "class", 5) || !strcmp(type, "typedef")) {
               // handles class, class+protected and class+private
               if (!strncmp(type, "class", 5)) {
                  char *cls = strtok(0, "-!+;");
                  // just in case remove trailing space and tab
                  while (*cls == ' ') cls++;
                  int len = strlen(cls) - 1;
                  while (cls[len] == ' ' || cls[len] == '\t')
                     cls[len--] = '\0';
                  //no space between tmpl arguments allowed
                  cls = Compress(cls);
                  // except for A<B<C> >!
                  UnCompressTemplate(cls);

                  // don't include "vector<string>" and "std::pair<" classes
                  if (!strncmp(cls, "vector<string>", 14) ||
                      !strncmp(cls, "std::pair<", 10))
                     continue;

                  // replace "::" by "@@" since TEnv uses ":" as delimeter
                  char *s = cls;
                  while (*s) {
                     if (*s == ':')
                        *s = '@';
                     else if (*s == ' ')
                        *s = '-';
                     s++;
                  }
                  classes.push_back(cls);
               }
            }
         }
         fclose(lfp);
      } else {
         fprintf(stderr, "cannot open linkdef file %s\n", linkdef);
      }
   }

   const char *libbase = solib.c_str();
   if (!fullpath) {
      if ((libbase = strrchr(libbase, '/')))
         libbase++;
      else
         libbase = solib.c_str();
   }

   vector<string>::const_iterator it;
   for (it = classes.begin(); it != classes.end(); it++) {
      fprintf(fp, "Library.%-35s %s", ((*it)+":").c_str(), libbase);

      if (solibdeps.size() > 0) {
         vector<string>::const_iterator depit;
         for (depit = solibdeps.begin(); depit != solibdeps.end(); depit++) {
            const char *deplib = depit->c_str();
            if (!fullpath) {
               if ((deplib = strrchr(deplib, '/')))
                  deplib++;
               else
                  deplib = depit->c_str();
            }
            fprintf(fp, " %s", deplib);
         }
      }
      fprintf(fp, "\n");
   }

   return 0;
}

//______________________________________________________________________________
int main(int argc, char **argv)
{
   string         solib;
   vector<string> solibdeps;
   vector<string> linkdefs;
   bool fullpath = false;
   bool replace  = false;
   FILE *fp      = stdout;

   if (argc > 1) {
      int ic = 1;
      if (!strcmp(argv[ic], "-?") || !strcmp(argv[ic], "-h")) {
         fprintf(stderr, usage, argv[0]);
         return 1;
      }
      if (!strcmp(argv[ic], "-f")) {
         fullpath = true;
         ic++;
      }
      if (!strcmp(argv[ic], "-o")) {
         ic++;
         fp = fopen(argv[ic], "w");
         if (!fp) {
            fprintf(stderr, "cannot open output file %s\n", argv[ic]);
            return 1;
         }
         ic++;
      }
      if (!strcmp(argv[ic], "-r")) {
         replace = true;
         ic++;
         fp = fopen(argv[ic], "a+");
         if (!fp) {
            fprintf(stderr, "cannot open output file %s\n", argv[ic]);
            return 1;
         }
         ic++;
      }
      if (!strcmp(argv[ic], "-l")) {
         ic++;
         solib = argv[ic];
#ifdef __APPLE__
         string::size_type i = solib.find(".dylib");
         if (i != string::npos)
            solib.replace(i, 6, ".so");
#endif
         ic++;
      }
      if (!strcmp(argv[ic], "-d")) {
         ic++;
         for (int i = ic; i < argc && argv[i][0] != '-'; i++) {
            string dl = argv[i];
#ifdef __APPLE__
            string::size_type j = dl.find(".dylib");
            if (j != string::npos)
               dl.replace(j, 6, ".so");
#endif
            solibdeps.push_back(dl);
            ic++;
         }
      }
      if (!strcmp(argv[ic], "-c")) {
         ic++;
         for (int i = ic; i < argc; i++) {
            linkdefs.push_back(argv[i]);
            ic++;
         }
      }
   } else {
      fprintf(stderr, usage, argv[0]);
      return 1;
   }

   if (replace) {
#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && \
    !defined(__OpenBSD__)
      // lock file
      if (lockf(fileno(fp), F_LOCK, (off_t)1) == -1) {
         fprintf(stderr, "rlibmap: locking failed, don't use gmake -j\n");
      }
#endif

      // remove entries for solib to be processed
      RemoveLib(solib, fullpath, fp);
   }

   LibMap(solib, solibdeps, linkdefs, fullpath, fp);

   if (replace) {
#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && \
    !defined(__OpenBSD__)
      // remove lock
      lseek(fileno(fp), 0, SEEK_SET);
      if (lockf(fileno(fp), F_ULOCK, (off_t)1) == -1) {
         //fprintf(stderr, "rlibmap: error unlocking output file\n");
      }
#endif
   }

   if (fp != stdout)
      fclose(fp);

   return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkVTKImageIO.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkVTKImageIO.h"
#include <stdio.h>

namespace itk
{

VTKImageIO::VTKImageIO()
{
  this->SetNumberOfDimensions(2);
  m_ByteOrder = LittleEndian;
  m_FileType = ASCII;

}

VTKImageIO::~VTKImageIO()
{
}

bool VTKImageIO::OpenVTKFileForReading(std::ifstream& os,
                                       const char* filename)

{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for reading
  itkDebugMacro(<< "Initialize: opening file " << filename);

  // Actually open the file
  int openMode = std::ios::in;

#ifdef _WIN32
  openMode |= std::ios::binary;
#endif
#if defined(__GNUC__) && __GNUC__ >= 3
  os.open(filename, static_cast<std::ios_base::openmode>(openMode));
#elif defined (__MWERKS__)
  os.open(filename, static_cast<std::ios_base::openmode>(openMode));
#else
  os.open(filename, openMode);
#endif
  if ( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file for reading: " << filename);
    return false;
    }

  return true;
}

bool VTKImageIO::OpenVTKFileForWriting(std::ofstream& os,
                                       const char* filename)

{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for writing
  itkDebugMacro(<< "Initialize: opening file " << filename);

  // Actually open the file
  int openMode = std::ios::out;

#ifdef _WIN32
  openMode |= std::ios::binary;
#endif
#if defined(__GNUC__) && __GNUC__ >= 3
  os.open(filename, static_cast<std::ios_base::openmode>(openMode));
#elif defined (__MWERKS__)
  os.open(filename, static_cast<std::ios_base::openmode>(openMode));
#else
  os.open(filename, openMode);
#endif
  if ( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file for writing: " << filename);
    return false;
    }

  return true;
}

bool VTKImageIO::CanReadFile(const char* filename)
{
  std::ifstream file;
  char buffer[256];
  std::string fname(filename);

  if ( fname.find(".vtk") >= fname.length() )
    {
    return false;
    }

  if ( ! this->OpenVTKFileForReading(file, filename) )
    {
    return false;
    }

  // Check to see if its a vtk structured points file
  file.getline(buffer,255);
  file.getline(buffer,255);
  file.getline(buffer,255);
  file.getline(buffer,255);

  fname = buffer;

  if ( fname.find("STRUCTURED_POINTS") < fname.length() ||
       fname.find("structured_points") < fname.length() )
    {
    return true;
    }
  else
    {
    return false;
    }
}

void VTKImageIO::InternalReadImageInformation(std::ifstream& file)
{
  char line[255];
  std::string text;

  if ( ! this->OpenVTKFileForReading(file, m_FileName.c_str()) )
    {
    itkExceptionMacro(<< "Cannot read requested file");
    }

  file.getline(line,255);
  file.getline(line,255);
  file.getline(line,255);
  text = line;
  if ( text.find("ASCII") < text.length() ||
       text.find("ascii") < text.length() )
    {
    this->SetFileTypeToASCII();
    }
  else if ( text.find("BINARY") < text.length() ||
            text.find("binary") < text.length() )
    {
    this->SetFileTypeToBinary();
    }
  else
    {
    itkExceptionMacro(<< "Unrecognized type");
    }
  file.getline(line,255);
  text = line;
  if ( text.find("STRUCTURED_POINTS") >= text.length() &&
       text.find("structured_points") >= text.length() )
    {
    itkExceptionMacro(<< "Not structured points, can't read");
    }

  //extract dimensions, spacing, origin
  unsigned int dims[3];
  float spacing[3];
  float origin[3];
  file.getline(line,255);
  text = line;

  // set values in case we don't find them
  this->SetNumberOfDimensions(3);
  m_Spacing[0] = 1.0;
  m_Spacing[1] = 1.0;
  m_Spacing[2] = 1.0;
  m_Origin[0] = 0.0;
  m_Origin[1] = 0.0;
  m_Origin[2] = 1.0;

  if ( text.find("DIMENSIONS") < text.length() ||
       text.find("dimensions") < text.length() )
    {
    sscanf(line, "%*s %d %d %d", dims, dims+1, dims+2);
    if ( dims[2] <= 1 )
      {
      this->SetNumberOfDimensions(2);
      }
    else
      {
      this->SetNumberOfDimensions(3);
      }
    for ( unsigned int i=0; i < m_NumberOfDimensions; i++ )
      {
      m_Dimensions[i] = dims[i];
      }
    }
  else
    {
    itkExceptionMacro(<<"No dimensions defined");
    }

  file.getline(line,255);
  text = line;

  for ( bool readScalars=false; !readScalars; )
    {
    if ( text.find("SPACING") < text.length() ||
         text.find("spacing") < text.length() )
      {
      sscanf(line, "%*s %f %f %f", spacing, spacing+1, spacing+2);
      for ( unsigned int i=0; i < m_NumberOfDimensions; i++ )
        {
        m_Spacing[i] = spacing[i];
        }
      }

    else if ( text.find("ORIGIN") < text.length() ||
              text.find("origin") < text.length() )
      {
      sscanf(line, "%*s %f %f %f", origin, origin+1, origin+2);
      for ( unsigned int i=0; i < m_NumberOfDimensions; i++ )
        {
        m_Origin[i] = origin[i];
        }
      }

    else if ( text.find("SCALARS") < text.length() ||
              text.find("scalars") < text.length() )
      {
      readScalars = true;

      char pixelType[256];
      sscanf(line, "%*s %*s %s", pixelType);
      text = pixelType;
      if ( text.find("float") < text.length() )
        {
        SetPixelType(FLOAT);
        SetComponentType(FLOAT);
        }
      else if ( text.find("double") < text.length() )
        {
        SetPixelType(DOUBLE);
        SetComponentType(DOUBLE);
        }
      else if ( text.find("unsigned_char") < text.length() )
        {
        SetPixelType(UCHAR);
        SetComponentType(UCHAR);
        }
      else if ( text.find("char") < text.length() )
        {
        SetPixelType(CHAR);
        SetComponentType(CHAR);
        }
      else if ( text.find("unsigned_short") < text.length() )
        {
        SetPixelType(USHORT);
        SetComponentType(USHORT);
        }
      else if ( text.find("short") < text.length() )
        {
        SetPixelType(SHORT);
        SetComponentType(SHORT);
        }
      else if ( text.find("unsigned_int") < text.length() )
        {
        SetPixelType(UINT);
        SetComponentType(UINT);
        }
      else if ( text.find("int") < text.length() )
        {
        SetPixelType(INT);
        SetComponentType(INT);
        }
      else if ( text.find("unsigned_long") < text.length() )
        {
        SetPixelType(ULONG);
        SetComponentType(ULONG);
        }
      else if ( text.find("long") < text.length() )
        {
        SetPixelType(LONG);
        SetComponentType(LONG);
        }
      else
        {
        itkExceptionMacro(<<"Unrecognized type");
        }
      }//found scalars

      file.getline(line,255);
      text = line;
      }
}

void VTKImageIO::Read(void* buffer)
{
  std::ifstream file;

  this->InternalReadImageInformation(file);

  //We are positioned at the data. The data is read depending on whether
  //it is ASCII or binary.
  if ( m_FileType == ASCII )
    {
    this->ReadBufferAsASCII(file, buffer, this->GetComponentType(),
                            this->GetImageSizeInComponents());
    }
  else
    {
    file.read(static_cast<char*>(buffer), this->GetImageSizeInBytes());
    }
}

void VTKImageIO::ReadImageInformation()
{
  std::ifstream file;
  this->InternalReadImageInformation(file);
}

bool VTKImageIO::CanWriteFile( const char* name )
{
  std::string filename = name;
  if ( filename != "" &&
       filename.find(".vtk") < filename.length() )
    {
    return true;
    }
  return false;
}

void VTKImageIO::Write(const void* buffer)
{
  std::ofstream file;
  if ( ! this->OpenVTKFileForWriting(file,m_FileName.c_str()) )
    {
    return;
    }

  // Check the image region for proper dimensions, etc.
  unsigned int numDims = this->GetNumberOfDimensions();
  if ( numDims < 2 || numDims > 3 )
    {
    itkExceptionMacro(<<"VTK Writer can only write 2 or 3-dimensional images");
    return;
    }
  ImageIORegion ioRegion = this->GetIORegion();

  // Write the VTK header information
  file << "# vtk DataFile Version 3.0\n";
  file << "VTK File Generated by Insight Segmentation and Registration Toolkit (ITK)\n";

  if ( this->GetFileType() == ASCII ) { file << "ASCII\n"; }
  else { file << "BINARY\n"; }

  // Write characteristics of the data
  file << "DATASET STRUCTURED_POINTS\n";
  if ( numDims == 2 )
    {
    file << "DIMENSIONS " << this->GetDimensions(0) << " "
         << this->GetDimensions(1) << " 1\n";
    file << "SPACING " << m_Spacing[0] << " " << m_Spacing[1] << " 1.0\n";
    file << "ORIGIN " << m_Origin[0] << " " << m_Origin[1] << " 0.0\n";
    }
  else //numDims == 3
    {
    file << "DIMENSIONS " << this->GetDimensions(0) << " "
         << this->GetDimensions(1) << " " << this->GetDimensions(2) << "\n";
    file << "SPACING " << m_Spacing[0] << " "
         << m_Spacing[1] << " " << m_Spacing[2] << "\n";
    file << "ORIGIN " << m_Origin[0] << " "
         << m_Origin[1] << " " << m_Origin[2] << "\n";
    }

  file << "POINT_DATA " << this->GetImageSizeInPixels() << "\n";
  file << "SCALARS scalars "
       << this->ReturnTypeAsString(this->GetComponentType()) << " "
       << this->GetNumberOfComponents() << "\n";
  file << "LOOKUP_TABLE default\n";

  // Write the actual pixel data
  if ( m_FileType == ASCII )
    {
    this->WriteBufferAsASCII(file, buffer, this->GetComponentType(),
                            this->GetImageSizeInComponents());
    }
  else //binary
    {
    file.write(static_cast<const char*>(buffer), this->GetImageSizeInBytes());
    }
}

void VTKImageIO::PrintSelf(std::ostream& os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
}

} // end namespace itk
<commit_msg>ENH: By default write images in "Binary" mode.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkVTKImageIO.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkVTKImageIO.h"
#include <stdio.h>

namespace itk
{

VTKImageIO::VTKImageIO()
{
  this->SetNumberOfDimensions(2);
  m_ByteOrder = LittleEndian;
  m_FileType = Binary;

}

VTKImageIO::~VTKImageIO()
{
}

bool VTKImageIO::OpenVTKFileForReading(std::ifstream& os,
                                       const char* filename)

{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for reading
  itkDebugMacro(<< "Initialize: opening file " << filename);

  // Actually open the file
  int openMode = std::ios::in;

#ifdef _WIN32
  openMode |= std::ios::binary;
#endif
#if defined(__GNUC__) && __GNUC__ >= 3
  os.open(filename, static_cast<std::ios_base::openmode>(openMode));
#elif defined (__MWERKS__)
  os.open(filename, static_cast<std::ios_base::openmode>(openMode));
#else
  os.open(filename, openMode);
#endif
  if ( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file for reading: " << filename);
    return false;
    }

  return true;
}

bool VTKImageIO::OpenVTKFileForWriting(std::ofstream& os,
                                       const char* filename)

{
  // Make sure that we have a file to
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }

  // Open the new file for writing
  itkDebugMacro(<< "Initialize: opening file " << filename);

  // Actually open the file
  int openMode = std::ios::out;

#ifdef _WIN32
  openMode |= std::ios::binary;
#endif
#if defined(__GNUC__) && __GNUC__ >= 3
  os.open(filename, static_cast<std::ios_base::openmode>(openMode));
#elif defined (__MWERKS__)
  os.open(filename, static_cast<std::ios_base::openmode>(openMode));
#else
  os.open(filename, openMode);
#endif
  if ( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file for writing: " << filename);
    return false;
    }

  return true;
}

bool VTKImageIO::CanReadFile(const char* filename)
{
  std::ifstream file;
  char buffer[256];
  std::string fname(filename);

  if ( fname.find(".vtk") >= fname.length() )
    {
    return false;
    }

  if ( ! this->OpenVTKFileForReading(file, filename) )
    {
    return false;
    }

  // Check to see if its a vtk structured points file
  file.getline(buffer,255);
  file.getline(buffer,255);
  file.getline(buffer,255);
  file.getline(buffer,255);

  fname = buffer;

  if ( fname.find("STRUCTURED_POINTS") < fname.length() ||
       fname.find("structured_points") < fname.length() )
    {
    return true;
    }
  else
    {
    return false;
    }
}

void VTKImageIO::InternalReadImageInformation(std::ifstream& file)
{
  char line[255];
  std::string text;

  if ( ! this->OpenVTKFileForReading(file, m_FileName.c_str()) )
    {
    itkExceptionMacro(<< "Cannot read requested file");
    }

  file.getline(line,255);
  file.getline(line,255);
  file.getline(line,255);
  text = line;
  if ( text.find("ASCII") < text.length() ||
       text.find("ascii") < text.length() )
    {
    this->SetFileTypeToASCII();
    }
  else if ( text.find("BINARY") < text.length() ||
            text.find("binary") < text.length() )
    {
    this->SetFileTypeToBinary();
    }
  else
    {
    itkExceptionMacro(<< "Unrecognized type");
    }
  file.getline(line,255);
  text = line;
  if ( text.find("STRUCTURED_POINTS") >= text.length() &&
       text.find("structured_points") >= text.length() )
    {
    itkExceptionMacro(<< "Not structured points, can't read");
    }

  //extract dimensions, spacing, origin
  unsigned int dims[3];
  float spacing[3];
  float origin[3];
  file.getline(line,255);
  text = line;

  // set values in case we don't find them
  this->SetNumberOfDimensions(3);
  m_Spacing[0] = 1.0;
  m_Spacing[1] = 1.0;
  m_Spacing[2] = 1.0;
  m_Origin[0] = 0.0;
  m_Origin[1] = 0.0;
  m_Origin[2] = 1.0;

  if ( text.find("DIMENSIONS") < text.length() ||
       text.find("dimensions") < text.length() )
    {
    sscanf(line, "%*s %d %d %d", dims, dims+1, dims+2);
    if ( dims[2] <= 1 )
      {
      this->SetNumberOfDimensions(2);
      }
    else
      {
      this->SetNumberOfDimensions(3);
      }
    for ( unsigned int i=0; i < m_NumberOfDimensions; i++ )
      {
      m_Dimensions[i] = dims[i];
      }
    }
  else
    {
    itkExceptionMacro(<<"No dimensions defined");
    }

  file.getline(line,255);
  text = line;

  for ( bool readScalars=false; !readScalars; )
    {
    if ( text.find("SPACING") < text.length() ||
         text.find("spacing") < text.length() )
      {
      sscanf(line, "%*s %f %f %f", spacing, spacing+1, spacing+2);
      for ( unsigned int i=0; i < m_NumberOfDimensions; i++ )
        {
        m_Spacing[i] = spacing[i];
        }
      }

    else if ( text.find("ORIGIN") < text.length() ||
              text.find("origin") < text.length() )
      {
      sscanf(line, "%*s %f %f %f", origin, origin+1, origin+2);
      for ( unsigned int i=0; i < m_NumberOfDimensions; i++ )
        {
        m_Origin[i] = origin[i];
        }
      }

    else if ( text.find("SCALARS") < text.length() ||
              text.find("scalars") < text.length() )
      {
      readScalars = true;

      char pixelType[256];
      sscanf(line, "%*s %*s %s", pixelType);
      text = pixelType;
      if ( text.find("float") < text.length() )
        {
        SetPixelType(FLOAT);
        SetComponentType(FLOAT);
        }
      else if ( text.find("double") < text.length() )
        {
        SetPixelType(DOUBLE);
        SetComponentType(DOUBLE);
        }
      else if ( text.find("unsigned_char") < text.length() )
        {
        SetPixelType(UCHAR);
        SetComponentType(UCHAR);
        }
      else if ( text.find("char") < text.length() )
        {
        SetPixelType(CHAR);
        SetComponentType(CHAR);
        }
      else if ( text.find("unsigned_short") < text.length() )
        {
        SetPixelType(USHORT);
        SetComponentType(USHORT);
        }
      else if ( text.find("short") < text.length() )
        {
        SetPixelType(SHORT);
        SetComponentType(SHORT);
        }
      else if ( text.find("unsigned_int") < text.length() )
        {
        SetPixelType(UINT);
        SetComponentType(UINT);
        }
      else if ( text.find("int") < text.length() )
        {
        SetPixelType(INT);
        SetComponentType(INT);
        }
      else if ( text.find("unsigned_long") < text.length() )
        {
        SetPixelType(ULONG);
        SetComponentType(ULONG);
        }
      else if ( text.find("long") < text.length() )
        {
        SetPixelType(LONG);
        SetComponentType(LONG);
        }
      else
        {
        itkExceptionMacro(<<"Unrecognized type");
        }
      }//found scalars

      file.getline(line,255);
      text = line;
      }
}

void VTKImageIO::Read(void* buffer)
{
  std::ifstream file;

  this->InternalReadImageInformation(file);

  //We are positioned at the data. The data is read depending on whether
  //it is ASCII or binary.
  if ( m_FileType == ASCII )
    {
    this->ReadBufferAsASCII(file, buffer, this->GetComponentType(),
                            this->GetImageSizeInComponents());
    }
  else
    {
    file.read(static_cast<char*>(buffer), this->GetImageSizeInBytes());
    }
}

void VTKImageIO::ReadImageInformation()
{
  std::ifstream file;
  this->InternalReadImageInformation(file);
}

bool VTKImageIO::CanWriteFile( const char* name )
{
  std::string filename = name;
  if ( filename != "" &&
       filename.find(".vtk") < filename.length() )
    {
    return true;
    }
  return false;
}

void VTKImageIO::Write(const void* buffer)
{
  std::ofstream file;
  if ( ! this->OpenVTKFileForWriting(file,m_FileName.c_str()) )
    {
    return;
    }

  // Check the image region for proper dimensions, etc.
  unsigned int numDims = this->GetNumberOfDimensions();
  if ( numDims < 2 || numDims > 3 )
    {
    itkExceptionMacro(<<"VTK Writer can only write 2 or 3-dimensional images");
    return;
    }
  ImageIORegion ioRegion = this->GetIORegion();

  // Write the VTK header information
  file << "# vtk DataFile Version 3.0\n";
  file << "VTK File Generated by Insight Segmentation and Registration Toolkit (ITK)\n";

  if ( this->GetFileType() == ASCII ) { file << "ASCII\n"; }
  else { file << "BINARY\n"; }

  // Write characteristics of the data
  file << "DATASET STRUCTURED_POINTS\n";
  if ( numDims == 2 )
    {
    file << "DIMENSIONS " << this->GetDimensions(0) << " "
         << this->GetDimensions(1) << " 1\n";
    file << "SPACING " << m_Spacing[0] << " " << m_Spacing[1] << " 1.0\n";
    file << "ORIGIN " << m_Origin[0] << " " << m_Origin[1] << " 0.0\n";
    }
  else //numDims == 3
    {
    file << "DIMENSIONS " << this->GetDimensions(0) << " "
         << this->GetDimensions(1) << " " << this->GetDimensions(2) << "\n";
    file << "SPACING " << m_Spacing[0] << " "
         << m_Spacing[1] << " " << m_Spacing[2] << "\n";
    file << "ORIGIN " << m_Origin[0] << " "
         << m_Origin[1] << " " << m_Origin[2] << "\n";
    }

  file << "POINT_DATA " << this->GetImageSizeInPixels() << "\n";
  file << "SCALARS scalars "
       << this->ReturnTypeAsString(this->GetComponentType()) << " "
       << this->GetNumberOfComponents() << "\n";
  file << "LOOKUP_TABLE default\n";

  // Write the actual pixel data
  if ( m_FileType == ASCII )
    {
    this->WriteBufferAsASCII(file, buffer, this->GetComponentType(),
                            this->GetImageSizeInComponents());
    }
  else //binary
    {
    file.write(static_cast<const char*>(buffer), this->GetImageSizeInBytes());
    }
}

void VTKImageIO::PrintSelf(std::ostream& os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
}

} // end namespace itk
<|endoftext|>


<commit_before>/*!
@file

@copyright Edouard Alligand and Joel Falcou 2015-2017
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_BRIGAND_FUNCTIONS_LOGICAL_XOR_HPP
#define BOOST_BRIGAND_FUNCTIONS_LOGICAL_XOR_HPP
#include <brigand/types/integral_constant.hpp>

namespace brigand
{
  template <typename A, typename B>
  struct xor_ : brigand::integral_constant<typename A::value_type, A::value != B::value> {};
}
#endif
<commit_msg>Delete xor.hpp<commit_after><|endoftext|>


<commit_before>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...))
{
  static L const l_(::std::forward<L>(l));

  struct S
  {
    static R f(A... args) noexcept(noexcept(l_(::std::forward<A>(args)...)))
    {
      return l_(::std::forward<A>(args)...);
    }
  };

  return S::f;
}

}

template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...))
{
  static bool full;

  static L l_(::std::forward<L>(l));

  if (full)
  {
    l_.~L();

    new (static_cast<void*>(&l_)) L(::std::forward<L>(l));
  }
  // else do nothing

  full = true;

  struct S
  {
    static R f(A... args) noexcept(noexcept(l_(::std::forward<A>(args)...)))
    {
      return l_(::std::forward<A>(args)...);
    }
  };

  return S::f;
}

}

template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<|endoftext|>


<commit_before>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...))
{
  static thread_local L l_(::std::forward<L>(l));
  static thread_local bool full;

  if (full)
  {
    l_.~L();
    new (static_cast<void*>(&l_)) L(::std::forward<L>(l));
  }
  else
  {
    full = true;
  }

  return [](A... args) noexcept(noexcept(l_(::std::forward<A>(args)...))) {
    return l_(::std::forward<A>(args)...);
  };
}

}

template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...))
{
  static thread_local L l_(::std::forward<L>(l));
  static thread_local bool full;

  if (full)
  {
    l_.~L();
    new (static_cast<void*>(&l_)) L(::std::forward<L>(l));
  }
  else
  {
    full = true;
  }

  struct S
  {
    static R f(A... args) noexcept(noexcept(l_(::std::forward<A>(args)...)))
    {
      return l_(::std::forward<A>(args)...);
    }
  };

  return &S::f;
}

}

template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<|endoftext|>