<commit_before>// Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved.
//
// 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 <hip/hip_runtime.h>

#include "rng/generators.hpp"

#include <rocrand.h>
#include <new>

#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */

rocrand_status ROCRANDAPI
rocrand_create_generator(rocrand_generator * generator, rocrand_rng_type rng_type)
{
    try
    {
        if(rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
        {
            *generator = new rocrand_philox4x32_10();
        }
        else if(rng_type == ROCRAND_RNG_PSEUDO_XORWOW)
        {
            *generator = new rocrand_generator_type<ROCRAND_RNG_PSEUDO_XORWOW>();
        }
        else if(rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
        {
            *generator = new rocrand_mrg32k3a();
        }
        else
        {
            return ROCRAND_STATUS_TYPE_ERROR;
        }
    }
    catch(const std::bad_alloc& e)
    {
        return ROCRAND_STATUS_INTERNAL_ERROR;
    }
    catch(rocrand_status status)
    {
        return ROCRAND_STATUS_SUCCESS;
    }
    return ROCRAND_STATUS_SUCCESS;
}

rocrand_status ROCRANDAPI
rocrand_destroy_generator(rocrand_generator generator)
{
    try
    {
        delete(generator);
    }
    catch(rocrand_status status)
    {
        return status;
    }
    return ROCRAND_STATUS_SUCCESS;
}

rocrand_status ROCRANDAPI
rocrand_generate(rocrand_generator generator,
                 unsigned int * output_data, size_t n)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate(output_data, n);
    }
    else if(generator->rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
    {
        rocrand_mrg32k3a * mrg32k3a_generator =
            static_cast<rocrand_mrg32k3a *>(generator);
        return mrg32k3a_generator->generate(output_data, n);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_uniform(rocrand_generator generator,
                         float * output_data, size_t n)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_uniform(output_data, n);
    }
    else if(generator->rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
    {
        rocrand_mrg32k3a * mrg32k3a_generator =
            static_cast<rocrand_mrg32k3a *>(generator);
        return mrg32k3a_generator->generate_uniform(output_data, n);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_uniform_double(rocrand_generator generator,
                                double * output_data, size_t n)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_uniform(output_data, n);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_normal(rocrand_generator generator,
                        float * output_data, size_t n,
                        float mean, float stddev)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_normal(output_data, n,
                                                        stddev, mean);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_normal_double(rocrand_generator generator,
                 double * output_data, size_t n,
                 double mean, double stddev)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_normal(output_data, n,
                                                        stddev, mean);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_log_normal(rocrand_generator generator,
                            float * output_data, size_t n,
                            float mean, float stddev)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_log_normal(output_data, n,
                                                            stddev, mean);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_log_normal_double(rocrand_generator generator,
                                   double * output_data, size_t n,
                                   double mean, double stddev)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_log_normal(output_data, n,
                                                            stddev, mean);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_poisson(rocrand_generator generator,
                         unsigned int * output_data, size_t n,
                         double lambda)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }
    if (lambda <= 0.0)
    {
        return ROCRAND_STATUS_OUT_OF_RANGE;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_poisson(output_data, n,
                                                         lambda);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_set_stream(rocrand_generator generator, hipStream_t stream)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        static_cast<rocrand_philox4x32_10 *>(generator)->set_stream(stream);
        return ROCRAND_STATUS_SUCCESS;
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_get_version(int * version)
{
    if(version == NULL)
    {
        return ROCRAND_STATUS_OUT_OF_RANGE;
    }

    *version = ROCRAND_VERSION;
    return ROCRAND_STATUS_SUCCESS;
}

#if defined(__cplusplus)
}
#endif /* __cplusplus */
<commit_msg>Updated host functions with mrg32k3a functions<commit_after>// Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved.
//
// 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 <hip/hip_runtime.h>

#include "rng/generators.hpp"

#include <rocrand.h>
#include <new>

#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */

rocrand_status ROCRANDAPI
rocrand_create_generator(rocrand_generator * generator, rocrand_rng_type rng_type)
{
    try
    {
        if(rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
        {
            *generator = new rocrand_philox4x32_10();
        }
        else if(rng_type == ROCRAND_RNG_PSEUDO_XORWOW)
        {
            *generator = new rocrand_generator_type<ROCRAND_RNG_PSEUDO_XORWOW>();
        }
        else if(rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
        {
            *generator = new rocrand_mrg32k3a();
        }
        else
        {
            return ROCRAND_STATUS_TYPE_ERROR;
        }
    }
    catch(const std::bad_alloc& e)
    {
        return ROCRAND_STATUS_INTERNAL_ERROR;
    }
    catch(rocrand_status status)
    {
        return ROCRAND_STATUS_SUCCESS;
    }
    return ROCRAND_STATUS_SUCCESS;
}

rocrand_status ROCRANDAPI
rocrand_destroy_generator(rocrand_generator generator)
{
    try
    {
        delete(generator);
    }
    catch(rocrand_status status)
    {
        return status;
    }
    return ROCRAND_STATUS_SUCCESS;
}

rocrand_status ROCRANDAPI
rocrand_generate(rocrand_generator generator,
                 unsigned int * output_data, size_t n)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate(output_data, n);
    }
    else if(generator->rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
    {
        rocrand_mrg32k3a * mrg32k3a_generator =
            static_cast<rocrand_mrg32k3a *>(generator);
        return mrg32k3a_generator->generate(output_data, n);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_uniform(rocrand_generator generator,
                         float * output_data, size_t n)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_uniform(output_data, n);
    }
    else if(generator->rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
    {
        rocrand_mrg32k3a * mrg32k3a_generator =
            static_cast<rocrand_mrg32k3a *>(generator);
        return mrg32k3a_generator->generate_uniform(output_data, n);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_uniform_double(rocrand_generator generator,
                                double * output_data, size_t n)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_uniform(output_data, n);
    }
    else if(generator->rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
    {
        rocrand_mrg32k3a * mrg32k3a_generator =
            static_cast<rocrand_mrg32k3a *>(generator);
        return mrg32k3a_generator->generate_uniform(output_data, n);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_normal(rocrand_generator generator,
                        float * output_data, size_t n,
                        float mean, float stddev)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_normal(output_data, n,
                                                        stddev, mean);
    }
    else if(generator->rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
    {
        rocrand_mrg32k3a * mrg32k3a_generator =
            static_cast<rocrand_mrg32k3a *>(generator);
        return mrg32k3a_generator->generate_normal(output_data, n,
                                                   stddev, mean);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_normal_double(rocrand_generator generator,
                 double * output_data, size_t n,
                 double mean, double stddev)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_normal(output_data, n,
                                                        stddev, mean);
    }
    else if(generator->rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
    {
        rocrand_mrg32k3a * mrg32k3a_generator =
            static_cast<rocrand_mrg32k3a *>(generator);
        return mrg32k3a_generator->generate_normal(output_data, n,
                                                   stddev, mean);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_log_normal(rocrand_generator generator,
                            float * output_data, size_t n,
                            float mean, float stddev)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_log_normal(output_data, n,
                                                            stddev, mean);
    }
    else if(generator->rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
    {
        rocrand_mrg32k3a * mrg32k3a_generator =
            static_cast<rocrand_mrg32k3a *>(generator);
        return mrg32k3a_generator->generate_log_normal(output_data, n,
                                                       stddev, mean);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_log_normal_double(rocrand_generator generator,
                                   double * output_data, size_t n,
                                   double mean, double stddev)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_log_normal(output_data, n,
                                                            stddev, mean);
    }
    else if(generator->rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
    {
        rocrand_mrg32k3a * mrg32k3a_generator =
            static_cast<rocrand_mrg32k3a *>(generator);
        return mrg32k3a_generator->generate_log_normal(output_data, n,
                                                       stddev, mean);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_generate_poisson(rocrand_generator generator,
                         unsigned int * output_data, size_t n,
                         double lambda)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }
    if (lambda <= 0.0)
    {
        return ROCRAND_STATUS_OUT_OF_RANGE;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        rocrand_philox4x32_10 * philox4x32_10_generator =
            static_cast<rocrand_philox4x32_10 *>(generator);
        return philox4x32_10_generator->generate_poisson(output_data, n,
                                                         lambda);
    }
    else if(generator->rng_type == ROCRAND_RNG_PSEUDO_MRG32K3A)
    {
        rocrand_mrg32k3a * mrg32k3a_generator =
            static_cast<rocrand_mrg32k3a *>(generator);
        return mrg32k3a_generator->generate_poisson(output_data, n,
                                                    lambda);
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_set_stream(rocrand_generator generator, hipStream_t stream)
{
    if(generator == NULL)
    {
        return ROCRAND_STATUS_NOT_INITIALIZED;
    }

    if(generator->rng_type == ROCRAND_RNG_PSEUDO_PHILOX4_32_10)
    {
        static_cast<rocrand_philox4x32_10 *>(generator)->set_stream(stream);
        return ROCRAND_STATUS_SUCCESS;
    }
    return ROCRAND_STATUS_TYPE_ERROR;
}

rocrand_status ROCRANDAPI
rocrand_get_version(int * version)
{
    if(version == NULL)
    {
        return ROCRAND_STATUS_OUT_OF_RANGE;
    }

    *version = ROCRAND_VERSION;
    return ROCRAND_STATUS_SUCCESS;
}

#if defined(__cplusplus)
}
#endif /* __cplusplus */
<|endoftext|>


<commit_before>/**@addtogroup Probe Test whether a given port on a host is connectable.
 * @{@file
 *
 * This application attempts to connect to a server and port, and just returns
 * the status as a result to the invoker.
 *
 * @author Nigel Bree <nigel.bree@gmail.com>
 *
 * Copyright (C) 2011 Nigel Bree; All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <winsock2.h>
#include <ws2tcpip.h>

/**
 * Simple command-line argument extraction, about as unsophisticated as it can
 * possibly get.
 */

wchar_t * split (wchar_t * args) {
        if (args == 0)
                return args;

        /*
         * The argument is quoted (which is typical of the first argument, the
         * program name, because of the need to avoid problems with spaces in
         * the path), in which case we skip to the ending quote first.
         */

        if (* args == '"') {
                for (;;) {
                        ++ args;
                        wchar_t         ch = * args;
                        if (ch == '"')
                                break;

                        if (ch == 0)
                                return 0;
                }
        }

        /*
         * Split at the next space.
         */

        for (;;) {
                wchar_t         ch = * args;
                if (ch == ' ')
                        break;

                if (ch == 0)
                        return 0;
                ++ args;
        }

        * args = 0;
        ++ args;

        /*
         * If there are additional spaces, consume them.
         */

        while (* args == ' ')
                ++ args;

        return args;
}

/**
 * If we're asked to probe for an NTTP port, then sometimes we have to deal
 * with local proxies.
 *
 * In this case, we actually try and read from the socket to at least get the
 * server's initial hello. For the annoying Avast! proxy, that at least does
 * not get sent until the real target responds to the proxy, and if the proxy
 * connection doesn't work (after 5-6 seconds, since it tries the TLS version
 * of the port even if we connected plain-text) then it spits a 400 out.
 */

int checkNntp (SOCKET s) {
        char            buf [128];
        int             result;
        result = recv (s, buf, sizeof (buf), 0);
        if (result < 5)
                return 1;

        /*
         * Various tedious socket-isms can apply, such as the bytes for the
         * initial response code trickling in over time. Let's not worry
         * about that, just deal with the basics.
         */

        void          * end = memchr (buf, ' ', result);
        if (end == 0)
                return 1;

        return memcmp (buf, "400", 3) == 0 ? 1 : 0;
}

/**
 * If we're asked to probe for an HTTP port, then we need to avoid problems
 * with local proxies.
 *
 * Unlike NNTP, the HTTP protocol is client-driven; as it turns out the way the
 * crappy Avast! proxy works is that it'll unilaterally close the connection if
 * it can't reach the real intended target, but in order to have this work for
 * real targets it pays to request a resource. The safest thing to ask for seems
 * to be favicon.ico - it's something lots of browsers request anyway and it's
 * almost always a small image, so we shouldn't clog up logs with requests for
 * 404 resources or get elaborate 404 response pages back.
 */

int checkHttp (SOCKET s, HANDLE show) {
static  char            head [] = "HEAD /favicon.ico HTTP/1.0\n\n";
        int             result;
        int             length = strlen (head);
        result = send (s, head, length, 0);
        if (result < length)
                return 1;

        char            buf [1024];
        result = recv (s, buf, sizeof (buf), 0);

        /*
         * Show the HTTP response, for debugging.
         */

        if (result > 0 && show > 0) {
                HANDLE          err = GetStdHandle (STD_ERROR_HANDLE);
                unsigned long   written = 0;
                WriteFile (err, buf, result, & written, 0);
        }

        return result < 5 ? 1 : 0;
}

/**
 * Probe for the indicated port at the given host.
 */

int probe (wchar_t * host, wchar_t * port, HANDLE show) {
        /*
         * Detect the presence of the Avast! virus scanner; it includes a set
         * of proxy-type firewalls that are somewhat tedious to deal with, and
         * in the case of NNTP mean that NNTP connections go through their
         * proxy; so, our connect will succeed (being locally looped back) and
         * send us nothing while the proxy module slowly decides whether it can
         * or can't connect to the real target over TLS or plain-text NNTP.
         *
         * So, if Avast! is present we can choose to either try and read from
         * the socket once it connects (so we can get the response code, which
         * will generally be 400 once the Avast proxy fails), or we can forget
         * the whole probing process because that introduces too much delay.
         */

        HMODULE         avast = GetModuleHandle (L"snxhk.dll");

        WSADATA         wsaData;
        if (WSAStartup (MAKEWORD (2, 2), & wsaData) != 0)
                return 2;

        SOCKET          s;
        s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s == SOCKET_ERROR)
                return 2;

        sockaddr_in     any;
        any.sin_family = AF_INET;
        any.sin_port = 0;
        any.sin_addr.S_un.S_addr = INADDR_ANY;
        if (bind (s, (sockaddr *) & any, sizeof (any)) != 0)
                return 2;

        /*
         * Look up the hostname and convert the port number into numeric form,
         * all handily in one function.
         */

        ADDRINFOW     * address;
        if (GetAddrInfoW (host, port, 0, & address) != 0)
                return 2;

        /*
         * Just test whether the port is open or not.
         */

        int             result;
        result = connect (s, address->ai_addr, address->ai_addrlen) ? 1 : 0;

        /*
         * Decide whether to actually wait for data, if we're dealing with the
         * Avast! proxy being present on a system.
         */

        sockaddr_in   * addr = (sockaddr_in *) address->ai_addr;
        switch (htons (addr->sin_port)) {
        case 119:
                if (avast && result == 0)
                        result = checkNntp (s);
                break;

        case 80:
                if (avast && result == 0)
                        result = checkHttp (s, show);
                break;

        default:
                break;
        }

        return result;
}

/**
 * This is intended as a "naked" WinMain without the Visual C++ run-time
 * at all (not just avoiding the broken locale machinery).
 */

int CALLBACK myWinMain (void) {
        HANDLE          err = GetStdHandle (STD_ERROR_HANDLE);
        unsigned long   written = 0;

        /*
         * Since we're not using the regular C machinery, get and split the
         * command line by hand. The CommandLineToArgvW () routine would do the
         * normal conversion to C style for us, but that depends on SHELL32.DLL
         * and we shouldn't need it.
         */

        wchar_t       * base = GetCommandLineW ();
        wchar_t       * name = split (base);
        wchar_t       * port = split (name);
        wchar_t       * extra = split (port);
        if (port == 0)
                return 2;

        int             result = probe (name, port, err);

        if (extra == 0)
                ExitProcess (result);

static  const char      text [] = "Probe result: ";
        WriteFile (err, text, strlen (text), & written, 0);

        char            buf [2] = { '0' + result };
        WriteFile (err, buf, 1, & written, 0);

        ExitProcess (result);
}
<commit_msg>Resolve another misfeature of the Avast! proxy in the probe assistant.<commit_after>/**@addtogroup Probe Test whether a given port on a host is connectable.
 * @{@file
 *
 * This application attempts to connect to a server and port, and just returns
 * the status as a result to the invoker.
 *
 * @author Nigel Bree <nigel.bree@gmail.com>
 *
 * Copyright (C) 2011 Nigel Bree; All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <winsock2.h>
#include <ws2tcpip.h>

/**
 * Simple command-line argument extraction, about as unsophisticated as it can
 * possibly get.
 */

wchar_t * split (wchar_t * args) {
        if (args == 0)
                return args;

        /*
         * The argument is quoted (which is typical of the first argument, the
         * program name, because of the need to avoid problems with spaces in
         * the path), in which case we skip to the ending quote first.
         */

        if (* args == '"') {
                for (;;) {
                        ++ args;
                        wchar_t         ch = * args;
                        if (ch == '"')
                                break;

                        if (ch == 0)
                                return 0;
                }
        }

        /*
         * Split at the next space.
         */

        for (;;) {
                wchar_t         ch = * args;
                if (ch == ' ')
                        break;

                if (ch == 0)
                        return 0;
                ++ args;
        }

        * args = 0;
        ++ args;

        /*
         * If there are additional spaces, consume them.
         */

        while (* args == ' ')
                ++ args;

        return args;
}

/**
 * If we're asked to probe for an NTTP port, then sometimes we have to deal
 * with local proxies.
 *
 * In this case, we actually try and read from the socket to at least get the
 * server's initial hello. For the annoying Avast! proxy, that at least does
 * not get sent until the real target responds to the proxy, and if the proxy
 * connection doesn't work (after 5-6 seconds, since it tries the TLS version
 * of the port even if we connected plain-text) then it spits a 400 out.
 */

int checkNntp (SOCKET s) {
        char            buf [128];
        int             result;
        result = recv (s, buf, sizeof (buf), 0);
        if (result < 5)
                return 1;

        /*
         * Various tedious socket-isms can apply, such as the bytes for the
         * initial response code trickling in over time. Let's not worry
         * about that, just deal with the basics.
         */

        void          * end = memchr (buf, ' ', result);
        if (end == 0)
                return 1;

        return memcmp (buf, "400", 3) == 0 ? 1 : 0;
}

/**
 * If we're asked to probe for an HTTP port, then we need to avoid problems
 * with local proxies.
 *
 * Unlike NNTP, the HTTP protocol is client-driven; as it turns out the way the
 * crappy Avast! proxy works is that it'll unilaterally close the connection if
 * it can't reach the real intended target, but in order to have this work for
 * real targets it pays to request a resource. The safest thing to ask for seems
 * to be favicon.ico - it's something lots of browsers request anyway and it's
 * almost always a small image, so we shouldn't clog up logs with requests for
 * 404 resources or get elaborate 404 response pages back.
 *
 * It turns out that the Avast! proxy has some other exciting misbehaviours; it
 * will sometimes (but not always) when a connection fails return an "HTTP/1.1
 * 200 OK" status with some fixed bogus fields, one of which is a "Refresh: 1;"
 * to re-fetch the target URL.
 */

int checkHttp (SOCKET s, HANDLE show) {
static  char            head [] = "HEAD /favicon.ico HTTP/1.0\n\n";
        int             result;
        int             length = strlen (head);
        result = send (s, head, length, 0);
        if (result < length)
                return 1;

        char            buf [1024];
        result = recv (s, buf, sizeof (buf) - 1, 0);

#if     1
        /*
         * Show the HTTP response, for debugging. I'll keep this in as long as
         * it doesn't cost me any compile-time space.
         */

        if (result > 0 && show > 0) {
                HANDLE          err = GetStdHandle (STD_ERROR_HANDLE);
                unsigned long   written = 0;
                WriteFile (err, buf, result, & written, 0);
        }
#endif

        /*
         * Normally we wouldn't care what the actual response text was, but to
         * deal with the fake response sometimes returned from Avast! I have to
         * recognize and suppress it.
         */

        if (result > 0) {
                buf [result] = 0;
                if (strstr (buf, "\nRefresh: 1;") != 0)
                        return 1;
        }

        return result < 5 ? 1 : 0;
}

/**
 * Probe for the indicated port at the given host.
 */

int probe (wchar_t * host, wchar_t * port, HANDLE show) {
        /*
         * Detect the presence of the Avast! virus scanner; it includes a set
         * of proxy-type firewalls that are somewhat tedious to deal with, and
         * in the case of NNTP mean that NNTP connections go through their
         * proxy; so, our connect will succeed (being locally looped back) and
         * send us nothing while the proxy module slowly decides whether it can
         * or can't connect to the real target over TLS or plain-text NNTP.
         *
         * So, if Avast! is present we can choose to either try and read from
         * the socket once it connects (so we can get the response code, which
         * will generally be 400 once the Avast proxy fails), or we can forget
         * the whole probing process because that introduces too much delay.
         */

        HMODULE         avast = GetModuleHandle (L"snxhk.dll");

        WSADATA         wsaData;
        if (WSAStartup (MAKEWORD (2, 2), & wsaData) != 0)
                return 2;

        SOCKET          s;
        s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s == SOCKET_ERROR)
                return 2;

        sockaddr_in     any;
        any.sin_family = AF_INET;
        any.sin_port = 0;
        any.sin_addr.S_un.S_addr = INADDR_ANY;
        if (bind (s, (sockaddr *) & any, sizeof (any)) != 0)
                return 2;

        /*
         * Look up the hostname and convert the port number into numeric form,
         * all handily in one function.
         */

        ADDRINFOW     * address;
        if (GetAddrInfoW (host, port, 0, & address) != 0)
                return 2;

        /*
         * Just test whether the port is open or not.
         */

        int             result;
        result = connect (s, address->ai_addr, address->ai_addrlen) ? 1 : 0;

        /*
         * Decide whether to actually wait for data, if we're dealing with the
         * Avast! proxy being present on a system.
         */

        sockaddr_in   * addr = (sockaddr_in *) address->ai_addr;
        switch (htons (addr->sin_port)) {
        case 119:
                if (avast && result == 0)
                        result = checkNntp (s);
                break;

        case 80:
                if (avast && result == 0)
                        result = checkHttp (s, show);
                break;

        default:
                break;
        }

        return result;
}

/**
 * This is intended as a "naked" WinMain without the Visual C++ run-time
 * at all (not just avoiding the broken locale machinery).
 */

int CALLBACK myWinMain (void) {
        HANDLE          err = GetStdHandle (STD_ERROR_HANDLE);
        unsigned long   written = 0;

        /*
         * Since we're not using the regular C machinery, get and split the
         * command line by hand. The CommandLineToArgvW () routine would do the
         * normal conversion to C style for us, but that depends on SHELL32.DLL
         * and we shouldn't need it.
         */

        wchar_t       * base = GetCommandLineW ();
        wchar_t       * name = split (base);
        wchar_t       * port = split (name);
        wchar_t       * extra = split (port);
        if (port == 0)
                return 2;

        int             result = probe (name, port, err);

        if (extra == 0)
                ExitProcess (result);

static  const char      text [] = "Probe result: ";
        WriteFile (err, text, strlen (text), & written, 0);

        char            buf [2] = { '0' + result };
        WriteFile (err, buf, 1, & written, 0);

        ExitProcess (result);
}
<|endoftext|>


<commit_before>// Ignore unused parameter warnings coming from cppunit headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/parallel_sync.h>

#include "test_comm.h"

#include <algorithm>

// THE CPPUNIT_TEST_SUITE_END macro expands to code that involves
// std::auto_ptr, which in turn produces -Wdeprecated-declarations
// warnings.  These can be ignored in GCC as long as we wrap the
// offending code in appropriate pragmas.  We can't get away with a
// single ignore_warnings.h inclusion at the beginning of this file,
// since the libmesh headers pull in a restore_warnings.h at some
// point.  We also don't bother restoring warnings at the end of this
// file since it's not a header.
#include <libmesh/ignore_warnings.h>

using namespace libMesh;

class ParallelSyncTest : public CppUnit::TestCase {
public:
  CPPUNIT_TEST_SUITE( ParallelSyncTest );

  CPPUNIT_TEST( testPush );

//  CPPUNIT_TEST( testPushOversized );

  CPPUNIT_TEST( testPull );

//  CPPUNIT_TEST( testPullOversized );

  CPPUNIT_TEST_SUITE_END();

public:
  void setUp()
  {}

  void tearDown()
  {}

  void testPushImpl(int M)
  {
    const int size = TestCommWorld->size(),
              rank = TestCommWorld->rank();

    // Data to send/recieve with each processor rank.  For this test,
    // processor p will send to destination d the integer d, in a
    // vector with sqrt(c)+1 copies, iff c := |p-d| is a square number.
    std::map<processor_id_type, std::vector<unsigned int> > data, received_data;

    for (int d=0; d != M; ++d)
      {
        int diffsize = std::abs(d-rank);
        int diffsqrt = std::sqrt(diffsize);
        if (diffsqrt*diffsqrt == diffsize)
          for (int i=-1; i != diffsqrt; ++i)
            data[d].push_back(d);
      }

    auto collect_data =
      [&received_data]
      (processor_id_type pid,
       const std::vector<unsigned int> & data)
      {
        received_data[pid] = data;
      };

    // Do the push
    Parallel::push_parallel_vector_data(*TestCommWorld, data, collect_data);

    // Test the received results, for each processor id p we're in
    // charge of.
    std::vector<std::size_t> checked_sizes(size, 0);
    for (int p=rank; p != M; p += size)
      for (int srcp=0; srcp != size; ++srcp)
        {
          int diffsize = std::abs(srcp-p);
          int diffsqrt = std::sqrt(diffsize);
          if (diffsqrt*diffsqrt != diffsize)
            {
              CPPUNIT_ASSERT_EQUAL(received_data.count(srcp), std::size_t(0));
              continue;
            }

          CPPUNIT_ASSERT_EQUAL(received_data.count(srcp), std::size_t(1));
          const std::vector<unsigned int> & datum = received_data[srcp];
          CPPUNIT_ASSERT_EQUAL(std::count(datum.begin(), datum.end(), p), std::ptrdiff_t(diffsqrt+1));
          checked_sizes[srcp] += diffsqrt+1;
        }

    for (int srcp=0; srcp != size; ++srcp)
      CPPUNIT_ASSERT_EQUAL(checked_sizes[srcp], received_data[srcp].size());
  }

  void testPush()
  {
    const int size = TestCommWorld->size();

    // Our sync functions are most typically used with a map of
    // processor ids that *only* includes ranks currently running.
    const int M = size;

    testPushImpl(M);
  }

  void testPushOversized()
  {
    const int size = TestCommWorld->size();

    // Our sync functions need to support sending to ranks that don't
    // exist!  If we're on N processors but working on a mesh
    // partitioned into M parts with M > N, then subpartition p
    // belongs to processor p%N.  Let's make M > N here.
    const int M = (size + 4) * 2;

    testPushImpl(M);
  }

  void testPullImpl(int M)
  {
    const int size = TestCommWorld->size(),
              rank = TestCommWorld->rank();

    // Data to send/recieve with each processor rank.  For this test,
    // processor p will send to destination d the integer d, in a
    // vector with sqrt(c)+1 copies, iff c := |p-d| is a square number.
    std::map<processor_id_type, std::vector<unsigned int> > data, received_data;

    for (int d=0; d != M; ++d)
      {
        int diffsize = std::abs(d-rank);
        int diffsqrt = std::sqrt(diffsize);
        if (diffsqrt*diffsqrt == diffsize)
          for (int i=-1; i != diffsqrt; ++i)
            data[d].push_back(d);
      }

    auto compose_replies =
      []
      (processor_id_type pid,
       const std::vector<unsigned int> & query,
       std::vector<unsigned int> & response)
      {
        const std::size_t query_size = query.size();
        response.resize(query_size);
        for (unsigned int i=0; i != query_size; ++i)
          response[i] = query[i]*query[i];
      };

    auto collect_replies =
      [&received_data]
      (processor_id_type pid,
       const std::vector<unsigned int> & query,
       const std::vector<unsigned int> & response)
      {
        const std::size_t query_size = query.size();
        CPPUNIT_ASSERT_EQUAL(query_size, response.size());
        for (unsigned int i=0; i != query_size; ++i)
          {
            CPPUNIT_ASSERT_EQUAL(query[i]*query[i], response[i]);
          }
        received_data[pid] = response;
      };

    // Do the pull
    unsigned int * ex = nullptr;
    Parallel::pull_parallel_vector_data
      (*TestCommWorld, data, compose_replies, collect_replies, ex);

    // Test the received results, for each processor id p we're in
    // charge of.
    std::vector<std::size_t> checked_sizes(size, 0);
    for (int p=rank; p != M; p += size)
      for (int srcp=0; srcp != size; ++srcp)
        {
          int diffsize = std::abs(srcp-p);
          int diffsqrt = std::sqrt(diffsize);
          if (diffsqrt*diffsqrt != diffsize)
            {
              CPPUNIT_ASSERT_EQUAL(received_data.count(srcp), std::size_t(0));
              continue;
            }

          CPPUNIT_ASSERT_EQUAL(received_data.count(srcp), std::size_t(1));
          const std::vector<unsigned int> & datum = received_data[srcp];
          CPPUNIT_ASSERT_EQUAL(std::count(datum.begin(), datum.end(), p*p), std::ptrdiff_t(diffsqrt+1));
          checked_sizes[srcp] += diffsqrt+1;
        }

    for (int srcp=0; srcp != size; ++srcp)
      CPPUNIT_ASSERT_EQUAL(checked_sizes[srcp], received_data[srcp].size());
  }

  void testPull()
  {
    const int size = TestCommWorld->size();

    // Our sync functions are most typically used with a map of
    // processor ids that *only* includes ranks currently running.
    const int M = size;

    testPullImpl(M);
  }

  void testPullOversized()
  {
    const int size = TestCommWorld->size();

    // Our sync functions need to support sending to ranks that don't
    // exist!  If we're on N processors but working on a mesh
    // partitioned into M parts with M > N, then subpartition p
    // belongs to processor p%N.  Let's make M > N here.
    const int M = (size + 4) * 2;

    testPullImpl(M);
  }

};

CPPUNIT_TEST_SUITE_REGISTRATION( ParallelSyncTest );
<commit_msg>Add push-vectors-of-vectors unit test<commit_after>// Ignore unused parameter warnings coming from cppunit headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/parallel_sync.h>

#include "test_comm.h"

#include <algorithm>

// THE CPPUNIT_TEST_SUITE_END macro expands to code that involves
// std::auto_ptr, which in turn produces -Wdeprecated-declarations
// warnings.  These can be ignored in GCC as long as we wrap the
// offending code in appropriate pragmas.  We can't get away with a
// single ignore_warnings.h inclusion at the beginning of this file,
// since the libmesh headers pull in a restore_warnings.h at some
// point.  We also don't bother restoring warnings at the end of this
// file since it's not a header.
#include <libmesh/ignore_warnings.h>

using namespace libMesh;

class ParallelSyncTest : public CppUnit::TestCase {
public:
  CPPUNIT_TEST_SUITE( ParallelSyncTest );

  // Our sync functions are most typically used with a map of
  // processor ids that *only* includes ranks currently running.
  CPPUNIT_TEST( testPush );
  CPPUNIT_TEST( testPull );
  CPPUNIT_TEST( testPushVecVec );

  // Our sync functions need to support sending to ranks that don't
  // exist!  If we're on N processors but working on a mesh
  // partitioned into M parts with M > N, then subpartition p belongs
  // to processor p%N.  Let's make M > N for these tests.
//  CPPUNIT_TEST( testPushOversized );
//  CPPUNIT_TEST( testPullOversized );
//  CPPUNIT_TEST( testPushVecVecOversized );

  CPPUNIT_TEST_SUITE_END();

public:
  void setUp()
  {}

  void tearDown()
  {}

  void testPushImpl(int M)
  {
    const int size = TestCommWorld->size(),
              rank = TestCommWorld->rank();

    // Data to send/recieve with each processor rank.  For this test,
    // processor p will send to destination d the integer d, in a
    // vector with sqrt(c)+1 copies, iff c := |p-d| is a square number.
    std::map<processor_id_type, std::vector<unsigned int> > data, received_data;

    for (int d=0; d != M; ++d)
      {
        int diffsize = std::abs(d-rank);
        int diffsqrt = std::sqrt(diffsize);
        if (diffsqrt*diffsqrt == diffsize)
          for (int i=-1; i != diffsqrt; ++i)
            data[d].push_back(d);
      }

    auto collect_data =
      [&received_data]
      (processor_id_type pid,
       const std::vector<unsigned int> & data)
      {
        received_data[pid] = data;
      };

    // Do the push
    Parallel::push_parallel_vector_data(*TestCommWorld, data, collect_data);

    // Test the received results, for each processor id p we're in
    // charge of.
    std::vector<std::size_t> checked_sizes(size, 0);
    for (int p=rank; p != M; p += size)
      for (int srcp=0; srcp != size; ++srcp)
        {
          int diffsize = std::abs(srcp-p);
          int diffsqrt = std::sqrt(diffsize);
          if (diffsqrt*diffsqrt != diffsize)
            {
              CPPUNIT_ASSERT_EQUAL(received_data.count(srcp), std::size_t(0));
              continue;
            }

          CPPUNIT_ASSERT_EQUAL(received_data.count(srcp), std::size_t(1));
          const std::vector<unsigned int> & datum = received_data[srcp];
          CPPUNIT_ASSERT_EQUAL(std::count(datum.begin(), datum.end(), p), std::ptrdiff_t(diffsqrt+1));
          checked_sizes[srcp] += diffsqrt+1;
        }

    for (int srcp=0; srcp != size; ++srcp)
      CPPUNIT_ASSERT_EQUAL(checked_sizes[srcp], received_data[srcp].size());
  }

  void testPush()
  {
    testPushImpl(TestCommWorld->size());
  }

  void testPushOversized()
  {
    testPushImpl((TestCommWorld->size() + 4) * 2);
  }

  void testPullImpl(int M)
  {
    const int size = TestCommWorld->size(),
              rank = TestCommWorld->rank();

    // Data to send/recieve with each processor rank.  For this test,
    // processor p will send to destination d the integer d, in a
    // vector with sqrt(c)+1 copies, iff c := |p-d| is a square number.
    std::map<processor_id_type, std::vector<unsigned int> > data, received_data;

    for (int d=0; d != M; ++d)
      {
        int diffsize = std::abs(d-rank);
        int diffsqrt = std::sqrt(diffsize);
        if (diffsqrt*diffsqrt == diffsize)
          for (int i=-1; i != diffsqrt; ++i)
            data[d].push_back(d);
      }

    auto compose_replies =
      []
      (processor_id_type pid,
       const std::vector<unsigned int> & query,
       std::vector<unsigned int> & response)
      {
        const std::size_t query_size = query.size();
        response.resize(query_size);
        for (unsigned int i=0; i != query_size; ++i)
          response[i] = query[i]*query[i];
      };

    auto collect_replies =
      [&received_data]
      (processor_id_type pid,
       const std::vector<unsigned int> & query,
       const std::vector<unsigned int> & response)
      {
        const std::size_t query_size = query.size();
        CPPUNIT_ASSERT_EQUAL(query_size, response.size());
        for (unsigned int i=0; i != query_size; ++i)
          {
            CPPUNIT_ASSERT_EQUAL(query[i]*query[i], response[i]);
          }
        received_data[pid] = response;
      };

    // Do the pull
    unsigned int * ex = nullptr;
    Parallel::pull_parallel_vector_data
      (*TestCommWorld, data, compose_replies, collect_replies, ex);

    // Test the received results, for each processor id p we're in
    // charge of.
    std::vector<std::size_t> checked_sizes(size, 0);
    for (int p=rank; p != M; p += size)
      for (int srcp=0; srcp != size; ++srcp)
        {
          int diffsize = std::abs(srcp-p);
          int diffsqrt = std::sqrt(diffsize);
          if (diffsqrt*diffsqrt != diffsize)
            {
              CPPUNIT_ASSERT_EQUAL(received_data.count(srcp), std::size_t(0));
              continue;
            }

          CPPUNIT_ASSERT_EQUAL(received_data.count(srcp), std::size_t(1));
          const std::vector<unsigned int> & datum = received_data[srcp];
          CPPUNIT_ASSERT_EQUAL(std::count(datum.begin(), datum.end(), p*p), std::ptrdiff_t(diffsqrt+1));
          checked_sizes[srcp] += diffsqrt+1;
        }

    for (int srcp=0; srcp != size; ++srcp)
      CPPUNIT_ASSERT_EQUAL(checked_sizes[srcp], received_data[srcp].size());
  }

  void testPull()
  {
    testPullImpl(TestCommWorld->size());
  }

  void testPullOversized()
  {
    testPullImpl((TestCommWorld->size() + 4) * 2);
  }

  void testPushVecVecImpl(int M)
  {
    const int size = TestCommWorld->size(),
              rank = TestCommWorld->rank();

    // Data to send/recieve with each processor rank.  For this test,
    // processor p will send to destination d the integer d, in two
    // subvectors with sqrt(c) and 1 copies, iff c := |p-d| is a
    // square number.
    std::map<processor_id_type, std::vector<std::vector<unsigned int>>> data, received_data;

    for (int d=0; d != M; ++d)
      {
        int diffsize = std::abs(d-rank);
        int diffsqrt = std::sqrt(diffsize);
        if (diffsqrt*diffsqrt == diffsize)
          {
            data[d].resize(2);
            for (int i=-1; i != diffsqrt; ++i)
              data[d][0].push_back(d);
            data[d][1].push_back(d);
          }
      }

    auto collect_data =
      [&received_data]
      (processor_id_type pid,
       const std::vector<std::vector<unsigned int>> & data)
      {
        received_data[pid] = data;
      };

    // Do the push
    Parallel::push_parallel_vector_data(*TestCommWorld, data, collect_data);

    // Test the received results, for each processor id p we're in
    // charge of.
    std::vector<std::size_t> checked_sizes(size, 0);
    for (int p=rank; p != M; p += size)
      for (int srcp=0; srcp != size; ++srcp)
        {
          int diffsize = std::abs(srcp-p);
          int diffsqrt = std::sqrt(diffsize);
          if (diffsqrt*diffsqrt != diffsize)
            {
              CPPUNIT_ASSERT_EQUAL(received_data.count(srcp), std::size_t(0));
              continue;
            }

          CPPUNIT_ASSERT_EQUAL(received_data.count(srcp), std::size_t(1));
          CPPUNIT_ASSERT_EQUAL(received_data[srcp].size(), std::size_t(2));
          const std::vector<unsigned int> & datum = received_data[srcp][0];
          CPPUNIT_ASSERT_EQUAL(std::count(datum.begin(), datum.end(), p), std::ptrdiff_t(diffsqrt+1));
          checked_sizes[srcp] += diffsqrt+1;
          CPPUNIT_ASSERT_EQUAL(received_data[srcp][1].size(), std::size_t(1));
          CPPUNIT_ASSERT_EQUAL(int(received_data[srcp][1][0]), p);
        }

    for (int srcp=0; srcp != size; ++srcp)
      CPPUNIT_ASSERT_EQUAL(checked_sizes[srcp], received_data[srcp].size());
  }

  void testPushVecVec()
  {
    testPushVecVecImpl(TestCommWorld->size());
  }

  void testPushVecVecOversized()
  {
    testPushVecVecImpl((TestCommWorld->size() + 4) * 2);
  }

};

CPPUNIT_TEST_SUITE_REGISTRATION( ParallelSyncTest );
<|endoftext|>


<commit_before>/*
 * =========================================================================================
 * Name        : processData.cpp
 * Description : student code for Assignment 1 - Data structures and Algorithms - Fall 2017
 * =========================================================================================
 */
#include "eventLib.h"
#include "dbLib.h"
#define ID_MAX_LENGTH   10

bool processEvent(ninjaEvent_t& event, L1List<NinjaInfo_t>& nList,void* pGData)  {
    // TODO: Your code comes here

    /// NOTE: The output of the event will be printed on one line
    /// end by the endline character.
    return true;
}

void processEvent_0(){

}

void processEvent_1(L1List<NinjaInfo_t>& nList){
	cout << "1:" << nList.getHead()->data.id << endl;
}

void processEvent_2(L1List<NinjaInfo_t>& nList){
	cout <<"2:" << nList.getLast()->data.id <<endl;
}

void processEvent_3(L1List<NinjaInfo_t>& nList){
	L1List<char[ID_MAX_LENGTH]>* ninjaid = new L1List<char[ID_MAX_LENGTH]>();
}

<commit_msg>small update processData<commit_after>/*
 * =========================================================================================
 * Name        : processData.cpp
 * Description : student code for Assignment 1 - Data structures and Algorithms - Fall 2017
 * =========================================================================================
 */
#include "eventLib.h"
#include "dbLib.h"
#define ID_MAX_LENGTH   10

bool processEvent(ninjaEvent_t& event, L1List<NinjaInfo_t>& nList,void* pGData)  {
    // TODO: Your code comes here

    /// NOTE: The output of the event will be printed on one line
    /// end by the endline character.
    return true;
}

void processEvent_0(){

}

void processEvent_1(L1List<NinjaInfo_t>& nList){
	cout << "1:" << nList.getHead()->data.id << endl;
}

void processEvent_2(L1List<NinjaInfo_t>& nList){
	cout <<"2:" << nList.getLast()->data.id <<endl;
}

void processEvent_3(L1List<NinjaInfo_t>& nList){
	L1List<NinjaInfo_t> ninjaid;
	L1Item<NinjaInfo_t>* pHead_id = ninjaid.getHead();// lay con tro head cua list id
	L1Item<NinjaInfo_t>* temp = pHead_id;
	L1Item<NinjaInfo_t>* pHead = nList.getHead();// lay con tro head cua list ninjainfo nList
	unsigned int size;
	while(pHead){
		while(temp){
			if(strcmp(pHead->data.id,temp->data.id) == 0) break;
			temp = temp->pNext;
		}
		if(temp == NULL) ninjaid.push_back(pHead->data);
		pHead = pHead->pNext;
	}
	size = ninjaid.getSize();
	cout <<"3:"<<size<<endl;
}

<|endoftext|>


<commit_before>/*
    Hash Map and hash support functions.
    Copyright (C) 2000 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include <string.h>
#include "cssysdef.h"
#include "csutil/hashmap.h"

//-----------------------------------------------------------------------------

inline static csHashKey rotate_bits_right_3(csHashKey h)
{
  return (h >> 3) | (h << 29);
}

csHashKey csHashCompute(char const* s, int n)
{
  csHashKey h = 0;
  char const* slim = s + n;
  while (s < slim)
    h = rotate_bits_right_3(h) + *s++;
  return h;
}

csHashKey csHashCompute(char const* s)
{
  csHashKey h = 0;
  while (*s != 0)
    h = rotate_bits_right_3(h) + *s++;
  return h;
}

//-----------------------------------------------------------------------------

csHashIterator::csHashIterator (csHashMap *hm)
{
  hash = hm;
  bucket = NULL;
  element_index = 0;
  bucket_index = (uint32)-1;
  do_iterate_key = false;
  GotoNextElement ();
}

csHashIterator::csHashIterator (csHashMap *hm, csHashKey hkey)
{
  uint32 idx = key % hm->NumBuckets;

  hash = hm;
  bucket = hm->Buckets[idx]; // NULL if bucket is empty.
  element_index = -1;
  bucket_index = idx;
  key = hkey;
  do_iterate_key = true;
  GotoNextSameKey ();
}

bool csHashIterator::HasNext ()
{
  return bucket != NULL;
}

void csHashIterator::GotoNextElement ()
{
  element_index++;
  if (!bucket || element_index >= bucket->Length ())
  {
    // Next bucket.
    bucket_index++;
    uint32 const nbuckets = (uint32)hash->Buckets.Length();
    while (bucket_index < nbuckets && !hash->Buckets[bucket_index])
      bucket_index++;
    if (bucket_index >= nbuckets)
      bucket = NULL;	// The end
    else
    {
      bucket = hash->Buckets[bucket_index];
      element_index = 0;
    }
  }
}

void csHashIterator::GotoNextSameKey ()
{
  if (!bucket) return;
  element_index++;
  while (element_index < bucket->Length () &&
  	bucket->Get(element_index)->key != key)
  {
    element_index++;
  }
  if (element_index >= bucket->Length ()) bucket = NULL;
}

csHashObject csHashIterator::Next ()
{
  if (bucket == NULL) return NULL;
  csHashObject obj = ((csHashElement*)((*bucket)[element_index]))->object;
  if (do_iterate_key) GotoNextSameKey ();
  else GotoNextElement ();
  return obj;
}

void csHashIterator::DeleteNext ()
{
  // @@@ Not yet implemented.
}

//-----------------------------------------------------------------------------

csHashMap::csHashMap (uint32 size)
{
  NumBuckets = size;
  Buckets.SetLength (size);
  for (uint32 i = 0 ; i < size ; i++)
    Buckets[i] = NULL;
}

csHashMap::~csHashMap ()
{
  DeleteAll ();
}

void csHashMap::Put (csHashKey key, csHashObject object)
{
  uint32 idx = key % NumBuckets;
  if (!Buckets[idx]) Buckets[idx] = new csHashBucket ();
  csHashBucket* bucket = Buckets[idx];
  csHashElement* element = new csHashElement ();
  element->key = key;
  element->object = object;
  bucket->Push (element);
}

csHashObject csHashMap::Get (csHashKey key) const
{
  uint32 idx = key % NumBuckets;
  if (!Buckets[idx]) return NULL;
  csHashBucket* bucket = Buckets[idx];
  for (int i = 0 ; i < bucket->Length () ; i++)
  {
    csHashElement* element = bucket->Get(i);
    if (element->key == key) return element->object;
  }
  return NULL;
}

void csHashMap::DeleteAll (csHashKey key)
{
  uint32 idx = key % NumBuckets;
  if (!Buckets[idx]) return;
  csHashBucket* bucket = Buckets[idx];
  for (uint32 i = bucket->Length () ; i-- > 0 ; )
  {
    csHashElement* element = bucket->Get(i);
    if (element->key == key)
      bucket->Delete (i);
  }
}

void csHashMap::DeleteAll ()
{
  for (uint32 b = Buckets.Length () ; b-- > 0 ; )
  {
    delete Buckets[b];
    Buckets[b] = NULL;
  }
}

//-----------------------------------------------------------------------------

csHashSet::csHashSet (uint32 size) : map (size)
{
}

void csHashSet::Add (csHashObject object)
{
  if (In (object)) return;
  AddNoTest (object);
}

void csHashSet::AddNoTest (csHashObject object)
{
  csHashKey key = (csHashKey)object;
  map.Put (key, object);
}

bool csHashSet::In (csHashObject object)
{
  csHashKey key = (csHashKey)object;
  csHashIterator it (&map, key);
  while (it.HasNext ())
  {
    csHashObject obj = it.Next ();
    if (obj == object)
      return true;
  }
  return false;
}

void csHashSet::DeleteAll ()
{
  map.DeleteAll ();
}

void csHashSet::Delete (csHashObject)
{
}
<commit_msg>fixed a bug in the hashmap iterator code<commit_after>/*
    Hash Map and hash support functions.
    Copyright (C) 2000 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include <string.h>
#include "cssysdef.h"
#include "csutil/hashmap.h"

//-----------------------------------------------------------------------------

inline static csHashKey rotate_bits_right_3(csHashKey h)
{
  return (h >> 3) | (h << 29);
}

csHashKey csHashCompute(char const* s, int n)
{
  csHashKey h = 0;
  char const* slim = s + n;
  while (s < slim)
    h = rotate_bits_right_3(h) + *s++;
  return h;
}

csHashKey csHashCompute(char const* s)
{
  csHashKey h = 0;
  while (*s != 0)
    h = rotate_bits_right_3(h) + *s++;
  return h;
}

//-----------------------------------------------------------------------------

csHashIterator::csHashIterator (csHashMap *hm)
{
  hash = hm;
  bucket = NULL;
  element_index = 0;
  bucket_index = (uint32)-1;
  do_iterate_key = false;
  GotoNextElement ();
}

csHashIterator::csHashIterator (csHashMap *hm, csHashKey hkey)
{
  uint32 idx = hkey % hm->NumBuckets;

  hash = hm;
  bucket = hm->Buckets[idx]; // NULL if bucket is empty.
  element_index = -1;
  bucket_index = idx;
  key = hkey;
  do_iterate_key = true;
  GotoNextSameKey ();
}

bool csHashIterator::HasNext ()
{
  return bucket != NULL;
}

void csHashIterator::GotoNextElement ()
{
  element_index++;
  if (!bucket || element_index >= bucket->Length ())
  {
    // Next bucket.
    bucket_index++;
    uint32 const nbuckets = (uint32)hash->Buckets.Length();
    while (bucket_index < nbuckets && !hash->Buckets[bucket_index])
      bucket_index++;
    if (bucket_index >= nbuckets)
      bucket = NULL;	// The end
    else
    {
      bucket = hash->Buckets[bucket_index];
      element_index = 0;
    }
  }
}

void csHashIterator::GotoNextSameKey ()
{
  if (!bucket) return;
  element_index++;
  while (element_index < bucket->Length () &&
  	bucket->Get(element_index)->key != key)
  {
    element_index++;
  }
  if (element_index >= bucket->Length ()) bucket = NULL;
}

csHashObject csHashIterator::Next ()
{
  if (bucket == NULL) return NULL;
  csHashObject obj = ((csHashElement*)((*bucket)[element_index]))->object;
  if (do_iterate_key) GotoNextSameKey ();
  else GotoNextElement ();
  return obj;
}

void csHashIterator::DeleteNext ()
{
  // @@@ Not yet implemented.
}

//-----------------------------------------------------------------------------

csHashMap::csHashMap (uint32 size)
{
  NumBuckets = size;
  Buckets.SetLength (size);
  for (uint32 i = 0 ; i < size ; i++)
    Buckets[i] = NULL;
}

csHashMap::~csHashMap ()
{
  DeleteAll ();
}

void csHashMap::Put (csHashKey key, csHashObject object)
{
  uint32 idx = key % NumBuckets;
  if (!Buckets[idx]) Buckets[idx] = new csHashBucket ();
  csHashBucket* bucket = Buckets[idx];
  csHashElement* element = new csHashElement ();
  element->key = key;
  element->object = object;
  bucket->Push (element);
}

csHashObject csHashMap::Get (csHashKey key) const
{
  uint32 idx = key % NumBuckets;
  if (!Buckets[idx]) return NULL;
  csHashBucket* bucket = Buckets[idx];
  for (int i = 0 ; i < bucket->Length () ; i++)
  {
    csHashElement* element = bucket->Get(i);
    if (element->key == key) return element->object;
  }
  return NULL;
}

void csHashMap::DeleteAll (csHashKey key)
{
  uint32 idx = key % NumBuckets;
  if (!Buckets[idx]) return;
  csHashBucket* bucket = Buckets[idx];
  for (uint32 i = bucket->Length () ; i-- > 0 ; )
  {
    csHashElement* element = bucket->Get(i);
    if (element->key == key)
      bucket->Delete (i);
  }
}

void csHashMap::DeleteAll ()
{
  for (uint32 b = Buckets.Length () ; b-- > 0 ; )
  {
    delete Buckets[b];
    Buckets[b] = NULL;
  }
}

//-----------------------------------------------------------------------------

csHashSet::csHashSet (uint32 size) : map (size)
{
}

void csHashSet::Add (csHashObject object)
{
  if (In (object)) return;
  AddNoTest (object);
}

void csHashSet::AddNoTest (csHashObject object)
{
  csHashKey key = (csHashKey)object;
  map.Put (key, object);
}

bool csHashSet::In (csHashObject object)
{
  csHashKey key = (csHashKey)object;
  csHashIterator it (&map, key);
  while (it.HasNext ())
  {
    csHashObject obj = it.Next ();
    if (obj == object)
      return true;
  }
  return false;
}

void csHashSet::DeleteAll ()
{
  map.DeleteAll ();
}

void csHashSet::Delete (csHashObject)
{
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief memory mapped files in posix
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Oreste Costa-Panaia
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "memory-map.h"

#ifdef TRI_HAVE_POSIX_MMAP

#include "Basics/logging.h"
#include "Basics/tri-strings.h"

#include <sys/mman.h>

////////////////////////////////////////////////////////////////////////////////
// @brief flush memory mapped file to disk
////////////////////////////////////////////////////////////////////////////////

int TRI_FlushMMFile (int fileDescriptor,
                     void* startingAddress,
                     size_t numOfBytesToFlush,
                     int flags) {

  // ...........................................................................
  // Possible flags to send are (based upon the Ubuntu Linux ASM include files:
  // #define MS_ASYNC        1             /* sync memory asynchronously */
  // #define MS_INVALIDATE   2               /* invalidate the caches */
  // #define MS_SYNC         4               /* synchronous memory sync */
  // Note: under windows all flushes are achieved synchronously
  // ...........................................................................

  int res = msync(startingAddress, numOfBytesToFlush, flags);

#ifdef __APPLE__
  if (res == 0) {
    res = fcntl(fileDescriptor, F_FULLFSYNC, 0);
  }
#endif

  if (res == 0) {
    // msync was successful
    return TRI_ERROR_NO_ERROR;
  }

  if (errno == ENOMEM) {
    // we have synced a region that was not mapped

    // set a special error. ENOMEM (out of memory) is not appropriate
    LOG_ERROR("msync failed for range %p - %p", startingAddress, (void*) (((char*) startingAddress) + numOfBytesToFlush));

    return TRI_ERROR_ARANGO_MSYNC_FAILED;
  }

  return TRI_ERROR_SYS_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
// @brief memory map a file
////////////////////////////////////////////////////////////////////////////////

int TRI_MMFile (void* memoryAddress,
                size_t numOfBytesToInitialize,
                int memoryProtection,
                int flags,
                int fileDescriptor,
                void** mmHandle,
                int64_t offset,
                void** result) {

  TRI_ASSERT(memoryAddress == nullptr);
  off_t offsetRetyped = (off_t) offset;
  TRI_ASSERT(offsetRetyped == 0);

  *mmHandle = nullptr; // only useful for Windows

  *result = mmap(memoryAddress, numOfBytesToInitialize, memoryProtection, flags, fileDescriptor, offsetRetyped);

  if (*result != MAP_FAILED) {
    return TRI_ERROR_NO_ERROR;
  }

  if (errno == ENOMEM) {
    return TRI_ERROR_OUT_OF_MEMORY_MMAP;
  }

  return TRI_ERROR_SYS_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
// @brief unmap a memory-mapped file
////////////////////////////////////////////////////////////////////////////////

int TRI_UNMMFile (void* memoryAddress,
                  size_t numOfBytesToUnMap,
                  int fileDescriptor,
                  void** mmHandle) {
  TRI_ASSERT(*mmHandle == nullptr); // only useful for Windows

  int res = munmap(memoryAddress, numOfBytesToUnMap);

  if (res == 0) {
    return TRI_ERROR_NO_ERROR;
  }

  if (errno == ENOSPC) {
    return TRI_ERROR_ARANGO_FILESYSTEM_FULL;
  }
  if (errno == ENOMEM) {
    return TRI_ERROR_OUT_OF_MEMORY_MMAP;
  }

  return TRI_ERROR_SYS_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
// @brief protect a region in a memory-mapped file
////////////////////////////////////////////////////////////////////////////////

int TRI_ProtectMMFile (void* memoryAddress,
                       size_t numOfBytesToProtect,
                       int flags,
                       int fileDescriptor,
                       void** mmHandle) {
  TRI_ASSERT(*mmHandle == nullptr); // only useful for Windows

  int res = mprotect(memoryAddress, numOfBytesToProtect, flags);

  if (res == 0) {
    return TRI_ERROR_NO_ERROR;
  }

  return TRI_ERROR_SYS_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief gives hints about upcoming sequential memory usage
////////////////////////////////////////////////////////////////////////////////

int TRI_MMFileAdvise (void* memoryAddress, size_t numOfBytes, int advice) {
#ifdef __linux__
  LOG_DEBUG("Doing madvise %d for %lu length %lu", advice,
            (uint64_t) memoryAddress, numOfBytes);
  int res = madvise(memoryAddress, numOfBytes, advice);

  if (res == 0) {
    return TRI_ERROR_NO_ERROR;
  }
  else {
    char buffer[256];
    char* p = strerror_r(errno, buffer, 256);
    LOG_INFO("madvise %d for %lu length %lu failed with: %s ",
             advice, (uint64_t) memoryAddress, numOfBytes, p);
    return TRI_ERROR_INTERNAL;
  }
#else
  return TRI_ERROR_NO_ERROR;
#endif
}

#endif

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>fix compiler warnings on 32bit<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief memory mapped files in posix
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Oreste Costa-Panaia
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "memory-map.h"

#ifdef TRI_HAVE_POSIX_MMAP

#include "Basics/logging.h"
#include "Basics/tri-strings.h"

#include <sys/mman.h>

////////////////////////////////////////////////////////////////////////////////
// @brief flush memory mapped file to disk
////////////////////////////////////////////////////////////////////////////////

int TRI_FlushMMFile (int fileDescriptor,
                     void* startingAddress,
                     size_t numOfBytesToFlush,
                     int flags) {

  // ...........................................................................
  // Possible flags to send are (based upon the Ubuntu Linux ASM include files:
  // #define MS_ASYNC        1             /* sync memory asynchronously */
  // #define MS_INVALIDATE   2               /* invalidate the caches */
  // #define MS_SYNC         4               /* synchronous memory sync */
  // Note: under windows all flushes are achieved synchronously
  // ...........................................................................

  int res = msync(startingAddress, numOfBytesToFlush, flags);

#ifdef __APPLE__
  if (res == 0) {
    res = fcntl(fileDescriptor, F_FULLFSYNC, 0);
  }
#endif

  if (res == 0) {
    // msync was successful
    return TRI_ERROR_NO_ERROR;
  }

  if (errno == ENOMEM) {
    // we have synced a region that was not mapped

    // set a special error. ENOMEM (out of memory) is not appropriate
    LOG_ERROR("msync failed for range %p - %p", startingAddress, (void*) (((char*) startingAddress) + numOfBytesToFlush));

    return TRI_ERROR_ARANGO_MSYNC_FAILED;
  }

  return TRI_ERROR_SYS_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
// @brief memory map a file
////////////////////////////////////////////////////////////////////////////////

int TRI_MMFile (void* memoryAddress,
                size_t numOfBytesToInitialize,
                int memoryProtection,
                int flags,
                int fileDescriptor,
                void** mmHandle,
                int64_t offset,
                void** result) {

  TRI_ASSERT(memoryAddress == nullptr);
  off_t offsetRetyped = (off_t) offset;
  TRI_ASSERT(offsetRetyped == 0);

  *mmHandle = nullptr; // only useful for Windows

  *result = mmap(memoryAddress, numOfBytesToInitialize, memoryProtection, flags, fileDescriptor, offsetRetyped);

  if (*result != MAP_FAILED) {
    return TRI_ERROR_NO_ERROR;
  }

  if (errno == ENOMEM) {
    return TRI_ERROR_OUT_OF_MEMORY_MMAP;
  }

  return TRI_ERROR_SYS_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
// @brief unmap a memory-mapped file
////////////////////////////////////////////////////////////////////////////////

int TRI_UNMMFile (void* memoryAddress,
                  size_t numOfBytesToUnMap,
                  int fileDescriptor,
                  void** mmHandle) {
  TRI_ASSERT(*mmHandle == nullptr); // only useful for Windows

  int res = munmap(memoryAddress, numOfBytesToUnMap);

  if (res == 0) {
    return TRI_ERROR_NO_ERROR;
  }

  if (errno == ENOSPC) {
    return TRI_ERROR_ARANGO_FILESYSTEM_FULL;
  }
  if (errno == ENOMEM) {
    return TRI_ERROR_OUT_OF_MEMORY_MMAP;
  }

  return TRI_ERROR_SYS_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
// @brief protect a region in a memory-mapped file
////////////////////////////////////////////////////////////////////////////////

int TRI_ProtectMMFile (void* memoryAddress,
                       size_t numOfBytesToProtect,
                       int flags,
                       int fileDescriptor,
                       void** mmHandle) {
  TRI_ASSERT(*mmHandle == nullptr); // only useful for Windows

  int res = mprotect(memoryAddress, numOfBytesToProtect, flags);

  if (res == 0) {
    return TRI_ERROR_NO_ERROR;
  }

  return TRI_ERROR_SYS_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief gives hints about upcoming sequential memory usage
////////////////////////////////////////////////////////////////////////////////

int TRI_MMFileAdvise (void* memoryAddress, size_t numOfBytes, int advice) {
#ifdef __linux__
  LOG_DEBUG("Doing madvise %d for %llu length %llu", advice,
            (unsigned long long) memoryAddress, (unsigned long long) numOfBytes);
  int res = madvise(memoryAddress, numOfBytes, advice);

  if (res == 0) {
    return TRI_ERROR_NO_ERROR;
  }
  else {
    char buffer[256];
    char* p = strerror_r(errno, buffer, 256);
    LOG_INFO("madvise %d for %llu length %llu failed with: %s ",
             advice, (unsigned long long) memoryAddress, (unsigned long long) numOfBytes, p);
    return TRI_ERROR_INTERNAL;
  }
#else
  return TRI_ERROR_NO_ERROR;
#endif
}

#endif

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>


<commit_before>/**
 *  Base.cpp
 *
 *  Implementation file for the base of all classes
 *
 *  @copyright 2014 - 2022 Copernica BV
 */
#include "includes.h"

/**
 *  Set up namespace
 */
namespace Php {

/**
 *  Overridable method that is called right before an object is destructed
 */
void Base::__destruct() const
{
    // destroy the object by default
    zend_objects_destroy_object(_impl->php());
}

/**
 *  Overridable method that is called to check if a property is set
 *
 *  The default implementation does nothing, and the script will fall back
 *  to accessing the regular object properties
 *
 *  @param  key
 *  @return bool
 */
bool Base::__isset(const Php::Value &key) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the unset function can be called
    throw NotImplemented();
}

/**
 *  Overridable method that is called to set a new property
 *
 *  The default implementation does nothing, and the script will fall back
 *  to accessing the regular object properties
 *
 *  @param  key
 *  @param  value
 */
void Base::__set(const Php::Value &key, const Php::Value &value) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the unset function can be called
    throw NotImplemented();
}

/**
 *  Retrieve a property
 *
 *  The default implementation does nothing, and the script will fall back
 *  to accessing the regular object properties
 *
 *  @param  key
 *  @return value
 */
Php::Value Base::__get(const Php::Value &key) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return nullptr;
}

/**
 *  Remove a member
 *
 *  The default implementation does nothing, and the script will fall back
 *  to accessing the regular object properties
 *
 *  @param key
 */
void Base::__unset(const Php::Value &key) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();
}

/**
 *  Call a method
 *
 *  This method is called when a method is called from the PHP script that
 *  was not explicitly defined. You can use this to catch variable method
 *  names, or to support all thinkable method names.
 *
 *  @param  method      Name of the method that was called
 *  @param  params      The parameters that were passed to the function
 *  @return Value       The return value
 */
Value Base::__call(const char *method, Parameters &params) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return nullptr;
}

/**
 *  Call the class as if it was a function
 *
 *  This method is called when a an object is used with () operators:
 *  $object(). You can override this method to make objects callable.
 *
 *  @param  params      The parameters that were passed to the function
 *  @return Value       The return value
 */
Value Base::__invoke(Parameters &params) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return nullptr;
}

/**
 *  Cast the object to a string
 *
 *  This method is called when an object is casted to a string, or when
 *  it is used in a string context
 *
 *  @return Value       The object as a string
 */
Value Base::__toString() const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return nullptr;
}

/**
 *  Cast the object to an integer
 *
 *  This method is called when an object is casted to an integer, or when
 *  it is used in an integer context
 *
 *  @return int         Integer value
 */
Value Base::__toInteger() const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return 0;
}

/**
 *  Cast the object to a float
 *
 *  This method is called when an object is casted to a float, or when it
 *  is used in a float context
 *
 *  @return double      Floating point value
 */
Value Base::__toFloat() const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return 0.0;
}

/**
 *  Cast the object to a boolean
 *
 *  This method is called when an object is casted to a bool, or when it
 *  is used in a boolean context
 *
 *  @return bool
 */
Value Base::__toBool() const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return false;
}

/**
 *  Compare the object with a different object
 *
 *  Check how a different object compares to this object
 *
 *  @param  that        Object to compare with
 *  @return int
 */
int Base::__compare(const Base &that) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return 1;
}

/**
 *  Method that is called when an explicit call to $object->serialize() is made
 *  Note that a call to serialize($object) does not end up in this function, but
 *  is handled by the user-space implementation of Serializable::serialize()).
 *  @return Php::Value
 */
Php::Value Base::__serialize()
{
    // 'this' refers to a Php::Base class, but we expect that is also implements the Serializable
    // interface (otherwise we would never have registered the __serialize function as a callback)
    auto *serializable = dynamic_cast<Serializable*>(this);

    // this one should not fail
    if (serializable == nullptr) return "";

    // pass the call to the interface
    return serializable->serialize();
}

/**
 *  Method that is called when an explicit call to $object->unserialize() is made
 *  Note that a call to unserialize($string) does not end up in this function, but
 *  is handled by the user-space implementation of Serializable::unserialize()).
 *  @param params       The passed parameters
 */
void Base::__unserialize(Php::Parameters &params)
{
    // 'this' refers to a Php::Base class, but we expect that is also implements the Serializable
    // interface (otherwise we would never have registered the __serialize function as a callback)
    auto *serializable = dynamic_cast<Serializable*>(this);

    // this one should not fail
    if (serializable == nullptr) return;

    // the passed in parameter
    Php::Value param = params[0];

    // make sure the parameter is indeed a string
    param.setType(Type::String);

    // pass the call to the interface
    serializable->unserialize(param.rawValue(), param.size());
}

/**
 *  Method that is called when an explicit call to $object->count() is made
 *  Note that a call to unserialize($string) does not end up in this function, but
 *  is handled by the user-space implementation of Serializable::count()).
 *  @param params       The passed parameters
 */
Php::Value Base::__count(Php::Parameters &params)
{
    // 'this' refers to a Php::Base class, but we expect that is also implements the Countable
    // interface (otherwise we would never have registered the __count function as a callback)
    auto *countable = dynamic_cast<Countable*>(this);

    // this one should not fail
    if (countable == nullptr) return -1;

    // pass the call to the interface
    return countable->count();
}

/**
 *  End namespace
 */
}

<commit_msg>when countable is not implemented, it is probably better to return 0<commit_after>/**
 *  Base.cpp
 *
 *  Implementation file for the base of all classes
 *
 *  @copyright 2014 - 2022 Copernica BV
 */
#include "includes.h"

/**
 *  Set up namespace
 */
namespace Php {

/**
 *  Overridable method that is called right before an object is destructed
 */
void Base::__destruct() const
{
    // destroy the object by default
    zend_objects_destroy_object(_impl->php());
}

/**
 *  Overridable method that is called to check if a property is set
 *
 *  The default implementation does nothing, and the script will fall back
 *  to accessing the regular object properties
 *
 *  @param  key
 *  @return bool
 */
bool Base::__isset(const Php::Value &key) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the unset function can be called
    throw NotImplemented();
}

/**
 *  Overridable method that is called to set a new property
 *
 *  The default implementation does nothing, and the script will fall back
 *  to accessing the regular object properties
 *
 *  @param  key
 *  @param  value
 */
void Base::__set(const Php::Value &key, const Php::Value &value) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the unset function can be called
    throw NotImplemented();
}

/**
 *  Retrieve a property
 *
 *  The default implementation does nothing, and the script will fall back
 *  to accessing the regular object properties
 *
 *  @param  key
 *  @return value
 */
Php::Value Base::__get(const Php::Value &key) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return nullptr;
}

/**
 *  Remove a member
 *
 *  The default implementation does nothing, and the script will fall back
 *  to accessing the regular object properties
 *
 *  @param key
 */
void Base::__unset(const Php::Value &key) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();
}

/**
 *  Call a method
 *
 *  This method is called when a method is called from the PHP script that
 *  was not explicitly defined. You can use this to catch variable method
 *  names, or to support all thinkable method names.
 *
 *  @param  method      Name of the method that was called
 *  @param  params      The parameters that were passed to the function
 *  @return Value       The return value
 */
Value Base::__call(const char *method, Parameters &params) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return nullptr;
}

/**
 *  Call the class as if it was a function
 *
 *  This method is called when a an object is used with () operators:
 *  $object(). You can override this method to make objects callable.
 *
 *  @param  params      The parameters that were passed to the function
 *  @return Value       The return value
 */
Value Base::__invoke(Parameters &params) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return nullptr;
}

