<commit_before>/******************************************************************************
 * $Id$
 *
 * Project:  libLAS - http://liblas.org - A BSD library for LAS format data.
 * Purpose:  LAS Schema implementation for C++ libLAS
 * Author:   Howard Butler, hobu.inc@gmail.com
 *
 ******************************************************************************
 * Copyright (c) 2010, Howard Butler
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following
 * conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided
 *       with the distribution.
 *     * Neither the name of the Martin Isenburg or Iowa Department
 *       of Natural Resources 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.
 ****************************************************************************/

#include <pdal/Schema.hpp>

#include <iostream>
#include <map>

#include <boost/lexical_cast.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <boost/uuid/uuid_io.hpp>
#include <boost/concept_check.hpp> // ignore_unused_variable_warning
#include <boost/algorithm/string.hpp>

#ifdef PDAL_HAVE_LIBXML2
#include <pdal/XMLSchema.hpp>
#endif

namespace pdal
{

Schema::Schema()
    : m_byteSize(0)
{
    return;
}

Schema::Schema(std::vector<Dimension> const& dimensions)
    : m_byteSize(0)
{

    for (std::vector<Dimension>::const_iterator i = dimensions.begin();
            i != dimensions.end(); ++i)
    {
        appendDimension(*i);
    }
}

/// copy constructor
Schema::Schema(Schema const& other)
    : m_byteSize(other.m_byteSize)
    , m_index(other.m_index)
{

}

// assignment constructor
Schema& Schema::operator=(Schema const& rhs)
{
    if (&rhs != this)
    {
        m_byteSize = rhs.m_byteSize;
        m_index = rhs.m_index;
    }

    return *this;
}

bool Schema::operator==(const Schema& other) const
{
    if (m_byteSize != other.m_byteSize) return false;

    if (m_index.size() != other.m_index.size()) return false;

    schema::index_by_index const& idx = m_index.get<schema::index>();
    schema::index_by_index const& idx2 = m_index.get<schema::index>();

    schema::index_by_index::size_type i(0);
    for (i = 0; i < idx.size(); ++i)
    {
        if (!(idx[i] == idx2[i]))
        {
            return false;
        }
    }

    return true;
}

bool Schema::operator!=(const Schema& other) const
{
    return !(*this==other);
}

void Schema::appendDimension(const Dimension& dim)
{
    // Copy the Dimension because we're going to overwrite/set some of
    // its attributes
    Dimension d(dim);

    schema::index_by_position& position_index = m_index.get<schema::position>();

    schema::index_by_position::const_reverse_iterator r = position_index.rbegin();

    // If we do not have anything in the index, set our current values.
    // Otherwise, use the values from the last entry in the index as our
    // starting point
    if (r != position_index.rend())
    {
        Dimension const& t = *r;

        m_byteSize = m_byteSize + d.getByteSize();

        d.setByteOffset(t.getByteOffset() + t.getByteSize());
    }
    else
    {
        m_byteSize = d.getByteSize();
        d.setByteOffset(0);
    }

    d.setPosition(m_index.size());

    schema::index_by_uid const& id_index = m_index.get<schema::uid>();
    schema::index_by_uid::size_type id_count = id_index.count(d.getUUID());

    if (id_count >0)
    {
        std::ostringstream oss;
        oss << "Dimension with uuid '" << d.getUUID() << "' already exists with name '" << d.getName() << "' and namespace '" << d.getNamespace() << "'";
        throw duplicate_dimension_id(oss.str());
    }
    std::pair<schema::index_by_position::iterator, bool> q = position_index.insert(d);
    if (!q.second)
    {
        std::ostringstream oss;
        oss << "Could not insert into schema index because of " << q.first->getName();
        throw schema_error(oss.str());
    }

    return;
}

const Dimension& Schema::getDimension( schema::size_type t) const
{
    schema::index_by_index const& idx = m_index.get<schema::index>();

    if (t >= idx.size())
        throw dimension_not_found("Index position is not valid");

    return idx.at(t);
}

boost::optional<Dimension const&> Schema::getDimensionOptional(schema::size_type t) const
{
    try
    {
        Dimension const& dim = getDimension(t);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }
}

const Dimension& Schema::getDimension(std::string const& name, std::string const& namespc) const
{

    std::size_t dot_position = name.find_last_of(".");

    std::string ns(namespc);
    std::string t(name);
    if (dot_position != std::string::npos && namespc.empty())
    {
        // We were given a dotted name instead of a name + ns.  Let's split them up.
        ns = name.substr(0,dot_position);
        t = name.substr(dot_position+1 /*skip the '.'*/, name.size());
    }

    schema::index_by_name const& name_index = m_index.get<schema::name>();
    schema::index_by_name::const_iterator it = name_index.find(t);

    schema::index_by_name::size_type count = name_index.count(t);

    std::ostringstream oss;
    oss << "Dimension with name '" << t << "' not found, unable to Schema::getDimension";

    if (it != name_index.end())
    {

        if (ns.size())
        {
            while (it != name_index.end())
            {
                if (boost::equals(ns, it->getNamespace()))
                {
                    return *it;
                }

                ++it;
            }
            std::ostringstream errmsg;
            errmsg << "Unable to find dimension with name '" << t << "' and namespace  '" << ns << "' in schema";
            throw dimension_not_found(errmsg.str());

        }

        if (count > 1)
        {

            std::pair<schema::index_by_name::const_iterator, schema::index_by_name::const_iterator> ret = name_index.equal_range(t);
            boost::uint32_t num_parents(0);
            boost::uint32_t num_children(0);
            std::map<dimension::id, dimension::id> relationships;

            // Test to make sure that the number of parent dimensions all with
            // the same name is equal to only 1. If there are multiple
            // dimensions with the same name, but no relationships defined,
            // we are in an error condition
            for (schema::index_by_name::const_iterator  o = ret.first; o != ret.second; ++o)
            {
                // Put a map together that maps parents to children that
                // we are going to walk to find the very last child in the
                // graph.
                std::pair<dimension::id, dimension::id> p(o->getParent(), o->getUUID());
                relationships.insert(p);

                // The parent dimension should have a nil parent of its own.
                // nil_uuid is the default parent of all dimensions as the y
                // are created
                if (o->getParent().is_nil())
                {
                    num_parents++;
                }
                else
                {
                    num_children++;
                }

            }

            if (num_parents != 1)
            {
                std::ostringstream oss;

                oss << "Schema has multiple dimensions with name '" << t << "', but "
                    "their parent/child relationships are not coherent. Multiple "
                    "parents are present.";

                throw multiple_parent_dimensions(oss.str());
            }

            dimension::id parent = boost::uuids::nil_uuid();

            // Starting at the parent (nil uuid), walk the child/parent graph down to the
            // end.  When we're done finding dimensions, what's left is the child
            // at the end of the graph.
            std::map<dimension::id, dimension::id>::const_iterator p = relationships.find(parent);
            dimension::id child;
            while (p != relationships.end())
            {
                child = p->second;
                p = relationships.find(p->second);
            }
            schema::index_by_uid::const_iterator pi = m_index.get<schema::uid>().find(child);
            if (pi != m_index.get<schema::uid>().end())
            {
                return *pi;
            }
            else
            {
                std::ostringstream errmsg;
                errmsg << "Unable to fetch subjugate dimension with id '" << child << "' in schema";
                throw dimension_not_found(errmsg.str());
            }
        }
        // we don't have a ns or we don't have multiples, return what we found
        return *it;
    }
    else
    {
        boost::uuids::uuid ps1;
        try
        {
            boost::uuids::string_generator gen;
            ps1 = gen(t);
        }
        catch (std::runtime_error&)
        {
            // invalid string for uuid
            throw dimension_not_found(oss.str());
        }

        schema::index_by_uid::const_iterator i = m_index.get<schema::uid>().find(ps1);

        if (i != m_index.get<schema::uid>().end())
        {
            if (ns.size())
            {
                while (i != m_index.get<schema::uid>().end())
                {
                    if (boost::equals(ns, i->getNamespace()))
                    {
                        return *i;
                    }

                    ++i;
                }

            }

            return *i;
        }
        else
        {
            oss.str("");
            oss << "Dimension with name '" << t << "' not found, unable to Schema::getDimension";
            throw dimension_not_found(oss.str());
        }

    }

}

boost::optional<Dimension const&> Schema::getDimensionOptional(std::string const& t, std::string const& ns) const
{

    try
    {
        Dimension const& dim = getDimension(t, ns);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }

}

bool Schema::setDimension(Dimension const& dim)
{
    // Try setting based on UUID first if it's there and not null.
    if (dim.getUUID() != boost::uuids::nil_uuid())
    {
        schema::index_by_uid& id_index = m_index.get<schema::uid>();
        schema::index_by_uid::const_iterator id = id_index.find(dim.getUUID());
        if (id != id_index.end())
        {
            id_index.replace(id, dim);
            return true;
        }
    }

    schema::index_by_name& name_index = m_index.get<schema::name>();
    schema::index_by_name::iterator it = name_index.find(dim.getName());
    // FIXME: If there are two dimensions with the same name here, we're
    // screwed if they both have the same namespace too
    if (it != name_index.end())
    {
        while (it != name_index.end())
        {
            if (boost::equals(dim.getNamespace(), it->getNamespace()))
            {
                name_index.replace(it, dim);
                return true;
            }
            ++it;
        }
    }
    else
    {
        std::ostringstream oss;
        oss << "Dimension with name '" << dim.getName() << "' not found, unable to Schema::setDimension";
        throw dimension_not_found(oss.str());
    }

    return true;
}

const Dimension& Schema::getDimension(dimension::id const& t) const
{
    /// getDimension for a dimension::id will not respect the isIgnored setting
    /// of the dimension.  Stages that wish to operate with dimensions with exacting
    /// specificity should take care to use uuids as their keys rather than
    /// names.
    schema::index_by_uid::const_iterator it = m_index.get<schema::uid>().find(t);

    if (it != m_index.get<schema::uid>().end())
    {
        return *it;
    }

    std::ostringstream oss;
    oss << "getDimension: dimension not found with uuid '" << boost::lexical_cast<std::string>(t) << "'";
    throw dimension_not_found(oss.str());
}

boost::optional<Dimension const&> Schema::getDimensionOptional(dimension::id const& t) const
{
    try
    {
        Dimension const& dim = getDimension(t);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }
}

Schema Schema::from_xml(std::string const& xml, std::string const& xsd)
{
#ifdef PDAL_HAVE_LIBXML2

    pdal::schema::Reader reader(xml, xsd);

    pdal::Schema schema = reader.getSchema();
    return schema;

#else
    boost::ignore_unused_variable_warning(xml);
    boost::ignore_unused_variable_warning(xsd);
    return Schema();
#endif
}

Schema Schema::from_xml(std::string const& xml)
{
#ifdef PDAL_HAVE_LIBXML2

    std::string xsd("");

    pdal::schema::Reader reader(xml, xsd);

    pdal::Schema schema = reader.getSchema();
    return schema;

#else
    boost::ignore_unused_variable_warning(xml);
    return Schema();
#endif
}

std::string Schema::to_xml(Schema const& schema, boost::property_tree::ptree const* metadata)
{
#ifdef PDAL_HAVE_LIBXML2

    pdal::schema::Writer writer(schema);

    if (metadata)
        writer.setMetadata(*metadata);

    return writer.getXML();

#else
    boost::ignore_unused_variable_warning(schema);
    return std::string("");
#endif
}

boost::property_tree::ptree Schema::toPTree() const
{
    boost::property_tree::ptree tree;

    schema::index_by_index const& idx = m_index.get<schema::index>();

    for (schema::index_by_index::const_iterator iter = idx.begin(); iter != idx.end(); ++iter)
    {
        const Dimension& dim = *iter;
        tree.add_child("dimension", dim.toPTree());
    }

    return tree;
}

void Schema::dump() const
{
    std::cout << *this;
}

std::ostream& operator<<(std::ostream& os, pdal::Schema const& schema)
{
    boost::property_tree::ptree tree = schema.toPTree();

    boost::property_tree::write_json(os, tree);

    return os;
}

} // namespace pdal
<commit_msg>Avoid unnecessarily formatting in getDimension<commit_after>/******************************************************************************
 * $Id$
 *
 * Project:  libLAS - http://liblas.org - A BSD library for LAS format data.
 * Purpose:  LAS Schema implementation for C++ libLAS
 * Author:   Howard Butler, hobu.inc@gmail.com
 *
 ******************************************************************************
 * Copyright (c) 2010, Howard Butler
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following
 * conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided
 *       with the distribution.
 *     * Neither the name of the Martin Isenburg or Iowa Department
 *       of Natural Resources 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.
 ****************************************************************************/

