<commit_before>#include "firmware_handler.hpp"

#include "image_handler.hpp"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <memory>
#include <string>
#include <vector>

namespace blobs
{

const std::string FirmwareBlobHandler::hashBlobID = "/flash/hash";
const std::string FirmwareBlobHandler::activeImageBlobID =
    "/flash/active/image";
const std::string FirmwareBlobHandler::activeHashBlobID = "/flash/active/hash";

std::unique_ptr<GenericBlobInterface>
    FirmwareBlobHandler::CreateFirmwareBlobHandler(
        const std::vector<HandlerPack>& firmwares,
        const std::vector<DataHandlerPack>& transports)
{
    /* There must be at least one. */
    if (!firmwares.size())
    {
        return nullptr;
    }
    if (!transports.size())
    {
        return nullptr;
    }

    std::vector<std::string> blobs;
    for (const auto& item : firmwares)
    {
        blobs.push_back(item.blobName);
    }

    if (0 == std::count(blobs.begin(), blobs.end(), hashBlobID))
    {
        return nullptr;
    }

    std::uint16_t bitmask = 0;
    for (const auto& item : transports)
    {
        /* TODO: can use std::accumulate() unless I'm mistaken. :D */
        bitmask |= item.bitmask;
    }

    return std::make_unique<FirmwareBlobHandler>(firmwares, blobs, transports,
                                                 bitmask);
}

bool FirmwareBlobHandler::canHandleBlob(const std::string& path)
{
    /* Check if the path is in our supported list (or active list). */
    if (std::count(blobIDs.begin(), blobIDs.end(), path))
    {
        return true;
    }

    return false;
}

std::vector<std::string> FirmwareBlobHandler::getBlobIds()
{
    /*
     * Grab the list of supported firmware.
     *
     * If there's an open firmware session, it'll already be present in the
     * list as "/flash/active/image", and if the hash has started,
     * "/flash/active/hash" regardless of mechanism.  This is done in the open
     * comamnd, no extra work is required here.
     */
    return blobIDs;
}

bool FirmwareBlobHandler::deleteBlob(const std::string& path)
{
    /*
     * Per the design, this mean abort, and this will trigger whatever
     * appropriate actions are required to abort the process.
     */
    return false;
}

bool FirmwareBlobHandler::stat(const std::string& path, struct BlobMeta* meta)
{
    /*
     * Stat on the files will return information such as what supported
     * transport mechanisms are available.
     *
     * Stat on an active file or hash will return information such as the size
     * of the data cached, and any additional pertinent information.  The
     * blob_state on the active files will return the state of the update.
     */

    /* We know we support this path because canHandle is called ahead */
    if (path == FirmwareBlobHandler::activeImageBlobID)
    {
        /* We need to return information for the image that's staged. */
    }
    else if (path == FirmwareBlobHandler::activeHashBlobID)
    {
        /* We need to return information for the hash that's staged. */
    }
    else
    {
        /* They are requesting information about the generic blob_id. */
        meta->blobState = bitmask;
        meta->size = 0;

        /* The generic blob_ids state is only the bits related to the transport
         * mechanisms. */
        return true;
    }

    return false;
}

/*
 * If you open /flash/image or /flash/tarball, or /flash/hash it will
 * interpret the open flags and perform whatever actions are required for
 * that update process.  The session returned can be used immediately for
 * sending data down, without requiring one to open the new active file.
 *
 * If you open the active flash image or active hash it will let you
 * overwrite pieces, depending on the state.
 *
 * Once the verification process has started the active files cannot be
 * opened.
 *
 * You can only have one open session at a time.  Which means, you can only
 * have one file open at a time.  Trying to open the hash blob_id while you
 * still have the flash image blob_id open will fail.  Opening the flash
 * blob_id when it is already open will fail.
 */
bool FirmwareBlobHandler::open(uint16_t session, uint16_t flags,
                               const std::string& path)
{
    /* Check that they've opened for writing - read back not supported. */
    if ((flags & OpenFlags::write) == 0)
    {
        return false;
    }

    /* TODO: Is the verification process underway? */

    /* Is there an open session already? We only allow one at a time.
     * TODO: Temporarily using a simple boolean flag until there's a full
     * session object to check.
     *
     * Further on this, if there's an active session to the hash we don't allow
     * re-opening the image, and if we have the image open, we don't allow
     * opening the hash.  This design decision may be re-evaluated, and changed
     * to only allow one session per object type (of the two types).  But,
     * consider if the hash is open, do we want to allow writing to the image?
     * And why would we?  But, really, the point of no-return is once the
     * verification process has begun -- which is done via commit() on the hash
     * blob_id, we no longer want to allow updating the contents.
     */
    if (fileOpen)
    {
        return false;
    }

    /* There are two abstractions at play, how you get the data and how you
     * handle that data. such that, whether the data comes from the PCI bridge
     * or LPC bridge is not connected to whether the data goes into a static
     * layout flash update or a UBI tarball.
     */

    /* Check the flags for the transport mechanism: if none match we don't
     * support what they request.
     */
    if ((flags & bitmask) == 0)
    {
        return false;
    }

    /* 2) there isn't, so what are they opening? */
    if (path == activeImageBlobID)
    {
        /* 2a) are they opening the active image? this can only happen if they
         * already started one (due to canHandleBlob's behavior).
         */
    }
    else if (path == activeHashBlobID)
    {
        /* 2b) are they opening the active hash? this can only happen if they
         * already started one (due to canHandleBlob's behavior).
         */
    }

    /* How are they expecting to copy this data? */
    auto d = std::find_if(
        transports.begin(), transports.end(),
        [&flags](const auto& iter) { return (iter.bitmask & flags); });
    if (d == transports.end())
    {
        return false;
    }

    /* We found the transport handler they requested, no surprise since
     * above we verify they selected at least one we wanted.
     */
    Session* curr;

    if (path == hashBlobID)
    {
        curr = &activeHash;

        /* 2c) are they opening the /flash/hash ? (to start the process) */

        /* Add active hash blob_id to canHandle list. */
        blobIDs.push_back(activeHashBlobID);
    }
    else
    {
        curr = &activeImage;

        /* add active image blob_id to canHandle list. */
        blobIDs.push_back(activeImageBlobID);
    }

    /* 2d) are they opening the /flash/tarball ? (to start the UBI process)
     */
    /* 2e) are they opening the /flash/image ? (to start the process) */
    /* 2...) are they opening the /flash/... ? (to start the process) */

    auto h = std::find_if(
        handlers.begin(), handlers.end(),
        [&path](const auto& iter) { return (iter.blobName == path); });
    if (h == handlers.end())
    {
        return false;
    }

    /* Ok, so we found a handler that matched, so call open() */
    if (!h->handler->open(path))
    {
        return false;
    }

    curr->flags = flags;
    curr->dataHandler = d->handler;
    curr->imageHandler = h->handler;

    lookup[session] = curr;

    return true;
}

std::vector<uint8_t> FirmwareBlobHandler::read(uint16_t session,
                                               uint32_t offset,
                                               uint32_t requestedSize)
{
    /*
     * Currently, the design does not provide this with a function, however,
     * it will likely change to support reading data back.
     */
    return {};
}

/**
 * The write command really just grabs the data from wherever it is and sends it
 * to the image handler.  It's the image handler's responsibility to deal with
 * the data provided.
 */
bool FirmwareBlobHandler::write(uint16_t session, uint32_t offset,
                                const std::vector<uint8_t>& data)
{
    auto item = lookup.find(session);
    if (item == lookup.end())
    {
        return false;
    }

    std::vector<std::uint8_t> bytes;

    if (item->second->flags & FirmwareUpdateFlags::ipmi)
    {
        bytes = data;
    }
    else
    {
        /* little endian required per design, and so on, but TODO: do endianness
         * with boost.
         */
        struct ExtChunkHdr header;

        if (data.size() != sizeof(header))
        {
            return false;
        }

        std::memcpy(&header, data.data(), data.size());
        bytes = item->second->dataHandler->copyFrom(header.length);
    }

    return item->second->imageHandler->write(offset, bytes);
}

/*
 * If the active session (image or hash) is over LPC, this allows
 * configuring it.  This option is only available before you start
 * writing data for the given item (image or hash).  This will return
 * false at any other part. -- the lpc handler portion will know to return
 * false.
 */
bool FirmwareBlobHandler::writeMeta(uint16_t session, uint32_t offset,
                                    const std::vector<uint8_t>& data)
{
    auto item = lookup.find(session);
    if (item == lookup.end())
    {
        return false;
    }

    if (item->second->flags & FirmwareUpdateFlags::ipmi)
    {
        return false;
    }

    return item->second->dataHandler->write(data);
}

bool FirmwareBlobHandler::commit(uint16_t session,
                                 const std::vector<uint8_t>& data)
{
    /*
     * If this command is called on the session for the hash image, it'll
     * trigger a systemd service `verify_image.service` to attempt to verify
     * the image. Before doing this, if the transport mechanism is not IPMI
     * BT, it'll shut down the mechanism used for transport preventing the
     * host from updating anything.
     */
    return false;
}
bool FirmwareBlobHandler::close(uint16_t session)
{
    /*
     * Close must be called on the firmware image before triggering
     * verification via commit. Once the verification is complete, you can
     * then close the hash file.
     *
     * If the `verify_image.service` returned success, closing the hash file
     * will have a specific behavior depending on the update. If it's UBI,
     * it'll perform the install. If it's static layout, it'll do nothing. The
     * verify_image service in the static layout case is responsible for placing
     * the file in the correct staging position.
     */
    return false;
}
bool FirmwareBlobHandler::stat(uint16_t session, struct BlobMeta* meta)
{
    /*
     * Return session specific information.
     */
    return false;
}
bool FirmwareBlobHandler::expire(uint16_t session)
{
    return false;
}
} // namespace blobs
<commit_msg>firmware: prevent writing or opening during verification<commit_after>#include "firmware_handler.hpp"