/**
 *  Cast the object to a string
 *
 *  This method is called when an object is casted to a string, or when
 *  it is used in a string context
 *
 *  @return Value       The object as a string
 */
Value Base::__toString() const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return nullptr;
}

/**
 *  Cast the object to an integer
 *
 *  This method is called when an object is casted to an integer, or when
 *  it is used in an integer context
 *
 *  @return int         Integer value
 */
Value Base::__toInteger() const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return 0;
}

/**
 *  Cast the object to a float
 *
 *  This method is called when an object is casted to a float, or when it
 *  is used in a float context
 *
 *  @return double      Floating point value
 */
Value Base::__toFloat() const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return 0.0;
}

/**
 *  Cast the object to a boolean
 *
 *  This method is called when an object is casted to a bool, or when it
 *  is used in a boolean context
 *
 *  @return bool
 */
Value Base::__toBool() const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return false;
}

/**
 *  Compare the object with a different object
 *
 *  Check how a different object compares to this object
 *
 *  @param  that        Object to compare with
 *  @return int
 */
int Base::__compare(const Base &that) const
{
    // throw an exception that will be caught in the ClassBase class,
    // so that the default implementation of the function can be called
    throw NotImplemented();

    // unreachable code
    return 1;
}

/**
 *  Method that is called when an explicit call to $object->serialize() is made
 *  Note that a call to serialize($object) does not end up in this function, but
 *  is handled by the user-space implementation of Serializable::serialize()).
 *  @return Php::Value
 */