#include <pdal/Schema.hpp>

#include <iostream>
#include <map>

#include <boost/lexical_cast.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <boost/uuid/uuid_io.hpp>
#include <boost/concept_check.hpp> // ignore_unused_variable_warning
#include <boost/algorithm/string.hpp>

#ifdef PDAL_HAVE_LIBXML2
#include <pdal/XMLSchema.hpp>
#endif

namespace pdal
{

Schema::Schema()
    : m_byteSize(0)
{
    return;
}

Schema::Schema(std::vector<Dimension> const& dimensions)
    : m_byteSize(0)
{

    for (std::vector<Dimension>::const_iterator i = dimensions.begin();
            i != dimensions.end(); ++i)
    {
        appendDimension(*i);
    }
}

/// copy constructor
Schema::Schema(Schema const& other)
    : m_byteSize(other.m_byteSize)
    , m_index(other.m_index)
{

}

// assignment constructor
Schema& Schema::operator=(Schema const& rhs)
{
    if (&rhs != this)
    {
        m_byteSize = rhs.m_byteSize;
        m_index = rhs.m_index;
    }

    return *this;
}

bool Schema::operator==(const Schema& other) const
{
    if (m_byteSize != other.m_byteSize) return false;

    if (m_index.size() != other.m_index.size()) return false;

    schema::index_by_index const& idx = m_index.get<schema::index>();
    schema::index_by_index const& idx2 = m_index.get<schema::index>();

    schema::index_by_index::size_type i(0);
    for (i = 0; i < idx.size(); ++i)
    {
        if (!(idx[i] == idx2[i]))
        {
            return false;
        }
    }

    return true;
}

bool Schema::operator!=(const Schema& other) const
{
    return !(*this==other);
}

void Schema::appendDimension(const Dimension& dim)
{
    // Copy the Dimension because we're going to overwrite/set some of
    // its attributes
    Dimension d(dim);

    schema::index_by_position& position_index = m_index.get<schema::position>();

    schema::index_by_position::const_reverse_iterator r = position_index.rbegin();

    // If we do not have anything in the index, set our current values.
    // Otherwise, use the values from the last entry in the index as our
    // starting point
    if (r != position_index.rend())
    {
        Dimension const& t = *r;

        m_byteSize = m_byteSize + d.getByteSize();

        d.setByteOffset(t.getByteOffset() + t.getByteSize());
    }
    else
    {
        m_byteSize = d.getByteSize();
        d.setByteOffset(0);
    }

    d.setPosition(m_index.size());

    schema::index_by_uid const& id_index = m_index.get<schema::uid>();
    schema::index_by_uid::size_type id_count = id_index.count(d.getUUID());

    if (id_count >0)
    {
        std::ostringstream oss;
        oss << "Dimension with uuid '" << d.getUUID() << "' already exists with name '" << d.getName() << "' and namespace '" << d.getNamespace() << "'";
        throw duplicate_dimension_id(oss.str());
    }
    std::pair<schema::index_by_position::iterator, bool> q = position_index.insert(d);
    if (!q.second)
    {
        std::ostringstream oss;
        oss << "Could not insert into schema index because of " << q.first->getName();
        throw schema_error(oss.str());
    }

    return;
}

const Dimension& Schema::getDimension( schema::size_type t) const
{
    schema::index_by_index const& idx = m_index.get<schema::index>();

    if (t >= idx.size())
        throw dimension_not_found("Index position is not valid");

    return idx.at(t);
}

boost::optional<Dimension const&> Schema::getDimensionOptional(schema::size_type t) const
{
    try
    {
        Dimension const& dim = getDimension(t);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }
}

const Dimension& Schema::getDimension(std::string const& name, std::string const& namespc) const
{

    std::size_t dot_position = name.find_last_of(".");

    std::string ns(namespc);
    std::string t(name);
    if (dot_position != std::string::npos && namespc.empty())
    {
        // We were given a dotted name instead of a name + ns.  Let's split them up.
        ns = name.substr(0,dot_position);
        t = name.substr(dot_position+1 /*skip the '.'*/, name.size());
    }

    schema::index_by_name const& name_index = m_index.get<schema::name>();
    schema::index_by_name::const_iterator it = name_index.find(t);

    schema::index_by_name::size_type count = name_index.count(t);

    if (it != name_index.end())
    {

        if (ns.size())
        {
            while (it != name_index.end())
            {
                if (boost::equals(ns, it->getNamespace()))
                {
                    return *it;
                }

                ++it;
            }
            std::ostringstream errmsg;
            errmsg << "Unable to find dimension with name '" << t << "' and namespace  '" << ns << "' in schema";
            throw dimension_not_found(errmsg.str());

        }

        if (count > 1)
        {

            std::pair<schema::index_by_name::const_iterator, schema::index_by_name::const_iterator> ret = name_index.equal_range(t);
            boost::uint32_t num_parents(0);
            boost::uint32_t num_children(0);
            std::map<dimension::id, dimension::id> relationships;

            // Test to make sure that the number of parent dimensions all with
            // the same name is equal to only 1. If there are multiple
            // dimensions with the same name, but no relationships defined,
            // we are in an error condition
            for (schema::index_by_name::const_iterator  o = ret.first; o != ret.second; ++o)
            {
                // Put a map together that maps parents to children that
                // we are going to walk to find the very last child in the
                // graph.
                std::pair<dimension::id, dimension::id> p(o->getParent(), o->getUUID());
                relationships.insert(p);

                // The parent dimension should have a nil parent of its own.
                // nil_uuid is the default parent of all dimensions as the y
                // are created
                if (o->getParent().is_nil())
                {
                    num_parents++;
                }
                else
                {
                    num_children++;
                }

            }

            if (num_parents != 1)
            {
                std::ostringstream oss;

                oss << "Schema has multiple dimensions with name '" << t << "', but "
                    "their parent/child relationships are not coherent. Multiple "
                    "parents are present.";

                throw multiple_parent_dimensions(oss.str());
            }

            dimension::id parent = boost::uuids::nil_uuid();

            // Starting at the parent (nil uuid), walk the child/parent graph down to the
            // end.  When we're done finding dimensions, what's left is the child
            // at the end of the graph.
            std::map<dimension::id, dimension::id>::const_iterator p = relationships.find(parent);
            dimension::id child;
            while (p != relationships.end())
            {
                child = p->second;
                p = relationships.find(p->second);
            }
            schema::index_by_uid::const_iterator pi = m_index.get<schema::uid>().find(child);
            if (pi != m_index.get<schema::uid>().end())
            {
                return *pi;
            }
            else
            {
                std::ostringstream errmsg;
                errmsg << "Unable to fetch subjugate dimension with id '" << child << "' in schema";
                throw dimension_not_found(errmsg.str());
            }
        }
        // we don't have a ns or we don't have multiples, return what we found
        return *it;
    }
    else
    {
        boost::uuids::uuid ps1;
        try
        {
            boost::uuids::string_generator gen;
            ps1 = gen(t);
        }
        catch (std::runtime_error&)
        {
            // invalid string for uuid
            std::ostringstream oss;
            oss << "Dimension with name '" << t << "' not found, unable to Schema::getDimension";
            throw dimension_not_found(oss.str());
        }

        schema::index_by_uid::const_iterator i = m_index.get<schema::uid>().find(ps1);

        if (i != m_index.get<schema::uid>().end())
        {
            if (ns.size())
            {
                while (i != m_index.get<schema::uid>().end())
                {
                    if (boost::equals(ns, i->getNamespace()))
                    {
                        return *i;
                    }

                    ++i;
                }

            }

            return *i;
        }
        else
        {
            std::ostringstream oss;
            oss << "Dimension with name '" << t << "' not found, unable to Schema::getDimension";
            throw dimension_not_found(oss.str());
        }

    }

}

boost::optional<Dimension const&> Schema::getDimensionOptional(std::string const& t, std::string const& ns) const
{

    try
    {
        Dimension const& dim = getDimension(t, ns);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }

}

bool Schema::setDimension(Dimension const& dim)
{
    // Try setting based on UUID first if it's there and not null.
    if (dim.getUUID() != boost::uuids::nil_uuid())
    {
        schema::index_by_uid& id_index = m_index.get<schema::uid>();
        schema::index_by_uid::const_iterator id = id_index.find(dim.getUUID());
        if (id != id_index.end())
        {
            id_index.replace(id, dim);
            return true;
        }
    }

    schema::index_by_name& name_index = m_index.get<schema::name>();
    schema::index_by_name::iterator it = name_index.find(dim.getName());
    // FIXME: If there are two dimensions with the same name here, we're
    // screwed if they both have the same namespace too
    if (it != name_index.end())
    {
        while (it != name_index.end())
        {
            if (boost::equals(dim.getNamespace(), it->getNamespace()))
            {
                name_index.replace(it, dim);
                return true;
            }
            ++it;
        }
    }
    else
    {
        std::ostringstream oss;
        oss << "Dimension with name '" << dim.getName() << "' not found, unable to Schema::setDimension";
        throw dimension_not_found(oss.str());
    }

    return true;
}

const Dimension& Schema::getDimension(dimension::id const& t) const
{
    /// getDimension for a dimension::id will not respect the isIgnored setting
    /// of the dimension.  Stages that wish to operate with dimensions with exacting
    /// specificity should take care to use uuids as their keys rather than
    /// names.
    schema::index_by_uid::const_iterator it = m_index.get<schema::uid>().find(t);

    if (it != m_index.get<schema::uid>().end())
    {
        return *it;
    }

    std::ostringstream oss;
    oss << "getDimension: dimension not found with uuid '" << boost::lexical_cast<std::string>(t) << "'";
    throw dimension_not_found(oss.str());
}

boost::optional<Dimension const&> Schema::getDimensionOptional(dimension::id const& t) const
{
    try
    {
        Dimension const& dim = getDimension(t);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }
}

Schema Schema::from_xml(std::string const& xml, std::string const& xsd)
{
#ifdef PDAL_HAVE_LIBXML2

    pdal::schema::Reader reader(xml, xsd);

    pdal::Schema schema = reader.getSchema();
    return schema;

#else
    boost::ignore_unused_variable_warning(xml);
    boost::ignore_unused_variable_warning(xsd);
    return Schema();
#endif
}

Schema Schema::from_xml(std::string const& xml)
{
#ifdef PDAL_HAVE_LIBXML2

    std::string xsd("");

    pdal::schema::Reader reader(xml, xsd);

    pdal::Schema schema = reader.getSchema();
    return schema;

#else
    boost::ignore_unused_variable_warning(xml);
    return Schema();
#endif
}

std::string Schema::to_xml(Schema const& schema, boost::property_tree::ptree const* metadata)
{
#ifdef PDAL_HAVE_LIBXML2

    pdal::schema::Writer writer(schema);

    if (metadata)
        writer.setMetadata(*metadata);

    return writer.getXML();

#else
    boost::ignore_unused_variable_warning(schema);
    return std::string("");
#endif
}

boost::property_tree::ptree Schema::toPTree() const
{
    boost::property_tree::ptree tree;

    schema::index_by_index const& idx = m_index.get<schema::index>();

    for (schema::index_by_index::const_iterator iter = idx.begin(); iter != idx.end(); ++iter)
    {
        const Dimension& dim = *iter;
        tree.add_child("dimension", dim.toPTree());
    }

    return tree;
}

void Schema::dump() const
{
    std::cout << *this;
}

std::ostream& operator<<(std::ostream& os, pdal::Schema const& schema)
{
    boost::property_tree::ptree tree = schema.toPTree();

    boost::property_tree::write_json(os, tree);

    return os;
}

} // namespace pdal
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: IClipBoardTest.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-19 17:52:35 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef DBACCESS_TABLEDESIGN_ICLIPBOARDTEST_HXX
#define DBACCESS_TABLEDESIGN_ICLIPBOARDTEST_HXX

