<commit_before>#ifndef STREAM_H
#define STREAM_H

// from http://www.mail-archive.com/protobuf@googlegroups.com/msg03417.html

#include <cassert>
#include <iostream>
#include <fstream>
#include <functional>
#include <vector>
#include <list>
#include "google/protobuf/stubs/common.h"
#include "google/protobuf/io/zero_copy_stream.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/io/gzip_stream.h"
#include "google/protobuf/io/coded_stream.h"

namespace stream {

// write objects
// count should be equal to the number of objects to write
// count is written before the objects, but if it is 0, it is not written
// if not all objects are written, return false, otherwise true
template <typename T>
bool write(std::ostream& out, uint64_t count, const std::function<T(uint64_t)>& lambda) {

    ::google::protobuf::io::ZeroCopyOutputStream *raw_out =
          new ::google::protobuf::io::OstreamOutputStream(&out);
    ::google::protobuf::io::GzipOutputStream *gzip_out =
          new ::google::protobuf::io::GzipOutputStream(raw_out);
    ::google::protobuf::io::CodedOutputStream *coded_out =
          new ::google::protobuf::io::CodedOutputStream(gzip_out);

    auto handle = [](bool ok) {
        if (!ok) throw std::runtime_error("stream::write: I/O error writing protobuf");
    };

    // prefix the chunk with the number of objects, if any objects are to be written
    if(count > 0) {
        coded_out->WriteVarint64(count);
        handle(!coded_out->HadError());
    }

    std::string s;
    uint64_t written = 0;
    for (uint64_t n = 0; n < count; ++n, ++written) {
        handle(lambda(n).SerializeToString(&s));
        // and prefix each object with its size
        coded_out->WriteVarint32(s.size());
        handle(!coded_out->HadError());
        coded_out->WriteRaw(s.data(), s.size());
        handle(!coded_out->HadError());
    }

    delete coded_out;
    delete gzip_out;
    delete raw_out;

    return !count || written == count;
}

template <typename T>
bool write_buffered(std::ostream& out, std::vector<T>& buffer, uint64_t buffer_limit) {
    bool wrote = false;
    if (buffer.size() >= buffer_limit) {
        std::function<T(uint64_t)> lambda = [&buffer](uint64_t n) { return buffer.at(n); };
#pragma omp critical (stream_out)
        wrote = write(out, buffer.size(), lambda);
        buffer.clear();
    }
    return wrote;
}

// deserialize the input stream into the objects
// skips over groups of objects with count 0
// takes a callback function to be called on the objects, and another to be called per object group.

template <typename T>
void for_each(std::istream& in,
              const std::function<void(T&)>& lambda,
              const std::function<void(uint64_t)>& handle_count) {

    ::google::protobuf::io::ZeroCopyInputStream *raw_in =
          new ::google::protobuf::io::IstreamInputStream(&in);
    ::google::protobuf::io::GzipInputStream *gzip_in =
          new ::google::protobuf::io::GzipInputStream(raw_in);
    ::google::protobuf::io::CodedInputStream *coded_in =
          new ::google::protobuf::io::CodedInputStream(gzip_in);

    auto handle = [](bool ok) {
        if (!ok) {
            throw std::runtime_error("[stream::for_each] obsolete, invalid, or corrupt protobuf input");
        }
    };

    uint64_t count;
    // this loop handles a chunked file with many pieces
    // such as we might write in a multithreaded process
    while (coded_in->ReadVarint64((::google::protobuf::uint64*) &count)) {

        handle_count(count);

        std::string s;
        for (uint64_t i = 0; i < count; ++i) {
            uint32_t msgSize = 0;
            delete coded_in;
            coded_in = new ::google::protobuf::io::CodedInputStream(gzip_in);
            // the messages are prefixed by their size
            handle(coded_in->ReadVarint32(&msgSize));
            if (msgSize) {
                handle(coded_in->ReadString(&s, msgSize));
                T object;
                handle(object.ParseFromString(s));
                lambda(object);
            }
        }
    }

    delete coded_in;
    delete gzip_in;
    delete raw_in;
}

template <typename T>
void for_each(std::istream& in,
              const std::function<void(T&)>& lambda) {
    std::function<void(uint64_t)> noop = [](uint64_t) { };
    for_each(in, lambda, noop);
}

template <typename T>
void for_each_parallel(std::istream& in,
                       const std::function<void(T&)>& lambda,
                       const std::function<void(uint64_t)>& handle_count) {

    // objects will be handed off to worker threads in batches of this many
    const uint64_t batch_size = 1024;
    // max # of such batches to be holding in memory
    const uint64_t max_batches_outstanding = 256;
    // number of batches currently being processed
    uint64_t batches_outstanding = 0;

    // this loop handles a chunked file with many pieces
    // such as we might write in a multithreaded process
    #pragma omp parallel default(none) shared(in, lambda, handle_count, batches_outstanding)
    #pragma omp single
    {
        auto handle = [](bool retval) -> void {
            if (!retval) throw std::runtime_error("obsolete, invalid, or corrupt protobuf input");
        };

        ::google::protobuf::io::ZeroCopyInputStream *raw_in =
            new ::google::protobuf::io::IstreamInputStream(&in);
        ::google::protobuf::io::GzipInputStream *gzip_in =
            new ::google::protobuf::io::GzipInputStream(raw_in);
        ::google::protobuf::io::CodedInputStream *coded_in =
            new ::google::protobuf::io::CodedInputStream(gzip_in);

        std::vector<std::string> *batch = nullptr;

        // process chunks prefixed by message count
        uint64_t count;
        while (coded_in->ReadVarint64((::google::protobuf::uint64*) &count)) {
            handle_count(count);
            for (uint64_t i = 0; i < count; ++i) {
                if (!batch) {
                     batch = new std::vector<std::string>();
                     batch->reserve(batch_size);
                }
                uint32_t msgSize = 0;
                // the messages are prefixed by their size
                handle(coded_in->ReadVarint32(&msgSize));
                if (msgSize) {
                    // pick off the message (serialized protobuf object)
                    std::string s;
                    handle(coded_in->ReadString(&s, msgSize));
                    batch->push_back(std::move(s));
                }

                if (batch->size() >= batch_size) {
                    // time to enqueue this batch for processing. first, block if
                    // we've hit max_batches_outstanding.
                    uint64_t b;
                    #pragma omp atomic capture
                    b = ++batches_outstanding;
                    while (b >= max_batches_outstanding) {
                        usleep(1000);
                        #pragma omp atomic read
                        b = batches_outstanding;
                    }
                    // spawn task to process this batch
                    #pragma omp task default(none) firstprivate(batch) shared(batches_outstanding, lambda, handle)
                    {
                        {
                            T object;
                            for (const std::string& s_j : *batch) {
                                // parse protobuf object and invoke lambda on it
                                handle(object.ParseFromString(s_j));
                                lambda(object);
                            }
                        } // scope object
                        delete batch;
                        #pragma omp atomic update
                        batches_outstanding--;
                    }

                    batch = nullptr;
                }

                // recycle the CodedInputStream in order to avoid its byte limit
                delete coded_in;
                coded_in = new ::google::protobuf::io::CodedInputStream(gzip_in);
            }
        }

        // process final batch
        if (batch) {
            {
                T object;
                for (const std::string& s_j : *batch) {
                    handle(object.ParseFromString(s_j));
                    lambda(object);
                }
            } // scope object
            delete batch;
        }

        delete coded_in;
        delete gzip_in;
        delete raw_in;
    }

    // Don't clean up function locals before tasks finish using them
    #pragma omp taskwait
}

template <typename T>
void for_each_parallel(std::istream& in,
              const std::function<void(T&)>& lambda) {
    std::function<void(uint64_t)> noop = [](uint64_t) { };
    for_each_parallel(in, lambda, noop);
}

}

#endif
<commit_msg>Remove redundant barrier; it was actually the variable move that fixed things<commit_after>#ifndef STREAM_H
#define STREAM_H

// from http://www.mail-archive.com/protobuf@googlegroups.com/msg03417.html

#include <cassert>
#include <iostream>
#include <fstream>
#include <functional>
#include <vector>
#include <list>
#include "google/protobuf/stubs/common.h"
#include "google/protobuf/io/zero_copy_stream.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/io/gzip_stream.h"
#include "google/protobuf/io/coded_stream.h"

namespace stream {

// write objects
// count should be equal to the number of objects to write
// count is written before the objects, but if it is 0, it is not written
// if not all objects are written, return false, otherwise true
template <typename T>
bool write(std::ostream& out, uint64_t count, const std::function<T(uint64_t)>& lambda) {

    ::google::protobuf::io::ZeroCopyOutputStream *raw_out =
          new ::google::protobuf::io::OstreamOutputStream(&out);
    ::google::protobuf::io::GzipOutputStream *gzip_out =
          new ::google::protobuf::io::GzipOutputStream(raw_out);
    ::google::protobuf::io::CodedOutputStream *coded_out =
          new ::google::protobuf::io::CodedOutputStream(gzip_out);

    auto handle = [](bool ok) {
        if (!ok) throw std::runtime_error("stream::write: I/O error writing protobuf");
    };

    // prefix the chunk with the number of objects, if any objects are to be written
    if(count > 0) {
        coded_out->WriteVarint64(count);
        handle(!coded_out->HadError());
    }

    std::string s;
    uint64_t written = 0;
    for (uint64_t n = 0; n < count; ++n, ++written) {
        handle(lambda(n).SerializeToString(&s));
        // and prefix each object with its size
        coded_out->WriteVarint32(s.size());
        handle(!coded_out->HadError());
        coded_out->WriteRaw(s.data(), s.size());
        handle(!coded_out->HadError());
    }

    delete coded_out;
    delete gzip_out;
    delete raw_out;

    return !count || written == count;
}

template <typename T>
bool write_buffered(std::ostream& out, std::vector<T>& buffer, uint64_t buffer_limit) {
    bool wrote = false;
    if (buffer.size() >= buffer_limit) {
        std::function<T(uint64_t)> lambda = [&buffer](uint64_t n) { return buffer.at(n); };
#pragma omp critical (stream_out)
        wrote = write(out, buffer.size(), lambda);
        buffer.clear();
    }
    return wrote;
}

// deserialize the input stream into the objects
// skips over groups of objects with count 0
// takes a callback function to be called on the objects, and another to be called per object group.

template <typename T>
void for_each(std::istream& in,
              const std::function<void(T&)>& lambda,
              const std::function<void(uint64_t)>& handle_count) {

    ::google::protobuf::io::ZeroCopyInputStream *raw_in =
          new ::google::protobuf::io::IstreamInputStream(&in);
    ::google::protobuf::io::GzipInputStream *gzip_in =
          new ::google::protobuf::io::GzipInputStream(raw_in);
    ::google::protobuf::io::CodedInputStream *coded_in =
          new ::google::protobuf::io::CodedInputStream(gzip_in);

    auto handle = [](bool ok) {
        if (!ok) {
            throw std::runtime_error("[stream::for_each] obsolete, invalid, or corrupt protobuf input");
        }
    };

    uint64_t count;
    // this loop handles a chunked file with many pieces
    // such as we might write in a multithreaded process
    while (coded_in->ReadVarint64((::google::protobuf::uint64*) &count)) {

        handle_count(count);

        std::string s;
        for (uint64_t i = 0; i < count; ++i) {
            uint32_t msgSize = 0;
            delete coded_in;
            coded_in = new ::google::protobuf::io::CodedInputStream(gzip_in);
            // the messages are prefixed by their size
            handle(coded_in->ReadVarint32(&msgSize));
            if (msgSize) {
                handle(coded_in->ReadString(&s, msgSize));
                T object;
                handle(object.ParseFromString(s));
                lambda(object);
            }
        }
    }

    delete coded_in;
    delete gzip_in;
    delete raw_in;
}

template <typename T>
void for_each(std::istream& in,
              const std::function<void(T&)>& lambda) {
    std::function<void(uint64_t)> noop = [](uint64_t) { };
    for_each(in, lambda, noop);
}

template <typename T>
void for_each_parallel(std::istream& in,
                       const std::function<void(T&)>& lambda,
                       const std::function<void(uint64_t)>& handle_count) {

    // objects will be handed off to worker threads in batches of this many
    const uint64_t batch_size = 1024;
    // max # of such batches to be holding in memory
    const uint64_t max_batches_outstanding = 256;
    // number of batches currently being processed
    uint64_t batches_outstanding = 0;

    // this loop handles a chunked file with many pieces
    // such as we might write in a multithreaded process
    #pragma omp parallel default(none) shared(in, lambda, handle_count, batches_outstanding)
    #pragma omp single
    {
        auto handle = [](bool retval) -> void {
            if (!retval) throw std::runtime_error("obsolete, invalid, or corrupt protobuf input");
        };

        ::google::protobuf::io::ZeroCopyInputStream *raw_in =
            new ::google::protobuf::io::IstreamInputStream(&in);
        ::google::protobuf::io::GzipInputStream *gzip_in =
            new ::google::protobuf::io::GzipInputStream(raw_in);
        ::google::protobuf::io::CodedInputStream *coded_in =
            new ::google::protobuf::io::CodedInputStream(gzip_in);

        std::vector<std::string> *batch = nullptr;

        // process chunks prefixed by message count
        uint64_t count;
        while (coded_in->ReadVarint64((::google::protobuf::uint64*) &count)) {
            handle_count(count);
            for (uint64_t i = 0; i < count; ++i) {
                if (!batch) {
                     batch = new std::vector<std::string>();
                     batch->reserve(batch_size);
                }
                uint32_t msgSize = 0;
                // the messages are prefixed by their size
                handle(coded_in->ReadVarint32(&msgSize));
                if (msgSize) {
                    // pick off the message (serialized protobuf object)
                    std::string s;
                    handle(coded_in->ReadString(&s, msgSize));
                    batch->push_back(std::move(s));
                }

                if (batch->size() >= batch_size) {
                    // time to enqueue this batch for processing. first, block if
                    // we've hit max_batches_outstanding.
                    uint64_t b;
                    #pragma omp atomic capture
                    b = ++batches_outstanding;
                    while (b >= max_batches_outstanding) {
                        usleep(1000);
                        #pragma omp atomic read
                        b = batches_outstanding;
                    }
                    // spawn task to process this batch
                    #pragma omp task default(none) firstprivate(batch) shared(batches_outstanding, lambda, handle)
                    {
                        {
                            T object;
                            for (const std::string& s_j : *batch) {
                                // parse protobuf object and invoke lambda on it
                                handle(object.ParseFromString(s_j));
                                lambda(object);
                            }
                        } // scope object
                        delete batch;
                        #pragma omp atomic update
                        batches_outstanding--;
                    }

                    batch = nullptr;
                }

                // recycle the CodedInputStream in order to avoid its byte limit
                delete coded_in;
                coded_in = new ::google::protobuf::io::CodedInputStream(gzip_in);
            }
        }

        // process final batch
        if (batch) {
            {
                T object;
                for (const std::string& s_j : *batch) {
                    handle(object.ParseFromString(s_j));
                    lambda(object);
                }
            } // scope object
            delete batch;
        }

        delete coded_in;
        delete gzip_in;
        delete raw_in;
    }
}

template <typename T>
void for_each_parallel(std::istream& in,
              const std::function<void(T&)>& lambda) {
    std::function<void(uint64_t)> noop = [](uint64_t) { };
    for_each_parallel(in, lambda, noop);
}

}