Php::Value Base::__serialize()
{
    // 'this' refers to a Php::Base class, but we expect that is also implements the Serializable
    // interface (otherwise we would never have registered the __serialize function as a callback)
    auto *serializable = dynamic_cast<Serializable*>(this);

    // this one should not fail
    if (serializable == nullptr) return "";

    // pass the call to the interface
    return serializable->serialize();
}

/**
 *  Method that is called when an explicit call to $object->unserialize() is made
 *  Note that a call to unserialize($string) does not end up in this function, but
 *  is handled by the user-space implementation of Serializable::unserialize()).
 *  @param params       The passed parameters
 */
void Base::__unserialize(Php::Parameters &params)
{
    // 'this' refers to a Php::Base class, but we expect that is also implements the Serializable
    // interface (otherwise we would never have registered the __serialize function as a callback)
    auto *serializable = dynamic_cast<Serializable*>(this);

    // this one should not fail
    if (serializable == nullptr) return;

    // the passed in parameter
    Php::Value param = params[0];

    // make sure the parameter is indeed a string
    param.setType(Type::String);

    // pass the call to the interface
    serializable->unserialize(param.rawValue(), param.size());
}

/**
 *  Method that is called when an explicit call to $object->count() is made
 *  Note that a call to unserialize($string) does not end up in this function, but
 *  is handled by the user-space implementation of Serializable::count()).
 *  @param params       The passed parameters
 */
Php::Value Base::__count(Php::Parameters &params)
{
    // 'this' refers to a Php::Base class, but we expect that is also implements the Countable
    // interface (otherwise we would never have registered the __count function as a callback)
    auto *countable = dynamic_cast<Countable*>(this);

    // this one should not fail
    if (countable == nullptr) return 0;

    // pass the call to the interface
    return countable->count();
}

/**
 *  End namespace
 */
}

<|endoftext|>