#include "image_handler.hpp"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <memory>
#include <string>
#include <vector>

namespace blobs
{

const std::string FirmwareBlobHandler::hashBlobID = "/flash/hash";
const std::string FirmwareBlobHandler::activeImageBlobID =
    "/flash/active/image";
const std::string FirmwareBlobHandler::activeHashBlobID = "/flash/active/hash";

std::unique_ptr<GenericBlobInterface>
    FirmwareBlobHandler::CreateFirmwareBlobHandler(
        const std::vector<HandlerPack>& firmwares,
        const std::vector<DataHandlerPack>& transports)
{
    /* There must be at least one. */
    if (!firmwares.size())
    {
        return nullptr;
    }
    if (!transports.size())
    {
        return nullptr;
    }

    std::vector<std::string> blobs;
    for (const auto& item : firmwares)
    {
        blobs.push_back(item.blobName);
    }

    if (0 == std::count(blobs.begin(), blobs.end(), hashBlobID))
    {
        return nullptr;
    }

    std::uint16_t bitmask = 0;
    for (const auto& item : transports)
    {
        /* TODO: can use std::accumulate() unless I'm mistaken. :D */
        bitmask |= item.bitmask;
    }

    return std::make_unique<FirmwareBlobHandler>(firmwares, blobs, transports,
                                                 bitmask);
}

bool FirmwareBlobHandler::canHandleBlob(const std::string& path)
{
    /* Check if the path is in our supported list (or active list). */
    if (std::count(blobIDs.begin(), blobIDs.end(), path))
    {
        return true;
    }

    return false;
}

std::vector<std::string> FirmwareBlobHandler::getBlobIds()
{
    /*
     * Grab the list of supported firmware.
     *
     * If there's an open firmware session, it'll already be present in the
     * list as "/flash/active/image", and if the hash has started,
     * "/flash/active/hash" regardless of mechanism.  This is done in the open
     * comamnd, no extra work is required here.
     */
    return blobIDs;
}

bool FirmwareBlobHandler::deleteBlob(const std::string& path)
{
    /*
     * Per the design, this mean abort, and this will trigger whatever
     * appropriate actions are required to abort the process.
     */
    return false;
}

bool FirmwareBlobHandler::stat(const std::string& path, struct BlobMeta* meta)
{
    /*
     * Stat on the files will return information such as what supported
     * transport mechanisms are available.
     *
     * Stat on an active file or hash will return information such as the size
     * of the data cached, and any additional pertinent information.  The
     * blob_state on the active files will return the state of the update.
     */

    /* We know we support this path because canHandle is called ahead */
    if (path == FirmwareBlobHandler::activeImageBlobID)
    {
        /* We need to return information for the image that's staged. */
    }
    else if (path == FirmwareBlobHandler::activeHashBlobID)
    {
        /* We need to return information for the hash that's staged. */
    }
    else
    {
        /* They are requesting information about the generic blob_id. */
        meta->blobState = bitmask;
        meta->size = 0;

        /* The generic blob_ids state is only the bits related to the transport
         * mechanisms. */
        return true;
    }

    return false;
}

/*
 * If you open /flash/image or /flash/tarball, or /flash/hash it will
 * interpret the open flags and perform whatever actions are required for
 * that update process.  The session returned can be used immediately for
 * sending data down, without requiring one to open the new active file.
 *
 * If you open the active flash image or active hash it will let you
 * overwrite pieces, depending on the state.
 *
 * Once the verification process has started the active files cannot be
 * opened.
 *
 * You can only have one open session at a time.  Which means, you can only
 * have one file open at a time.  Trying to open the hash blob_id while you
 * still have the flash image blob_id open will fail.  Opening the flash
 * blob_id when it is already open will fail.
 */
bool FirmwareBlobHandler::open(uint16_t session, uint16_t flags,
                               const std::string& path)
{
    /* Check that they've opened for writing - read back not supported. */
    if ((flags & OpenFlags::write) == 0)
    {
        return false;
    }

    /* Is the verification process underway? */
    if (state == UpdateState::verificationStarted)
    {
        return false;
    }

    /* Is there an open session already? We only allow one at a time.
     * TODO: Temporarily using a simple boolean flag until there's a full
     * session object to check.
     *
     * Further on this, if there's an active session to the hash we don't allow
     * re-opening the image, and if we have the image open, we don't allow
     * opening the hash.  This design decision may be re-evaluated, and changed
     * to only allow one session per object type (of the two types).  But,
     * consider if the hash is open, do we want to allow writing to the image?
     * And why would we?  But, really, the point of no-return is once the
     * verification process has begun -- which is done via commit() on the hash
     * blob_id, we no longer want to allow updating the contents.
     */
    if (fileOpen)
    {
        return false;
    }

    /* There are two abstractions at play, how you get the data and how you
     * handle that data. such that, whether the data comes from the PCI bridge
     * or LPC bridge is not connected to whether the data goes into a static
     * layout flash update or a UBI tarball.
     */

    /* Check the flags for the transport mechanism: if none match we don't
     * support what they request.
     */
    if ((flags & bitmask) == 0)
    {
        return false;
    }

    /* 2) there isn't, so what are they opening? */
    if (path == activeImageBlobID)
    {
        /* 2a) are they opening the active image? this can only happen if they
         * already started one (due to canHandleBlob's behavior).
         */
    }
    else if (path == activeHashBlobID)
    {
        /* 2b) are they opening the active hash? this can only happen if they
         * already started one (due to canHandleBlob's behavior).
         */
    }

    /* How are they expecting to copy this data? */
    auto d = std::find_if(
        transports.begin(), transports.end(),
        [&flags](const auto& iter) { return (iter.bitmask & flags); });
    if (d == transports.end())
    {
        return false;
    }

    /* We found the transport handler they requested, no surprise since
     * above we verify they selected at least one we wanted.
     */
    Session* curr;

    if (path == hashBlobID)
    {
        curr = &activeHash;

        /* 2c) are they opening the /flash/hash ? (to start the process) */

        /* Add active hash blob_id to canHandle list. */
        blobIDs.push_back(activeHashBlobID);
    }
    else
    {
        curr = &activeImage;

        /* add active image blob_id to canHandle list. */
        blobIDs.push_back(activeImageBlobID);
    }

    /* 2d) are they opening the /flash/tarball ? (to start the UBI process)
     */
    /* 2e) are they opening the /flash/image ? (to start the process) */
    /* 2...) are they opening the /flash/... ? (to start the process) */

    auto h = std::find_if(
        handlers.begin(), handlers.end(),
        [&path](const auto& iter) { return (iter.blobName == path); });
    if (h == handlers.end())
    {
        return false;
    }

    /* Ok, so we found a handler that matched, so call open() */
    if (!h->handler->open(path))
    {
        return false;
    }

    curr->flags = flags;
    curr->dataHandler = d->handler;
    curr->imageHandler = h->handler;

    lookup[session] = curr;

    return true;
}

std::vector<uint8_t> FirmwareBlobHandler::read(uint16_t session,
                                               uint32_t offset,
                                               uint32_t requestedSize)
{
    /*
     * Currently, the design does not provide this with a function, however,
     * it will likely change to support reading data back.
     */
    return {};
}

/**
 * The write command really just grabs the data from wherever it is and sends it
 * to the image handler.  It's the image handler's responsibility to deal with
 * the data provided.
 */
bool FirmwareBlobHandler::write(uint16_t session, uint32_t offset,
                                const std::vector<uint8_t>& data)
{
    auto item = lookup.find(session);
    if (item == lookup.end())
    {
        return false;
    }

    /* Prevent writing during verification. */
    if (state == UpdateState::verificationStarted)
    {
        return false;
    }

    std::vector<std::uint8_t> bytes;

    if (item->second->flags & FirmwareUpdateFlags::ipmi)
    {
        bytes = data;
    }
    else
    {
        /* little endian required per design, and so on, but TODO: do endianness
         * with boost.
         */
        struct ExtChunkHdr header;

        if (data.size() != sizeof(header))
        {
            return false;
        }

        std::memcpy(&header, data.data(), data.size());
        bytes = item->second->dataHandler->copyFrom(header.length);
    }

    return item->second->imageHandler->write(offset, bytes);
}

/*
 * If the active session (image or hash) is over LPC, this allows
 * configuring it.  This option is only available before you start
 * writing data for the given item (image or hash).  This will return
 * false at any other part. -- the lpc handler portion will know to return
 * false.
 */
bool FirmwareBlobHandler::writeMeta(uint16_t session, uint32_t offset,
                                    const std::vector<uint8_t>& data)
{
    auto item = lookup.find(session);
    if (item == lookup.end())
    {
        return false;
    }

    if (item->second->flags & FirmwareUpdateFlags::ipmi)
    {
        return false;
    }

    return item->second->dataHandler->write(data);
}

bool FirmwareBlobHandler::commit(uint16_t session,
                                 const std::vector<uint8_t>& data)
{
    /*
     * If this command is called on the session for the hash image, it'll
     * trigger a systemd service `verify_image.service` to attempt to verify
     * the image. Before doing this, if the transport mechanism is not IPMI
     * BT, it'll shut down the mechanism used for transport preventing the
     * host from updating anything.
     */
    return false;
}
bool FirmwareBlobHandler::close(uint16_t session)
{
    /*
     * Close must be called on the firmware image before triggering
     * verification via commit. Once the verification is complete, you can
     * then close the hash file.
     *
     * If the `verify_image.service` returned success, closing the hash file
     * will have a specific behavior depending on the update. If it's UBI,
     * it'll perform the install. If it's static layout, it'll do nothing. The
     * verify_image service in the static layout case is responsible for placing
     * the file in the correct staging position.
     */
    return false;
}
bool FirmwareBlobHandler::stat(uint16_t session, struct BlobMeta* meta)
{
    /*
     * Return session specific information.
     */
    return false;
}
bool FirmwareBlobHandler::expire(uint16_t session)
{
    return false;
}
} // namespace blobs
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
using namespace std;