#endif
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
/// \file  string.cpp
//------------------------------------------------------------------------------
/// \brief Implementation of general purpose functions for string processing
//------------------------------------------------------------------------------
// Copyright (c) 2010 Serge Aleynikov <saleyn@gmail.com>
// Created: 2010-05-06
//------------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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

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

***** END LICENSE BLOCK *****
*/

#include <utxx/string.hpp>
#include <utxx/print_opts.hpp>

namespace utxx {

std::string to_bin_string(const char* a_buf, size_t a_sz,
                          bool a_hex, bool a_readable, bool a_eol)
{
    std::stringstream out;
    const char* begin = a_buf, *end = a_buf + a_sz;
    print_opts  opts  = a_hex
                      ? (a_readable ? print_opts::printable_or_hex : print_opts::hex)
                      : (a_readable ? print_opts::printable_or_dec : print_opts::dec);
    output(out, begin, end, opts, ",", "", "\"", "<<", ">>");
    if (a_eol) out << std::endl;
    return out.str();
}

bool wildcard_match(const char* a_input, const char* a_pattern)
{
    // Pattern match a_input against a_pattern, and exit
    // at the end of the input string
    for(const char* ip = nullptr, *pp = nullptr; *a_input;)
        if (*a_pattern == '*') {
            if (!*++a_pattern)
                return true;    // Reached '*' at the end of pattern

            pp = a_pattern;     // Store matching state right after '*'
            ip = a_input;
        } else if ((*a_pattern == *a_input) || (*a_pattern == '?')) {
            a_pattern++;        // Continue successful input match
            a_input++;
        } else if (pp) {
            a_pattern = pp;     // Match failed - restore state of pattern after '*'
            a_input   = ++ip;   // Advance the input on every match failure
        } else
            return false;       // Match failed before the first '*' is found

    // Skip trailing '*' in the pattern, since they don't affect the outcome:
    while (*a_pattern == '*') a_pattern++;

    // This point is reached only when the a_input string was fully
    // exhaused. If at this point the a_pattern is exhaused too ('\0'),
    // there's a match, otherwise pattern match is incomplete.
    return !*a_pattern;
}

} // namespace utxx
<commit_msg>Cleanup<commit_after>//------------------------------------------------------------------------------
/// \file  string.cpp
//------------------------------------------------------------------------------
/// \brief Implementation of general purpose functions for string processing
//------------------------------------------------------------------------------
// Copyright (c) 2010 Serge Aleynikov <saleyn@gmail.com>
// Created: 2010-05-06
//------------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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

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

***** END LICENSE BLOCK *****
*/

#include <utxx/string.hpp>
#include <utxx/print_opts.hpp>

namespace utxx {

std::string to_bin_string(const char* a_buf, size_t a_sz,
                          bool a_hex, bool a_readable, bool a_eol)
{
    std::stringstream out;
    const char* begin = a_buf, *end = a_buf + a_sz;
    print_opts  opts  = a_hex
                      ? (a_readable ? print_opts::printable_or_hex : print_opts::hex)
                      : (a_readable ? print_opts::printable_or_dec : print_opts::dec);
    output(out, begin, end, opts, ",", "", "\"", "<<", ">>");
    if (a_eol) out << std::endl;
    return out.str();
}

bool wildcard_match(const char* a_input, const char* a_pattern)
{
    // Pattern match a_input against a_pattern, and exit
    // at the end of the input string
    for(const char* ip = nullptr, *pp = nullptr; *a_input;)
        if (*a_pattern == '*') {
            if (!*++a_pattern)
                return true;    // Reached '*' at the end of pattern
            pp = a_pattern;     // Store matching state right after '*'
            ip = a_input;
        } else if ((*a_pattern == *a_input) || (*a_pattern == '?')) {
            a_pattern++;        // Continue successful input match
            a_input++;
        } else if (pp) {
            a_pattern = pp;     // Match failed - restore state of pattern after '*'
            a_input   = ++ip;   // Advance the input on every match failure
        } else
            return false;       // Match failed before the first '*' is found

    // Skip trailing '*' in the pattern, since they don't affect the outcome:
    while (*a_pattern == '*') a_pattern++;

    // This point is reached only when the a_input string was fully
    // exhaused. If at this point the a_pattern is exhaused too ('\0'),
    // there's a match, otherwise pattern match is incomplete.
    return !*a_pattern;
}

} // namespace utxx
<|endoftext|>