namespace dbaui
{
    class SAL_NO_VTABLE IClipboardTest
    {
    public:
        virtual sal_Bool isCutAllowed()         = 0;
        virtual sal_Bool isCopyAllowed()        = 0;
        virtual sal_Bool isPasteAllowed()       = 0;

        virtual sal_Bool hasChildPathFocus()    = 0;

        virtual void copy()     = 0;
        virtual void cut()      = 0;
        virtual void paste()    = 0;
    };
}
#endif // DBACCESS_TABLEDESIGN_ICLIPBOARDTEST_HXX
<commit_msg>INTEGRATION: CWS insight01 (1.2.64); FILE MERGED 2003/08/15 08:50:56 oj 1.2.64.1: #111075# ongoing new dbaapp work<commit_after>/*************************************************************************
 *
 *  $RCSfile: IClipBoardTest.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2004-08-02 15:52:38 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef DBACCESS_TABLEDESIGN_ICLIPBOARDTEST_HXX
#define DBACCESS_TABLEDESIGN_ICLIPBOARDTEST_HXX
#ifndef _SAL_TYPES_H_
#include <sal/types.h>
#endif

namespace dbaui
{
    class SAL_NO_VTABLE IClipboardTest
    {
    public:
        virtual sal_Bool isCutAllowed()         = 0;
        virtual sal_Bool isCopyAllowed()        = 0;
        virtual sal_Bool isPasteAllowed()       = 0;

        virtual sal_Bool hasChildPathFocus()    = 0;

        virtual void copy()     = 0;
        virtual void cut()      = 0;
        virtual void paste()    = 0;
    };
}
#endif // DBACCESS_TABLEDESIGN_ICLIPBOARDTEST_HXX
<|endoftext|>


<commit_before>#include "indri/DocListIterator.hpp"
#include "indri/Index.hpp"
#include "indri/Repository.hpp"
#include "w_scanner.hpp"
#include "query_train_file.hpp"

#include "cereal/archives/binary.hpp"
#include "CLI/CLI.hpp"
#include "inverted_index.hpp"

#include <iostream>
#include <tuple>
#include <unistd.h>
#include <unordered_set>

using namespace indri::api;

indri::collection::Repository repository;

std::vector<std::string> uniq_terms(const std::vector<std::string> &qry);

struct bigram {
    size_t term_a;
    size_t term_b;

    bigram(size_t a, size_t b) : term_a(a), term_b(b) {}

    bool operator<(const bigram &rhs) const {
        return std::tie(term_a, term_b) < std::tie(rhs.term_a, rhs.term_b);
    }
};

int main(int argc, char *argv[]) {

    constexpr int   w_size     = 8; //!< window size
    std::string query_file;
    std::string lexicon_file;
    std::string repo_path;
    std::string output_file;

    CLI::App app{"Create bigram inverted index."};
    app.add_option("-q,--query-file", query_file, "Query filename")->required();
    app.add_option("-r,--repo-path", repo_path, "Repo path")->required();
    app.add_option("-l,--lexicon", lexicon_file, "Lexicon file")->required();
    app.add_option("-o,--out-file", output_file, "Output filename")->required();

    CLI11_PARSE(app, argc, argv);

    //<! open read index
    indri::collection::Repository repo;
    repo.openRead(repo_path);
    indri::collection::Repository::index_state state = repo.indexes();
    const auto &                               index = (*state)[0];

    //!< init scanner
    WScanner w_scanner = WScanner(w_size);
    //!< prepare the output file

    std::ofstream               os(output_file, std::ios::binary);
    cereal::BinaryOutputArchive archive(os);

    InvertedIndex inv_idx;

    // load lexicon
    std::ifstream              lexicon_f(lexicon_file);
    cereal::BinaryInputArchive iarchive_lex(lexicon_f);
    Lexicon                    lexicon;
    iarchive_lex(lexicon);

    uint64_t                                   tot_doc    = lexicon.document_count();
    std::cerr << "Open Index, containing: " << tot_doc << " docs\n";

    //!< load query set
    // load query file
    std::ifstream ifs(query_file);
    if (!ifs.is_open()) {
        std::cerr << "Could not open file: " << query_file << std::endl;
        exit(EXIT_FAILURE);
    }
    query_train_file qtfile(ifs, lexicon);
    ifs.close();
    std::vector<std::vector<std::string>> qry_set;
    auto queries = qtfile.get_queries();
    for (auto &qry : queries) {
        qry_set.push_back(qry.stems);
    }

    // bigrams already done
    std::map<bigram, bool> bigram_seen;

    //!< start iterating over queries
    for (std::vector<std::vector<std::string>>::iterator qset_iter = qry_set.begin();
         qset_iter != qry_set.end();
         qset_iter++) {
        std::string              qry_str  = "";
        std::vector<std::string> curr_qry = uniq_terms(*qset_iter);
        if (curr_qry.size() < 2) {
            std::cerr << "Omit one term query." << std::endl;
        } else {
            // bigrams of query terms
            std::vector<std::pair<std::string, std::string>> qry_bigrams;
            for (size_t i = 0; i < curr_qry.size(); ++i) {
                for (size_t j = 0; j < curr_qry.size(); ++j) {
                    if (i == j)
                        continue;
                    qry_bigrams.push_back(std::make_pair(curr_qry[i], curr_qry[j]));
                }
            }

            for (auto &curr_bigram : qry_bigrams) {
                bigram term_bigram(lexicon.term(curr_bigram.first),
                                   lexicon.term(curr_bigram.second));

                std::map<bigram, bool>::iterator found;

                found = std::find_if(bigram_seen.begin(),
                                     bigram_seen.end(),
                                     [&](const std::pair<bigram, bool> &el) {
                                         return (el.first.term_a == term_bigram.term_a &&
                                                 el.first.term_b == term_bigram.term_b) ||
                                                (el.first.term_a == term_bigram.term_b &&
                                                 el.first.term_b == term_bigram.term_a);
                                     });

                if (found == bigram_seen.end()) {
                    std::vector<indri::index::DocListIterator *> doc_iters(2);
                    uint64_t                                     min_df   = tot_doc;
                    int                                          min_term = -1;
                    for (int i = 0; i < 2; ++i) {
                        std::string curr_str = (i == 0) ? curr_bigram.first : curr_bigram.second;

                        qry_str += curr_str + " ";
                        // get inverted list iterator and start with the term has smallest
                        // df
                        size_t tid = lexicon.term(curr_str);
                        if (lexicon.is_oov(tid)) {
                          // skip terms that don't exist
                          break;
                        }
                        uint64_t curr_df = lexicon[tid].document_count();
                        doc_iters[i]     = index->docListIterator(curr_str);
                        if (!doc_iters[i]) {
                            break;
                        }
                        doc_iters[i]->startIteration();
                        if (curr_df <= min_df) {
                            min_term = i;
                            min_df   = curr_df;
                        }
                    }

                    if (!doc_iters[0] || !doc_iters[1]) {
                        qry_str = "";
                        continue;
                    }

                    //!< start counting and then dumping out the results
                    std::vector<std::pair<lemur::api::DOCID_T, uint64_t>> window_postings =
                        w_scanner.window_count(doc_iters, min_term);

                    PostingList pl(qry_str, w_scanner.collection_cnt());
                    std::vector<uint32_t> docs;
                    std::vector<uint32_t> freqs;
                    for (auto post_iter = window_postings.begin(); post_iter != window_postings.end(); ++post_iter) {
                        docs.push_back(post_iter->first);
                        freqs.push_back(post_iter->second);
                    }
                    if(docs.size() == 0) {
                        continue;
                    }
                    pl.add_list(docs, freqs);
                    inv_idx.push_back(pl);
                    qry_str = "";

                    bigram_seen.emplace(std::pair<bigram, bool>(
                        {lexicon.term(curr_bigram.first), lexicon.term(curr_bigram.second)},
                        true));
                    delete doc_iters[0];
                    delete doc_iters[1];
                }
            }
        }
        w_scanner.set_wsize(w_size);
    }
    archive(inv_idx);
    return 0;
}

std::vector<std::string> uniq_terms(const std::vector<std::string> &qry) {
    std::vector<std::string>        qry_tokens; //!< original order must be kept
    std::unordered_set<std::string> uniq_terms; //!< deduplicate
    for (size_t i = 0; i < qry.size(); ++i) {
        std::string curr_token = qry[i];
        if (uniq_terms.empty() || uniq_terms.find(curr_token) == uniq_terms.end()) {
            qry_tokens.push_back(curr_token);
            uniq_terms.insert(curr_token);
        }
    }
    return qry_tokens;
}
<commit_msg>Ensure `qry_str` is empty for next pass<commit_after>#include "indri/DocListIterator.hpp"
#include "indri/Index.hpp"
#include "indri/Repository.hpp"
#include "w_scanner.hpp"
#include "query_train_file.hpp"

#include "cereal/archives/binary.hpp"
#include "CLI/CLI.hpp"
#include "inverted_index.hpp"

#include <iostream>
#include <tuple>
#include <unistd.h>
#include <unordered_set>