typedef unsigned long long ull;

const int MAX = 1000001;

#define endl '\n'

int isPrime(int number, vector<ull>&prime) {
    if(number == 2) return 1;
    if(number % 2 == 0) return 0;
    for(const int &i: prime) {
        if(i*i > number) return 1;
        if(number % i == 0) return 0;
    }
    return 1;
}

vector<ull> findPrimeSums(const int MAX) {
    vector<ull> primes(MAX + 1, 0);
    vector<ull> values;
    for(int i = 2; i < MAX; ++i) {
        primes[i] = primes[i - 1];
        if(isPrime(i, values)) {
            primes[i] += i;
            values.push_back(i);
        }
    }
    return primes;
}

int main() {
    vector<ull> primes = findPrimeSums(MAX);
    int tests; cin >> tests;
    for(int i = 0; i < tests; ++i) {
        int N; cin >> N;
        cout << primes[N] << endl;
    }
    return 0;
}<commit_msg>Change code on the correct for problem #11<commit_after>#include <vector>
#include <iostream>
using namespace std;

typedef vector<int> vint;
typedef vector<vint> vvint;

#define endl '\n'
#define max(a, b) a > b ? a : b

const int SIZE = 20, WINDOW = 3;

vvint matrix(SIZE, vint(SIZE));

int down(vvint &m) {
    int result = 0;
    for(int i = 0; i < (SIZE - WINDOW); ++i)
        for(int j = 0; j < SIZE; ++j) {
            int sum = 1;
            for(int k = 0; k <= WINDOW; ++k)
                sum *= m[i + k][j];
            result = max(result, sum);
    }
    return result;
}

int right(vvint &m) {
    int result = 0;
    for(int i = 0; i < SIZE; ++i)
        for(int j = 0; j < (SIZE - WINDOW); ++j) {
            int sum = 1;
            for(int k = 0; k <= WINDOW; ++k)
                sum *= m[i][j + k];
            result = max(result, sum);
    }
    return result;
}

int diag(vvint &m) {
    int result = 0;
    for(int i = 0; i < (SIZE - WINDOW); ++i)
        for(int j = 0; j < (SIZE - WINDOW); ++j) {
            int sum = 1;
            for(int k = 0; k <= WINDOW; ++k)
                sum *= m[i + k][j + k];
        result = max(result, sum);
    }
    return result;
}

int antidiag(vvint &m) {
    int result = 0;
    for(int i = 0; i < (SIZE - WINDOW); ++i)
        for(int j = WINDOW; j < SIZE; ++j) {
            int sum = 1;
            for(int k = 0; k <= WINDOW; ++k)
                sum *= m[i + k][j - k];
            result = max(result, sum);
    }
    return result;
}

int calculate(vvint &m) {
    int result = 0;
    result = max(result, down(m));
    result = max(result, right(m));
    result = max(result, diag(m));
    result = max(result, antidiag(m));
    return result;
}

int main() {
    for(int i = 0; i < SIZE; ++i)
        for(int j = 0; j < SIZE; ++j)
            cin >> matrix[i][j];
    cout << calculate(matrix) << endl;
    return 0;
}<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/un.h>
#include <pthread.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <poll.h>

#include "portal.h"
#include "sock_utils.h"

#define MAX_FD_ARRAY 10

static struct {
    struct memrequest req;
    int sockfd;
    int valid;
    int inflight;
} head;
static struct memresponse respitem;
static int trace_port;// = 1;
static int fd_array[MAX_FD_ARRAY];
static int fd_array_index = 0;

static void *pthread_worker(void *p)
{
    int listening_socket = init_listening(SOCKET_NAME, NULL);
    if (trace_port)
        fprintf(stderr, "%s[%d]: waiting for a connection...\n",__FUNCTION__, listening_socket);
    while (1) {
        int sockfd = accept(listening_socket, NULL, NULL);
        if (sockfd == -1) {
            fprintf(stderr, "%s[%d]: accept error %s\n",__FUNCTION__, listening_socket, strerror(errno));
            exit(1);
        }
        if (trace_port)
            printf("[%s:%d] sockfd %d\n", __FUNCTION__, __LINE__, sockfd);
        fd_array[fd_array_index++] = sockfd;
    }
}

extern "C" void initPortal(void)
{
    pthread_t threaddata;
    pthread_create(&threaddata, NULL, &pthread_worker, NULL);
}

extern "C" void interruptLevel(uint32_t ivalue)
{
    static struct memresponse respitem;
    int i;
    if (ivalue != respitem.data) {
        respitem.portal = MAGIC_PORTAL_FOR_SENDING_INTERRUPT;
        respitem.data = ivalue;
        if (trace_port)
            printf("%s: %d\n", __FUNCTION__, ivalue);
        for (i = 0; i < fd_array_index; i++)
           portalSendFd(fd_array[i], &respitem, sizeof(respitem), -1);
    }
}

#if 0
static unsigned long long int rdtsc(void)
{
   unsigned long long int x;
   unsigned a, d;

   __asm__ volatile("rdtsc" : "=a" (a), "=d" (d));

   return ((unsigned long long)a) | (((unsigned long long)d) << 32);;
}
#endif
extern "C" bool checkForRequest(uint32_t rr)
{
#if 0
static int counter;
static int timeoutcount;
static int last_short;
static long long last_val;
long long this_val = rdtsc();
last_val = (this_val - last_val)/1000;
counter++;
if (last_val <= 3)
   last_short++;
if (last_short == 2) {
timeoutcount++;
    last_short = 0;
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 10000;
    select(0, NULL, NULL, NULL, &timeout);
}
last_val = this_val;
#endif
    if (!head.valid){
	int rv = -1, i, recvfd;
        for (i = 0; i < fd_array_index; i++) {
            head.sockfd = fd_array[i];
            rv = portalRecvFd(head.sockfd, &head.req, sizeof(head.req), &recvfd);
	    if(rv > 0){
	        assert(rv == sizeof(memrequest));
	        respitem.portal = head.req.portal;
	        head.valid = 1;
	        head.inflight = 1;
                if (recvfd != -1)
                    head.req.data_or_tag = recvfd;
	        if(trace_port)
	            fprintf(stderr, "processr p=%d w=%d, a=%8lx, dt=%8x:",
		        head.req.portal, head.req.write_flag, (long)head.req.addr, head.req.data_or_tag);
                break;
	    }
        }
    }
    return head.valid && head.inflight == 1 && head.req.write_flag == (int)rr;
}

extern "C" unsigned long long getRequest32(uint32_t rr)
{
    if(trace_port)
        fprintf(stderr, " get%c", rr ? '\n' : ':');
    if (rr)
        head.valid = 0;
    head.inflight = 0;
    return (((unsigned long long)head.req.data_or_tag) << 32) | ((long)head.req.addr);
}

extern "C" void readResponse32(unsigned int data, unsigned int tag)
{
    if(trace_port)
        fprintf(stderr, " read = %x\n", data);
    head.valid = 0;
    respitem.data = data;
    respitem.tag = tag;
    portalSendFd(head.sockfd, &respitem, sizeof(respitem), -1);
}

#define NUM_LINKS 16

struct linkInfo {
    char name[128];
    int listening;
    int socket[1];
    int fd[1];
    uint64_t rxdata[1];
    uint64_t txdata[1];
    pthread_mutex_t mutex;
    int up;
} linkInfo[NUM_LINKS];

struct linkInfo *getLinkInfo(int linknumber, int listening)
{
    char name[128];
    snprintf(name, sizeof(name), "sim.link.%d", linknumber);
    for (int i = 0; i < NUM_LINKS; i++) {
	struct linkInfo *li = &linkInfo[i];
	if (li->name[0] == 0) {
	    strncpy(li->name, name, sizeof(li->name));;
	    li->listening = listening;
	    return li;
	} else if ((strcmp(li->name, name) == 0)
		   && li->listening == listening) {
	    return li;
	}
    }
    return 0;
}

static void *bsimLinkWorker(void *p)
{
    struct linkInfo *li = (struct linkInfo *)p;
    char iname[128];
    int i;
    const char *socketdir = ".";
    if (getenv("SIM_LINK_DIR"))
	socketdir = getenv("SIM_LINK_DIR");

    for (i = 0; i < 1; i++) {
	snprintf(iname, sizeof(iname), "%s/%s", socketdir, li->name);
	if (li->listening) {
	    li->socket[i] = init_listening(iname, NULL);
	    li->fd[i] = accept(li->socket[i], NULL, NULL);
	    if (li->fd[i] == -1) {
		fprintf(stderr, "%s:%d[%d]: accept error %s\n",__FUNCTION__, __LINE__, li->socket[i], strerror(errno));
		return 0;
	    }
	    fprintf(stderr, "%s:%d[%d]: accept ok fd=%d\n",__FUNCTION__, __LINE__, li->socket[i], li->fd[i]);
	} else {
	    li->socket[i] = 0;
	    li->fd[i] = init_connecting(iname, NULL);
	    fprintf(stderr, "%s:%d[%d]: connect ok fd=%d\n",__FUNCTION__, __LINE__, li->socket[i], li->fd[i]);
	}
	fcntl(li->fd[i], F_SETFL, O_NONBLOCK);
    }
    li->up = 1;
    return 0;
}