<commit_before>/**
 * A class which describes the properties and actions of an SSL server socket.
 *
 * @date                    August 22, 2014
 * @author                  Joeri HERMANS
 * @version                 0.1
 *
 * Copyright 2014 Joeri HERMANS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// BEGIN Includes. ///////////////////////////////////////////////////

// System dependencies.
#include <arpa/inet.h>
#include <cassert>
#include <cstring>
#include <ctime>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>

// Application dependencies.
#include <ias/network/posix/ssl/posix_ssl_server_socket.h>
#include <ias/network/posix/ssl/posix_ssl_socket.h>
#include <ias/logger/logger.h>

// END Includes. /////////////////////////////////////////////////////

inline void PosixSslServerSocket::initialize( void ) {
    mSslContext = nullptr;
}

void PosixSslServerSocket::setFileDescriptor( const int fd ) {
    mFileDescriptor = fd;
}

void PosixSslServerSocket::loadCertificates( const std::string & certificateFile,
                                             const std::string & keyFile ) {
    SSL_CTX * sslContext;
    int rc;

    sslContext = SSL_CTX_new(SSLv3_server_method());
    rc = SSL_CTX_load_verify_locations(sslContext,certificateFile.c_str(),keyFile.c_str());
    if( rc <= 0 )
        ERR_print_errors_fp(stdout);
    rc = SSL_CTX_set_default_verify_paths(sslContext);
    if( rc <= 0 )
        ERR_print_errors_fp(stdout);
    rc = SSL_CTX_use_certificate_file(sslContext,certificateFile.c_str(),SSL_FILETYPE_PEM);
    if( rc <= 0 )
        ERR_print_errors_fp(stdout);
    rc = SSL_CTX_use_PrivateKey_file(sslContext,keyFile.c_str(),SSL_FILETYPE_PEM);
    if( rc <= 0 )
        ERR_print_errors_fp(stdout);
    setSslContext(sslContext);
}

void PosixSslServerSocket::setSslContext( SSL_CTX * sslContext ) {
    // Checking the precondition.
    assert( sslContext != nullptr );

    mSslContext = sslContext;
}

Socket * PosixSslServerSocket::allocateSocket( const int fd ) const {
    Socket * socket;
    SSL * ssl;

    // Checking the precondition.
    assert( fd >= 0 );

    ssl = SSL_new(mSslContext);
    SSL_set_fd(ssl, fd);
    if( SSL_accept(ssl) <= 0 ) {
        SSL_free(ssl);
        close(fd);
        socket = nullptr;
    } else {
        socket = new PosixSslSocket(ssl);
    }

    return ( socket );
}

PosixSslServerSocket::PosixSslServerSocket( const unsigned int port,
                                            SSL_CTX * sslContext ) :
    ServerSocket(port) {
    initialize();
    setFileDescriptor(-1);
    setSslContext(sslContext);
}

PosixSslServerSocket::PosixSslServerSocket( const unsigned int port,
                                            const std::string & certificatFile,
                                            const std::string & keyFile ) :
    ServerSocket(port) {
    initialize();
    setFileDescriptor(-1);
    loadCertificates(certificatFile,keyFile);
}

PosixSslServerSocket::~PosixSslServerSocket( void ) {
    stopListening();
}

void PosixSslServerSocket::stopListening( void ) {
    if( isBound() ) {
        close(mFileDescriptor);
        setFileDescriptor(-1);
        SSL_CTX_free(mSslContext);
        mSslContext = nullptr;
    }
}

bool PosixSslServerSocket::bindToPort( void ) {
    struct addrinfo hints;
    struct addrinfo * serverInfo;
    std::string portString;
    bool bound;
    int fd;

    if( isBound() ) {
        bound = true;
    } else {
        bound = false;
        memset(&hints,0,sizeof hints);
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;
        portString = std::to_string(getPort());
        if( getaddrinfo(nullptr,portString.c_str(),&hints,&serverInfo) == 0 ) {
            fd = socket(serverInfo->ai_family,serverInfo->ai_socktype,
                        serverInfo->ai_protocol);
            if( fd >= 0 ) {
                int yes = 1;

                setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof yes);
                if( bind(fd,serverInfo->ai_addr,serverInfo->ai_addrlen) == 0 &&
                    listen(fd,20) == 0 ) {
                    bound = true;
                    FD_ZERO(&mRfds);
                    FD_SET(fd,&mRfds);
                    setFileDescriptor(fd);
                }
            }
            freeaddrinfo(serverInfo);
        }
    }

    return ( bound );
}

bool PosixSslServerSocket::isBound( void ) const {
    return ( mFileDescriptor >= 0 );
}

Socket * PosixSslServerSocket::acceptSocket( void ) {
    struct sockaddr addr;
    socklen_t addrLength;
    Socket * socket;
    int fd;

    socket = nullptr;
    if( isBound() ) {
        memset(&addr,0,sizeof addr);
        memset(&addrLength,0,sizeof addrLength);
        fd = accept(mFileDescriptor,&addr,&addrLength);
        if( fd >= 0 ) {
            socket = allocateSocket(fd);
        }
    }

    return ( socket );
}

Socket * PosixSslServerSocket::acceptSocket( const std::time_t seconds ) {
    struct sockaddr addr;
    socklen_t addrLength;
    timeval tv;
    Socket * socket;
    int fd;

    socket = nullptr;
    tv.tv_sec = seconds;
    tv.tv_usec = 0;
    FD_ZERO(&mRfds);
    FD_SET(mFileDescriptor,&mRfds);
    if( isBound() &&
        select(mFileDescriptor + 1,&mRfds,nullptr,nullptr,&tv) > 0 ) {
        memset(&addr,0,sizeof addr);
        memset(&addrLength,0,sizeof addrLength);
        fd = accept(mFileDescriptor,&addr,&addrLength);
        if( fd >= 0 ) {
            socket = allocateSocket(fd);
        }
    }

    return ( socket );
}
<commit_msg>Add debugging information.<commit_after>/**
 * A class which describes the properties and actions of an SSL server socket.
 *
 * @date                    August 22, 2014
 * @author                  Joeri HERMANS
 * @version                 0.1
 *
 * Copyright 2014 Joeri HERMANS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// BEGIN Includes. ///////////////////////////////////////////////////

// System dependencies.
#include <arpa/inet.h>
#include <cassert>
#include <cstring>
#include <ctime>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>

// Application dependencies.
#include <ias/network/posix/ssl/posix_ssl_server_socket.h>
#include <ias/network/posix/ssl/posix_ssl_socket.h>
#include <ias/logger/logger.h>

// END Includes. /////////////////////////////////////////////////////

inline void PosixSslServerSocket::initialize( void ) {
    mSslContext = nullptr;
}

void PosixSslServerSocket::setFileDescriptor( const int fd ) {
    mFileDescriptor = fd;
}

void PosixSslServerSocket::loadCertificates( const std::string & certificateFile,
                                             const std::string & keyFile ) {
    SSL_CTX * sslContext;
    int rc;

    sslContext = SSL_CTX_new(SSLv3_server_method());
    rc = SSL_CTX_load_verify_locations(sslContext,certificateFile.c_str(),keyFile.c_str());
    if( rc <= 0 )
        ERR_print_errors_fp(stdout);
    rc = SSL_CTX_set_default_verify_paths(sslContext);
    if( rc <= 0 )
        ERR_print_errors_fp(stdout);
    rc = SSL_CTX_use_certificate_file(sslContext,certificateFile.c_str(),SSL_FILETYPE_PEM);
    if( rc <= 0 )
        ERR_print_errors_fp(stdout);
    rc = SSL_CTX_use_PrivateKey_file(sslContext,keyFile.c_str(),SSL_FILETYPE_PEM);
    if( rc <= 0 )
        ERR_print_errors_fp(stdout);
    setSslContext(sslContext);
}

void PosixSslServerSocket::setSslContext( SSL_CTX * sslContext ) {
    // Checking the precondition.
    assert( sslContext != nullptr );

    mSslContext = sslContext;
}

Socket * PosixSslServerSocket::allocateSocket( const int fd ) const {
    Socket * socket;
    SSL * ssl;

    // Checking the precondition.
    assert( fd >= 0 );

    ssl = SSL_new(mSslContext);
    SSL_set_fd(ssl, fd);
    if( SSL_accept(ssl) <= 0 ) {
        SSL_free(ssl);
        close(fd);
        socket = nullptr;
    } else {
        socket = new PosixSslSocket(ssl);
    }

    return ( socket );
}

PosixSslServerSocket::PosixSslServerSocket( const unsigned int port,
                                            SSL_CTX * sslContext ) :
    ServerSocket(port) {
    initialize();
    setFileDescriptor(-1);
    setSslContext(sslContext);
}

PosixSslServerSocket::PosixSslServerSocket( const unsigned int port,
                                            const std::string & certificatFile,
                                            const std::string & keyFile ) :
    ServerSocket(port) {
    initialize();
    setFileDescriptor(-1);
    loadCertificates(certificatFile,keyFile);
}

PosixSslServerSocket::~PosixSslServerSocket( void ) {
    stopListening();
}

void PosixSslServerSocket::stopListening( void ) {
    if( isBound() ) {
        close(mFileDescriptor);
        setFileDescriptor(-1);
        SSL_CTX_free(mSslContext);
        mSslContext = nullptr;
    }
}

#include <iostream>

bool PosixSslServerSocket::bindToPort( void ) {
    struct addrinfo hints;
    struct addrinfo * serverInfo;
    std::string portString;
    bool bound;
    int fd;

    if( isBound() ) {
        bound = true;
    } else {
        bound = false;
        memset(&hints,0,sizeof hints);
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;
        portString = std::to_string(getPort());
        if( getaddrinfo(nullptr,portString.c_str(),&hints,&serverInfo) == 0 ) {
            fd = socket(serverInfo->ai_family,serverInfo->ai_socktype,
                        serverInfo->ai_protocol);
            if( fd >= 0 ) {
                int yes = 1;

                setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof yes);
                if( bind(fd,serverInfo->ai_addr,serverInfo->ai_addrlen) == 0 &&
                    listen(fd,20) == 0 ) {
                    bound = true;
                    FD_ZERO(&mRfds);
                    FD_SET(fd,&mRfds);
                    setFileDescriptor(fd);
                } else {
                    std::cout << "Could not bind to port." << std::endl;
                }
            } else {
                std::cout << "Could not allocate socket." << std::endl;
            }
            freeaddrinfo(serverInfo);
        }
    }

    return ( bound );
}

bool PosixSslServerSocket::isBound( void ) const {
    return ( mFileDescriptor >= 0 );
}

Socket * PosixSslServerSocket::acceptSocket( void ) {
    struct sockaddr addr;
    socklen_t addrLength;
    Socket * socket;
    int fd;

    socket = nullptr;
    if( isBound() ) {
        memset(&addr,0,sizeof addr);
        memset(&addrLength,0,sizeof addrLength);
        fd = accept(mFileDescriptor,&addr,&addrLength);
        if( fd >= 0 ) {
            socket = allocateSocket(fd);
        }
    }

    return ( socket );
}

Socket * PosixSslServerSocket::acceptSocket( const std::time_t seconds ) {
    struct sockaddr addr;
    socklen_t addrLength;
    timeval tv;
    Socket * socket;
    int fd;

    socket = nullptr;
    tv.tv_sec = seconds;
    tv.tv_usec = 0;
    FD_ZERO(&mRfds);
    FD_SET(mFileDescriptor,&mRfds);
    if( isBound() &&
        select(mFileDescriptor + 1,&mRfds,nullptr,nullptr,&tv) > 0 ) {
        memset(&addr,0,sizeof addr);
        memset(&addrLength,0,sizeof addrLength);
        fd = accept(mFileDescriptor,&addr,&addrLength);
        if( fd >= 0 ) {
            socket = allocateSocket(fd);
        }
    }

    return ( socket );
}
<|endoftext|>


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

#include "object_registry.h"

#include "scoped_thread_state_change.h"

namespace art {

mirror::Object* const ObjectRegistry::kInvalidObject = reinterpret_cast<mirror::Object*>(1);

std::ostream& operator<<(std::ostream& os, const ObjectRegistryEntry& rhs) {
  os << "ObjectRegistryEntry[" << rhs.jni_reference_type
     << ",reference=" << rhs.jni_reference
     << ",count=" << rhs.reference_count
     << ",id=" << rhs.id << "]";
  return os;
}

ObjectRegistry::ObjectRegistry()
    : lock_("ObjectRegistry lock", kJdwpObjectRegistryLock), next_id_(1) {
}

JDWP::RefTypeId ObjectRegistry::AddRefType(mirror::Class* c) {
  return InternalAdd(c);
}

JDWP::ObjectId ObjectRegistry::Add(mirror::Object* o) {
  return InternalAdd(o);
}

JDWP::ObjectId ObjectRegistry::InternalAdd(mirror::Object* o) {
  if (o == nullptr) {
    return 0;
  }

  // Call IdentityHashCode here to avoid a lock level violation between lock_ and monitor_lock.
  int32_t identity_hash_code = o->IdentityHashCode();
  ScopedObjectAccessUnchecked soa(Thread::Current());
  MutexLock mu(soa.Self(), lock_);
  ObjectRegistryEntry* entry = nullptr;
  if (ContainsLocked(soa.Self(), o, identity_hash_code, &entry)) {
    // This object was already in our map.
    ++entry->reference_count;
  } else {
    entry = new ObjectRegistryEntry;
    entry->jni_reference_type = JNIWeakGlobalRefType;
    entry->jni_reference = nullptr;
    entry->reference_count = 0;
    entry->id = 0;
    entry->identity_hash_code = identity_hash_code;
    object_to_entry_.insert(std::make_pair(identity_hash_code, entry));

    // This object isn't in the registry yet, so add it.
    JNIEnv* env = soa.Env();

    jobject local_reference = soa.AddLocalReference<jobject>(o);

    entry->jni_reference_type = JNIWeakGlobalRefType;
    entry->jni_reference = env->NewWeakGlobalRef(local_reference);
    entry->reference_count = 1;
    entry->id = next_id_++;

    id_to_entry_.Put(entry->id, entry);

    env->DeleteLocalRef(local_reference);
  }
  return entry->id;
}

bool ObjectRegistry::Contains(mirror::Object* o, ObjectRegistryEntry** out_entry) {
  if (o == nullptr) {
    return false;
  }
  // Call IdentityHashCode here to avoid a lock level violation between lock_ and monitor_lock.
  int32_t identity_hash_code = o->IdentityHashCode();
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  return ContainsLocked(self, o, identity_hash_code, out_entry);
}

bool ObjectRegistry::ContainsLocked(Thread* self, mirror::Object* o, int32_t identity_hash_code,
                                    ObjectRegistryEntry** out_entry) {
  DCHECK(o != nullptr);
  for (auto it = object_to_entry_.lower_bound(identity_hash_code), end = object_to_entry_.end();
       it != end && it->first == identity_hash_code; ++it) {
    ObjectRegistryEntry* entry = it->second;
    if (o == self->DecodeJObject(entry->jni_reference)) {
      if (out_entry != nullptr) {
        *out_entry = entry;
      }
      return true;
    }
  }
  return false;
}

void ObjectRegistry::Clear() {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  VLOG(jdwp) << "Object registry contained " << object_to_entry_.size() << " entries";
  // Delete all the JNI references.
  JNIEnv* env = self->GetJniEnv();
  for (const auto& pair : object_to_entry_) {
    const ObjectRegistryEntry& entry = *pair.second;
    if (entry.jni_reference_type == JNIWeakGlobalRefType) {
      env->DeleteWeakGlobalRef(entry.jni_reference);
    } else {
      env->DeleteGlobalRef(entry.jni_reference);
    }
  }
  // Clear the maps.
  object_to_entry_.clear();
  id_to_entry_.clear();
}

mirror::Object* ObjectRegistry::InternalGet(JDWP::ObjectId id) {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  if (it == id_to_entry_.end()) {
    return kInvalidObject;
  }
  ObjectRegistryEntry& entry = *it->second;
  return self->DecodeJObject(entry.jni_reference);
}

jobject ObjectRegistry::GetJObject(JDWP::ObjectId id) {
  if (id == 0) {
    return NULL;
  }
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  CHECK(it != id_to_entry_.end()) << id;
  ObjectRegistryEntry& entry = *it->second;
  return entry.jni_reference;
}

void ObjectRegistry::DisableCollection(JDWP::ObjectId id) {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  CHECK(it != id_to_entry_.end());
  Promote(*it->second);
}

void ObjectRegistry::EnableCollection(JDWP::ObjectId id) {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  CHECK(it != id_to_entry_.end());
  Demote(*it->second);
}

void ObjectRegistry::Demote(ObjectRegistryEntry& entry) {
  if (entry.jni_reference_type == JNIGlobalRefType) {
    Thread* self = Thread::Current();
    JNIEnv* env = self->GetJniEnv();
    jobject global = entry.jni_reference;
    entry.jni_reference = env->NewWeakGlobalRef(entry.jni_reference);
    entry.jni_reference_type = JNIWeakGlobalRefType;
    env->DeleteGlobalRef(global);
  }
}

void ObjectRegistry::Promote(ObjectRegistryEntry& entry) {
  if (entry.jni_reference_type == JNIWeakGlobalRefType) {
    Thread* self = Thread::Current();
    JNIEnv* env = self->GetJniEnv();
    jobject weak = entry.jni_reference;
    entry.jni_reference = env->NewGlobalRef(entry.jni_reference);
    entry.jni_reference_type = JNIGlobalRefType;
    env->DeleteWeakGlobalRef(weak);
  }
}

bool ObjectRegistry::IsCollected(JDWP::ObjectId id) {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  CHECK(it != id_to_entry_.end());
  ObjectRegistryEntry& entry = *it->second;
  if (entry.jni_reference_type == JNIWeakGlobalRefType) {
    JNIEnv* env = self->GetJniEnv();
    return env->IsSameObject(entry.jni_reference, NULL);  // Has the jweak been collected?
  } else {
    return false;  // We hold a strong reference, so we know this is live.
  }
}

void ObjectRegistry::DisposeObject(JDWP::ObjectId id, uint32_t reference_count) {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  if (it == id_to_entry_.end()) {
    return;
  }
  ObjectRegistryEntry* entry = it->second;
  entry->reference_count -= reference_count;
  if (entry->reference_count <= 0) {
    JNIEnv* env = self->GetJniEnv();
    // Erase the object from the maps. Note object may be null if it's
    // a weak ref and the GC has cleared it.
    int32_t hash_code = entry->identity_hash_code;
    for (auto it = object_to_entry_.lower_bound(hash_code), end = object_to_entry_.end();
         it != end && it->first == hash_code; ++it) {
      if (entry == it->second) {
        object_to_entry_.erase(it);
        break;
      }
    }
    if (entry->jni_reference_type == JNIWeakGlobalRefType) {
      env->DeleteWeakGlobalRef(entry->jni_reference);
    } else {
      env->DeleteGlobalRef(entry->jni_reference);
    }
    id_to_entry_.erase(id);
    delete entry;
  }
}

}  // namespace art
<commit_msg>am 0c173466: Merge "Fix memory leak in JDWP object registry"<commit_after>/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "object_registry.h"

#include "scoped_thread_state_change.h"

namespace art {

mirror::Object* const ObjectRegistry::kInvalidObject = reinterpret_cast<mirror::Object*>(1);

std::ostream& operator<<(std::ostream& os, const ObjectRegistryEntry& rhs) {
  os << "ObjectRegistryEntry[" << rhs.jni_reference_type
     << ",reference=" << rhs.jni_reference
     << ",count=" << rhs.reference_count
     << ",id=" << rhs.id << "]";
  return os;
}

ObjectRegistry::ObjectRegistry()
    : lock_("ObjectRegistry lock", kJdwpObjectRegistryLock), next_id_(1) {
}

JDWP::RefTypeId ObjectRegistry::AddRefType(mirror::Class* c) {
  return InternalAdd(c);
}

JDWP::ObjectId ObjectRegistry::Add(mirror::Object* o) {
  return InternalAdd(o);
}

JDWP::ObjectId ObjectRegistry::InternalAdd(mirror::Object* o) {
  if (o == nullptr) {
    return 0;
  }

  // Call IdentityHashCode here to avoid a lock level violation between lock_ and monitor_lock.
  int32_t identity_hash_code = o->IdentityHashCode();
  ScopedObjectAccessUnchecked soa(Thread::Current());
  MutexLock mu(soa.Self(), lock_);
  ObjectRegistryEntry* entry = nullptr;
  if (ContainsLocked(soa.Self(), o, identity_hash_code, &entry)) {
    // This object was already in our map.
    ++entry->reference_count;
  } else {
    entry = new ObjectRegistryEntry;
    entry->jni_reference_type = JNIWeakGlobalRefType;
    entry->jni_reference = nullptr;
    entry->reference_count = 0;
    entry->id = 0;
    entry->identity_hash_code = identity_hash_code;
    object_to_entry_.insert(std::make_pair(identity_hash_code, entry));

    // This object isn't in the registry yet, so add it.
    JNIEnv* env = soa.Env();

    jobject local_reference = soa.AddLocalReference<jobject>(o);

    entry->jni_reference_type = JNIWeakGlobalRefType;
    entry->jni_reference = env->NewWeakGlobalRef(local_reference);
    entry->reference_count = 1;
    entry->id = next_id_++;

    id_to_entry_.Put(entry->id, entry);

    env->DeleteLocalRef(local_reference);
  }
  return entry->id;
}

bool ObjectRegistry::Contains(mirror::Object* o, ObjectRegistryEntry** out_entry) {
  if (o == nullptr) {
    return false;
  }
  // Call IdentityHashCode here to avoid a lock level violation between lock_ and monitor_lock.
  int32_t identity_hash_code = o->IdentityHashCode();
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  return ContainsLocked(self, o, identity_hash_code, out_entry);
}

bool ObjectRegistry::ContainsLocked(Thread* self, mirror::Object* o, int32_t identity_hash_code,
                                    ObjectRegistryEntry** out_entry) {
  DCHECK(o != nullptr);
  for (auto it = object_to_entry_.lower_bound(identity_hash_code), end = object_to_entry_.end();
       it != end && it->first == identity_hash_code; ++it) {
    ObjectRegistryEntry* entry = it->second;
    if (o == self->DecodeJObject(entry->jni_reference)) {
      if (out_entry != nullptr) {
        *out_entry = entry;
      }
      return true;
    }
  }
  return false;
}

void ObjectRegistry::Clear() {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  VLOG(jdwp) << "Object registry contained " << object_to_entry_.size() << " entries";
  // Delete all the JNI references.
  JNIEnv* env = self->GetJniEnv();
  for (const auto& pair : object_to_entry_) {
    const ObjectRegistryEntry* entry = pair.second;
    if (entry->jni_reference_type == JNIWeakGlobalRefType) {
      env->DeleteWeakGlobalRef(entry->jni_reference);
    } else {
      env->DeleteGlobalRef(entry->jni_reference);
    }
    delete entry;
  }
  // Clear the maps.
  object_to_entry_.clear();
  id_to_entry_.clear();
}

mirror::Object* ObjectRegistry::InternalGet(JDWP::ObjectId id) {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  if (it == id_to_entry_.end()) {
    return kInvalidObject;
  }
  ObjectRegistryEntry& entry = *it->second;
  return self->DecodeJObject(entry.jni_reference);
}

jobject ObjectRegistry::GetJObject(JDWP::ObjectId id) {
  if (id == 0) {
    return NULL;
  }
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  CHECK(it != id_to_entry_.end()) << id;
  ObjectRegistryEntry& entry = *it->second;
  return entry.jni_reference;
}

void ObjectRegistry::DisableCollection(JDWP::ObjectId id) {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  CHECK(it != id_to_entry_.end());
  Promote(*it->second);
}

void ObjectRegistry::EnableCollection(JDWP::ObjectId id) {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  CHECK(it != id_to_entry_.end());
  Demote(*it->second);
}

void ObjectRegistry::Demote(ObjectRegistryEntry& entry) {
  if (entry.jni_reference_type == JNIGlobalRefType) {
    Thread* self = Thread::Current();
    JNIEnv* env = self->GetJniEnv();
    jobject global = entry.jni_reference;
    entry.jni_reference = env->NewWeakGlobalRef(entry.jni_reference);
    entry.jni_reference_type = JNIWeakGlobalRefType;
    env->DeleteGlobalRef(global);
  }
}

void ObjectRegistry::Promote(ObjectRegistryEntry& entry) {
  if (entry.jni_reference_type == JNIWeakGlobalRefType) {
    Thread* self = Thread::Current();
    JNIEnv* env = self->GetJniEnv();
    jobject weak = entry.jni_reference;
    entry.jni_reference = env->NewGlobalRef(entry.jni_reference);
    entry.jni_reference_type = JNIGlobalRefType;
    env->DeleteWeakGlobalRef(weak);
  }
}

bool ObjectRegistry::IsCollected(JDWP::ObjectId id) {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  CHECK(it != id_to_entry_.end());
  ObjectRegistryEntry& entry = *it->second;
  if (entry.jni_reference_type == JNIWeakGlobalRefType) {
    JNIEnv* env = self->GetJniEnv();
    return env->IsSameObject(entry.jni_reference, NULL);  // Has the jweak been collected?
  } else {
    return false;  // We hold a strong reference, so we know this is live.
  }
}

void ObjectRegistry::DisposeObject(JDWP::ObjectId id, uint32_t reference_count) {
  Thread* self = Thread::Current();
  MutexLock mu(self, lock_);
  auto it = id_to_entry_.find(id);
  if (it == id_to_entry_.end()) {
    return;
  }
  ObjectRegistryEntry* entry = it->second;
  entry->reference_count -= reference_count;
  if (entry->reference_count <= 0) {
    JNIEnv* env = self->GetJniEnv();
    // Erase the object from the maps. Note object may be null if it's
    // a weak ref and the GC has cleared it.
    int32_t hash_code = entry->identity_hash_code;
    for (auto it = object_to_entry_.lower_bound(hash_code), end = object_to_entry_.end();
         it != end && it->first == hash_code; ++it) {
      if (entry == it->second) {
        object_to_entry_.erase(it);
        break;
      }
    }
    if (entry->jni_reference_type == JNIWeakGlobalRefType) {
      env->DeleteWeakGlobalRef(entry->jni_reference);
    } else {
      env->DeleteGlobalRef(entry->jni_reference);
    }
    id_to_entry_.erase(id);
    delete entry;
  }
}

}  // namespace art
<|endoftext|>


<commit_before>#include "SpikeAndSlabPrior.h"

#include <SmurffCpp/IO/MatrixIO.h>
#include <SmurffCpp/IO/GenericIO.h>
#include <SmurffCpp/Utils/Error.h>

using namespace smurff;
using namespace Eigen;

SpikeAndSlabPrior::SpikeAndSlabPrior(std::shared_ptr<Session> session, uint32_t mode)
   : NormalOnePrior(session, mode, "SpikeAndSlabPrior")
{

}

void SpikeAndSlabPrior::init()
{
   NormalOnePrior::init();

   const int K = num_latent();
   const int D = num_cols();
   const int nview = data().nview(m_mode);

   THROWERROR_ASSERT(D > 0);

   Zcol.init(MatrixXd::Zero(K,nview));
   W2col.init(MatrixXd::Zero(K,nview));

   //-- prior params
   alpha = ArrayXXd::Ones(K,nview);
   Zkeep = ArrayXXd::Constant(K, nview, D);
   r = ArrayXXd::Constant(K,nview,.5);

   log_alpha = alpha.log();
   log_r = - r.log() + (ArrayXXd::Ones(K, nview) - r).log();
}

void SpikeAndSlabPrior::update_prior()
{
   const int nview = data().nview(m_mode);
   const int K = num_latent();

   Zkeep = Zcol.combine();
   auto W2c = W2col.combine();

   // update hyper params (alpha and r) (per view)
   for(int v=0; v<nview; ++v) {
       const int D = data().view_size(m_mode, v);
       r.col(v) = ( Zkeep.col(v).array() + prior_beta ) / ( D + prior_beta * D ) ;
       auto ww = W2c.col(v).array() / 2 + prior_beta_0;
       auto tmpz = Zkeep.col(v).array() / 2 + prior_alpha_0 ;
       alpha.col(v) = tmpz.binaryExpr(ww, [](double a, double b)->double {
               return rgamma(a, 1/b) + 1e-7;
       });
   }

   Zcol.reset();
   W2col.reset();

   log_alpha = alpha.log();
   log_r = - r.log() + (ArrayXXd::Ones(K, nview) - r).log();
}

void SpikeAndSlabPrior::restore(std::shared_ptr<const StepFile> sf)
{
  const int K = num_latent();
  const int nview = data().nview(m_mode);

  NormalOnePrior::restore(sf);

  //compute Zcol
  int d = 0;
  ArrayXXd Z(ArrayXXd::Zero(K,nview));
  ArrayXXd W2(ArrayXXd::Zero(K,nview));
  for(int v=0; v<data().nview(m_mode); ++v)
  {
      for(int i=0; i<data().view_size(m_mode, v); ++i, ++d)
      {
        for(int k=0; k<K; ++k) if (U()(k,d) != 0) Z(k,v)++;
        W2.col(v) += U().col(d).array().square();
      }
  }
  THROWERROR_ASSERT(d == num_cols());

  Zcol.reset();
  W2col.reset();
  Zcol.local() = Z;
  W2col.local() = W2;

  update_prior();
}

std::pair<double, double> SpikeAndSlabPrior::sample_latent(int d, int k, const MatrixXd& XX, const VectorXd& yX)
{
    const int v = data().view(m_mode, d);
    double mu, lambda;

    MatrixXd aXX = alpha.matrix().col(v).asDiagonal();
    aXX += XX;
    std::tie(mu, lambda) = NormalOnePrior::sample_latent(d, k, aXX, yX);

    auto Ucol = U().col(d);
    double z1 = log_r(k,v) -  0.5 * (lambda * mu * mu - std::log(lambda) + log_alpha(k,v));
    double z = 1 / (1 + exp(z1));
    double p = rand_unif(0,1);
    if (Zkeep(k,v) > 0 && p < z) {
        Zcol.local()(k,v)++;
        W2col.local()(k,v) += Ucol(k) * Ucol(k);
    } else {
        Ucol(k) = .0;
    }

    return std::make_pair(mu, lambda);
}

std::ostream &SpikeAndSlabPrior::status(std::ostream &os, std::string indent) const
{
   const int V = data().nview(m_mode);
   for(int v=0; v<V; ++v)
   {
       int Zcount = (Zkeep.col(v).array() > 0).count();
       os << indent << m_name << ": Z[" << v << "] = " << Zcount << "/" << num_latent() << std::endl;
   }
   return os;
}
<commit_msg>FIX: SpikeAndSlab: resize log_alpha and log_r properly<commit_after>#include "SpikeAndSlabPrior.h"

#include <SmurffCpp/IO/MatrixIO.h>
#include <SmurffCpp/IO/GenericIO.h>
#include <SmurffCpp/Utils/Error.h>

using namespace smurff;
using namespace Eigen;

SpikeAndSlabPrior::SpikeAndSlabPrior(std::shared_ptr<Session> session, uint32_t mode)
   : NormalOnePrior(session, mode, "SpikeAndSlabPrior")
{

}

void SpikeAndSlabPrior::init()
{
   NormalOnePrior::init();

   const int K = num_latent();
   const int D = num_cols();
   const int nview = data().nview(m_mode);

   THROWERROR_ASSERT(D > 0);

   Zcol.init(MatrixXd::Zero(K,nview));
   W2col.init(MatrixXd::Zero(K,nview));

   //-- prior params
   Zkeep = ArrayXXd::Constant(K, nview, D);

   alpha = ArrayXXd::Ones(K,nview);
   log_alpha.resize(K, nview);
   log_alpha = alpha.log();

   r = ArrayXXd::Constant(K,nview,.5);
   log_r.resize(K, nview);
   log_r = - r.log() + (ArrayXXd::Ones(K, nview) - r).log();
}

void SpikeAndSlabPrior::update_prior()
{
   const int nview = data().nview(m_mode);
   const int K = num_latent();

   Zkeep = Zcol.combine();
   auto W2c = W2col.combine();

   // update hyper params (alpha and r) (per view)
   for(int v=0; v<nview; ++v) {
       const int D = data().view_size(m_mode, v);
       r.col(v) = ( Zkeep.col(v).array() + prior_beta ) / ( D + prior_beta * D ) ;
       auto ww = W2c.col(v).array() / 2 + prior_beta_0;
       auto tmpz = Zkeep.col(v).array() / 2 + prior_alpha_0 ;
       alpha.col(v) = tmpz.binaryExpr(ww, [](double a, double b)->double {
               return rgamma(a, 1/b) + 1e-7;
       });
   }

   Zcol.reset();
   W2col.reset();

   log_alpha = alpha.log();
   log_r = - r.log() + (ArrayXXd::Ones(K, nview) - r).log();
}

void SpikeAndSlabPrior::restore(std::shared_ptr<const StepFile> sf)
{
  const int K = num_latent();
  const int nview = data().nview(m_mode);

  NormalOnePrior::restore(sf);

  //compute Zcol
  int d = 0;
  ArrayXXd Z(ArrayXXd::Zero(K,nview));
  ArrayXXd W2(ArrayXXd::Zero(K,nview));
  for(int v=0; v<data().nview(m_mode); ++v)
  {
      for(int i=0; i<data().view_size(m_mode, v); ++i, ++d)
      {
        for(int k=0; k<K; ++k) if (U()(k,d) != 0) Z(k,v)++;
        W2.col(v) += U().col(d).array().square();
      }
  }
  THROWERROR_ASSERT(d == num_cols());

  Zcol.reset();
  W2col.reset();
  Zcol.local() = Z;
  W2col.local() = W2;

  update_prior();
}

std::pair<double, double> SpikeAndSlabPrior::sample_latent(int d, int k, const MatrixXd& XX, const VectorXd& yX)
{
    const int v = data().view(m_mode, d);
    double mu, lambda;

    MatrixXd aXX = alpha.matrix().col(v).asDiagonal();
    aXX += XX;
    std::tie(mu, lambda) = NormalOnePrior::sample_latent(d, k, aXX, yX);

    auto Ucol = U().col(d);
    double z1 = log_r(k,v) -  0.5 * (lambda * mu * mu - std::log(lambda) + log_alpha(k,v));
    double z = 1 / (1 + exp(z1));
    double p = rand_unif(0,1);
    if (Zkeep(k,v) > 0 && p < z) {
        Zcol.local()(k,v)++;
        W2col.local()(k,v) += Ucol(k) * Ucol(k);
    } else {
        Ucol(k) = .0;
    }

    return std::make_pair(mu, lambda);
}

std::ostream &SpikeAndSlabPrior::status(std::ostream &os, std::string indent) const
{
   const int V = data().nview(m_mode);
   for(int v=0; v<V; ++v)
   {
       int Zcount = (Zkeep.col(v).array() > 0).count();
       os << indent << m_name << ": Z[" << v << "] = " << Zcount << "/" << num_latent() << std::endl;
   }
   return os;
}
<|endoftext|>


<commit_before><commit_msg>coverity#1266492 Untrusted value as argument<commit_after><|endoftext|>


<commit_before>#/*****************************************************************************
 * SV_Bedpe.cpp
 * (c) 2012 - Ryan M. Layer
 * Hall Laboratory
 * Quinlan Laboratory
 * Department of Computer Science
 * Department of Biochemistry and Molecular Genetics
 * Department of Public Health Sciences and Center for Public Health Genomics,
 * University of Virginia
 * rl6sf@virginia.edu
 *
 * Licenced under the GNU General Public License 2.0 license.
 * ***************************************************************************/