using namespace indri::api;

indri::collection::Repository repository;

std::vector<std::string> uniq_terms(const std::vector<std::string> &qry);

struct bigram {
    size_t term_a;
    size_t term_b;

    bigram(size_t a, size_t b) : term_a(a), term_b(b) {}

    bool operator<(const bigram &rhs) const {
        return std::tie(term_a, term_b) < std::tie(rhs.term_a, rhs.term_b);
    }
};

int main(int argc, char *argv[]) {

    constexpr int   w_size     = 8; //!< window size
    std::string query_file;
    std::string lexicon_file;
    std::string repo_path;
    std::string output_file;

    CLI::App app{"Create bigram inverted index."};
    app.add_option("-q,--query-file", query_file, "Query filename")->required();
    app.add_option("-r,--repo-path", repo_path, "Repo path")->required();
    app.add_option("-l,--lexicon", lexicon_file, "Lexicon file")->required();
    app.add_option("-o,--out-file", output_file, "Output filename")->required();

    CLI11_PARSE(app, argc, argv);

    //<! open read index
    indri::collection::Repository repo;
    repo.openRead(repo_path);
    indri::collection::Repository::index_state state = repo.indexes();
    const auto &                               index = (*state)[0];

    //!< init scanner
    WScanner w_scanner = WScanner(w_size);
    //!< prepare the output file

    std::ofstream               os(output_file, std::ios::binary);
    cereal::BinaryOutputArchive archive(os);

    InvertedIndex inv_idx;

    // load lexicon
    std::ifstream              lexicon_f(lexicon_file);
    cereal::BinaryInputArchive iarchive_lex(lexicon_f);
    Lexicon                    lexicon;
    iarchive_lex(lexicon);

    uint64_t                                   tot_doc    = lexicon.document_count();
    std::cerr << "Open Index, containing: " << tot_doc << " docs\n";

    //!< load query set
    // load query file
    std::ifstream ifs(query_file);
    if (!ifs.is_open()) {
        std::cerr << "Could not open file: " << query_file << std::endl;
        exit(EXIT_FAILURE);
    }
    query_train_file qtfile(ifs, lexicon);
    ifs.close();
    std::vector<std::vector<std::string>> qry_set;
    auto queries = qtfile.get_queries();
    for (auto &qry : queries) {
        qry_set.push_back(qry.stems);
    }

    // bigrams already done
    std::map<bigram, bool> bigram_seen;

    //!< start iterating over queries
    for (std::vector<std::vector<std::string>>::iterator qset_iter = qry_set.begin();
         qset_iter != qry_set.end();
         qset_iter++) {
        std::string              qry_str  = "";
        std::vector<std::string> curr_qry = uniq_terms(*qset_iter);
        if (curr_qry.size() < 2) {
            std::cerr << "Omit one term query." << std::endl;
        } else {
            // bigrams of query terms
            std::vector<std::pair<std::string, std::string>> qry_bigrams;
            for (size_t i = 0; i < curr_qry.size(); ++i) {
                for (size_t j = 0; j < curr_qry.size(); ++j) {
                    if (i == j)
                        continue;
                    qry_bigrams.push_back(std::make_pair(curr_qry[i], curr_qry[j]));
                }
            }

            for (auto &curr_bigram : qry_bigrams) {
                bigram term_bigram(lexicon.term(curr_bigram.first),
                                   lexicon.term(curr_bigram.second));

                std::map<bigram, bool>::iterator found;

                found = std::find_if(bigram_seen.begin(),
                                     bigram_seen.end(),
                                     [&](const std::pair<bigram, bool> &el) {
                                         return (el.first.term_a == term_bigram.term_a &&
                                                 el.first.term_b == term_bigram.term_b) ||
                                                (el.first.term_a == term_bigram.term_b &&
                                                 el.first.term_b == term_bigram.term_a);
                                     });

                if (found == bigram_seen.end()) {
                    std::vector<indri::index::DocListIterator *> doc_iters(2);
                    uint64_t                                     min_df   = tot_doc;
                    int                                          min_term = -1;
                    for (int i = 0; i < 2; ++i) {
                        std::string curr_str = (i == 0) ? curr_bigram.first : curr_bigram.second;

                        qry_str += curr_str + " ";
                        // get inverted list iterator and start with the term has smallest
                        // df
                        size_t tid = lexicon.term(curr_str);
                        if (lexicon.is_oov(tid)) {
                          // skip terms that don't exist
                          break;
                        }
                        uint64_t curr_df = lexicon[tid].document_count();
                        doc_iters[i]     = index->docListIterator(curr_str);
                        if (!doc_iters[i]) {
                            break;
                        }
                        doc_iters[i]->startIteration();
                        if (curr_df <= min_df) {
                            min_term = i;
                            min_df   = curr_df;
                        }
                    }

                    if (!doc_iters[0] || !doc_iters[1]) {
                        qry_str = "";
                        continue;
                    }

                    //!< start counting and then dumping out the results
                    std::vector<std::pair<lemur::api::DOCID_T, uint64_t>> window_postings =
                        w_scanner.window_count(doc_iters, min_term);

                    PostingList pl(qry_str, w_scanner.collection_cnt());
                    std::vector<uint32_t> docs;
                    std::vector<uint32_t> freqs;
                    for (auto post_iter = window_postings.begin(); post_iter != window_postings.end(); ++post_iter) {
                        docs.push_back(post_iter->first);
                        freqs.push_back(post_iter->second);
                    }
                    qry_str = "";
                    if (docs.size() == 0) {
                        continue;
                    }
                    pl.add_list(docs, freqs);
                    inv_idx.push_back(pl);

                    bigram_seen.emplace(std::pair<bigram, bool>(
                        {lexicon.term(curr_bigram.first), lexicon.term(curr_bigram.second)},
                        true));
                    delete doc_iters[0];
                    delete doc_iters[1];
                }
            }
        }
        w_scanner.set_wsize(w_size);
    }
    archive(inv_idx);
    return 0;
}

std::vector<std::string> uniq_terms(const std::vector<std::string> &qry) {
    std::vector<std::string>        qry_tokens; //!< original order must be kept
    std::unordered_set<std::string> uniq_terms; //!< deduplicate
    for (size_t i = 0; i < qry.size(); ++i) {
        std::string curr_token = qry[i];
        if (uniq_terms.empty() || uniq_terms.find(curr_token) == uniq_terms.end()) {
            qry_tokens.push_back(curr_token);
            uniq_terms.insert(curr_token);
        }
    }
    return qry_tokens;
}
<|endoftext|>


<commit_before>#include "source/common/runtime/runtime_features.h"

#include "absl/flags/commandlineflag.h"
#include "absl/flags/flag.h"
#include "absl/strings/match.h"
#include "absl/strings/str_replace.h"

#define RUNTIME_GUARD(name) ABSL_FLAG(bool, name, true, "");        // NOLINT
#define FALSE_RUNTIME_GUARD(name) ABSL_FLAG(bool, name, false, ""); // NOLINT

// Add additional features here to enable the new code paths by default.
//
// Per documentation in CONTRIBUTING.md is expected that new high risk code paths be guarded
// by runtime feature guards. If you add a guard of the form
// RUNTIME_GUARD(envoy_reloadable_features_my_feature_name)
// here you can guard code checking against "envoy.reloadable_features.my_feature_name".
// Please note the swap of envoy_reloadable_features_ to envoy.reloadable_features.!
//
// if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.my_feature_name")) {
//   [new code path]
// else {
//   [old_code_path]
// }
//
// Runtime features are true by default, so the new code path is exercised.
// To make a runtime feature false by default, use FALSE_RUNTIME_GUARD, and add
// a TODO to change it to true.
//
// If issues are found that require a runtime feature to be disabled, it should be reported
// ASAP by filing a bug on github. Overriding non-buggy code is strongly discouraged to avoid the
// problem of the bugs being found after the old code path has been removed.
RUNTIME_GUARD(envoy_reloadable_features_allow_adding_content_type_in_local_replies);
RUNTIME_GUARD(envoy_reloadable_features_allow_upstream_inline_write);
RUNTIME_GUARD(envoy_reloadable_features_append_or_truncate);
RUNTIME_GUARD(envoy_reloadable_features_append_to_accept_content_encoding_only_once);
RUNTIME_GUARD(envoy_reloadable_features_conn_pool_delete_when_idle);
RUNTIME_GUARD(envoy_reloadable_features_conn_pool_new_stream_with_early_data_and_http3);
RUNTIME_GUARD(envoy_reloadable_features_correctly_validate_alpn);
RUNTIME_GUARD(envoy_reloadable_features_deprecate_global_ints);
RUNTIME_GUARD(envoy_reloadable_features_disable_tls_inspector_injection);
RUNTIME_GUARD(envoy_reloadable_features_do_not_await_headers_on_upstream_timeout_to_emit_stats);
RUNTIME_GUARD(envoy_reloadable_features_enable_grpc_async_client_cache);
RUNTIME_GUARD(envoy_reloadable_features_handle_stream_reset_during_hcm_encoding);
RUNTIME_GUARD(envoy_reloadable_features_http1_lazy_read_disable);
RUNTIME_GUARD(envoy_reloadable_features_http2_allow_capacity_increase_by_settings);
RUNTIME_GUARD(envoy_reloadable_features_http2_new_codec_wrapper);
RUNTIME_GUARD(envoy_reloadable_features_http_100_continue_case_insensitive);
RUNTIME_GUARD(envoy_reloadable_features_http_reject_path_with_fragment);
RUNTIME_GUARD(envoy_reloadable_features_http_strip_fragment_from_path_unsafe_if_disabled);
RUNTIME_GUARD(envoy_reloadable_features_internal_address);
RUNTIME_GUARD(envoy_reloadable_features_listener_reuse_port_default_enabled);
RUNTIME_GUARD(envoy_reloadable_features_new_tcp_connection_pool);
RUNTIME_GUARD(envoy_reloadable_features_no_extension_lookup_by_name);
RUNTIME_GUARD(envoy_reloadable_features_override_request_timeout_by_gateway_timeout);
RUNTIME_GUARD(envoy_reloadable_features_postpone_h3_client_connect_to_next_loop);
RUNTIME_GUARD(envoy_reloadable_features_proxy_102_103);
RUNTIME_GUARD(envoy_reloadable_features_sanitize_http_header_referer);
RUNTIME_GUARD(envoy_reloadable_features_skip_delay_close);
RUNTIME_GUARD(envoy_reloadable_features_skip_dispatching_frames_for_closed_connection);
RUNTIME_GUARD(envoy_reloadable_features_strict_check_on_ipv4_compat);
RUNTIME_GUARD(envoy_reloadable_features_support_locality_update_on_eds_cluster_endpoints);
RUNTIME_GUARD(envoy_reloadable_features_test_feature_true);
RUNTIME_GUARD(envoy_reloadable_features_top_level_ecds_stats);
RUNTIME_GUARD(envoy_reloadable_features_udp_listener_updates_filter_chain_in_place);
RUNTIME_GUARD(envoy_reloadable_features_update_expected_rq_timeout_on_retry);
RUNTIME_GUARD(envoy_reloadable_features_update_grpc_response_error_tag);
RUNTIME_GUARD(envoy_reloadable_features_use_dns_ttl);
RUNTIME_GUARD(envoy_reloadable_features_validate_connect);
RUNTIME_GUARD(envoy_restart_features_explicit_wildcard_resource);
RUNTIME_GUARD(envoy_restart_features_no_runtime_singleton);
RUNTIME_GUARD(envoy_restart_features_use_apple_api_for_dns_lookups);