extern "C" void bsimLinkOpen(int linknumber, int listening)
{
    fprintf(stderr, "%s:%d pid=%d linknumber=%d listening=%d\n", __func__, __LINE__, getpid(), linknumber, listening);
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    if (li) {
	li->listening = listening;
	pthread_mutex_init(&li->mutex, NULL);
	pthread_t threaddata;
	pthread_create(&threaddata, NULL, &bsimLinkWorker, li);
    }
}
extern "C" int bsimLinkUp(int linknumber, int listening)
{
  struct linkInfo *li = getLinkInfo(linknumber, listening);
  if (li)
      return li->up;
  else
      return 0;
}

extern "C" int bsimLinkCanReceive(int linknumber, int listening)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    struct pollfd pollfd[1];
    int i = 0;
    if (!li->fd[i])
	return 0;
    pollfd[0].fd = li->fd[i];
    pollfd[0].events = POLLIN|POLLRDHUP;
    int status = poll(pollfd, 1, 0);
    if (status && pollfd[0].revents & POLLRDHUP) {
	fprintf(stderr, "%s:%d revents=%d, closing fd %d\n", __FUNCTION__, __LINE__, pollfd[0].revents, li->fd[0]);
	close(li->fd[0]);
	li->fd[0] = 0;
	return 0;
    }
    return status;
}
extern "C" int bsimLinkCanTransmit(int linknumber, int listening)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    struct pollfd pollfd[1];
    int i = 0;
    if (!li->fd[i])
	return 0;
    pollfd[0].fd = li->fd[i];
    pollfd[0].events = POLLOUT|POLLHUP;
    int status = poll(pollfd, 1, 0);
    if (status && pollfd[0].revents&POLLHUP) {
	fprintf(stderr, "%s:%d revents=%d, closing fd %d\n", __FUNCTION__, __LINE__, pollfd[0].revents, li->fd[0]);
	close(li->fd[i]);
	li->fd[i] = 0;
	return 0;
    }
    return status;
}
extern "C" uint32_t bsimLinkReceive32(int linknumber, int listening)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    uint32_t *prxdata = (uint32_t *)&li->rxdata;
    int i = 0;
    memset(li->rxdata, 0xbc, sizeof(uint32_t));
    int numBytes = read(li->fd[i], li->rxdata, sizeof(uint32_t));
    if (0 && numBytes > 0)
	fprintf(stderr, "%s:%d linknumber=%d listening=%d numBytes=%d\n", __func__, __LINE__, linknumber, listening, numBytes);
    if (numBytes <= 0)
      fprintf(stderr, "%s:%d linknumber=%d listening=%d numBytes=%d errno=%d\n", __func__, __LINE__, linknumber, listening, numBytes, errno);
    return *prxdata;
}
extern "C" int bsimLinkTransmit32(int linknumber, int listening, uint32_t val)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    //fprintf(stderr, "%s:%d linknumber=%d listening=%d val=%d\n", __func__, __LINE__, linknumber, listening, val);
    int i = 0;
    int numBytes = write(li->fd[i], &val, sizeof(uint32_t));
    //fprintf(stderr, "%s:%d linknumber=%d val=%d numBytes=%d\n", __func__, __LINE__, linknumber, val, numBytes);
    return 0;
}
extern "C" uint64_t bsimLinkReceive64(int linknumber, int listening)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    int i = 0;
    memset(li->rxdata, 0xbc, sizeof(uint64_t));
    int numBytes = read(li->fd[i], li->rxdata, sizeof(uint64_t));
    if (0 && numBytes > 0)
	fprintf(stderr, "%s:%d linknumber=%d listening=%d numBytes=%d\n", __func__, __LINE__, linknumber, listening, numBytes);
    if (numBytes <= 0)
      fprintf(stderr, "%s:%d linknumber=%d listening=%d numBytes=%d errno=%d\n", __func__, __LINE__, linknumber, listening, numBytes, errno);
    return *(uint64_t*)&li->rxdata;
}
extern "C" int bsimLinkTransmit64(int linknumber, int listening, uint64_t val)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    //fprintf(stderr, "%s:%d linknumber=%d listening=%d val=%d\n", __func__, __LINE__, linknumber, listening, val);
    int i = 0;
    int numBytes = write(li->fd[i], &val, sizeof(uint64_t));
    //fprintf(stderr, "%s:%d linknumber=%d val=%lld numBytes=%d\n", __func__, __LINE__, linknumber, val, numBytes);
    return 0;
}

<commit_msg>print name of SimLink when closing<commit_after>// Copyright (c) 2013-2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/un.h>
#include <pthread.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <poll.h>

#include "portal.h"
#include "sock_utils.h"

#define MAX_FD_ARRAY 10

static struct {
    struct memrequest req;
    int sockfd;
    int valid;
    int inflight;
} head;
static struct memresponse respitem;
static int trace_port;// = 1;
static int fd_array[MAX_FD_ARRAY];
static int fd_array_index = 0;

static void *pthread_worker(void *p)
{
    int listening_socket = init_listening(SOCKET_NAME, NULL);
    if (trace_port)
        fprintf(stderr, "%s[%d]: waiting for a connection...\n",__FUNCTION__, listening_socket);
    while (1) {
        int sockfd = accept(listening_socket, NULL, NULL);
        if (sockfd == -1) {
            fprintf(stderr, "%s[%d]: accept error %s\n",__FUNCTION__, listening_socket, strerror(errno));
            exit(1);
        }
        if (trace_port)
            printf("[%s:%d] sockfd %d\n", __FUNCTION__, __LINE__, sockfd);
        fd_array[fd_array_index++] = sockfd;
    }
}

extern "C" void initPortal(void)
{
    pthread_t threaddata;
    pthread_create(&threaddata, NULL, &pthread_worker, NULL);
}

extern "C" void interruptLevel(uint32_t ivalue)
{
    static struct memresponse respitem;
    int i;
    if (ivalue != respitem.data) {
        respitem.portal = MAGIC_PORTAL_FOR_SENDING_INTERRUPT;
        respitem.data = ivalue;
        if (trace_port)
            printf("%s: %d\n", __FUNCTION__, ivalue);
        for (i = 0; i < fd_array_index; i++)
           portalSendFd(fd_array[i], &respitem, sizeof(respitem), -1);
    }
}

#if 0
static unsigned long long int rdtsc(void)
{
   unsigned long long int x;
   unsigned a, d;

   __asm__ volatile("rdtsc" : "=a" (a), "=d" (d));

   return ((unsigned long long)a) | (((unsigned long long)d) << 32);;
}
#endif
extern "C" bool checkForRequest(uint32_t rr)
{
#if 0
static int counter;
static int timeoutcount;
static int last_short;
static long long last_val;
long long this_val = rdtsc();
last_val = (this_val - last_val)/1000;
counter++;
if (last_val <= 3)
   last_short++;
if (last_short == 2) {
timeoutcount++;
    last_short = 0;
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 10000;
    select(0, NULL, NULL, NULL, &timeout);
}
last_val = this_val;
#endif
    if (!head.valid){
	int rv = -1, i, recvfd;
        for (i = 0; i < fd_array_index; i++) {
            head.sockfd = fd_array[i];
            rv = portalRecvFd(head.sockfd, &head.req, sizeof(head.req), &recvfd);
	    if(rv > 0){
	        assert(rv == sizeof(memrequest));
	        respitem.portal = head.req.portal;
	        head.valid = 1;
	        head.inflight = 1;
                if (recvfd != -1)
                    head.req.data_or_tag = recvfd;
	        if(trace_port)
	            fprintf(stderr, "processr p=%d w=%d, a=%8lx, dt=%8x:",
		        head.req.portal, head.req.write_flag, (long)head.req.addr, head.req.data_or_tag);
                break;
	    }
        }
    }
    return head.valid && head.inflight == 1 && head.req.write_flag == (int)rr;
}

extern "C" unsigned long long getRequest32(uint32_t rr)
{
    if(trace_port)
        fprintf(stderr, " get%c", rr ? '\n' : ':');
    if (rr)
        head.valid = 0;
    head.inflight = 0;
    return (((unsigned long long)head.req.data_or_tag) << 32) | ((long)head.req.addr);
}

extern "C" void readResponse32(unsigned int data, unsigned int tag)
{
    if(trace_port)
        fprintf(stderr, " read = %x\n", data);
    head.valid = 0;
    respitem.data = data;
    respitem.tag = tag;
    portalSendFd(head.sockfd, &respitem, sizeof(respitem), -1);
}

#define NUM_LINKS 16

struct linkInfo {
    char name[128];
    int listening;
    int socket[1];
    int fd[1];
    uint64_t rxdata[1];
    uint64_t txdata[1];
    pthread_mutex_t mutex;
    int up;
} linkInfo[NUM_LINKS];

struct linkInfo *getLinkInfo(int linknumber, int listening)
{
    char name[128];
    snprintf(name, sizeof(name), "sim.link.%d", linknumber);
    for (int i = 0; i < NUM_LINKS; i++) {
	struct linkInfo *li = &linkInfo[i];
	if (li->name[0] == 0) {
	    strncpy(li->name, name, sizeof(li->name));;
	    li->listening = listening;
	    return li;
	} else if ((strcmp(li->name, name) == 0)
		   && li->listening == listening) {
	    return li;
	}
    }
    return 0;
}