#include "BamAncillary.h"
using namespace BamTools;

#include "SV_BedpeReader.h"
#include "SV_BreakPoint.h"
#include "SV_Bedpe.h"
#include "log_space.h"
#include "bedFilePE.h"

#include <iostream>
#include <algorithm>
#include <string>
#include <math.h>

using namespace std;

//{{{ SV_Bedpe:: SV_Bedpe(const BEDPE *bedpeEntry)
SV_Bedpe::
SV_Bedpe(const BEDPE *bedpeEntry,
         int _weight,
         int _ev_id,
         SV_BedpeReader *_reader)
{
    reader = _reader;

    ev_id = _ev_id;
    struct interval tmp_a, tmp_b;

    tmp_a.start = bedpeEntry->start1;
    tmp_a.end = bedpeEntry->end1 - 1;
    tmp_a.chr = bedpeEntry->chrom1;
    tmp_a.strand = bedpeEntry->strand1[0];

    tmp_b.start = bedpeEntry->start2;
    tmp_b.end = bedpeEntry->end2 - 1;
    tmp_b.chr = bedpeEntry->chrom2;
    tmp_b.strand = bedpeEntry->strand2[0];

    if ( tmp_a.chr.compare(tmp_b.chr) > 0 ) {
        side_l = tmp_a;
        side_r = tmp_b;
    } else if ( tmp_a.chr.compare(tmp_b.chr) < 0 ) {
        side_l = tmp_b;
        side_r = tmp_a;
    } else { // ==
        if (tmp_a.start > tmp_b.start) {
            side_l = tmp_b;
            side_r = tmp_a;
        } else {
            side_l = tmp_a;
            side_r = tmp_b;
        }
    }

    vector<string>::const_iterator it;
    type = -1;
    for (it = bedpeEntry->fields.begin();
            it != bedpeEntry->fields.end(); ++it) {

        if ( it->find("TYPE:") == 0 ) {
            string type_string = it->substr(5,it->length() - 5);

            if (type_string.compare("DELETION") == 0) {
                type = SV_BreakPoint::DELETION;
            } else if (type_string.compare("DUPLICATION") == 0) {
                type = SV_BreakPoint::DUPLICATION;
            } else if (type_string.compare("INVERSION") == 0) {
                type = SV_BreakPoint::INVERSION;
            } else {
                cerr << "ERROR IN BEDPE FILE.  TYPE \""<< type_string <<
                     "\" not supported (DELETION,DUPLICATION,INVERSION)" <<
                     endl;
                abort();
            }

        }
    }

    if (type == -1) {
        cerr << "ERROR IN BEDPE FILE.  Either no TYPE field. " <<
             endl;
        abort();
    }

    weight = _weight;
}
//}}}