// Begin false flags. These should come with a TODO to flip true.
// Sentinel and test flag.
FALSE_RUNTIME_GUARD(envoy_reloadable_features_test_feature_false);
// TODO(alyssawilk) flip true once H2 caching is on by default.
FALSE_RUNTIME_GUARD(envoy_reloadable_features_allow_concurrency_for_alpn_pool);
// TODO(alyssawilk, junr03) flip (and add release notes + docs) these after Lyft tests
FALSE_RUNTIME_GUARD(envoy_reloadable_features_allow_multiple_dns_addresses);
// TODO(adisuissa) reset to true to enable unified mux by default
FALSE_RUNTIME_GUARD(envoy_reloadable_features_unified_mux);
// TODO(kbaichoo): Make this enabled by default when fairness and chunking
// are implemented, and we've had more cpu time.
FALSE_RUNTIME_GUARD(envoy_reloadable_features_defer_processing_backedup_streams);
// TODO(rgs1): Make this enabled after Pinterest tests
FALSE_RUNTIME_GUARD(envoy_reloadable_features_thrift_connection_draining);
// TODO(birenroy) flip after a burn-in period
// Requires envoy_reloadable_features_http2_new_codec_wrapper to be enabled.
FALSE_RUNTIME_GUARD(envoy_reloadable_features_http2_use_oghttp2);

// Block of non-boolean flags. These are deprecated. Do not add more.
ABSL_FLAG(uint64_t, envoy_headermap_lazy_map_min_size, 3, "");  // NOLINT
ABSL_FLAG(uint64_t, re2_max_program_size_error_level, 100, ""); // NOLINT
ABSL_FLAG(uint64_t, re2_max_program_size_warn_level,            // NOLINT
          std::numeric_limits<uint32_t>::max(), "");            // NOLINT

namespace Envoy {
namespace Runtime {
namespace {

std::string swapPrefix(std::string name) {
  return absl::StrReplaceAll(name, {{"envoy_", "envoy."}, {"features_", "features."}});
}

} // namespace

// This is a singleton class to map Envoy style flag names to absl flags
class RuntimeFeatures {
public:
  RuntimeFeatures();

  // Get the command line flag corresponding to the Envoy style feature name, or
  // nullptr if it is not a registered flag.
  absl::CommandLineFlag* getFlag(absl::string_view feature) const {
    auto it = all_features_.find(feature);
    if (it == all_features_.end()) {
      return nullptr;
    }
    return it->second;
  }

private:
  absl::flat_hash_map<std::string, absl::CommandLineFlag*> all_features_;
};

using RuntimeFeaturesDefaults = ConstSingleton<RuntimeFeatures>;

RuntimeFeatures::RuntimeFeatures() {
  absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> flags = absl::GetAllFlags();
  for (auto& it : flags) {
    absl::string_view name = it.second->Name();
    if ((!absl::StartsWith(name, "envoy_reloadable_features_") &&
         !absl::StartsWith(name, "envoy_restart_features_")) ||
        !it.second->TryGet<bool>().has_value()) {
      continue;
    }
    std::string envoy_name = swapPrefix(std::string(name));
    all_features_.emplace(envoy_name, it.second);
  }
}

bool hasRuntimePrefix(absl::string_view feature) {
  // Track Envoy reloadable and restart features, excluding synthetic QUIC flags
  // which are not tracked in the list below.
  return (absl::StartsWith(feature, "envoy.reloadable_features.") &&
          !absl::StartsWith(feature, "envoy.reloadable_features.FLAGS_quic")) ||
         absl::StartsWith(feature, "envoy.restart_features.");
}

bool isRuntimeFeature(absl::string_view feature) {
  return RuntimeFeaturesDefaults::get().getFlag(feature) != nullptr;
}

bool runtimeFeatureEnabled(absl::string_view feature) {
  absl::CommandLineFlag* flag = RuntimeFeaturesDefaults::get().getFlag(feature);
  if (flag == nullptr) {
    IS_ENVOY_BUG(absl::StrCat("Unable to find runtime feature ", feature));
    return false;
  }
  // We validate in map creation that the flag is a boolean.
  return flag->TryGet<bool>().value();
}

uint64_t getInteger(absl::string_view feature, uint64_t default_value) {
  if (absl::StartsWith(feature, "envoy.")) {
    // DO NOT ADD MORE FLAGS HERE. This function deprecated.
    if (feature == "envoy.http.headermap.lazy_map_min_size") {
      return absl::GetFlag(FLAGS_envoy_headermap_lazy_map_min_size);
    }
  }
  if (absl::StartsWith(feature, "re2.")) {
    if (feature == "re2.max_program_size.error_level") {
      return absl::GetFlag(FLAGS_re2_max_program_size_error_level);
    } else if (feature == "re2.max_program_size.warn_level") {
      return absl::GetFlag(FLAGS_re2_max_program_size_warn_level);
    }
  }
  IS_ENVOY_BUG(absl::StrCat("requested an unsupported integer ", feature));
  return default_value;
}

void maybeSetRuntimeGuard(absl::string_view name, bool value) {
  absl::CommandLineFlag* flag = RuntimeFeaturesDefaults::get().getFlag(name);
  if (flag == nullptr) {
    IS_ENVOY_BUG(absl::StrCat("Unable to find runtime feature ", name));
    return;
  }
  std::string err;
  flag->ParseFrom(value ? "true" : "false", &err);
}

void maybeSetDeprecatedInts(absl::string_view name, uint32_t value) {
  if (!absl::StartsWith(name, "envoy.") && !absl::StartsWith(name, "re2.")) {
    return;
  }

  // DO NOT ADD MORE FLAGS HERE. This function deprecated and being removed.
  if (name == "envoy.http.headermap.lazy_map_min_size") {
    if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.deprecate_global_ints")) {
      IS_ENVOY_BUG(absl::StrCat(
          "The Envoy community is attempting to remove global integers. Given you use ", name,
          " please immediately file an upstream issue to retain the functionality as it will "
          "otherwise be removed following the usual deprecation cycle."));
    }
    absl::SetFlag(&FLAGS_envoy_headermap_lazy_map_min_size, value);
  } else if (name == "re2.max_program_size.error_level") {
    absl::SetFlag(&FLAGS_re2_max_program_size_error_level, value);
  } else if (name == "re2.max_program_size.warn_level") {
    absl::SetFlag(&FLAGS_re2_max_program_size_warn_level, value);
  }
}

} // namespace Runtime
} // namespace Envoy
<commit_msg>runtime: remove stale guard (#21020)<commit_after>#include "source/common/runtime/runtime_features.h"

#include "absl/flags/commandlineflag.h"
#include "absl/flags/flag.h"
#include "absl/strings/match.h"
#include "absl/strings/str_replace.h"

#define RUNTIME_GUARD(name) ABSL_FLAG(bool, name, true, "");        // NOLINT
#define FALSE_RUNTIME_GUARD(name) ABSL_FLAG(bool, name, false, ""); // NOLINT

// Add additional features here to enable the new code paths by default.
//
// Per documentation in CONTRIBUTING.md is expected that new high risk code paths be guarded
// by runtime feature guards. If you add a guard of the form
// RUNTIME_GUARD(envoy_reloadable_features_my_feature_name)
// here you can guard code checking against "envoy.reloadable_features.my_feature_name".
// Please note the swap of envoy_reloadable_features_ to envoy.reloadable_features.!
//
// if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.my_feature_name")) {
//   [new code path]
// else {
//   [old_code_path]
// }
//
// Runtime features are true by default, so the new code path is exercised.
// To make a runtime feature false by default, use FALSE_RUNTIME_GUARD, and add
// a TODO to change it to true.
//
// If issues are found that require a runtime feature to be disabled, it should be reported
// ASAP by filing a bug on github. Overriding non-buggy code is strongly discouraged to avoid the
// problem of the bugs being found after the old code path has been removed.
RUNTIME_GUARD(envoy_reloadable_features_allow_adding_content_type_in_local_replies);
RUNTIME_GUARD(envoy_reloadable_features_allow_upstream_inline_write);
RUNTIME_GUARD(envoy_reloadable_features_append_or_truncate);
RUNTIME_GUARD(envoy_reloadable_features_append_to_accept_content_encoding_only_once);
RUNTIME_GUARD(envoy_reloadable_features_conn_pool_delete_when_idle);
RUNTIME_GUARD(envoy_reloadable_features_conn_pool_new_stream_with_early_data_and_http3);
RUNTIME_GUARD(envoy_reloadable_features_correctly_validate_alpn);
RUNTIME_GUARD(envoy_reloadable_features_deprecate_global_ints);
RUNTIME_GUARD(envoy_reloadable_features_disable_tls_inspector_injection);
RUNTIME_GUARD(envoy_reloadable_features_do_not_await_headers_on_upstream_timeout_to_emit_stats);
RUNTIME_GUARD(envoy_reloadable_features_enable_grpc_async_client_cache);
RUNTIME_GUARD(envoy_reloadable_features_handle_stream_reset_during_hcm_encoding);
RUNTIME_GUARD(envoy_reloadable_features_http1_lazy_read_disable);
RUNTIME_GUARD(envoy_reloadable_features_http2_allow_capacity_increase_by_settings);
RUNTIME_GUARD(envoy_reloadable_features_http2_new_codec_wrapper);
RUNTIME_GUARD(envoy_reloadable_features_http_100_continue_case_insensitive);
RUNTIME_GUARD(envoy_reloadable_features_http_reject_path_with_fragment);
RUNTIME_GUARD(envoy_reloadable_features_http_strip_fragment_from_path_unsafe_if_disabled);
RUNTIME_GUARD(envoy_reloadable_features_internal_address);
RUNTIME_GUARD(envoy_reloadable_features_new_tcp_connection_pool);
RUNTIME_GUARD(envoy_reloadable_features_no_extension_lookup_by_name);
RUNTIME_GUARD(envoy_reloadable_features_override_request_timeout_by_gateway_timeout);
RUNTIME_GUARD(envoy_reloadable_features_postpone_h3_client_connect_to_next_loop);
RUNTIME_GUARD(envoy_reloadable_features_proxy_102_103);
RUNTIME_GUARD(envoy_reloadable_features_sanitize_http_header_referer);
RUNTIME_GUARD(envoy_reloadable_features_skip_delay_close);
RUNTIME_GUARD(envoy_reloadable_features_skip_dispatching_frames_for_closed_connection);
RUNTIME_GUARD(envoy_reloadable_features_strict_check_on_ipv4_compat);
RUNTIME_GUARD(envoy_reloadable_features_support_locality_update_on_eds_cluster_endpoints);
RUNTIME_GUARD(envoy_reloadable_features_test_feature_true);
RUNTIME_GUARD(envoy_reloadable_features_top_level_ecds_stats);
RUNTIME_GUARD(envoy_reloadable_features_udp_listener_updates_filter_chain_in_place);
RUNTIME_GUARD(envoy_reloadable_features_update_expected_rq_timeout_on_retry);
RUNTIME_GUARD(envoy_reloadable_features_update_grpc_response_error_tag);
RUNTIME_GUARD(envoy_reloadable_features_use_dns_ttl);
RUNTIME_GUARD(envoy_reloadable_features_validate_connect);
RUNTIME_GUARD(envoy_restart_features_explicit_wildcard_resource);
RUNTIME_GUARD(envoy_restart_features_no_runtime_singleton);
RUNTIME_GUARD(envoy_restart_features_use_apple_api_for_dns_lookups);

// Begin false flags. These should come with a TODO to flip true.
// Sentinel and test flag.
FALSE_RUNTIME_GUARD(envoy_reloadable_features_test_feature_false);
// TODO(alyssawilk) flip true once H2 caching is on by default.
FALSE_RUNTIME_GUARD(envoy_reloadable_features_allow_concurrency_for_alpn_pool);
// TODO(alyssawilk, junr03) flip (and add release notes + docs) these after Lyft tests
FALSE_RUNTIME_GUARD(envoy_reloadable_features_allow_multiple_dns_addresses);
// TODO(adisuissa) reset to true to enable unified mux by default
FALSE_RUNTIME_GUARD(envoy_reloadable_features_unified_mux);
// TODO(kbaichoo): Make this enabled by default when fairness and chunking
// are implemented, and we've had more cpu time.
FALSE_RUNTIME_GUARD(envoy_reloadable_features_defer_processing_backedup_streams);
// TODO(rgs1): Make this enabled after Pinterest tests
FALSE_RUNTIME_GUARD(envoy_reloadable_features_thrift_connection_draining);
// TODO(birenroy) flip after a burn-in period
// Requires envoy_reloadable_features_http2_new_codec_wrapper to be enabled.
FALSE_RUNTIME_GUARD(envoy_reloadable_features_http2_use_oghttp2);

// Block of non-boolean flags. These are deprecated. Do not add more.
ABSL_FLAG(uint64_t, envoy_headermap_lazy_map_min_size, 3, "");  // NOLINT
ABSL_FLAG(uint64_t, re2_max_program_size_error_level, 100, ""); // NOLINT
ABSL_FLAG(uint64_t, re2_max_program_size_warn_level,            // NOLINT
          std::numeric_limits<uint32_t>::max(), "");            // NOLINT

namespace Envoy {
namespace Runtime {
namespace {

std::string swapPrefix(std::string name) {
  return absl::StrReplaceAll(name, {{"envoy_", "envoy."}, {"features_", "features."}});
}

} // namespace

// This is a singleton class to map Envoy style flag names to absl flags
class RuntimeFeatures {
public:
  RuntimeFeatures();

  // Get the command line flag corresponding to the Envoy style feature name, or
  // nullptr if it is not a registered flag.
  absl::CommandLineFlag* getFlag(absl::string_view feature) const {
    auto it = all_features_.find(feature);
    if (it == all_features_.end()) {
      return nullptr;
    }
    return it->second;
  }

private:
  absl::flat_hash_map<std::string, absl::CommandLineFlag*> all_features_;
};

using RuntimeFeaturesDefaults = ConstSingleton<RuntimeFeatures>;

RuntimeFeatures::RuntimeFeatures() {
  absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> flags = absl::GetAllFlags();
  for (auto& it : flags) {
    absl::string_view name = it.second->Name();
    if ((!absl::StartsWith(name, "envoy_reloadable_features_") &&
         !absl::StartsWith(name, "envoy_restart_features_")) ||
        !it.second->TryGet<bool>().has_value()) {
      continue;
    }
    std::string envoy_name = swapPrefix(std::string(name));
    all_features_.emplace(envoy_name, it.second);
  }
}

bool hasRuntimePrefix(absl::string_view feature) {
  // Track Envoy reloadable and restart features, excluding synthetic QUIC flags
  // which are not tracked in the list below.
  return (absl::StartsWith(feature, "envoy.reloadable_features.") &&
          !absl::StartsWith(feature, "envoy.reloadable_features.FLAGS_quic")) ||
         absl::StartsWith(feature, "envoy.restart_features.");
}

bool isRuntimeFeature(absl::string_view feature) {
  return RuntimeFeaturesDefaults::get().getFlag(feature) != nullptr;
}

bool runtimeFeatureEnabled(absl::string_view feature) {
  absl::CommandLineFlag* flag = RuntimeFeaturesDefaults::get().getFlag(feature);
  if (flag == nullptr) {
    IS_ENVOY_BUG(absl::StrCat("Unable to find runtime feature ", feature));
    return false;
  }
  // We validate in map creation that the flag is a boolean.
  return flag->TryGet<bool>().value();
}

uint64_t getInteger(absl::string_view feature, uint64_t default_value) {
  if (absl::StartsWith(feature, "envoy.")) {
    // DO NOT ADD MORE FLAGS HERE. This function deprecated.
    if (feature == "envoy.http.headermap.lazy_map_min_size") {
      return absl::GetFlag(FLAGS_envoy_headermap_lazy_map_min_size);
    }
  }
  if (absl::StartsWith(feature, "re2.")) {
    if (feature == "re2.max_program_size.error_level") {
      return absl::GetFlag(FLAGS_re2_max_program_size_error_level);
    } else if (feature == "re2.max_program_size.warn_level") {
      return absl::GetFlag(FLAGS_re2_max_program_size_warn_level);
    }
  }
  IS_ENVOY_BUG(absl::StrCat("requested an unsupported integer ", feature));
  return default_value;
}

void maybeSetRuntimeGuard(absl::string_view name, bool value) {
  absl::CommandLineFlag* flag = RuntimeFeaturesDefaults::get().getFlag(name);
  if (flag == nullptr) {
    IS_ENVOY_BUG(absl::StrCat("Unable to find runtime feature ", name));
    return;
  }
  std::string err;
  flag->ParseFrom(value ? "true" : "false", &err);
}

void maybeSetDeprecatedInts(absl::string_view name, uint32_t value) {
  if (!absl::StartsWith(name, "envoy.") && !absl::StartsWith(name, "re2.")) {
    return;
  }

  // DO NOT ADD MORE FLAGS HERE. This function deprecated and being removed.
  if (name == "envoy.http.headermap.lazy_map_min_size") {
    if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.deprecate_global_ints")) {
      IS_ENVOY_BUG(absl::StrCat(
          "The Envoy community is attempting to remove global integers. Given you use ", name,
          " please immediately file an upstream issue to retain the functionality as it will "
          "otherwise be removed following the usual deprecation cycle."));
    }
    absl::SetFlag(&FLAGS_envoy_headermap_lazy_map_min_size, value);
  } else if (name == "re2.max_program_size.error_level") {
    absl::SetFlag(&FLAGS_re2_max_program_size_error_level, value);
  } else if (name == "re2.max_program_size.warn_level") {
    absl::SetFlag(&FLAGS_re2_max_program_size_warn_level, value);
  }
}

} // namespace Runtime
} // namespace Envoy
<|endoftext|>