static void *bsimLinkWorker(void *p)
{
    struct linkInfo *li = (struct linkInfo *)p;
    char iname[128];
    int i;
    const char *socketdir = ".";
    if (getenv("SIM_LINK_DIR"))
	socketdir = getenv("SIM_LINK_DIR");

    for (i = 0; i < 1; i++) {
	snprintf(iname, sizeof(iname), "%s/%s", socketdir, li->name);
	if (li->listening) {
	    li->socket[i] = init_listening(iname, NULL);
	    li->fd[i] = accept(li->socket[i], NULL, NULL);
	    if (li->fd[i] == -1) {
		fprintf(stderr, "%s:%d[%d]: accept error %s\n",__FUNCTION__, __LINE__, li->socket[i], strerror(errno));
		return 0;
	    }
	    fprintf(stderr, "%s:%d[%d]: accept ok fd=%d\n",__FUNCTION__, __LINE__, li->socket[i], li->fd[i]);
	} else {
	    li->socket[i] = 0;
	    li->fd[i] = init_connecting(iname, NULL);
	    fprintf(stderr, "%s:%d[%d]: connect ok fd=%d\n",__FUNCTION__, __LINE__, li->socket[i], li->fd[i]);
	}
	fcntl(li->fd[i], F_SETFL, O_NONBLOCK);
    }
    li->up = 1;
    return 0;
}

extern "C" void bsimLinkOpen(int linknumber, int listening)
{
    fprintf(stderr, "%s:%d pid=%d linknumber=%d listening=%d\n", __func__, __LINE__, getpid(), linknumber, listening);
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    if (li) {
	li->listening = listening;
	pthread_mutex_init(&li->mutex, NULL);
	pthread_t threaddata;
	pthread_create(&threaddata, NULL, &bsimLinkWorker, li);
    }
}
extern "C" int bsimLinkUp(int linknumber, int listening)
{
  struct linkInfo *li = getLinkInfo(linknumber, listening);
  if (li)
      return li->up;
  else
      return 0;
}

extern "C" int bsimLinkCanReceive(int linknumber, int listening)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    struct pollfd pollfd[1];
    int i = 0;
    if (!li->fd[i])
	return 0;
    pollfd[0].fd = li->fd[i];
    pollfd[0].events = POLLIN|POLLRDHUP;
    int status = poll(pollfd, 1, 0);
    if (status && pollfd[0].revents & POLLRDHUP) {
	fprintf(stderr, "%s:%d revents=%d, closing link %s\n", __FUNCTION__, __LINE__, pollfd[0].revents, li->name);
	close(li->fd[0]);
	li->fd[0] = 0;
	return 0;
    }
    return status;
}
extern "C" int bsimLinkCanTransmit(int linknumber, int listening)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    struct pollfd pollfd[1];
    int i = 0;
    if (!li->fd[i])
	return 0;
    pollfd[0].fd = li->fd[i];
    pollfd[0].events = POLLOUT|POLLHUP;
    int status = poll(pollfd, 1, 0);
    if (status && pollfd[0].revents&POLLHUP) {
	fprintf(stderr, "%s:%d revents=%d, closing link %s\n", __FUNCTION__, __LINE__, pollfd[0].revents, li->name);
	close(li->fd[i]);
	li->fd[i] = 0;
	return 0;
    }
    return status;
}
extern "C" uint32_t bsimLinkReceive32(int linknumber, int listening)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    uint32_t *prxdata = (uint32_t *)&li->rxdata;
    int i = 0;
    memset(li->rxdata, 0xbc, sizeof(uint32_t));
    int numBytes = read(li->fd[i], li->rxdata, sizeof(uint32_t));
    if (0 && numBytes > 0)
	fprintf(stderr, "%s:%d linknumber=%d listening=%d numBytes=%d\n", __func__, __LINE__, linknumber, listening, numBytes);
    if (numBytes <= 0)
      fprintf(stderr, "%s:%d linknumber=%d listening=%d numBytes=%d errno=%d\n", __func__, __LINE__, linknumber, listening, numBytes, errno);
    return *prxdata;
}
extern "C" int bsimLinkTransmit32(int linknumber, int listening, uint32_t val)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    //fprintf(stderr, "%s:%d linknumber=%d listening=%d val=%d\n", __func__, __LINE__, linknumber, listening, val);
    int i = 0;
    int numBytes = write(li->fd[i], &val, sizeof(uint32_t));
    //fprintf(stderr, "%s:%d linknumber=%d val=%d numBytes=%d\n", __func__, __LINE__, linknumber, val, numBytes);
    return 0;
}
extern "C" uint64_t bsimLinkReceive64(int linknumber, int listening)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    int i = 0;
    memset(li->rxdata, 0xbc, sizeof(uint64_t));
    int numBytes = read(li->fd[i], li->rxdata, sizeof(uint64_t));
    if (0 && numBytes > 0)
	fprintf(stderr, "%s:%d linknumber=%d listening=%d numBytes=%d\n", __func__, __LINE__, linknumber, listening, numBytes);
    if (numBytes <= 0)
      fprintf(stderr, "%s:%d linknumber=%d listening=%d numBytes=%d errno=%d\n", __func__, __LINE__, linknumber, listening, numBytes, errno);
    return *(uint64_t*)&li->rxdata;
}
extern "C" int bsimLinkTransmit64(int linknumber, int listening, uint64_t val)
{
    struct linkInfo *li = getLinkInfo(linknumber, listening);
    //fprintf(stderr, "%s:%d linknumber=%d listening=%d val=%d\n", __func__, __LINE__, linknumber, listening, val);
    int i = 0;
    int numBytes = write(li->fd[i], &val, sizeof(uint64_t));
    //fprintf(stderr, "%s:%d linknumber=%d val=%lld numBytes=%d\n", __func__, __LINE__, linknumber, val, numBytes);
    return 0;
}

<|endoftext|>


<commit_before>#include <leveldb/db.h>
#include <leveldb/slice.h>
#include <leveldb/env.h>
#include <leveldb/write_batch.h>

#include <unistd.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <errno.h>
#include <time.h>
#include <netinet/tcp.h>
#include <list>

using namespace std;

static const int RESULT_GOOD = 1273252631;
static const int RESULT_BAD = 9999;
static const int RESULT_NOTFOUND = 133133;

leveldb::DB* db;
leveldb::WriteOptions write_options;

void error(const char *msg)
{
  perror(msg);
  exit(1);
}

struct connection_info
{
  int fd;
};

int read_fully(int fd, char* buffer, int len)
{
  int offset = 0;
  while(offset < len)
  {
    int r = read(fd, buffer + offset, len - offset);
    if (r <= 0) return r;
    offset += r;
  }

  return offset;
}

int write_fully(int fd, const char* buffer, int len)
{
  int offset = 0;
  while(offset < len)
  {
    int r = write(fd, buffer + offset, len - offset);
    if (r < 0) cout << "errno:" << errno << " " << strerror(errno) << endl;
    if (r <= 0) return r;
    offset += r;
  }

  return offset;
}

/*
 * The data in the slice will need to be freed
 */
int read_slice(int fd, leveldb::Slice &s)
{
  int sz;
  if(read_fully(fd, (char*)&sz, sizeof(sz)) <= 0) return -1;

  sz = ntohl(sz);

  char* data= NULL;

  if (sz > 0)
  {
    data = new char[sz];

    if(read_fully(fd, data, sz) <= 0)
    {
      return -1;
    }
  }

  s = leveldb::Slice(data,sz);

  //delete data;
  return 0;
}

int write_slice(int fd, leveldb::Slice &s)
{
  int sz = htonl(s.size());

  if (write_fully(fd, (char*)&sz, sizeof(sz)) < 0) return -1;
  if (write_fully(fd, s.data(), s.size()) < 0) return -1;
  return 0;
}