//{{{ ostream& operator << (ostream& out, const SV_Pair& p)
ostream& operator << (ostream& out, const SV_Bedpe& p)
{

    out << p.side_l.chr << "," <<
        p.side_l.start << "," <<
        p.side_l.end << "," <<
        p.side_l.strand <<
        "\t" <<
        p.side_r.chr << "," <<
        p.side_r.start << "," <<
        p.side_r.end << "," <<
        p.side_r.strand;

    return out;
}
//}}}

//{{{ SV_BreakPoint* SV_Pair:: get_bp()
SV_BreakPoint*
SV_Bedpe::
get_bp()
{
    // Make a new break point
    SV_BreakPoint *new_bp = new SV_BreakPoint(this);

    set_bp_interval_start_end(&(new_bp->interval_l),
                              &side_l,
                              &side_r,
                              0,
                              reader->distro_size);
    set_bp_interval_start_end(&(new_bp->interval_r),
                              &side_r,
                              &side_l,
                              0,
                              reader->distro_size);

    //set_bp_interval_probability(&(new_bp->interval_l));
    //set_bp_interval_probability(&(new_bp->interval_r));
    new_bp->interval_r.p = NULL;
    new_bp->interval_l.p = NULL;

    new_bp->type = type;
    new_bp->weight = weight;

    return new_bp;
}
//}}}