<commit_before>/****************************************************************
Purpose:
	Look for a "core" file at a given location.  Return TRUE if it
	exists and appears complete and correct, and FALSE otherwise.
	The SUN core consists of a header, the data and stack segments
	and finally the uarea.  We check the magic number in the header
	first.  If that's OK we then calculate what the size of the
	core should be using the size of the header, the sizes of the
	data and stack areas recorded in the header and the size of the
	uarea as defined in "sys/param.h".  We then compare this
	calculation with the actual size of the file.
Portability:
	This code depends upon the core format for SUNOS4.1 systems,
	and is not portable to other systems.

Modified for Solaris by : Dhaval N. Shah
							 University of Wisconsin, Madison
**                           Computer Sciences Department
******************************************************************/

#define _ALL_SOURCE

#include "condor_common.h"
#include "condor_debug.h"
#include "condor_constants.h"
#include "condor_jobqueue.h"
#include <sys/file.h>
#include <sys/core.h>
#include <sys/param.h>
#include "proto.h"

static char *_FileName_ = __FILE__;     /* Used by EXCEPT (see except.h)     */
#if defined(Solaris)
  #define UPAGES 4
  #define NBPG 0x1000   /*couldnt get this val from header files. Rough
		        estimate from Suns header files - Raghu */
  #undef CORE_MAGIC
  #if defined(X86)
  #define CORE_MAGIC 0x464c457f  /* at least, this is the magic for my
									core file - Jim B. */
  #else
  #define CORE_MAGIC 0x7f454c46
  #endif
#endif

const int       UAREA_SIZE = UPAGES * NBPG;
const int	HEADER_SIZE = sizeof(struct core);

int
core_is_valid( char *name )
{
	struct core header;

	int		fd;
	int		total_size;
	off_t	file_size;

	dprintf( D_ALWAYS,
		"Analyzing core file \"%s\" for existence and completeness\n", name
	);

	if( (fd=open(name,O_RDONLY)) < 0 ) {
		dprintf( D_ALWAYS, "Can't open core file \"%s\"", name );
		return FALSE;
	}

	if( read(fd,(char *)&header,HEADER_SIZE) != HEADER_SIZE ) {
		dprintf( D_ALWAYS, "Can't read header from core file\n" );
		(void)close( fd );
		return FALSE;
	}

	file_size = lseek( fd, (off_t)0, SEEK_END );
	(void)close( fd );

	if( header.c_magic != CORE_MAGIC ) {
		dprintf( D_ALWAYS,
			"Core file - bad magic number (0x%x)\n", header.c_magic
		);
		return FALSE;
	}

	dprintf( D_ALWAYS,
		"Core file - magic number OK\n"
	);

	/* the size test is bogus on Solaris -- there is something wrong
	   with the header information -- I'm taking it out.  -Jim B. */

/*	total_size = header.c_len + header.c_dsize + header.c_ssize + UAREA_SIZE;

	if( file_size != total_size ) {
		dprintf( D_ALWAYS,
			"file_size should be %d, but is %d\n", total_size, file_size
		);
		return FALSE;
	} else {
		dprintf( D_ALWAYS,
			"Core file_size of %d is correct\n", file_size
		); */
		return TRUE;
/*	} */

#if 0
	dprintf( D_ALWAYS, "c_len = %d bytes\n", header.c_len );
	dprintf( D_ALWAYS, "c_dsize = %d bytes\n", header.c_dsize );
	dprintf( D_ALWAYS, "c_ssize = %d bytes\n", header.c_ssize );
	dprintf( D_ALWAYS, "UAREA_SIZE = %d bytes\n", UAREA_SIZE );
	dprintf( D_ALWAYS, "total_size = %d bytes\n", total_size );
#endif

}
<commit_msg>show errno when we can't open a core file on Solaris<commit_after>/****************************************************************
Purpose:
	Look for a "core" file at a given location.  Return TRUE if it
	exists and appears complete and correct, and FALSE otherwise.
	The SUN core consists of a header, the data and stack segments
	and finally the uarea.  We check the magic number in the header
	first.  If that's OK we then calculate what the size of the
	core should be using the size of the header, the sizes of the
	data and stack areas recorded in the header and the size of the
	uarea as defined in "sys/param.h".  We then compare this
	calculation with the actual size of the file.