void* handle_connection(void* arg)
{
  connection_info* info=(connection_info*)arg;
  int fd = info->fd;

  //FILE* f = fdopen(fd, "w+");

  // [action][options]
  // actions
  //  1 - get (size = bytes of data) (data = key)
  //        [size][keydata]
  //  2 - put (size = number of keyvalues)
  //        [key_size][keydata][value_size][valuedata]
  //  3 - putall
  //        [items]
  //          [key_size][keydata][value_size][valuedata] (item times)
  //  4 - getprefix
  //        [size][keydata]
  // Returns for puts: int status code, 0 = no problems
  // Return for gets: int status code, 0 = no problems, [size][valuedata]
  // Returns for getprefix: int status code
  //   [items]
  //     [key_size][keydata][value_size][valuedata] (item times)

  bool problems=false;

  while(!problems)
  {
    char action[2];

    if (read_fully(fd, action, 2) <= 0) { problems=true; break;}

    if (action[0] == 1)
    {
      leveldb::Slice key;
      if (read_slice(fd, key) < 0) { problems=true; break;}
      string value;
      leveldb::Status db_stat = db->Get(leveldb::ReadOptions(),key, &value);

      delete key.data();

      int status=RESULT_GOOD;

      if (db_stat.IsNotFound())
      {
        status=RESULT_NOTFOUND;
      }

      int net_status=htonl(status);
      write_fully(fd, (char*)&net_status, sizeof(net_status));

      if (status==RESULT_GOOD)
      {
        leveldb::Slice s = leveldb::Slice(value);
        if (write_slice(fd, s) < 0) { problems=true; break;}
      }

      fsync(fd);

    }
    else if (action[0] == 2)
    {
      leveldb::Slice key;
      leveldb::Slice value;

      if (read_slice(fd, key) < 0) { problems=true; break;}
      if (read_slice(fd, value) < 0) { problems=true; break;}

      leveldb::Status db_stat = db->Put(write_options,key, value);

      delete key.data();
      delete value.data();

      int status=RESULT_BAD;

      if (db_stat.ok())
      {
        status=RESULT_GOOD;
      }
      status=htonl(status);
      write_fully(fd, (char*)&status, sizeof(status));
      fsync(fd);

    }
    else if (action[0] == 3)
    {
      int items;
      if(read_fully(fd, (char*)&items, sizeof(items)) <= 0) { problems=true; break;}
      items = ntohl(items);

      leveldb::WriteBatch write_batch;

      list<leveldb::Slice> slices;

      for(int i = 0; i<items; i++)
      {

        leveldb::Slice key;
        leveldb::Slice value;

        if (read_slice(fd, key) < 0) { problems=true; break;}
        if (read_slice(fd, value) < 0) { problems=true; break;}

        write_batch.Put(key, value);
        slices.push_back(key);
        slices.push_back(value);
      }

      if (problems) break;
      leveldb::Status db_stat = db->Write(write_options, &write_batch);

      int status=RESULT_BAD;
      if (db_stat.ok())
      {
        status=RESULT_GOOD;
      }

      for(list<leveldb::Slice>::iterator I = slices.begin(); I!=slices.end(); I++)
      {
        delete I->data();
      }

      status=htonl(status);
      write_fully(fd, (char*)&status, sizeof(status));
      fsync(fd);

    }
    else if (action[0] == 4)
    {
      leveldb::Slice prefix;

      if (read_slice(fd, prefix) < 0) { problems=true; break;}

      list<leveldb::Slice> slices;

      leveldb::Iterator* I = db->NewIterator(leveldb::ReadOptions());

      int items=0;
      for(I->Seek(prefix); I->Valid() && I->key().starts_with(prefix) ;I->Next())
      {
        slices.push_back(I->key());
        slices.push_back(I->value());
        items++;
      }

      int status=RESULT_GOOD;
      status=htonl(status);
      write_fully(fd, (char*)&status, sizeof(status));

      items=htonl(items);
      write_fully(fd, (char*)&items, sizeof(items));

      for(list<leveldb::Slice>::iterator I = slices.begin(); I!=slices.end(); I++)
      {
        leveldb::Slice s=*I;
        if (write_slice(fd, s) < 0) { problems=true; break;}
      }

      delete prefix.data();
      delete I;

    }
    else
    {
      problems=true;
    }

  }
  cout << "Closing socket with problems" << endl;
  close(fd);

}

int main(int argc, char* argv[])
{
  if (argc != 2)
  {
    cout << "Params: ./levelnet path_level_db" << endl;
    return -1;
  }

  leveldb::Options options;
  options.create_if_missing = true;
  leveldb::Status status = leveldb::DB::Open(options, argv[1], &db);

  write_options.sync = true;

  if (!status.ok()) cerr << status.ToString() << endl;

  int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  struct sockaddr_in serv_addr;
  int yes=1;

  setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
  setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(int));

  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(8844);
  if (bind(sockfd, (struct sockaddr *) &serv_addr,
    sizeof(serv_addr)) < 0)
    error("ERROR on binding");

  listen(sockfd,16);

  while(true)
  {
    socklen_t clilen;
    struct sockaddr_in cli_addr;
    clilen = sizeof(cli_addr);

    int newsockfd = accept(sockfd,
      (struct sockaddr *) &cli_addr,
      &clilen);

    pthread_t pt;
    connection_info info;
    info.fd = newsockfd;
    pthread_create(&pt, NULL, handle_connection, &info);

  }

}
<commit_msg>Adding debug log<commit_after>#include <leveldb/db.h>
#include <leveldb/slice.h>
#include <leveldb/env.h>
#include <leveldb/write_batch.h>

#include <unistd.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <errno.h>
#include <time.h>
#include <netinet/tcp.h>
#include <list>

using namespace std;

static const int RESULT_GOOD = 1273252631;
static const int RESULT_BAD = 9999;
static const int RESULT_NOTFOUND = 133133;

leveldb::DB* db;
leveldb::WriteOptions write_options;

void error(const char *msg)
{
  perror(msg);
  exit(1);
}

struct connection_info
{
  int fd;
};

int read_fully(int fd, char* buffer, int len)
{
  int offset = 0;
  while(offset < len)
  {
    int r = read(fd, buffer + offset, len - offset);
    if (r <= 0) return r;
    offset += r;
  }

  return offset;
}

int write_fully(int fd, const char* buffer, int len)
{
  int offset = 0;
  while(offset < len)
  {
    int r = write(fd, buffer + offset, len - offset);
    if (r < 0) cout << "errno:" << errno << " " << strerror(errno) << endl;
    if (r <= 0) return r;
    offset += r;
  }

  return offset;
}

/*
 * The data in the slice will need to be freed
 */
int read_slice(int fd, leveldb::Slice &s)
{
  int sz;
  if(read_fully(fd, (char*)&sz, sizeof(sz)) <= 0) return -1;

  sz = ntohl(sz);

  char* data= NULL;

  if (sz > 0)
  {
    data = new char[sz];

    if(read_fully(fd, data, sz) <= 0)
    {
      return -1;
    }
  }

  s = leveldb::Slice(data,sz);

  //delete data;
  return 0;
}

int write_slice(int fd, leveldb::Slice &s)
{
  int sz = htonl(s.size());

  if (write_fully(fd, (char*)&sz, sizeof(sz)) < 0) return -1;
  if (write_fully(fd, s.data(), s.size()) < 0) return -1;
  return 0;
}

void* handle_connection(void* arg)
{
  connection_info* info=(connection_info*)arg;
  int fd = info->fd;

  //FILE* f = fdopen(fd, "w+");

  // [action][options]
  // actions
  //  1 - get (size = bytes of data) (data = key)
  //        [size][keydata]
  //  2 - put (size = number of keyvalues)
  //        [key_size][keydata][value_size][valuedata]
  //  3 - putall
  //        [items]
  //          [key_size][keydata][value_size][valuedata] (item times)
  //  4 - getprefix
  //        [size][keydata]
  // Returns for puts: int status code, 0 = no problems
  // Return for gets: int status code, 0 = no problems, [size][valuedata]
  // Returns for getprefix: int status code
  //   [items]
  //     [key_size][keydata][value_size][valuedata] (item times)

  bool problems=false;

  while(!problems)
  {
    char action[2];

    if (read_fully(fd, action, 2) <= 0) { problems=true; break;}

    if (action[0] == 1)
    {
      leveldb::Slice key;
      if (read_slice(fd, key) < 0) { problems=true; break;}
      string value;
      leveldb::Status db_stat = db->Get(leveldb::ReadOptions(),key, &value);

      delete key.data();

      int status=RESULT_GOOD;

      if (db_stat.IsNotFound())
      {
        status=RESULT_NOTFOUND;
      }

      int net_status=htonl(status);
      write_fully(fd, (char*)&net_status, sizeof(net_status));

      if (status==RESULT_GOOD)
      {
        leveldb::Slice s = leveldb::Slice(value);
        if (write_slice(fd, s) < 0) { problems=true; break;}
      }

      fsync(fd);

    }
    else if (action[0] == 2)
    {
      leveldb::Slice key;
      leveldb::Slice value;

      if (read_slice(fd, key) < 0) { problems=true; break;}
      if (read_slice(fd, value) < 0) { problems=true; break;}

      leveldb::Status db_stat = db->Put(write_options,key, value);

      delete key.data();
      delete value.data();

      int status=RESULT_BAD;

      if (db_stat.ok())
      {
        status=RESULT_GOOD;
      }
      else
      {
        cout << db_stat.ToString() << endl;
      }
      status=htonl(status);
      write_fully(fd, (char*)&status, sizeof(status));
      fsync(fd);

    }
    else if (action[0] == 3)
    {
      int items;
      if(read_fully(fd, (char*)&items, sizeof(items)) <= 0) { problems=true; break;}
      items = ntohl(items);

      leveldb::WriteBatch write_batch;

      list<leveldb::Slice> slices;

      for(int i = 0; i<items; i++)
      {

        leveldb::Slice key;
        leveldb::Slice value;

        if (read_slice(fd, key) < 0) { problems=true; break;}
        if (read_slice(fd, value) < 0) { problems=true; break;}

        write_batch.Put(key, value);
        slices.push_back(key);
        slices.push_back(value);
      }

      if (problems) break;
      leveldb::Status db_stat = db->Write(write_options, &write_batch);

      int status=RESULT_BAD;
      if (db_stat.ok())
      {
        status=RESULT_GOOD;
      }

      for(list<leveldb::Slice>::iterator I = slices.begin(); I!=slices.end(); I++)
      {
        delete I->data();
      }

      status=htonl(status);
      write_fully(fd, (char*)&status, sizeof(status));
      fsync(fd);

    }
    else if (action[0] == 4)
    {
      leveldb::Slice prefix;

      if (read_slice(fd, prefix) < 0) { problems=true; break;}

      list<leveldb::Slice> slices;

      leveldb::Iterator* I = db->NewIterator(leveldb::ReadOptions());

      int items=0;
      for(I->Seek(prefix); I->Valid() && I->key().starts_with(prefix) ;I->Next())
      {
        slices.push_back(I->key());
        slices.push_back(I->value());
        items++;
      }

      int status=RESULT_GOOD;
      status=htonl(status);
      write_fully(fd, (char*)&status, sizeof(status));

      items=htonl(items);
      write_fully(fd, (char*)&items, sizeof(items));

      for(list<leveldb::Slice>::iterator I = slices.begin(); I!=slices.end(); I++)
      {
        leveldb::Slice s=*I;
        if (write_slice(fd, s) < 0) { problems=true; break;}
      }

      delete prefix.data();
      delete I;

    }
    else
    {
      problems=true;
    }

  }
  cout << "Closing socket with problems" << endl;
  close(fd);

}