//{{{ void SV_Bedpe:: set_bp_interval_start_end(struct breakpoint_interval *i,
void
SV_Bedpe::
set_bp_interval_start_end(struct breakpoint_interval *i,
                          struct interval *target_interval,
                          struct interval *target_pair,
                          int back_distance,
                          int distro_size)
{
    i->i.chr = target_interval->chr;
    i->i.strand = target_interval->strand;
    i->i.start = target_interval->start;
    i->i.end = target_interval->end;
    i->i.start_clip = 0;
}
//}}}

//{{{ log_space* SV_Bedpe:: get_bp_interval_probability(char strand)
log_space*
SV_Bedpe::
get_bp_interval_probability(char strand,
                            int distro_size,
                            double *distro)
{
    CHR_POS size = distro_size;
    log_space *tmp_p = (log_space *) malloc(size * sizeof(log_space));
    CHR_POS j;
    for (j = 0; j < size; ++j) {
        if (strand == '+')
            tmp_p[j] = get_ls(distro[j]);
        else
            tmp_p[(size - 1) - j] = get_ls(distro[j]);
    }

    return tmp_p;
}
//}}}

//{{{ void SV_Pair:: print_evidence()
void
SV_Bedpe::
print_evidence()
{
    print_bedpe(0);
}
//}}}

//{{{ void SV_Bedpe:: print_bedpe(int score)
void
SV_Bedpe::
print_bedpe(int score)
{
    // use the address of the current object as the id
    string sep = "\t";
    cout <<
         side_l.chr << sep <<
         side_l.start << sep <<
         (side_l.end + 1) << sep <<
         side_r.chr << sep <<
         side_r.start << sep<<
         (side_r.end + 1) << sep<<
         this << sep <<
         score << sep <<
         side_l.strand << "\t" <<
         side_r.strand <<
         endl;
}
//}}}

//{{{ void SV_Bedpe:: process_bedpe(const BEDPE *bedpeEntry,
void
SV_Bedpe::
process_bedpe(const BEDPE *bedpeEntry,
              UCSCBins<SV_BreakPoint*> &r_bin,
              int weight,
              int ev_id,
              SV_BedpeReader *reader)
{
    SV_Bedpe *new_bedpe = new SV_Bedpe(bedpeEntry,
                                       weight,
                                       ev_id,
                                       reader);

    SV_BreakPoint *new_bp = new_bedpe->get_bp();
    new_bp->cluster(r_bin);
}
//}}}

//{{{ string SV_Bedpe:: evidence_type()
string
SV_Bedpe::
evidence_type()
{
    return "bedpe";
}
//}}}

//{{{ void SV_Pair:: set_interval_probability()
void
SV_Bedpe::
set_bp_interval_probability(struct breakpoint_interval *i)
{
    CHR_POS size = i->i.end - i->i.start + 1;
    log_space *tmp_p = (log_space *) malloc(size * sizeof(log_space));
    //log_space *src_p;

    double v = 1.0 / ((double )size);

    //int offset = i->i.start_clip;
    CHR_POS j;
    for (j = 0; j < size; ++j) {
        //tmp_p[j] = src_p[j + offset];
        tmp_p[j] = get_ls(v);
    }

    i->p = tmp_p;
}
//}}}
<commit_msg>Add translocations to BEDPE<commit_after>#/*****************************************************************************
 * SV_Bedpe.cpp
 * (c) 2012 - Ryan M. Layer
 * Hall Laboratory
 * Quinlan Laboratory
 * Department of Computer Science
 * Department of Biochemistry and Molecular Genetics
 * Department of Public Health Sciences and Center for Public Health Genomics,
 * University of Virginia
 * rl6sf@virginia.edu
 *
 * Licenced under the GNU General Public License 2.0 license.
 * ***************************************************************************/
#include "BamAncillary.h"
using namespace BamTools;

#include "SV_BedpeReader.h"
#include "SV_BreakPoint.h"
#include "SV_Bedpe.h"
#include "log_space.h"
#include "bedFilePE.h"

#include <iostream>
#include <algorithm>
#include <string>
#include <math.h>

using namespace std;

//{{{ SV_Bedpe:: SV_Bedpe(const BEDPE *bedpeEntry)
SV_Bedpe::
SV_Bedpe(const BEDPE *bedpeEntry,
         int _weight,
         int _ev_id,
         SV_BedpeReader *_reader)
{
    reader = _reader;

    ev_id = _ev_id;
    struct interval tmp_a, tmp_b;

    tmp_a.start = bedpeEntry->start1;
    tmp_a.end = bedpeEntry->end1 - 1;
    tmp_a.chr = bedpeEntry->chrom1;
    tmp_a.strand = bedpeEntry->strand1[0];

    tmp_b.start = bedpeEntry->start2;
    tmp_b.end = bedpeEntry->end2 - 1;
    tmp_b.chr = bedpeEntry->chrom2;
    tmp_b.strand = bedpeEntry->strand2[0];

    if ( tmp_a.chr.compare(tmp_b.chr) > 0 ) {
        side_l = tmp_a;
        side_r = tmp_b;
    } else if ( tmp_a.chr.compare(tmp_b.chr) < 0 ) {
        side_l = tmp_b;
        side_r = tmp_a;
    } else { // ==
        if (tmp_a.start > tmp_b.start) {
            side_l = tmp_b;
            side_r = tmp_a;
        } else {
            side_l = tmp_a;
            side_r = tmp_b;
        }
    }

    vector<string>::const_iterator it;
    type = -1;
    for (it = bedpeEntry->fields.begin();
            it != bedpeEntry->fields.end(); ++it) {

        if ( it->find("TYPE:") == 0 ) {
            string type_string = it->substr(5,it->length() - 5);

            if (type_string.compare("DELETION") == 0) {
                type = SV_BreakPoint::DELETION;
            } else if (type_string.compare("DUPLICATION") == 0) {
                type = SV_BreakPoint::DUPLICATION;
            } else if (type_string.compare("INVERSION") == 0) {
                type = SV_BreakPoint::INVERSION;
            } else if (type_string.compare("TRANSLOCATION") == 0) {
                type = SV_BreakPoint::TRANSLOCATION;
            } else {
                cerr << "ERROR IN BEDPE FILE.  TYPE \""<< type_string <<
                     "\" not supported " <<
                     "(DELETION,DUPLICATION,INVERSION,TRANSLOCATION)" <<
                     endl;
                abort();
            }

        }
    }

    if (type == -1) {
        cerr << "ERROR IN BEDPE FILE.  Either no TYPE field. " <<
             endl;
        abort();
    }

    weight = _weight;
}
//}}}

//{{{ ostream& operator << (ostream& out, const SV_Pair& p)
ostream& operator << (ostream& out, const SV_Bedpe& p)
{

    out << p.side_l.chr << "," <<
        p.side_l.start << "," <<
        p.side_l.end << "," <<
        p.side_l.strand <<
        "\t" <<
        p.side_r.chr << "," <<
        p.side_r.start << "," <<
        p.side_r.end << "," <<
        p.side_r.strand;

    return out;
}
//}}}

//{{{ SV_BreakPoint* SV_Pair:: get_bp()
SV_BreakPoint*
SV_Bedpe::
get_bp()
{
    // Make a new break point
    SV_BreakPoint *new_bp = new SV_BreakPoint(this);

    set_bp_interval_start_end(&(new_bp->interval_l),
                              &side_l,
                              &side_r,
                              0,
                              reader->distro_size);
    set_bp_interval_start_end(&(new_bp->interval_r),
                              &side_r,
                              &side_l,
                              0,
                              reader->distro_size);

    //set_bp_interval_probability(&(new_bp->interval_l));
    //set_bp_interval_probability(&(new_bp->interval_r));
    new_bp->interval_r.p = NULL;
    new_bp->interval_l.p = NULL;

    new_bp->type = type;
    new_bp->weight = weight;

    return new_bp;
}
//}}}

//{{{ void SV_Bedpe:: set_bp_interval_start_end(struct breakpoint_interval *i,
void
SV_Bedpe::
set_bp_interval_start_end(struct breakpoint_interval *i,
                          struct interval *target_interval,
                          struct interval *target_pair,
                          int back_distance,
                          int distro_size)
{
    i->i.chr = target_interval->chr;
    i->i.strand = target_interval->strand;
    i->i.start = target_interval->start;
    i->i.end = target_interval->end;
    i->i.start_clip = 0;
}
//}}}

//{{{ log_space* SV_Bedpe:: get_bp_interval_probability(char strand)
log_space*
SV_Bedpe::
get_bp_interval_probability(char strand,
                            int distro_size,
                            double *distro)
{
    CHR_POS size = distro_size;
    log_space *tmp_p = (log_space *) malloc(size * sizeof(log_space));
    CHR_POS j;
    for (j = 0; j < size; ++j) {
        if (strand == '+')
            tmp_p[j] = get_ls(distro[j]);
        else
            tmp_p[(size - 1) - j] = get_ls(distro[j]);
    }

    return tmp_p;
}
//}}}

//{{{ void SV_Pair:: print_evidence()
void
SV_Bedpe::
print_evidence()
{
    print_bedpe(0);
}
//}}}

//{{{ void SV_Bedpe:: print_bedpe(int score)
void
SV_Bedpe::
print_bedpe(int score)
{
    // use the address of the current object as the id
    string sep = "\t";
    cout <<
         side_l.chr << sep <<
         side_l.start << sep <<
         (side_l.end + 1) << sep <<
         side_r.chr << sep <<
         side_r.start << sep<<
         (side_r.end + 1) << sep<<
         this << sep <<
         score << sep <<
         side_l.strand << "\t" <<
         side_r.strand <<
         endl;
}
//}}}

//{{{ void SV_Bedpe:: process_bedpe(const BEDPE *bedpeEntry,
void
SV_Bedpe::
process_bedpe(const BEDPE *bedpeEntry,
              UCSCBins<SV_BreakPoint*> &r_bin,
              int weight,
              int ev_id,
              SV_BedpeReader *reader)
{
    SV_Bedpe *new_bedpe = new SV_Bedpe(bedpeEntry,
                                       weight,
                                       ev_id,
                                       reader);

    SV_BreakPoint *new_bp = new_bedpe->get_bp();
    new_bp->cluster(r_bin);
}
//}}}

//{{{ string SV_Bedpe:: evidence_type()
string
SV_Bedpe::
evidence_type()
{
    return "bedpe";
}
//}}}

//{{{ void SV_Pair:: set_interval_probability()
void
SV_Bedpe::
set_bp_interval_probability(struct breakpoint_interval *i)
{
    CHR_POS size = i->i.end - i->i.start + 1;
    log_space *tmp_p = (log_space *) malloc(size * sizeof(log_space));
    //log_space *src_p;

    double v = 1.0 / ((double )size);

    //int offset = i->i.start_clip;
    CHR_POS j;
    for (j = 0; j < size; ++j) {
        //tmp_p[j] = src_p[j + offset];
        tmp_p[j] = get_ls(v);
    }

    i->p = tmp_p;
}
//}}}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdint.h>
#include <math.h>

// For lightweight communication with the FPGA:
#define FPGA_MANAGER_BASE 0xFF706000
#define FPGA_GPO_OFFSET 0x10
#define FPGA_GPI_OFFSET 0x14