Portability:
	This code depends upon the core format for SUNOS4.1 systems,
	and is not portable to other systems.

Modified for Solaris by : Dhaval N. Shah
							 University of Wisconsin, Madison
**                           Computer Sciences Department
******************************************************************/

#define _ALL_SOURCE

#include "condor_common.h"
#include "condor_debug.h"
#include "condor_constants.h"
#include "condor_jobqueue.h"
#include <sys/file.h>
#include <sys/core.h>
#include <sys/param.h>
#include "proto.h"

static char *_FileName_ = __FILE__;     /* Used by EXCEPT (see except.h)     */
#if defined(Solaris)
  #define UPAGES 4
  #define NBPG 0x1000   /*couldnt get this val from header files. Rough
		        estimate from Suns header files - Raghu */
  #undef CORE_MAGIC
  #if defined(X86)
  #define CORE_MAGIC 0x464c457f  /* at least, this is the magic for my
									core file - Jim B. */
  #else
  #define CORE_MAGIC 0x7f454c46
  #endif
#endif

const int       UAREA_SIZE = UPAGES * NBPG;
const int	HEADER_SIZE = sizeof(struct core);

int
core_is_valid( char *name )
{
	struct core header;

	int		fd;
	int		total_size;
	off_t	file_size;

	dprintf( D_ALWAYS,
		"Analyzing core file \"%s\" for existence and completeness\n", name
	);

	if( (fd=open(name,O_RDONLY)) < 0 ) {
		dprintf( D_ALWAYS, "Can't open core file \"%s\", errno = %d\n",
				 name, errno );
		return FALSE;
	}

	if( read(fd,(char *)&header,HEADER_SIZE) != HEADER_SIZE ) {
		dprintf( D_ALWAYS, "Can't read header from core file\n" );
		(void)close( fd );
		return FALSE;
	}

	file_size = lseek( fd, (off_t)0, SEEK_END );
	(void)close( fd );

	if( header.c_magic != CORE_MAGIC ) {
		dprintf( D_ALWAYS,
			"Core file - bad magic number (0x%x)\n", header.c_magic
		);
		return FALSE;
	}

	dprintf( D_ALWAYS,
		"Core file - magic number OK\n"
	);

	/* the size test is bogus on Solaris -- there is something wrong
	   with the header information -- I'm taking it out.  -Jim B. */

/*	total_size = header.c_len + header.c_dsize + header.c_ssize + UAREA_SIZE;

	if( file_size != total_size ) {
		dprintf( D_ALWAYS,
			"file_size should be %d, but is %d\n", total_size, file_size
		);
		return FALSE;
	} else {
		dprintf( D_ALWAYS,
			"Core file_size of %d is correct\n", file_size
		); */
		return TRUE;
/*	} */

#if 0
	dprintf( D_ALWAYS, "c_len = %d bytes\n", header.c_len );
	dprintf( D_ALWAYS, "c_dsize = %d bytes\n", header.c_dsize );
	dprintf( D_ALWAYS, "c_ssize = %d bytes\n", header.c_ssize );
	dprintf( D_ALWAYS, "UAREA_SIZE = %d bytes\n", UAREA_SIZE );
	dprintf( D_ALWAYS, "total_size = %d bytes\n", total_size );
#endif

}
<|endoftext|>


<commit_before>#ifndef LogEntry_hpp1
#define LogEntry_hpp1

#include "era.hpp"

namespace era01 {

class LogEntry {
 private:
  TimeInfo zTime;
  string zMsg;

 public:
  LogEntry();
  LogEntry(const char* msg);
  LogEntry(const LogEntry& obj);
  LogEntry(const TimeInfo& entry, string msg);
  virtual ~LogEntry() {}

  bool parse(string);
  bool sameDate(const LogEntry& ref) const;

  virtual TimeInfo time() const;
  virtual string entry() const;
  virtual string message() const;
};
}

#endif
<commit_msg>Related & trivial updates.<commit_after>#ifndef LogEntry_hpp1
#define LogEntry_hpp1

#include "era.hpp"

namespace era01 {

class LogEntry {
 private:
  TimeInfo zTime;
  string zMsg;

 public:
  LogEntry();
  LogEntry(const char *msg);
  LogEntry(const LogEntry& obj);
  LogEntry(const TimeInfo& entry, const string &msg);
  LogEntry(const TimeStruct& entry, const string &msg);
  virtual ~LogEntry() {}

  bool parse(string);
  bool sameDate(const LogEntry& ref) const;

  virtual TimeInfo time() const;
  virtual string entry() const;
  virtual string message() const;
};
}

#endif
<|endoftext|>


<commit_before>#ifndef SRC_PORTS_DETAIL_ACTIVE_SOURCE_PROXY_HPP_
#define SRC_PORTS_DETAIL_ACTIVE_SOURCE_PROXY_HPP_

#include <functional>

#include <flexcore/core/connection.hpp>
#include <flexcore/pure/port_connection.hpp>

namespace fc
{

namespace detail
{

//policy classes for determining argument order in connect calls in the proxy
struct active_sink_first
{
	template<class sink_t, class source_t>
	struct source
	{
		typedef source_t type;
	};

	template<class sink_t, class source_t>
	struct sink
	{
		typedef sink_t type;
		typedef void result_t;
	};

	template<class sink_t, class source_t>
	auto operator()(sink_t&& sink, source_t&& source)
	{
		return ::fc::connect(std::forward<source_t>(source), std::forward<sink_t>(sink));
	}
};
struct active_source_first
{
	template<class source_t, class sink_t>
	struct source
	{
		typedef source_t type;
	};

	template<class source_t, class sink_t>
	struct sink
	{
		typedef sink_t type;
		typedef result_of_t<source_t> result_t;
	};
	template<class source_t, class sink_t>
	auto operator()(source_t&& source, sink_t&& sink)
	{
		return ::fc::connect(std::forward<source_t>(source), std::forward<sink_t>(sink));
	}
};

template <class T>
struct always_false : std::false_type
{
};

/**
 * \brief contains connections of active_connectables during creation.
 *
 * active_connection_proxy is used to store the intermediate objects created,
 * when a connection is build up from an active connectable
 * Until the active connectable is connected to a proper passive,
 * the connection is not complete and no value can be pulled or send through.
 * Nonetheless, the connection needs to be stored to allow further connections.
 * the active_connection_proxy stores these temporary objects.
 *
 * \tparam active_ is the active connection,
 * \tparam passive_t the passive side of the connection durint buildup
 * \tparam
 * {
 * connect_policy a policy class which makes sure parameters to connect
 * inside the proxy are in the correct order.
 * }
 * */
template<class active_t, class passive_t, class connect_policy>
struct active_connection_proxy
{
	static_assert(is_active<std::decay_t<active_t>>{},
			"active_t in proxy needs to be active connectable");

	typedef typename
			connect_policy::template sink<active_t, passive_t>::result_t result_t;

	active_connection_proxy(active_t active_, passive_t passive) :
			active(std::forward<active_t>(active_)),
			stored_passive(std::forward<passive_t>(passive))
	{}

	/**
	 * \brief connects a passive connectable to the active_connection_proxy.
	 *
	 * connects the new_source to the current stored source
	 * then connects this connection to the sink which completes the connection
	 *
	 * \pre new_passive_t needs to be passive connectable.
	 * \post new_passive is now connected to active via the connection stored in the proxy.
	 * \returns port connection tag object.
	 */
	template<class new_passive_t, class enable = void>
	auto connect(new_passive_t&& new_passive,
	             std::enable_if_t<(is_passive_source<std::decay_t<new_passive_t>>{} or
	                               is_passive_sink_for<std::decay_t<new_passive_t>, result_t>{})>* = nullptr) &&
	{
		auto tmp = connect_policy()(std::forward<passive_t>(stored_passive),
		                            std::forward<new_passive_t>(new_passive));
		return std::forward<active_t>(active).connect(std::move(tmp));
	}

	/**
	 * \brief connects a connectable, which is not a passive connectable to the
	 *        active_connection_proxy.
	 *
	 * connects the new_connectable to the current stored source
	 *
	 * \pre new_connectable_t needs to be connectable
	 * \post new_connectable_t is connected to the old passive.
	 * \returns a active_connection_proxy, which contains the new_connectable in its connection.
	 */
	template <class new_connectable_t,
	          class = std::enable_if_t<not(is_passive_source<std::decay_t<new_connectable_t>>{} or
	                                       is_passive_sink_for<std::decay_t<new_connectable_t>, result_t>{})>>
	auto connect(new_connectable_t&& new_connectable) &&
	{
		auto connection = connect_policy()(std::forward<passive_t>(stored_passive),
		                                   std::forward<new_connectable_t>(new_connectable));
		return active_connection_proxy<
				active_t,
				decltype(connection),
				connect_policy>(active, std::move(connection));
	}

	/**
	 * \brief catch function to prevent active_connection_proxies from being treated as lvalues.
	 */
	template <class new_connectable_t>
	void connect(new_connectable_t&&) &
	{
		static_assert(always_false<new_connectable_t>{}, "active_connection_proxies cannot be used multiple times.");
	}