int main(int argc, char* argv[])
{
  if (argc != 2)
  {
    cout << "Params: ./levelnet path_level_db" << endl;
    return -1;
  }

  leveldb::Options options;
  options.create_if_missing = true;
  leveldb::Status status = leveldb::DB::Open(options, argv[1], &db);

  write_options.sync = true;

  if (!status.ok()) cerr << status.ToString() << endl;

  int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  struct sockaddr_in serv_addr;
  int yes=1;

  setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
  setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(int));

  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(8844);
  if (bind(sockfd, (struct sockaddr *) &serv_addr,
    sizeof(serv_addr)) < 0)
    error("ERROR on binding");

  listen(sockfd,16);

  while(true)
  {
    socklen_t clilen;
    struct sockaddr_in cli_addr;
    clilen = sizeof(cli_addr);

    int newsockfd = accept(sockfd,
      (struct sockaddr *) &cli_addr,
      &clilen);

    pthread_t pt;
    connection_info info;
    info.fd = newsockfd;
    pthread_create(&pt, NULL, handle_connection, &info);

  }

}
<|endoftext|>


<commit_before>
#include "QmitkRegisterClasses.h"
#include "QmitkRenderWindow.h"

#include "mitkDataTreeNodeFactory.h"

#include <itksys/SystemTools.hxx>
#include <qapplication.h>

//##Documentation
//## @brief Load one or more data sets (many image, surface
//## and other formats) and display it in a 2D view
//##
//## Only very slightly different to Step1: Use DataTreeNodeFactory
//## instead of PicFileReader, and read more than one data set.
int main(int argc, char* argv[])
{
  QApplication qtapplication( argc, argv );

  if(argc<2)
  {
    fprintf( stderr, "Usage:   %s [filename1] [filename2] ...\n\n",
      itksys::SystemTools::GetFilenameName(argv[0]).c_str() );
    return 1;
  }

  // Register Qmitk-dependent global instances
  QmitkRegisterClasses();

  //*************************************************************************
  // Part I: Basic initialization
  //*************************************************************************

  // Create a tree
  // For now we need a DataTree to initialize a DataStorage later on. In the
  // future, the DataStorage will be independent of the DataTree
  mitk::DataTree::Pointer tree=mitk::DataTree::New();

  // Create a data storage object. We will use it as a singleton
  mitk::DataStorage* storage = mitk::DataStorage::CreateInstance(tree);

  //*************************************************************************
  // Part II: Create some data by reading files
  //*************************************************************************
  int i;
  for(i=1; i<argc; ++i)
  {
    // For testing
    if(strcmp(argv[i], "-testing")==0) continue;

    // Create a DataTreeNodeFactory to read a data format supported
    // by the DataTreeNodeFactory (many image formats, surface formats, etc.)
    mitk::DataTreeNodeFactory::Pointer nodeReader=mitk::DataTreeNodeFactory::New();
    const char * filename = argv[i];
    try
    {
      nodeReader->SetFileName(filename);
      nodeReader->Update();
      //*********************************************************************
      // Part III: Put the data into the datastorage
      //*********************************************************************

      // Since the DataTreeNodeFactory directly creates a node,
      // use the datastorage to add the read node
      storage->Add(nodeReader->GetOutput());
    }
    catch(...)
    {
      fprintf( stderr, "Could not open file %s \n\n", filename );
      exit(2);
    }
  }

  //*************************************************************************
  // Part IV: Create window and pass the datastorage to it
  //*************************************************************************

  // Create a RenderWindow
  QmitkRenderWindow renderWindow;

  // Tell the RenderWindow which (part of) the datastorage to render
  renderWindow.GetRenderer()->SetData(storage);

  // Initialize the RenderWindow
  mitk::RenderingManager::GetInstance()->InitializeViews( storage );

  // Select a slice
  renderWindow.GetSliceNavigationController()->GetSlice()->SetPos( 0 );

  //*************************************************************************
  // Part V: Qt-specific initialization
  //*************************************************************************
  qtapplication.setMainWidget(&renderWindow);
  renderWindow.show();
  renderWindow.resize( 256, 256 );

  // for testing
  #include "QtTesting.h"
  if(strcmp(argv[argc-1], "-testing")!=0)
    return qtapplication.exec();
  else
    return QtTesting();

  // Release all resources used by the data storage and
  // the datatree
  mitk::DataStorage::ShutdownSingleton();
}