// HPS-to-FPGA:
#define H2F_DATA_READY (1 << 0)

// FPGA-to-HPS:
#define F2H_BUSY (1 << 0)

// Shared memory addresses:
#define BASE 0x38000000
#define RAM_SIZE 0x40000000
#define COLOR_BUFFER_1_OFFSET 0
#define BUFFER_SIZE (800*480*4)
#define COLOR_BUFFER_2_OFFSET (COLOR_BUFFER_1_OFFSET + BUFFER_SIZE)
#define Z_BUFFER_OFFSET (COLOR_BUFFER_2_OFFSET + BUFFER_SIZE)
#define PROTOCOL_BUFFER_OFFSET (Z_BUFFER_OFFSET + BUFFER_SIZE)

// Protocol command number:
#define CMD_CLEAR 1
#define CMD_ZCLEAR 2
#define CMD_PATTERN 3
#define CMD_DRAW 4
#define CMD_BITMAP 5
#define CMD_SWAP 6
#define CMD_END 7

// Draw type:
#define DRAW_TRIANGLES 0
#define DRAW_LINES 1
#define DRAW_POINTS 2
#define DRAW_LINE_STRIP 3
#define DRAW_TRIANGLE_STRIP 5
#define DRAW_TRIANGLE_FAN 6

void cmd_clear(volatile uint64_t **p, uint8_t red, uint8_t green, uint8_t blue)
{
    *(*p)++ = CMD_CLEAR
	| ((uint64_t) red << 56)
	| ((uint64_t) green << 48)
	| ((uint64_t) blue << 40);
}

void cmd_draw(volatile uint64_t **p, int type, int count)
{
    *(*p)++ = CMD_DRAW
    	| ((uint64_t) type << 8)
	| ((uint64_t) count << 16);
}

void vertex(volatile uint64_t **p, int x, int y, int z,
    uint8_t red, uint8_t green, uint8_t blue)
{
    *(*p)++ =
    	  ((uint64_t) x << 2)
	| ((uint64_t) y << 15)
	| ((uint64_t) red << 56)
	| ((uint64_t) green << 48)
	| ((uint64_t) blue << 40);
}

void cmd_swap(volatile uint64_t **p)
{
    *(*p)++ = CMD_SWAP;
}

void cmd_end(volatile uint64_t **p)
{
    *(*p)++ = CMD_END;
}

int main()
{
    int dev_mem = open("/dev/mem", O_RDWR);
    if(dev_mem == 0) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // Get access to lightweight FPGA communication.
    uint8_t *fpga_manager_base = (uint8_t *) mmap(0, 64,
	PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem, FPGA_MANAGER_BASE);
    if(fpga_manager_base == 0) {
        perror("mmap for fpga manager base");
        exit(EXIT_FAILURE);
    }
    volatile uint32_t *gpo = (uint32_t*)(fpga_manager_base + FPGA_GPO_OFFSET);
    volatile uint32_t *gpi = (uint32_t*)(fpga_manager_base + FPGA_GPI_OFFSET);

    // Get access to the various RAM buffers.
    uint8_t *buffers_base = (uint8_t *) mmap(0, RAM_SIZE - BASE,
	PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem, BASE);
    if(buffers_base == 0) {
        perror("mmap for buffers");
        exit(EXIT_FAILURE);
    }
    volatile uint64_t *protocol_buffer =
	(uint64_t *) (buffers_base + PROTOCOL_BUFFER_OFFSET);

    *gpo = 0;
    int counter = 0;
    while (1) {
	// Start of frame.

	// Write protocol buffer.
	printf("Writing protocol buffer.\n");
	volatile uint64_t *p = protocol_buffer;
	cmd_clear(&p,
	    (counter & 0x04) ? 32 : 0,
	    (counter & 0x02) ? 32 : 0,
	    (counter & 0x01) ? 32 : 0);
	cmd_draw(&p, DRAW_TRIANGLES, 1);
	vertex(&p,
	    800/2 + (int) (200*sin(counter/10.0)),
	    450/2 + (int) (200*cos(counter/10.0)),
	    0, 50, 100, 150);
	vertex(&p,
	    800/2 + (int) (200*sin(counter/10.0 + M_PI*2/3)),
	    450/2 + (int) (200*cos(counter/10.0 + M_PI*2/3)),
	    0, 50, 100, 150);
	vertex(&p,
	    800/2 + (int) (200*sin(counter/10.0 + M_PI*4/3)),
	    450/2 + (int) (200*cos(counter/10.0 + M_PI*4/3)),
	    0, 50, 100, 150);
	cmd_swap(&p);
	cmd_end(&p);
	printf("    Wrote %d words:\n", p - protocol_buffer);
	for (volatile uint64_t *t = protocol_buffer; t < p; t++) {
	    printf("        0x%016llX\n", *t);
	}

	// Tell FPGA that our data is ready.
	printf("Telling FPGA that the data is ready.\n");
	*gpo |= H2F_DATA_READY;

	// Wait until we find out that it has heard us.
	printf("Waiting for FPGA to get busy.\n");
	while ((*gpi & F2H_BUSY) == 0) {
	    // Busy loop.
	}

	// Let FPGA know that we know that it's busy.
	printf("Telling FPGA that we know it's busy.\n");
	*gpo &= ~H2F_DATA_READY;

	// Wait until it's done rasterizing.
	printf("Waiting for FPGA to finish rasterizing.\n");
	while ((*gpi & F2H_BUSY) != 0) {
	    // Busy loop.
	}

	usleep(1000*100);
	counter++;
    }

    exit(EXIT_SUCCESS);
}

<commit_msg>Turn of debug printf and usleep() now that we block on swap buffers.<commit_after>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdint.h>
#include <math.h>

#undef DEBUG_PRINT

// For lightweight communication with the FPGA:
#define FPGA_MANAGER_BASE 0xFF706000
#define FPGA_GPO_OFFSET 0x10
#define FPGA_GPI_OFFSET 0x14

// HPS-to-FPGA:
#define H2F_DATA_READY (1 << 0)

// FPGA-to-HPS:
#define F2H_BUSY (1 << 0)

// Shared memory addresses:
#define BASE 0x38000000
#define RAM_SIZE 0x40000000
#define COLOR_BUFFER_1_OFFSET 0
#define BUFFER_SIZE (800*480*4)
#define COLOR_BUFFER_2_OFFSET (COLOR_BUFFER_1_OFFSET + BUFFER_SIZE)
#define Z_BUFFER_OFFSET (COLOR_BUFFER_2_OFFSET + BUFFER_SIZE)
#define PROTOCOL_BUFFER_OFFSET (Z_BUFFER_OFFSET + BUFFER_SIZE)

// Protocol command number:
#define CMD_CLEAR 1
#define CMD_ZCLEAR 2
#define CMD_PATTERN 3
#define CMD_DRAW 4
#define CMD_BITMAP 5
#define CMD_SWAP 6
#define CMD_END 7

// Draw type:
#define DRAW_TRIANGLES 0
#define DRAW_LINES 1
#define DRAW_POINTS 2
#define DRAW_LINE_STRIP 3
#define DRAW_TRIANGLE_STRIP 5
#define DRAW_TRIANGLE_FAN 6

void cmd_clear(volatile uint64_t **p, uint8_t red, uint8_t green, uint8_t blue)
{
    *(*p)++ = CMD_CLEAR
	| ((uint64_t) red << 56)
	| ((uint64_t) green << 48)
	| ((uint64_t) blue << 40);
}

void cmd_draw(volatile uint64_t **p, int type, int count)
{
    *(*p)++ = CMD_DRAW
    	| ((uint64_t) type << 8)
	| ((uint64_t) count << 16);
}

void vertex(volatile uint64_t **p, int x, int y, int z,
    uint8_t red, uint8_t green, uint8_t blue)
{
    *(*p)++ =
    	  ((uint64_t) x << 2)
	| ((uint64_t) y << 15)
	| ((uint64_t) red << 56)
	| ((uint64_t) green << 48)
	| ((uint64_t) blue << 40);
}

void cmd_swap(volatile uint64_t **p)
{
    *(*p)++ = CMD_SWAP;
}

void cmd_end(volatile uint64_t **p)
{
    *(*p)++ = CMD_END;
}

int main()
{
    int dev_mem = open("/dev/mem", O_RDWR);
    if(dev_mem == 0) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // Get access to lightweight FPGA communication.
    uint8_t *fpga_manager_base = (uint8_t *) mmap(0, 64,
	PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem, FPGA_MANAGER_BASE);
    if(fpga_manager_base == 0) {
        perror("mmap for fpga manager base");
        exit(EXIT_FAILURE);
    }
    volatile uint32_t *gpo = (uint32_t*)(fpga_manager_base + FPGA_GPO_OFFSET);
    volatile uint32_t *gpi = (uint32_t*)(fpga_manager_base + FPGA_GPI_OFFSET);

    // Get access to the various RAM buffers.
    uint8_t *buffers_base = (uint8_t *) mmap(0, RAM_SIZE - BASE,
	PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem, BASE);
    if(buffers_base == 0) {
        perror("mmap for buffers");
        exit(EXIT_FAILURE);
    }
    volatile uint64_t *protocol_buffer =
	(uint64_t *) (buffers_base + PROTOCOL_BUFFER_OFFSET);

    *gpo = 0;
    int counter = 0;
    while (1) {
	// Start of frame.

	// Write protocol buffer.
#ifdef DEBUG_PRINT
	printf("Writing protocol buffer.\n");
#endif
	volatile uint64_t *p = protocol_buffer;
	if (0) {
	    cmd_clear(&p,
		(counter & 0x04) ? 255 : 0,
		(counter & 0x02) ? 255 : 0,
		(counter & 0x01) ? 255 : 0);
	} else {
	    cmd_clear(&p, 0, 0, 0);
	}
	cmd_draw(&p, DRAW_TRIANGLES, 1);
	vertex(&p,
	    800/2 + (int) (200*sin(counter/10.0)),
	    450/2 + (int) (200*cos(counter/10.0)),
	    0, 50, 100, 150);
	vertex(&p,
	    800/2 + (int) (200*sin(counter/10.0 + M_PI*2/3)),
	    450/2 + (int) (200*cos(counter/10.0 + M_PI*2/3)),
	    0, 50, 100, 150);
	vertex(&p,
	    800/2 + (int) (200*sin(counter/10.0 + M_PI*4/3)),
	    450/2 + (int) (200*cos(counter/10.0 + M_PI*4/3)),
	    0, 50, 100, 150);
	cmd_swap(&p);
	cmd_end(&p);
#ifdef DEBUG_PRINT
	printf("    Wrote %d words:\n", p - protocol_buffer);
	for (volatile uint64_t *t = protocol_buffer; t < p; t++) {
	    printf("        0x%016llX\n", *t);
	}
#endif

	// Tell FPGA that our data is ready.
#ifdef DEBUG_PRINT
	printf("Telling FPGA that the data is ready.\n");
#endif
	*gpo |= H2F_DATA_READY;

	// Wait until we find out that it has heard us.
#ifdef DEBUG_PRINT
	printf("Waiting for FPGA to get busy.\n");
#endif
	while ((*gpi & F2H_BUSY) == 0) {
	    // Busy loop.
	}

	// Let FPGA know that we know that it's busy.
#ifdef DEBUG_PRINT
	printf("Telling FPGA that we know it's busy.\n");
#endif
	*gpo &= ~H2F_DATA_READY;

	// Wait until it's done rasterizing.
#ifdef DEBUG_PRINT
	printf("Waiting for FPGA to finish rasterizing.\n");
#endif
	while ((*gpi & F2H_BUSY) != 0) {
	    // Busy loop.
	}

	// usleep(1000*100);
	counter++;
    }

    exit(EXIT_SUCCESS);
}

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "Stroika/Frameworks/StroikaPreComp.h"

#include    <iostream>