	active_t active;
	passive_t stored_passive;
};

template<class active_t, class passive_t, class argument_order, class Enable = void>
struct active_passive_connect_impl;

/// Specialization of connect to call member connect of stream_proxy.
template<class active_t, class passive_t, class argument_order>
struct active_passive_connect_impl
	<	active_t,
		passive_t,
		argument_order,
		std::enable_if_t<is_instantiation_of<active_connection_proxy, std::decay_t<active_t>>{}>
	>
{
	auto operator()(active_t&& active, passive_t&& passive)
	{
		return std::forward<active_t>(active).connect(std::forward<passive_t>(passive));
	}
};

/**
 * Specialization of active_passive_connect_impl for the case of connecting a standard connectable
 * which is not a is_passive_sink to a is_passive_source.
 * \return a stream_proxy which contains the active && the passive.
 */
template<class active_t, class passive_t, class argument_order>
struct active_passive_connect_impl
	<	active_t,
		passive_t,
		argument_order,
		std::enable_if_t
			<	!is_instantiation_of< active_connection_proxy,std::decay_t<active_t>>{}
				&&	(	(	is_active_source<std::decay_t<active_t>>{}
						&& !fc::is_passive_sink_for<std::decay_t<passive_t>,
						                            typename std::decay_t<active_t>::result_t>{}
						)
					||	(	fc::is_active_sink<std::decay_t<active_t>>{}
						&& !fc::is_passive_source<std::decay_t<passive_t>>{}
						)
					)>
	>
{
	auto operator()(active_t&& active, passive_t&& passive)
	{
		return active_connection_proxy<active_t, passive_t, argument_order>
				(std::forward<active_t>(active), std::forward<passive_t>(passive));
	}
};

/**
 * Specialization for the case of connecting a active_port to a passive_port.
 * \pre active_t needs to be a active_connectable.
 * \pre passive_t needs to be a passive_connectable.
 * \post active is now connected to passive
 * \return port_connection tag object with the type information of the connection.
 */
template<class active_t, class passive_t, class argument_order>
struct active_passive_connect_impl
	<	active_t,
		passive_t,
		argument_order,
		std::enable_if_t
			<	!is_instantiation_of< active_connection_proxy, std::decay_t<active_t>>{}
				&&	(	(	is_active_source<std::decay_t<active_t>>{}
						&& fc::is_passive_sink_for<std::decay_t<passive_t>,
						                            typename std::decay_t<active_t>::result_t>{}
					)
					||	(	fc::is_active_sink<std::decay_t<active_t>>{}
						&&	fc::is_passive_source<std::decay_t<passive_t>>{}
						)
					)>
	>
{
	auto operator()(active_t&& active, passive_t&& passive)
	{

		std::forward<active_t>(active).connect(std::forward<passive_t>(passive));
		using source_t = typename argument_order::template source<active_t, passive_t>::type;
		using sink_t = typename argument_order::template sink<active_t, passive_t>::type;
		return port_connection<source_t, sink_t, result_of_t<active_t>>();
	}
};

template<class source_t, class sink_t>
struct connect_impl
	<	source_t,
		sink_t,
		std::enable_if_t<fc::is_active<std::decay_t<source_t>>{}>
	>
{
	auto operator()(source_t&& source, sink_t&& sink)
	{
		// source is active, thus it is the first parameter
		return active_passive_connect_impl<source_t, sink_t, active_source_first>()
		    (std::forward<source_t>(source), std::forward<sink_t>(sink));
	}
};

template<class source_t, class sink_t>
struct connect_impl
	<	source_t,
		sink_t,
		std::enable_if_t<fc::is_active<std::decay_t<sink_t>>{}>
	>
{
	auto operator()(source_t&& source, sink_t&& sink)
	{
		// sink is active, thus it is the first parameter
		return active_passive_connect_impl<sink_t, source_t, active_sink_first>()
				(std::forward<sink_t>(sink), std::forward<source_t>(source));
	}
};

}  //namespace detail

template<class T, class U> struct is_active_sink<
	detail::active_connection_proxy<T, U, detail::active_sink_first>>
		: std::true_type {};
template<class T, class U> struct is_active_source<
	detail::active_connection_proxy<T, U, detail::active_source_first>>
		: std::true_type {};
}  //namespace fc

#endif /* SRC_PORTS_DETAIL_ACTIVE_SOURCE_PROXY_HPP_ */
<commit_msg>active_conn_proxy: Fix connection chains with changing param/ret types<commit_after>#ifndef SRC_PORTS_DETAIL_ACTIVE_SOURCE_PROXY_HPP_
#define SRC_PORTS_DETAIL_ACTIVE_SOURCE_PROXY_HPP_

#include <functional>

#include <flexcore/core/connection.hpp>
#include <flexcore/pure/port_connection.hpp>

namespace fc
{

namespace detail
{

//policy classes for determining argument order in connect calls in the proxy
struct active_sink_first
{
	template<class sink_t, class source_t>
	struct source
	{
		typedef source_t type;
	};

	template<class sink_t, class source_t>
	struct sink
	{
		typedef sink_t type;
		typedef void result_t;
	};

	template<class sink_t, class source_t>
	auto operator()(sink_t&& sink, source_t&& source)
	{
		return ::fc::connect(std::forward<source_t>(source), std::forward<sink_t>(sink));
	}
};
struct active_source_first
{
	template<class source_t, class sink_t>
	struct source
	{
		typedef source_t type;
	};

	template<class source_t, class sink_t>
	struct sink
	{
		typedef sink_t type;
		using result_t = typename detail::result_of_fwd<sink_t, result_of_t<source_t>>::type::type;
	};
	template<class source_t, class sink_t>
	auto operator()(source_t&& source, sink_t&& sink)
	{
		return ::fc::connect(std::forward<source_t>(source), std::forward<sink_t>(sink));
	}
};

template <class T>
struct always_false : std::false_type
{
};

/**
 * \brief contains connections of active_connectables during creation.
 *
 * active_connection_proxy is used to store the intermediate objects created,
 * when a connection is build up from an active connectable
 * Until the active connectable is connected to a proper passive,
 * the connection is not complete and no value can be pulled or send through.
 * Nonetheless, the connection needs to be stored to allow further connections.
 * the active_connection_proxy stores these temporary objects.
 *
 * \tparam active_ is the active connection,
 * \tparam passive_t the passive side of the connection durint buildup
 * \tparam
 * {
 * connect_policy a policy class which makes sure parameters to connect
 * inside the proxy are in the correct order.
 * }
 * */
template<class active_t, class passive_t, class connect_policy>
struct active_connection_proxy
{
	static_assert(is_active<std::decay_t<active_t>>{},
			"active_t in proxy needs to be active connectable");

	typedef typename
			connect_policy::template sink<active_t, passive_t>::result_t result_t;

	active_connection_proxy(active_t active_, passive_t passive) :
			active(std::forward<active_t>(active_)),
			stored_passive(std::forward<passive_t>(passive))
	{}

	/**
	 * \brief connects a passive connectable to the active_connection_proxy.
	 *
	 * connects the new_source to the current stored source
	 * then connects this connection to the sink which completes the connection
	 *
	 * \pre new_passive_t needs to be passive connectable.
	 * \post new_passive is now connected to active via the connection stored in the proxy.
	 * \returns port connection tag object.
	 */
	template<class new_passive_t, class enable = void>
	auto connect(new_passive_t&& new_passive,
	             std::enable_if_t<(is_passive_source<std::decay_t<new_passive_t>>{} or
	                               is_passive_sink_for<std::decay_t<new_passive_t>, result_t>{})>* = nullptr) &&
	{
		auto tmp = connect_policy()(std::forward<passive_t>(stored_passive),
		                            std::forward<new_passive_t>(new_passive));
		return std::forward<active_t>(active).connect(std::move(tmp));
	}

	/**
	 * \brief connects a connectable, which is not a passive connectable to the
	 *        active_connection_proxy.
	 *
	 * connects the new_connectable to the current stored source
	 *
	 * \pre new_connectable_t needs to be connectable
	 * \post new_connectable_t is connected to the old passive.
	 * \returns a active_connection_proxy, which contains the new_connectable in its connection.
	 */
	template <class new_connectable_t,
	          class = std::enable_if_t<not(is_passive_source<std::decay_t<new_connectable_t>>{} or
	                                       is_passive_sink_for<std::decay_t<new_connectable_t>, result_t>{})>>
	auto connect(new_connectable_t&& new_connectable) &&
	{
		auto connection = connect_policy()(std::forward<passive_t>(stored_passive),
		                                   std::forward<new_connectable_t>(new_connectable));
		return active_connection_proxy<
				active_t,
				decltype(connection),
				connect_policy>(active, std::move(connection));
	}

	/**
	 * \brief catch function to prevent active_connection_proxies from being treated as lvalues.
	 */
	template <class new_connectable_t>
	void connect(new_connectable_t&&) &
	{
		static_assert(always_false<new_connectable_t>{}, "active_connection_proxies cannot be used multiple times.");
	}

	active_t active;
	passive_t stored_passive;
};

template<class active_t, class passive_t, class argument_order, class Enable = void>
struct active_passive_connect_impl;

/// Specialization of connect to call member connect of stream_proxy.
template<class active_t, class passive_t, class argument_order>
struct active_passive_connect_impl
	<	active_t,
		passive_t,
		argument_order,
		std::enable_if_t<is_instantiation_of<active_connection_proxy, std::decay_t<active_t>>{}>
	>
{
	auto operator()(active_t&& active, passive_t&& passive)
	{
		return std::forward<active_t>(active).connect(std::forward<passive_t>(passive));
	}
};

/**
 * Specialization of active_passive_connect_impl for the case of connecting a standard connectable
 * which is not a is_passive_sink to a is_passive_source.
 * \return a stream_proxy which contains the active && the passive.
 */
template<class active_t, class passive_t, class argument_order>
struct active_passive_connect_impl
	<	active_t,
		passive_t,
		argument_order,
		std::enable_if_t
			<	!is_instantiation_of< active_connection_proxy,std::decay_t<active_t>>{}
				&&	(	(	is_active_source<std::decay_t<active_t>>{}
						&& !fc::is_passive_sink_for<std::decay_t<passive_t>,
						                            typename std::decay_t<active_t>::result_t>{}
						)
					||	(	fc::is_active_sink<std::decay_t<active_t>>{}
						&& !fc::is_passive_source<std::decay_t<passive_t>>{}
						)
					)>
	>
{
	auto operator()(active_t&& active, passive_t&& passive)
	{
		return active_connection_proxy<active_t, passive_t, argument_order>
				(std::forward<active_t>(active), std::forward<passive_t>(passive));
	}
};

/**
 * Specialization for the case of connecting a active_port to a passive_port.
 * \pre active_t needs to be a active_connectable.
 * \pre passive_t needs to be a passive_connectable.
 * \post active is now connected to passive
 * \return port_connection tag object with the type information of the connection.
 */
template<class active_t, class passive_t, class argument_order>
struct active_passive_connect_impl
	<	active_t,
		passive_t,
		argument_order,
		std::enable_if_t
			<	!is_instantiation_of< active_connection_proxy, std::decay_t<active_t>>{}
				&&	(	(	is_active_source<std::decay_t<active_t>>{}
						&& fc::is_passive_sink_for<std::decay_t<passive_t>,
						                            typename std::decay_t<active_t>::result_t>{}
					)
					||	(	fc::is_active_sink<std::decay_t<active_t>>{}
						&&	fc::is_passive_source<std::decay_t<passive_t>>{}
						)
					)>
	>
{
	auto operator()(active_t&& active, passive_t&& passive)
	{

		std::forward<active_t>(active).connect(std::forward<passive_t>(passive));
		using source_t = typename argument_order::template source<active_t, passive_t>::type;
		using sink_t = typename argument_order::template sink<active_t, passive_t>::type;
		return port_connection<source_t, sink_t, result_of_t<active_t>>();
	}
};

template<class source_t, class sink_t>
struct connect_impl
	<	source_t,
		sink_t,
		std::enable_if_t<fc::is_active<std::decay_t<source_t>>{}>
	>
{
	auto operator()(source_t&& source, sink_t&& sink)
	{
		// source is active, thus it is the first parameter
		return active_passive_connect_impl<source_t, sink_t, active_source_first>()
		    (std::forward<source_t>(source), std::forward<sink_t>(sink));
	}
};

template<class source_t, class sink_t>
struct connect_impl
	<	source_t,
		sink_t,
		std::enable_if_t<fc::is_active<std::decay_t<sink_t>>{}>
	>
{
	auto operator()(source_t&& source, sink_t&& sink)
	{
		// sink is active, thus it is the first parameter
		return active_passive_connect_impl<sink_t, source_t, active_sink_first>()
				(std::forward<sink_t>(sink), std::forward<source_t>(source));
	}
};

}  //namespace detail

template<class T, class U> struct is_active_sink<
	detail::active_connection_proxy<T, U, detail::active_sink_first>>
		: std::true_type {};
template<class T, class U> struct is_active_source<
	detail::active_connection_proxy<T, U, detail::active_source_first>>
		: std::true_type {};
}  //namespace fc

#endif /* SRC_PORTS_DETAIL_ACTIVE_SOURCE_PROXY_HPP_ */
<|endoftext|>