/**
\example Step2.cpp
*/
<commit_msg>FIX (#1661): changed index of starting slice to 2, in order to correct picture-offset<commit_after>
#include "QmitkRegisterClasses.h"
#include "QmitkRenderWindow.h"

#include "mitkDataTreeNodeFactory.h"

#include <itksys/SystemTools.hxx>
#include <qapplication.h>

//##Documentation
//## @brief Load one or more data sets (many image, surface
//## and other formats) and display it in a 2D view
//##
//## Only very slightly different to Step1: Use DataTreeNodeFactory
//## instead of PicFileReader, and read more than one data set.
int main(int argc, char* argv[])
{
  QApplication qtapplication( argc, argv );

  if(argc<2)
  {
    fprintf( stderr, "Usage:   %s [filename1] [filename2] ...\n\n",
      itksys::SystemTools::GetFilenameName(argv[0]).c_str() );
    return 1;
  }

  // Register Qmitk-dependent global instances
  QmitkRegisterClasses();

  //*************************************************************************
  // Part I: Basic initialization
  //*************************************************************************

  // Create a tree
  // For now we need a DataTree to initialize a DataStorage later on. In the
  // future, the DataStorage will be independent of the DataTree
  mitk::DataTree::Pointer tree=mitk::DataTree::New();

  // Create a data storage object. We will use it as a singleton
  mitk::DataStorage* storage = mitk::DataStorage::CreateInstance(tree);

  //*************************************************************************
  // Part II: Create some data by reading files
  //*************************************************************************
  int i;
  for(i=1; i<argc; ++i)
  {
    // For testing
    if(strcmp(argv[i], "-testing")==0) continue;

    // Create a DataTreeNodeFactory to read a data format supported
    // by the DataTreeNodeFactory (many image formats, surface formats, etc.)
    mitk::DataTreeNodeFactory::Pointer nodeReader=mitk::DataTreeNodeFactory::New();
    const char * filename = argv[i];
    try
    {
      nodeReader->SetFileName(filename);
      nodeReader->Update();
      //*********************************************************************
      // Part III: Put the data into the datastorage
      //*********************************************************************

      // Since the DataTreeNodeFactory directly creates a node,
      // use the datastorage to add the read node
      storage->Add(nodeReader->GetOutput());
    }
    catch(...)
    {
      fprintf( stderr, "Could not open file %s \n\n", filename );
      exit(2);
    }
  }

  //*************************************************************************
  // Part IV: Create window and pass the datastorage to it
  //*************************************************************************

  // Create a RenderWindow
  QmitkRenderWindow renderWindow;

  // Tell the RenderWindow which (part of) the datastorage to render
  renderWindow.GetRenderer()->SetData(storage);

  // Initialize the RenderWindow
  mitk::RenderingManager::GetInstance()->InitializeViews( storage );

  // Select a slice
  renderWindow.GetSliceNavigationController()->GetSlice()->SetPos( 2 );

  //*************************************************************************
  // Part V: Qt-specific initialization
  //*************************************************************************
  qtapplication.setMainWidget(&renderWindow);
  renderWindow.show();
  renderWindow.resize( 256, 256 );

  // for testing
  #include "QtTesting.h"
  if(strcmp(argv[argc-1], "-testing")!=0)
    return qtapplication.exec();
  else
    return QtTesting();

  // Release all resources used by the data storage and
  // the datatree
  mitk::DataStorage::ShutdownSingleton();
}

/**
\example Step2.cpp
*/
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2006, Ken McDonell.  All Rights Reserved.
 * Copyright (c) 2007, Aconex.  All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

//
// Source Class
//
// manipulate one or more PMAPI contexts

#include <QtGui/QMessageBox>
#include "namespace.h"
#include "main.h"

#define DESPERATE 1

QList<QmcContext *>contextList;
QmcContext *currentContext;

Source::Source(QmcGroup *group)
{
    my.fetchGroup = group;
    my.context = NULL;
}

QString Source::makeSourceBaseName(const QmcContext *cp)
{
    if (cp->source().type() == PM_CONTEXT_ARCHIVE)
	return cp->source().source();
    return cp->source().host();
}

QString Source::makeSourceAnnotatedName(const QmcContext *cp)
{
    QString t;

    if (cp->source().type() == PM_CONTEXT_HOST) {
	t = cp->source().host();
	// TODO - pmproxy host support needed here.
	t.append(" (no proxy)");
    }
    else {
	t = cp->source().source();
	t.append(" (");
	t.append(cp->source().host());
	t.append(")");
    }
    return t;
}

QString Source::makeComboText(const QmcContext *ctx)
{
    return makeSourceAnnotatedName(ctx);
}

int useSourceContext(QWidget *parent, QString &source)
{
    int sts;
    QmcGroup *group = activeTab->group();
    uint_t ctxcount = group->numContexts();

    // TODO: proxy support needed (we toss proxy hostname atm)
    console->post("useSourceContext trying new source: host=%s proxy=%s",
			(const char *)source.toAscii(), "none");

    if ((sts = group->use(activeSources->type(), source)) < 0) {
	QString msg;
	msg.sprintf("Failed to %s \"%s\".\n%s.\n\n",
		    (activeSources->type() == PM_CONTEXT_HOST) ?
		    "connect to pmcd on" : "open archive",
		    (const char *)source.toAscii(), pmErrStr(sts));
	QMessageBox::warning(parent, pmProgname, msg,
		QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape,
		QMessageBox::NoButton, QMessageBox::NoButton);
    }
    else if (group->numContexts() > ctxcount)
	activeSources->add(group->which());
    return sts;
}

int Source::useComboContext(QWidget *parent, QComboBox *combo)
{
    QString source = combo->currentText();
    int sts = useSourceContext(parent, source);
    if (sts < 0)
	combo->removeItem(0);
    return sts;
}

int Source::type()
{
    return currentContext ? currentContext->source().type() : -1;
}

QString Source::host()
{
    // TODO: nathans - these aint QString's, theyre char* ... hmm?
    return my.context ? my.context->source().host() : NULL;
}

const char *Source::sourceAscii()
{
#if DESPERATE
    console->post("Source::sourceAscii(): currentContext=%p", currentContext);
#endif

    if (!currentContext)
    	return NULL;

#if DESPERATE
    console->post("  currentContext handle=%d source=%s",
		  currentContext->handle(),
		  currentContext->source().sourceAscii());
#endif

    return currentContext->source().sourceAscii();
}

void Source::add(QmcContext *context)
{
    bool send_bounds = (context->source().type() == PM_CONTEXT_ARCHIVE);

    contextList.append(context);
    currentContext = context;
    my.context = context;

#if DESPERATE
    dump();
#endif

    // For archives, send a message to kmtime to grow its time window.
    // This is already done if we're the first, so don't do it again;
    // we also don't have a kmtime connection yet if processing args.

    if (kmtime && send_bounds) {
	const QmcSource *source = &context->source();
	QString tz = source->timezone();
	QString host = source->host();
	struct timeval logStartTime = source->start();
	struct timeval logEndTime = source->end();
	kmtime->addArchive(&logStartTime, &logEndTime, tz, host);
    }
}

void Source::dump()
{
    QTextStream cerr(stderr);
    cerr << "Source::dump: current: " << currentContext;
    for (int i = 0; i < contextList.size(); i++) {
	contextList.at(i)->dump(cerr);
	contextList.at(i)->dumpMetrics(cerr);
    }
}

void Source::setupCombo(QComboBox *combo)
{
    combo->clear();
    for (int i = 0; i < contextList.size(); i++) {
	QmcContext *cp = contextList.at(i);
	QString source = makeComboText(cp);
	combo->insertItem(i, source);
	if (cp == currentContext)
	    combo->setCurrentIndex(i);
    }
}

void Source::setCurrentInCombo(QComboBox *combo)
{
    if (!currentContext)
	return;

    QString source = makeComboText(currentContext);
    for (int i = 0; i < combo->count(); i++) {
	if (combo->itemText(i) == source) {
	    combo->setCurrentIndex(i);
	    return;
	}
    }
}

// Called from a QComboBox widget, where name is setup by Source::setupCombo
//
void Source::setCurrentFromCombo(const QString name)
{
    for (int i = 0; i < contextList.size(); i++) {
	QmcContext *cp = contextList.at(i);
	if (name == makeComboText(cp)) {
	    currentContext = cp;
	    return;
	}
    }
}

void Source::setupTree(QTreeWidget *tree)
{
    NameSpace *current = NULL;
    QList<QTreeWidgetItem*> items;

    tree->clear();
    for (int i = 0; i < contextList.size(); i++) {
	QmcContext *cp = contextList.at(i);
	NameSpace *name = new NameSpace(tree, cp, activeTab->isArchiveSource());
	name->setExpanded(true);
	name->setSelectable(false);
	tree->addTopLevelItem(name);
	if (cp == currentContext)
	    current = name;
	items.append(name);
    }
    tree->insertTopLevelItems(0, items);
    if (current)
    	tree->setCurrentItem(current);
}
<commit_msg>Chop any proxy hostname from the name passed (eventually) to pmNewContext<commit_after>/*
 * Copyright (c) 2006, Ken McDonell.  All Rights Reserved.
 * Copyright (c) 2007, Aconex.  All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

//
// Source Class
//
// manipulate one or more PMAPI contexts

#include <QtGui/QMessageBox>
#include "namespace.h"
#include "main.h"

#define DESPERATE 1

QList<QmcContext *>contextList;
QmcContext *currentContext;

Source::Source(QmcGroup *group)
{
    my.fetchGroup = group;
    my.context = NULL;
}

QString Source::makeSourceBaseName(const QmcContext *cp)
{
    if (cp->source().type() == PM_CONTEXT_ARCHIVE)
	return cp->source().source();
    return cp->source().host();
}

QString Source::makeSourceAnnotatedName(const QmcContext *cp)
{
    QString t;

    if (cp->source().type() == PM_CONTEXT_HOST) {
	t = cp->source().host();
	// TODO - pmproxy host support needed here.
	t.append(" (no proxy)");
    }
    else {
	t = cp->source().source();
	t.append(" (");
	t.append(cp->source().host());
	t.append(")");
    }
    return t;
}

QString Source::makeComboText(const QmcContext *ctx)
{
    return makeSourceAnnotatedName(ctx);
}

int useSourceContext(QWidget *parent, QString &source)
{
    int sts;
    QmcGroup *group = activeTab->group();
    uint_t ctxcount = group->numContexts();

    // TODO: proxy support needed (we toss proxy hostname atm)
    source = source.section(QChar(' '), 0, 0);

    console->post("useSourceContext trying new source: host=%s proxy=%s",
			(const char *)source.toAscii(), "none");

    if ((sts = group->use(activeSources->type(), source)) < 0) {
	QString msg;
	msg.sprintf("Failed to %s \"%s\".\n%s.\n\n",
		    (activeSources->type() == PM_CONTEXT_HOST) ?
		    "connect to pmcd on" : "open archive",
		    (const char *)source.toAscii(), pmErrStr(sts));
	QMessageBox::warning(parent, pmProgname, msg,
		QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape,
		QMessageBox::NoButton, QMessageBox::NoButton);
    }
    else if (group->numContexts() > ctxcount)
	activeSources->add(group->which());
    return sts;
}

int Source::useComboContext(QWidget *parent, QComboBox *combo)
{
    QString source = combo->currentText();
    int sts = useSourceContext(parent, source);
    if (sts < 0)
	combo->removeItem(0);
    return sts;
}

int Source::type()
{
    return currentContext ? currentContext->source().type() : -1;
}

QString Source::host()
{
    // TODO: nathans - these aint QString's, theyre char* ... hmm?
    return my.context ? my.context->source().host() : NULL;
}

const char *Source::sourceAscii()
{
#if DESPERATE
    console->post("Source::sourceAscii(): currentContext=%p", currentContext);
#endif

    if (!currentContext)
    	return NULL;

#if DESPERATE
    console->post("  currentContext handle=%d source=%s",
		  currentContext->handle(),
		  currentContext->source().sourceAscii());
#endif

    return currentContext->source().sourceAscii();
}

void Source::add(QmcContext *context)
{
    bool send_bounds = (context->source().type() == PM_CONTEXT_ARCHIVE);

    contextList.append(context);
    currentContext = context;
    my.context = context;

#if DESPERATE
    dump();
#endif

    // For archives, send a message to kmtime to grow its time window.
    // This is already done if we're the first, so don't do it again;
    // we also don't have a kmtime connection yet if processing args.

    if (kmtime && send_bounds) {
	const QmcSource *source = &context->source();
	QString tz = source->timezone();
	QString host = source->host();
	struct timeval logStartTime = source->start();
	struct timeval logEndTime = source->end();
	kmtime->addArchive(&logStartTime, &logEndTime, tz, host);
    }
}

void Source::dump()
{
    QTextStream cerr(stderr);
    cerr << "Source::dump: current: " << currentContext;
    for (int i = 0; i < contextList.size(); i++) {
	contextList.at(i)->dump(cerr);
	contextList.at(i)->dumpMetrics(cerr);
    }
}

void Source::setupCombo(QComboBox *combo)
{
    combo->clear();
    for (int i = 0; i < contextList.size(); i++) {
	QmcContext *cp = contextList.at(i);
	QString source = makeComboText(cp);
	combo->insertItem(i, source);
	if (cp == currentContext)
	    combo->setCurrentIndex(i);
    }
}

void Source::setCurrentInCombo(QComboBox *combo)
{
    if (!currentContext)
	return;

    QString source = makeComboText(currentContext);
    for (int i = 0; i < combo->count(); i++) {
	if (combo->itemText(i) == source) {
	    combo->setCurrentIndex(i);
	    return;
	}
    }
}

// Called from a QComboBox widget, where name is setup by Source::setupCombo
//
void Source::setCurrentFromCombo(const QString name)
{
    for (int i = 0; i < contextList.size(); i++) {
	QmcContext *cp = contextList.at(i);
	if (name == makeComboText(cp)) {
	    currentContext = cp;
	    return;
	}
    }
}

void Source::setupTree(QTreeWidget *tree)
{
    NameSpace *current = NULL;
    QList<QTreeWidgetItem*> items;

    tree->clear();
    for (int i = 0; i < contextList.size(); i++) {
	QmcContext *cp = contextList.at(i);
	NameSpace *name = new NameSpace(tree, cp, activeTab->isArchiveSource());
	name->setExpanded(true);
	name->setSelectable(false);
	tree->addTopLevelItem(name);
	if (cp == currentContext)
	    current = name;
	items.append(name);
    }
    tree->insertTopLevelItems(0, items);
    if (current)
    	tree->setCurrentItem(current);
}
<|endoftext|>