#include    "Stroika/Foundation/Characters/String2Float.h"
#include    "Stroika/Foundation/DataExchange/JSON/Writer.h"
#include    "Stroika/Foundation/Execution/CommandLine.h"
#if     qPlatform_POSIX
#include    "Stroika/Foundation/Execution/SignalHandlers.h"
#endif
#include    "Stroika/Foundation/Execution/WaitableEvent.h"
#include    "Stroika/Foundation/Memory/Optional.h"
#include    "Stroika/Foundation/Streams/BasicBinaryOutputStream.h"

#include    "Stroika/Frameworks/SystemPerformance/AllInstruments.h"
#include    "Stroika/Frameworks/SystemPerformance/Capturer.h"
#include    "Stroika/Frameworks/SystemPerformance/Measurement.h"

using   namespace std;

using   namespace Stroika::Foundation;
using   namespace Stroika::Frameworks;
using   namespace Stroika::Frameworks::SystemPerformance;

using   Characters::Character;
using   Characters::String;
using   Containers::Sequence;
using   Memory::Optional;

namespace {
    string  Serialize_ (VariantValue v, bool oneLineMode)
    {
        Streams::BasicBinaryOutputStream    out;
        DataExchange::JSON::Writer ().Write (v, out);
        // strip CRLF - so shows up on one line
        String result = String::FromUTF8 (out.As<string> ());
        if (oneLineMode) {
            result = result.StripAll ([] (Character c)-> bool { return c == '\n' or c == '\r';});
        }
        return result.AsNarrowSDKString ();
    }
}

int main (int argc, const char* argv[])
{
#if     qPlatform_POSIX
    // Many performance instruments use pipes
    // @todo - REVIEW IF REALLY NEEDED AND WHY? SO LONG AS NO FAIL SHOULDNT BE?
    //  --LGP 2014-02-05
    Execution::SignalHandlerRegistry::Get ().SetSignalHandlers (SIGPIPE, Execution::SignalHandlerRegistry::kIGNORED);
#endif
    bool                        printUsage  =   false;
    bool                        printNames  =   false;
    bool                        oneLineMode =   false;
    Time::DurationSecondsType   runFor      =   30.0;
    Set<InstrumentNameType> run;
    Sequence<String>  args    =   Execution::ParseCommandLine (argc, argv);
    for (auto argi = args.begin (); argi != args.end(); ++argi) {
        if (Execution::MatchesCommandLineArgument (*argi, L"h")) {
            printUsage = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"l")) {
            printNames = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"o")) {
            oneLineMode = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"r")) {
            ++argi;
            if (argi != args.end ()) {
                run.Add (*argi);
            }
            else {
                cerr << "Expected arg to -r" << endl;
                return EXIT_FAILURE;
            }
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"t")) {
            ++argi;
            if (argi != args.end ()) {
                runFor = Characters::String2Float<Time::DurationSecondsType> (*argi);
            }
            else {
                cerr << "Expected arg to -t" << endl;
                return EXIT_FAILURE;
            }
        }
    }
    if (printUsage) {
        cerr << "Usage: SystemPerformanceClient [-h] [-l] [-f] [-r RUN-INSTRUMENT]*" << endl;
        cerr << "    -h prints this help" << endl;
        cerr << "    -o prints instrument results (with newlines stripped)" << endl;
        cerr << "    -l prints only the instrument names" << endl;
        cerr << "    -r runs the given instrument (it can be repeated)" << endl;
        cerr << "    -t time to run for (if zero dont use capturer code)" << endl;
        return EXIT_SUCCESS;
    }

    try {
        if (printNames) {
            cout << "Instrument:" << endl;
            for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                cout << "  " << i.fInstrumentName.GetPrintName ().AsNarrowSDKString () << endl;
                // print measurements too?
            }
            return EXIT_SUCCESS;
        }

        bool    useCapturer =   runFor > 0;
        if (useCapturer) {
            /*
             * Demo using capturer
             */
            Capturer capturer;
            {
                CaptureSet cs;
                cs.SetRunPeriod (Duration (15));
                for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                    if (not run.empty ()) {
                        if (not run.Contains (i.fInstrumentName)) {
                            continue;
                        }
                    }
                    cs.AddInstrument (i);
                }
                capturer.AddCaptureSet (cs);
            }
            capturer.AddMeasurementsCallback ([oneLineMode] (MeasurementSet ms) {
                cout << "    Measured-At: " << ms.fMeasuredAt.Format ([] (DateTime dt) { return dt.Format (); }).AsNarrowSDKString () << endl;
                for (Measurement mi : ms.fMeasurements) {
                    cout << "    " << mi.fType.GetPrintName ().AsNarrowSDKString () << ": " << Serialize_ (mi.fValue, oneLineMode) << endl;
                }
            });

            // run til timeout and then fall out...
            IgnoreExceptionsForCall (Execution::WaitableEvent (Execution::WaitableEvent::eAutoReset).Wait (runFor));
        }
        else {
            /*
             * Demo NOT using capturer
             */
            cout << "Results for each instrument:" << endl;
            for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                if (not run.empty ()) {
                    if (not run.Contains (i.fInstrumentName)) {
                        continue;
                    }
                }
                cout << "  " << i.fInstrumentName.GetPrintName ().AsNarrowSDKString () << endl;
                MeasurementSet m = i.Capture ();
                if (m.fMeasurements.empty ()) {
                    cout << "    NO DATA";
                }
                else {
                    cout << "    Measured-At: " << m.fMeasuredAt.Format ([] (DateTime dt) { return dt.Format (); }).AsNarrowSDKString () << endl;
                    for (Measurement mi : m.fMeasurements) {
                        cout << "    " << mi.fType.GetPrintName ().AsNarrowSDKString () << ": " << Serialize_ (mi.fValue, oneLineMode) << endl;
                    }
                }
            }
        }
    }
    catch (...) {
        cerr << "Exception - terminating..." << endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
<commit_msg>undid hack to Samples/SystemPerformanceClient for recent Range<>::Format() change - now default arg works fine<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "Stroika/Frameworks/StroikaPreComp.h"

#include    <iostream>

#include    "Stroika/Foundation/Characters/String2Float.h"
#include    "Stroika/Foundation/DataExchange/JSON/Writer.h"
#include    "Stroika/Foundation/Execution/CommandLine.h"
#if     qPlatform_POSIX
#include    "Stroika/Foundation/Execution/SignalHandlers.h"
#endif
#include    "Stroika/Foundation/Execution/WaitableEvent.h"
#include    "Stroika/Foundation/Memory/Optional.h"
#include    "Stroika/Foundation/Streams/BasicBinaryOutputStream.h"

#include    "Stroika/Frameworks/SystemPerformance/AllInstruments.h"
#include    "Stroika/Frameworks/SystemPerformance/Capturer.h"
#include    "Stroika/Frameworks/SystemPerformance/Measurement.h"

using   namespace std;

using   namespace Stroika::Foundation;
using   namespace Stroika::Frameworks;
using   namespace Stroika::Frameworks::SystemPerformance;

using   Characters::Character;
using   Characters::String;
using   Containers::Sequence;
using   Memory::Optional;

namespace {
    string  Serialize_ (VariantValue v, bool oneLineMode)
    {
        Streams::BasicBinaryOutputStream    out;
        DataExchange::JSON::Writer ().Write (v, out);
        // strip CRLF - so shows up on one line
        String result = String::FromUTF8 (out.As<string> ());
        if (oneLineMode) {
            result = result.StripAll ([] (Character c)-> bool { return c == '\n' or c == '\r';});
        }
        return result.AsNarrowSDKString ();
    }
}

int main (int argc, const char* argv[])
{
#if     qPlatform_POSIX
    // Many performance instruments use pipes
    // @todo - REVIEW IF REALLY NEEDED AND WHY? SO LONG AS NO FAIL SHOULDNT BE?
    //  --LGP 2014-02-05
    Execution::SignalHandlerRegistry::Get ().SetSignalHandlers (SIGPIPE, Execution::SignalHandlerRegistry::kIGNORED);
#endif
    bool                        printUsage  =   false;
    bool                        printNames  =   false;
    bool                        oneLineMode =   false;
    Time::DurationSecondsType   runFor      =   30.0;
    Set<InstrumentNameType> run;
    Sequence<String>  args    =   Execution::ParseCommandLine (argc, argv);
    for (auto argi = args.begin (); argi != args.end(); ++argi) {
        if (Execution::MatchesCommandLineArgument (*argi, L"h")) {
            printUsage = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"l")) {
            printNames = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"o")) {
            oneLineMode = true;
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"r")) {
            ++argi;
            if (argi != args.end ()) {
                run.Add (*argi);
            }
            else {
                cerr << "Expected arg to -r" << endl;
                return EXIT_FAILURE;
            }
        }
        if (Execution::MatchesCommandLineArgument (*argi, L"t")) {
            ++argi;
            if (argi != args.end ()) {
                runFor = Characters::String2Float<Time::DurationSecondsType> (*argi);
            }
            else {
                cerr << "Expected arg to -t" << endl;
                return EXIT_FAILURE;
            }
        }
    }
    if (printUsage) {
        cerr << "Usage: SystemPerformanceClient [-h] [-l] [-f] [-r RUN-INSTRUMENT]*" << endl;
        cerr << "    -h prints this help" << endl;
        cerr << "    -o prints instrument results (with newlines stripped)" << endl;
        cerr << "    -l prints only the instrument names" << endl;
        cerr << "    -r runs the given instrument (it can be repeated)" << endl;
        cerr << "    -t time to run for (if zero dont use capturer code)" << endl;
        return EXIT_SUCCESS;
    }

    try {
        if (printNames) {
            cout << "Instrument:" << endl;
            for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                cout << "  " << i.fInstrumentName.GetPrintName ().AsNarrowSDKString () << endl;
                // print measurements too?
            }
            return EXIT_SUCCESS;
        }

        bool    useCapturer =   runFor > 0;
        if (useCapturer) {
            /*
             * Demo using capturer
             */
            Capturer capturer;
            {
                CaptureSet cs;
                cs.SetRunPeriod (Duration (15));
                for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                    if (not run.empty ()) {
                        if (not run.Contains (i.fInstrumentName)) {
                            continue;
                        }
                    }
                    cs.AddInstrument (i);
                }
                capturer.AddCaptureSet (cs);
            }
            capturer.AddMeasurementsCallback ([oneLineMode] (MeasurementSet ms) {
                cout << "    Measured-At: " << ms.fMeasuredAt.Format ().AsNarrowSDKString () << endl;
                for (Measurement mi : ms.fMeasurements) {
                    cout << "    " << mi.fType.GetPrintName ().AsNarrowSDKString () << ": " << Serialize_ (mi.fValue, oneLineMode) << endl;
                }
            });

            // run til timeout and then fall out...
            IgnoreExceptionsForCall (Execution::WaitableEvent (Execution::WaitableEvent::eAutoReset).Wait (runFor));
        }
        else {
            /*
             * Demo NOT using capturer
             */
            cout << "Results for each instrument:" << endl;
            for (Instrument i : SystemPerformance::GetAllInstruments ()) {
                if (not run.empty ()) {
                    if (not run.Contains (i.fInstrumentName)) {
                        continue;
                    }
                }
                cout << "  " << i.fInstrumentName.GetPrintName ().AsNarrowSDKString () << endl;
                MeasurementSet m = i.Capture ();
                if (m.fMeasurements.empty ()) {
                    cout << "    NO DATA";
                }
                else {
                    cout << "    Measured-At: " << m.fMeasuredAt.Format ().AsNarrowSDKString () << endl;
                    for (Measurement mi : m.fMeasurements) {
                        cout << "    " << mi.fType.GetPrintName ().AsNarrowSDKString () << ": " << Serialize_ (mi.fValue, oneLineMode) << endl;
                    }
                }
            }
        }
    }
    catch (...) {
        cerr << "Exception - terminating..." << endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
<|endoftext|>