<commit_before>// Copyright (c) 2017 The Khronos Group Inc.
// Copyright (c) 2017 Valve Corporation
// Copyright (c) 2017 LunarG, Inc.
//
// 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.
//
// Author: Mark Young <marky@lunarg.com>
//

#pragma once

#include "xr_dependencies.h"

#if defined(XR_OS_LINUX)
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#endif

// Structure used to track the global runtime file information
struct GlobalRuntimeFile {
    bool valid;
    bool locked;
    std::string file_name;
    std::string runtime_name;
#if defined(XR_OS_LINUX)
    int32_t file_descriptor;
#elif defined(XR_OS_APPLE)
    // TBD
#elif defined(XR_OS_WINDOWS)
    HANDLE file_handle;
#else
    // TBD
#endif
};

// This is a CMake generated file with #defines for any functions/includes
// that it found present.  This is currently necessary to properly determine
// if secure_getenv or __secure_getenv are present
#if !defined(OPENXR_NON_CMAKE_BUILD)
#include "common_cmake_config.h"
#endif  // !defined(OPENXR_NON_CMAKE_BUILD)

// Environment variables
#if defined(XR_OS_LINUX)

static inline char* PlatformUtilsGetEnv(const char* name) { return getenv(name); }

static inline char* PlatformUtilsGetSecureEnv(const char* name) {
#ifdef HAVE_SECURE_GETENV
    return secure_getenv(name);
#elif defined(HAVE___SECURE_GETENV)
    return __secure_getenv(name);
#else
#pragma message(                                                    \
    "Warning:  Falling back to non-secure getenv for environmental" \
    "lookups!  Consider updating to a different libc.")

    return PlatformUtilsGetEnv(name);
#endif
}

static inline void PlatformUtilsFreeEnv(char* val) {
    // No freeing of memory necessary for Linux, but we should at least touch
    // the val and inst pointers to get rid of compiler warnings.
    (void)val;
}

// Prefix for the Linux/Apple global runtime JSON file name
static const std::string rt_dir_prefix = "/usr/local/share/openxr/";
static const std::string rt_filename = "/active_runtime.json";

static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string& file_name) {
    file_name = rt_dir_prefix;
    file_name += std::to_string(major_version);
    file_name += rt_filename;
    return true;
}

static inline bool PlatformLockGlobalRuntimeFile(uint16_t major_version, GlobalRuntimeFile& global_rt_file) {
    bool success = false;
    try {
        global_rt_file = {};
        // Get the filename
        if (PlatformGetGlobalRuntimeFileName(major_version, global_rt_file.file_name)) {
            // Initialize the global runtime file info
            // Open a file descriptor to the file.
            global_rt_file.file_descriptor = open(global_rt_file.file_name.c_str(), O_RDWR);
            if (0 <= global_rt_file.file_descriptor) {
                flock fcntl_lock = {};
                global_rt_file.valid = true;

                // Test to see if a lock's already present
                fcntl_lock.l_type = F_WRLCK;
                fcntl_lock.l_whence = SEEK_SET;
                fcntl_lock.l_start = 0;
                fcntl_lock.l_len = 0;
                if (-1 == fcntl(global_rt_file.file_descriptor, F_OFD_GETLK, &fcntl_lock)) {
                    std::string error_msg = "fcntl(querylock | ";
                    error_msg += global_rt_file.file_name;
                    error_msg += ", FD: ";
                    error_msg += std::to_string(global_rt_file.file_descriptor);
                    error_msg += ", ErrorNo: ";
                    error_msg += std::to_string(errno);
                    error_msg += ")";
                    perror(error_msg.c_str());
                } else if (fcntl_lock.l_type == F_RDLCK || fcntl_lock.l_type == F_WRLCK) {
                    std::cerr << "Process " << std::to_string(fcntl_lock.l_pid) << " has a lock on " << global_rt_file.file_name
                              << " already!" << std::endl;
                } else {
                    // Lock the entire file for writing
                    fcntl_lock.l_type = F_WRLCK;
                    fcntl_lock.l_whence = SEEK_SET;
                    fcntl_lock.l_start = 0;
                    fcntl_lock.l_len = 0;
                    if (-1 == fcntl(global_rt_file.file_descriptor, F_OFD_SETLK, &fcntl_lock)) {
                        std::string error_msg = "fcntl(lock | ";
                        error_msg += global_rt_file.file_name;
                        error_msg += ", FD: ";
                        error_msg += std::to_string(global_rt_file.file_descriptor);
                        error_msg += ", ErrorNo: ";
                        error_msg += std::to_string(errno);
                        error_msg += ")";
                        perror(error_msg.c_str());
                    } else {
                        global_rt_file.locked = true;
                        success = true;
                    }
                }
                // Get the name of the runtime from the JSON (just crudely)
                if (success) {
                    char buffer[4096];
                    std::string contents = "";
                    while (read(global_rt_file.file_descriptor, &buffer, 4095) > 0) {
                        contents += buffer;
                    }
                    std::size_t name_index = contents.find("\"name\"");
                    if (std::string::npos != name_index) {
                        std::size_t begin_quote_index = contents.find("\"", name_index + 6);
                        std::size_t end_quote_index = contents.find("\"", begin_quote_index + 1);
                        if (std::string::npos != begin_quote_index && std::string::npos != end_quote_index) {
                            global_rt_file.runtime_name =
                                contents.substr(begin_quote_index + 1, end_quote_index - begin_quote_index - 1);
                        }
                    }
                }
            } else {
                std::string error_msg = "open(";
                error_msg += global_rt_file.file_name;
                error_msg += ")";
                perror(error_msg.c_str());
            }
        }
    } catch (...) {
    }
    // Cleanup on failure
    if (!success) {
        if (global_rt_file.valid) {
            close(global_rt_file.file_descriptor);
            global_rt_file.valid = false;
            global_rt_file.file_name = "";
        }
    }
    return success;
}

static inline bool PlatformUnlockGlobalRuntimeFile(GlobalRuntimeFile& global_rt_file) {
    bool success = false;
    try {
        if (global_rt_file.valid && global_rt_file.locked) {
            flock fcntl_lock = {};
            // Unlock the entire file for writing
            fcntl_lock.l_type = F_UNLCK;
            fcntl_lock.l_whence = SEEK_SET;
            fcntl_lock.l_start = 0;
            fcntl_lock.l_len = 0;
            if (-1 == fcntl(global_rt_file.file_descriptor, F_OFD_SETLK, &fcntl_lock)) {
                std::string error_msg = "fcntl(unlock | ";
                error_msg += global_rt_file.file_name;
                error_msg += ", FD: ";
                error_msg += std::to_string(global_rt_file.file_descriptor);
                error_msg += ", ErrorNo: ";
                error_msg += std::to_string(errno);
                error_msg += ")";
                perror(error_msg.c_str());
            } else {
                global_rt_file.locked = false;
                success = true;
            }
            if (-1 == close(global_rt_file.file_descriptor)) {
                std::string error_msg = "close(";
                error_msg += global_rt_file.file_name;
                error_msg += ", FD: ";
                error_msg += std::to_string(global_rt_file.file_descriptor);
                error_msg += ", ErrorNo: ";
                error_msg += std::to_string(errno);
                error_msg += ")";
                perror(error_msg.c_str());
                success = false;
            } else {
                global_rt_file.file_descriptor = -1;
                global_rt_file.valid = false;
                global_rt_file.file_name = "";
            }
        }
    } catch (...) {
    }
    return success;
}

#elif defined(XR_OS_APPLE)

static inline char *PlatformUtilsGetEnv(const char *name) { return getenv(name); }

static inline char *PlatformUtilsGetSecureEnv(const char *name) {
#ifdef HAVE_SECURE_GETENV
    return secure_getenv(name);
#elif defined(HAVE___SECURE_GETENV)
    return __secure_getenv(name);
#else
#pragma message(                                                    \
    "Warning:  Falling back to non-secure getenv for environmental" \
    "lookups!  Consider updating to a different libc.")

    return PlatformUtilsGetEnv(name);
#endif
}

static inline void PlatformUtilsFreeEnv(char *val) {
    // No freeing of memory necessary for Linux, but we should at least touch
    // the val and inst pointers to get rid of compiler warnings.
    (void)val;
}

// Prefix for the Linux/Apple global runtime JSON file name
static const std::string rt_dir_prefix = "/usr/local/share/openxr/";
static const std::string rt_filename = "/active_runtime.json";

static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string &file_name) {
    file_name = rt_dir_prefix;
    file_name += std::to_string(major_version);
    file_name += rt_filename;
    return true;
}

static inline bool PlatformLockGlobalRuntimeFile(uint16_t major_version, GlobalRuntimeFile &global_rt_file) {
    // Stub func
    (void)major_version;
    (void)global_rt_file;
    return false;
}

static inline bool PlatformUnlockGlobalRuntimeFile(GlobalRuntimeFile &global_rt_file) {
    // Stub func
    (void)global_rt_file;
    return false;
}

#elif defined(XR_OS_WINDOWS)

static inline char *PlatformUtilsGetEnv(const char *name) {
    char *retVal;
    DWORD valSize;

    valSize = GetEnvironmentVariableA(name, nullptr, 0);

    // valSize DOES include the null terminator, so for any set variable
    // will always be at least 1. If it's 0, the variable wasn't set.
    if (valSize == 0) {
        return nullptr;
    }

    // Allocate the space necessary for the registry entry
    retVal = new char[valSize + 1];
    GetEnvironmentVariableA(name, retVal, valSize);
    return retVal;
}

static inline char *PlatformUtilsGetSecureEnv(const char *name) {
    // No secure version for Windows as far as I know
    return PlatformUtilsGetEnv(name);
}

static inline void PlatformUtilsFreeEnv(char *val) {
    if (nullptr != val) {
        delete[] val;
        val = nullptr;
    }
}

// Prefix for the Windows global runtime JSON file name
static const std::string rt_file_folder = "\\ProgramData\\Khronos\\OpenXR\\";
static const std::string rt_file_prefix = "\\openxr_runtime_";

static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string &file_name) {
    bool ret_value = false;
    try {
        char *sys_drive = PlatformUtilsGetSecureEnv("SystemDrive");
        if (nullptr != sys_drive) {
            file_name = sys_drive;
            PlatformUtilsFreeEnv(sys_drive);
            file_name += rt_file_folder;
            if (sizeof(void *) == 8) {
                file_name += "64";
            } else {
                file_name += "32";
            }
            file_name += rt_file_prefix;
            file_name += std::to_string(major_version);
            file_name += ".json";
            ret_value = true;
        }
    } catch (...) {
    }
    return ret_value;
}

static inline bool PlatformLockGlobalRuntimeFile(uint16_t major_version, GlobalRuntimeFile &global_rt_file) {
    bool ret_value = false;
    std::string rt_filename;
    if (PlatformGetGlobalRuntimeFileName(major_version, rt_filename)) {
        HANDLE file_handle = CreateFileA(rt_filename.c_str(), (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ, nullptr,
                                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
        if (file_handle != INVALID_HANDLE_VALUE) {
            global_rt_file.valid = true;
            global_rt_file.locked = true;
            global_rt_file.file_handle = file_handle;
            ret_value = true;
        }
        // Get the name of the runtime from the JSON (just crudely)
        if (ret_value) {
            char buffer[4096];
            DWORD num_bytes_read = 0;
            std::string contents = "";
            while (FALSE != ReadFile(file_handle, buffer, 4095, &num_bytes_read, nullptr)) {
                if (num_bytes_read == 0) {
                    break;
                }
                contents += buffer;
            }
            std::size_t name_index = contents.find("\"name\"");
            if (std::string::npos != name_index) {
                std::size_t begin_quote_index = contents.find("\"", name_index + 6);
                std::size_t end_quote_index = contents.find("\"", begin_quote_index + 1);
                if (std::string::npos != begin_quote_index && std::string::npos != end_quote_index) {
                    global_rt_file.runtime_name = contents.substr(begin_quote_index + 1, end_quote_index - begin_quote_index - 1);
                }
            }
        }
    }
    return ret_value;
}

static inline bool PlatformUnlockGlobalRuntimeFile(GlobalRuntimeFile &global_rt_file) {
    if (global_rt_file.valid && global_rt_file.locked && CloseHandle(global_rt_file.file_handle)) {
        global_rt_file.valid = false;
        global_rt_file.locked = false;
        global_rt_file.file_handle = nullptr;
        return true;
    }
    return false;
}

#else  // Not Linux or Windows

static inline char *PlatformUtilsGetEnv(const char *name) {
    // Stub func
    (void)name;
    return nullptr;
}

static inline char *PlatformUtilsGetSecureEnv(const char *name) {
    // Stub func
    (void)name;
    return nullptr;
}

static inline void PlatformUtilsFreeEnv(char *val) {
    // Stub func
    (void)val;
}

static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string &file_name) {
    // Stub func
    (void)major_version;
    (void)file_name;
    return false;
}

static inline bool PlatformLockGlobalRuntimeFile(uint16_t major_version, GlobalRuntimeFile &global_rt_file) {
    // Stub func
    (void)major_version;
    (void)global_rt_file;
    return false;
}

static inline bool PlatformUnlockGlobalRuntimeFile(GlobalRuntimeFile &global_rt_file) {
    // Stub func
    (void)global_rt_file;
    return false;
}

#endif
<commit_msg>Remove dead code<commit_after>// Copyright (c) 2017 The Khronos Group Inc.
// Copyright (c) 2017 Valve Corporation
// Copyright (c) 2017 LunarG, Inc.
//
// 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.
//
// Author: Mark Young <marky@lunarg.com>
//

#pragma once

#include "xr_dependencies.h"

#if defined(XR_OS_LINUX)
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#endif

// This is a CMake generated file with #defines for any functions/includes
// that it found present.  This is currently necessary to properly determine
// if secure_getenv or __secure_getenv are present
#if !defined(OPENXR_NON_CMAKE_BUILD)
#include "common_cmake_config.h"
#endif  // !defined(OPENXR_NON_CMAKE_BUILD)

// Environment variables
#if defined(XR_OS_LINUX)

static inline char* PlatformUtilsGetEnv(const char* name) { return getenv(name); }

static inline char* PlatformUtilsGetSecureEnv(const char* name) {
#ifdef HAVE_SECURE_GETENV
    return secure_getenv(name);
#elif defined(HAVE___SECURE_GETENV)
    return __secure_getenv(name);
#else
#pragma message(                                                    \
    "Warning:  Falling back to non-secure getenv for environmental" \
    "lookups!  Consider updating to a different libc.")

    return PlatformUtilsGetEnv(name);
#endif
}

static inline void PlatformUtilsFreeEnv(char* val) {
    // No freeing of memory necessary for Linux, but we should at least touch
    // the val and inst pointers to get rid of compiler warnings.
    (void)val;
}

// Prefix for the Linux/Apple global runtime JSON file name
static const std::string rt_dir_prefix = "/usr/local/share/openxr/";
static const std::string rt_filename = "/active_runtime.json";

static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string& file_name) {
    file_name = rt_dir_prefix;
    file_name += std::to_string(major_version);
    file_name += rt_filename;
    return true;
}

#elif defined(XR_OS_APPLE)

static inline char *PlatformUtilsGetEnv(const char *name) { return getenv(name); }

static inline char *PlatformUtilsGetSecureEnv(const char *name) {
#ifdef HAVE_SECURE_GETENV
    return secure_getenv(name);
#elif defined(HAVE___SECURE_GETENV)
    return __secure_getenv(name);
#else
#pragma message(                                                    \
    "Warning:  Falling back to non-secure getenv for environmental" \
    "lookups!  Consider updating to a different libc.")

    return PlatformUtilsGetEnv(name);
#endif
}

static inline void PlatformUtilsFreeEnv(char *val) {
    // No freeing of memory necessary for Linux, but we should at least touch
    // the val and inst pointers to get rid of compiler warnings.
    (void)val;
}

// Prefix for the Linux/Apple global runtime JSON file name
static const std::string rt_dir_prefix = "/usr/local/share/openxr/";
static const std::string rt_filename = "/active_runtime.json";

static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string &file_name) {
    file_name = rt_dir_prefix;
    file_name += std::to_string(major_version);
    file_name += rt_filename;
    return true;
}

#elif defined(XR_OS_WINDOWS)

static inline char *PlatformUtilsGetEnv(const char *name) {
    char *retVal;
    DWORD valSize;

    valSize = GetEnvironmentVariableA(name, nullptr, 0);

    // valSize DOES include the null terminator, so for any set variable
    // will always be at least 1. If it's 0, the variable wasn't set.
    if (valSize == 0) {
        return nullptr;
    }

    // Allocate the space necessary for the registry entry
    retVal = new char[valSize + 1];
    GetEnvironmentVariableA(name, retVal, valSize);
    return retVal;
}

static inline char *PlatformUtilsGetSecureEnv(const char *name) {
    // No secure version for Windows as far as I know
    return PlatformUtilsGetEnv(name);
}

static inline void PlatformUtilsFreeEnv(char *val) {
    if (nullptr != val) {
        delete[] val;
        val = nullptr;
    }
}

// Prefix for the Windows global runtime JSON file name
static const std::string rt_file_folder = "\\ProgramData\\Khronos\\OpenXR\\";
static const std::string rt_file_prefix = "\\openxr_runtime_";

static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string &file_name) {
    bool ret_value = false;
    try {
        char *sys_drive = PlatformUtilsGetSecureEnv("SystemDrive");
        if (nullptr != sys_drive) {
            file_name = sys_drive;
            PlatformUtilsFreeEnv(sys_drive);
            file_name += rt_file_folder;
            if (sizeof(void *) == 8) {
                file_name += "64";
            } else {
                file_name += "32";
            }
            file_name += rt_file_prefix;
            file_name += std::to_string(major_version);
            file_name += ".json";
            ret_value = true;
        }
    } catch (...) {
    }
    return ret_value;
}

#else  // Not Linux or Windows

static inline char *PlatformUtilsGetEnv(const char *name) {
    // Stub func
    (void)name;
    return nullptr;
}

static inline char *PlatformUtilsGetSecureEnv(const char *name) {
    // Stub func
    (void)name;
    return nullptr;
}

static inline void PlatformUtilsFreeEnv(char *val) {
    // Stub func
    (void)val;
}

static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string &file_name) {
    // Stub func
    (void)major_version;
    (void)file_name;
    return false;
}

#endif
<|endoftext|>


<commit_before>/* $Id$ */

/*
 * Copyright (c) 2013 Roland van Rijswijk-Deij
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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 AUTHOR ``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 AUTHOR 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.
 */

/*****************************************************************************
 silvia_keygen.cpp

 Issuer key generation utility
 *****************************************************************************/

#include "config.h"
#include "silvia_issuer_keygen.h"
#include "silvia_parameters.h"
#include "silvia_macros.h"
#include <string>
#include <unistd.h>

// Default modulus size for new keys
#define DEFAULT_BITSIZE 2048

void version(void)
{
	printf("The Simple Library for Verifying and Issuing Attributes (silvia)\n");
	printf("\n");
	printf("Issuer key generation utility version %s\n", VERSION);
	printf("\n");
	printf("Copyright (c) 2013 Roland van Rijswijk-Deij\n\n");
	printf("Use, modification and redistribution of this software is subject to the terms\n");
	printf("of the license agreement. This software is licensed under a 2-clause BSD-style\n");
	printf("license a copy of which is included as the file LICENSE in the distribution.\n");
}

void usage(void)
{
	printf("Silvia issuer key generation utility %s\n\n", VERSION);
	printf("Usage:\n");
	printf("\tsilvia_keygen -a <#-attribs> [-n <bits>] [-p <file>] [-P <file>]\n");
	printf("\tsilvia_keygen -h\n");
	printf("\tsilvia_keygen -v\n");
	printf("\n");
	printf("\t-a <#-attribs> Generate a key-pair supporting credentials with at most\n");
	printf("\t               <#-attribs> attributes per credentials\n");
	printf("\t-n <bits>      Generate a key-pair with a <bits>-bit modulus (defaults\n");
	printf("\t               to %d)\n", DEFAULT_BITSIZE);
	printf("\t-p <file>      Output the public key to <file> (defaults to stdout)\n");
	printf("\t-P <file>      Output the private key to <file> (defaults to stdout)\n");
	printf("\n");
	printf("\t-h             Print this help message\n");
	printf("\n");
	printf("\t-v             Print the version number\n");
}

int generate_key_pair(FILE* pub_key_file, FILE* priv_key_file, size_t num_attribs, size_t bit_size)
{
	printf("Generating %zd-bit issuer key pair for %zd attributes ... ", bit_size, num_attribs); fflush(stdout);

	// Set key size
	silvia_system_parameters::i()->set_l_n(bit_size);

	// Generate key-pair
	silvia_pub_key* pub_key;
	silvia_priv_key* priv_key;

	silvia_issuer_keyfactory::i()->generate_keypair(num_attribs + 1, &pub_key, &priv_key);

	printf("OK\n");

	// Output the public key
	fprintf(pub_key_file, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
	fprintf(pub_key_file, "<IssuerPublicKey xmlns=\"http://www.zurich.ibm.com/security/idemix\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.zurich.ibm.com/security/idemix IssuerPublicKey.xsd\">\n");
	fprintf(pub_key_file, "  <References>\n");
    fprintf(pub_key_file, "    <GroupParameters>http://www.zurich.ibm.com/security/idmx/v2/gp.xml</GroupParameters>\n");
	fprintf(pub_key_file, "  </References>\n");
	fprintf(pub_key_file, "  <Elements>\n");
    fprintf(pub_key_file, "    <S>"); fprintmpzdec(pub_key_file, pub_key->get_S()); fprintf(pub_key_file, "</S>\n");
    fprintf(pub_key_file, "    <Z>"); fprintmpzdec(pub_key_file, pub_key->get_Z()); fprintf(pub_key_file, "</Z>\n");
    fprintf(pub_key_file, "    <n>"); fprintmpzdec(pub_key_file, pub_key->get_n()); fprintf(pub_key_file, "</n>\n");
    fprintf(pub_key_file, "    <Bases num=\"%zd\">\n", num_attribs);

    for (size_t i = 0; i < num_attribs; i++)
    {
		fprintf(pub_key_file, "      <Base_%zd>", i); fprintmpzdec(pub_key_file, pub_key->get_R()[i]); fprintf(pub_key_file, "</Base_%zd>\n", i);
	}

    fprintf(pub_key_file, "    </Bases>\n");
	fprintf(pub_key_file, "  </Elements>\n");
	fprintf(pub_key_file, "  <Features>\n");
    fprintf(pub_key_file, "    <Epoch length=\"432000\"/>\n");
	fprintf(pub_key_file, "  </Features>\n");
	fprintf(pub_key_file, "</IssuerPublicKey>\n");

	// Output the private key
	fprintf(priv_key_file, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
	fprintf(priv_key_file, "<IssuerPrivateKey xmlns=\"http://www.zurich.ibm.com/security/idemix\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.zurich.ibm.com/security/idemix IssuerPrivateKey.xsd\">\n");
	fprintf(priv_key_file, "  <References>\n");
    fprintf(priv_key_file, "    <IssuerPublicKey>http://www.issuer.com/ipk.xml</IssuerPublicKey>\n");
	fprintf(priv_key_file, "  </References>\n");
	fprintf(priv_key_file, "  <Elements>\n");
    fprintf(priv_key_file, "    <n>"); fprintmpzdec(priv_key_file, pub_key->get_n()); fprintf(priv_key_file, "</n>\n");
    fprintf(priv_key_file, "
"); fprintmpzdec(priv_key_file, priv_key->get_p()); fprintf(priv_key_file, "
\n");
    fprintf(priv_key_file, "    <pPrime>"); fprintmpzdec(priv_key_file, priv_key->get_p_prime()); fprintf(priv_key_file, "</pPrime>\n");
    fprintf(priv_key_file, "    <q>"); fprintmpzdec(priv_key_file, priv_key->get_q()); fprintf(priv_key_file, "</q>\n");
    fprintf(priv_key_file, "    <qPrime>"); fprintmpzdec(priv_key_file, priv_key->get_q_prime()); fprintf(priv_key_file, "</qPrime>\n");
	fprintf(priv_key_file, "  </Elements>\n");
	fprintf(priv_key_file, "</IssuerPrivateKey>\n");

	delete pub_key;
	delete priv_key;

	return 1;
}

int main(int argc, char* argv[])
{
	// Program parameters
	size_t bit_size = DEFAULT_BITSIZE;
	size_t num_attribs = 0;
	std::string pub_key_filename;
	std::string priv_key_filename;
	int c = 0;

	while ((c = getopt(argc, argv, "a:n:p:P:hv")) != -1)
	{
		switch (c)
		{
		case 'h':
			usage();
			return 0;
		case 'v':
			version();
			return 0;
		case 'a':
			num_attribs = atoi(optarg);
			break;
		case 'n':
			bit_size = atoi(optarg);
			break;
		case 'p':
			pub_key_filename = std::string(optarg);
			break;
		case 'P':
			priv_key_filename = std::string(optarg);
			break;
		}
	}

	if (num_attribs <= 0)
	{
		fprintf(stderr, "Missing argument -a; please specify a number of attributes\n");

		return -1;
	}

	FILE* pub_key_file = stdout;
	FILE* priv_key_file = stdout;

	if (!pub_key_filename.empty())
	{
		pub_key_file = fopen(pub_key_filename.c_str(), "w");

		if (pub_key_file == NULL)
		{
			fprintf(stderr, "Failed to open %s for writing\n", pub_key_filename.c_str());

			return -1;
		}

		printf("Writing public key to %s\n", pub_key_filename.c_str());
	}

	if (!priv_key_filename.empty())
	{
		priv_key_file = fopen(priv_key_filename.c_str(), "w");

		if (priv_key_file == NULL)
		{
			fprintf(stderr, "Failed to open %s for writing\n", priv_key_filename.c_str());

			return -1;
		}

		printf("Writing private key to %s\n", priv_key_filename.c_str());
	}

	generate_key_pair(pub_key_file, priv_key_file, num_attribs, bit_size);

	if (!pub_key_filename.empty()) fclose(pub_key_file);
	if (!priv_key_filename.empty()) fclose(priv_key_file);

	return 0;
}
<commit_msg>Fixed off-by-one-error, now prints all genertaed bases<commit_after>/* $Id$ */

/*
 * Copyright (c) 2013 Roland van Rijswijk-Deij
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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 AUTHOR ``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 AUTHOR 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.
 */

/*****************************************************************************
 silvia_keygen.cpp

 Issuer key generation utility
 *****************************************************************************/

#include "config.h"
#include "silvia_issuer_keygen.h"
#include "silvia_parameters.h"
#include "silvia_macros.h"
#include <string>
#include <unistd.h>

// Default modulus size for new keys
#define DEFAULT_BITSIZE 2048

void version(void)
{
	printf("The Simple Library for Verifying and Issuing Attributes (silvia)\n");
	printf("\n");
	printf("Issuer key generation utility version %s\n", VERSION);
	printf("\n");
	printf("Copyright (c) 2013 Roland van Rijswijk-Deij\n\n");
	printf("Use, modification and redistribution of this software is subject to the terms\n");
	printf("of the license agreement. This software is licensed under a 2-clause BSD-style\n");
	printf("license a copy of which is included as the file LICENSE in the distribution.\n");
}

void usage(void)
{
	printf("Silvia issuer key generation utility %s\n\n", VERSION);
	printf("Usage:\n");
	printf("\tsilvia_keygen -a <#-attribs> [-n <bits>] [-p <file>] [-P <file>]\n");
	printf("\tsilvia_keygen -h\n");
	printf("\tsilvia_keygen -v\n");
	printf("\n");
	printf("\t-a <#-attribs> Generate a key-pair supporting credentials with at most\n");
	printf("\t               <#-attribs> attributes per credentials\n");
	printf("\t-n <bits>      Generate a key-pair with a <bits>-bit modulus (defaults\n");
	printf("\t               to %d)\n", DEFAULT_BITSIZE);
	printf("\t-p <file>      Output the public key to <file> (defaults to stdout)\n");
	printf("\t-P <file>      Output the private key to <file> (defaults to stdout)\n");
	printf("\n");
	printf("\t-h             Print this help message\n");
	printf("\n");
	printf("\t-v             Print the version number\n");
}

int generate_key_pair(FILE* pub_key_file, FILE* priv_key_file, size_t num_attribs, size_t bit_size)
{
	printf("Generating %zd-bit issuer key pair for %zd attributes ... ", bit_size, num_attribs); fflush(stdout);

	// Set key size
	silvia_system_parameters::i()->set_l_n(bit_size);

	// Generate key-pair
	silvia_pub_key* pub_key;
	silvia_priv_key* priv_key;

	silvia_issuer_keyfactory::i()->generate_keypair(num_attribs + 1, &pub_key, &priv_key);

	printf("OK\n");

	// Output the public key
	fprintf(pub_key_file, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
	fprintf(pub_key_file, "<IssuerPublicKey xmlns=\"http://www.zurich.ibm.com/security/idemix\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.zurich.ibm.com/security/idemix IssuerPublicKey.xsd\">\n");
	fprintf(pub_key_file, "  <References>\n");
    fprintf(pub_key_file, "    <GroupParameters>http://www.zurich.ibm.com/security/idmx/v2/gp.xml</GroupParameters>\n");
	fprintf(pub_key_file, "  </References>\n");
	fprintf(pub_key_file, "  <Elements>\n");
    fprintf(pub_key_file, "    <S>"); fprintmpzdec(pub_key_file, pub_key->get_S()); fprintf(pub_key_file, "</S>\n");
    fprintf(pub_key_file, "    <Z>"); fprintmpzdec(pub_key_file, pub_key->get_Z()); fprintf(pub_key_file, "</Z>\n");
    fprintf(pub_key_file, "    <n>"); fprintmpzdec(pub_key_file, pub_key->get_n()); fprintf(pub_key_file, "</n>\n");
    fprintf(pub_key_file, "    <Bases num=\"%zd\">\n", num_attribs);

    for (size_t i = 0; i < num_attribs + 1; i++)
    {
		fprintf(pub_key_file, "      <Base_%zd>", i); fprintmpzdec(pub_key_file, pub_key->get_R()[i]); fprintf(pub_key_file, "</Base_%zd>\n", i);
	}

    fprintf(pub_key_file, "    </Bases>\n");
	fprintf(pub_key_file, "  </Elements>\n");
	fprintf(pub_key_file, "  <Features>\n");
    fprintf(pub_key_file, "    <Epoch length=\"432000\"/>\n");
	fprintf(pub_key_file, "  </Features>\n");
	fprintf(pub_key_file, "</IssuerPublicKey>\n");

	// Output the private key
	fprintf(priv_key_file, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
	fprintf(priv_key_file, "<IssuerPrivateKey xmlns=\"http://www.zurich.ibm.com/security/idemix\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.zurich.ibm.com/security/idemix IssuerPrivateKey.xsd\">\n");
	fprintf(priv_key_file, "  <References>\n");
    fprintf(priv_key_file, "    <IssuerPublicKey>http://www.issuer.com/ipk.xml</IssuerPublicKey>\n");
	fprintf(priv_key_file, "  </References>\n");
	fprintf(priv_key_file, "  <Elements>\n");
    fprintf(priv_key_file, "    <n>"); fprintmpzdec(priv_key_file, pub_key->get_n()); fprintf(priv_key_file, "</n>\n");
    fprintf(priv_key_file, "
"); fprintmpzdec(priv_key_file, priv_key->get_p()); fprintf(priv_key_file, "
\n");
    fprintf(priv_key_file, "    <pPrime>"); fprintmpzdec(priv_key_file, priv_key->get_p_prime()); fprintf(priv_key_file, "</pPrime>\n");
    fprintf(priv_key_file, "    <q>"); fprintmpzdec(priv_key_file, priv_key->get_q()); fprintf(priv_key_file, "</q>\n");
    fprintf(priv_key_file, "    <qPrime>"); fprintmpzdec(priv_key_file, priv_key->get_q_prime()); fprintf(priv_key_file, "</qPrime>\n");
	fprintf(priv_key_file, "  </Elements>\n");
	fprintf(priv_key_file, "</IssuerPrivateKey>\n");

	delete pub_key;
	delete priv_key;

	return 1;
}

int main(int argc, char* argv[])
{
	// Program parameters
	size_t bit_size = DEFAULT_BITSIZE;
	size_t num_attribs = 0;
	std::string pub_key_filename;
	std::string priv_key_filename;
	int c = 0;

	while ((c = getopt(argc, argv, "a:n:p:P:hv")) != -1)
	{
		switch (c)
		{
		case 'h':
			usage();
			return 0;
		case 'v':
			version();
			return 0;
		case 'a':
			num_attribs = atoi(optarg);
			break;
		case 'n':
			bit_size = atoi(optarg);
			break;
		case 'p':
			pub_key_filename = std::string(optarg);
			break;
		case 'P':
			priv_key_filename = std::string(optarg);
			break;
		}
	}

	if (num_attribs <= 0)
	{
		fprintf(stderr, "Missing argument -a; please specify a number of attributes\n");

		return -1;
	}

	FILE* pub_key_file = stdout;
	FILE* priv_key_file = stdout;

	if (!pub_key_filename.empty())
	{
		pub_key_file = fopen(pub_key_filename.c_str(), "w");

		if (pub_key_file == NULL)
		{
			fprintf(stderr, "Failed to open %s for writing\n", pub_key_filename.c_str());

			return -1;
		}

		printf("Writing public key to %s\n", pub_key_filename.c_str());
	}

	if (!priv_key_filename.empty())
	{
		priv_key_file = fopen(priv_key_filename.c_str(), "w");

		if (priv_key_file == NULL)
		{
			fprintf(stderr, "Failed to open %s for writing\n", priv_key_filename.c_str());

			return -1;
		}

		printf("Writing private key to %s\n", priv_key_filename.c_str());
	}

	generate_key_pair(pub_key_file, priv_key_file, num_attribs, bit_size);

	if (!pub_key_filename.empty()) fclose(pub_key_file);
	if (!priv_key_filename.empty()) fclose(priv_key_file);

	return 0;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2016 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
#ifndef MAPNIK_FACE_HPP
#define MAPNIK_FACE_HPP

//mapnik
#include <mapnik/config.hpp>
#include <mapnik/text/glyph_info.hpp>
#include <mapnik/util/noncopyable.hpp>

#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>

extern "C"
{
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_STROKER_H
}

#pragma GCC diagnostic pop

//stl
#include <memory>
#include <string>
#include <vector>

namespace mapnik
{

class MAPNIK_DECL font_face : util::noncopyable
{
public:
    font_face(FT_Face face);

    std::string family_name() const
    {
        return std::string(face_->family_name);
    }

    std::string style_name() const
    {
        return std::string(face_->style_name);
    }

    FT_Face get_face() const
    {
        return face_;
    }

    bool set_character_sizes(double size);
    bool set_unscaled_character_sizes();

    bool glyph_dimensions(glyph_info &glyph) const;

    ~font_face();

private:
    FT_Face face_;
};
using face_ptr = std::shared_ptr<font_face>;

class MAPNIK_DECL font_face_set : private util::noncopyable
{
public:
    using iterator = std::vector<face_ptr>::iterator;
    font_face_set(void) : faces_(){}

    void add(face_ptr face);
    void set_character_sizes(double size);
    void set_unscaled_character_sizes();

    std::size_t size() const { return faces_.size(); }
    iterator begin() { return faces_.begin(); }
    iterator end() { return faces_.end(); }
private:
    std::vector<face_ptr> faces_;
};
using face_set_ptr = std::unique_ptr<font_face_set>;

// FT_Stroker wrapper
class stroker : util::noncopyable
{
public:
    explicit stroker(FT_Stroker s)
        : s_(s) {}
    ~stroker();

    void init(double radius);
    FT_Stroker const& get() const { return s_; }
private:
    FT_Stroker s_;
};

} //ns mapnik

#endif // FACE_HPP
<commit_msg>add color_font_ member<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2016 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
#ifndef MAPNIK_FACE_HPP
#define MAPNIK_FACE_HPP

//mapnik
#include <mapnik/config.hpp>
#include <mapnik/text/glyph_info.hpp>
#include <mapnik/util/noncopyable.hpp>

#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>

extern "C"
{
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_STROKER_H
}

#pragma GCC diagnostic pop

//stl
#include <memory>
#include <string>
#include <vector>

namespace mapnik
{

class MAPNIK_DECL font_face : util::noncopyable
{
public:
    font_face(FT_Face face);

    std::string family_name() const
    {
        return std::string(face_->family_name);
    }

    std::string style_name() const
    {
        return std::string(face_->style_name);
    }

    FT_Face get_face() const
    {
        return face_;
    }

    bool set_character_sizes(double size);
    bool set_unscaled_character_sizes();

    bool glyph_dimensions(glyph_info &glyph) const;

    inline bool is_color() const { return color_font_;}

    ~font_face();

private:
    FT_Face face_;
    bool color_font_ = false;
};
using face_ptr = std::shared_ptr<font_face>;

class MAPNIK_DECL font_face_set : private util::noncopyable
{
public:
    using iterator = std::vector<face_ptr>::iterator;
    font_face_set(void) : faces_(){}

    void add(face_ptr face);
    void set_character_sizes(double size);
    void set_unscaled_character_sizes();

    std::size_t size() const { return faces_.size(); }
    iterator begin() { return faces_.begin(); }
    iterator end() { return faces_.end(); }
private:
    std::vector<face_ptr> faces_;
};
using face_set_ptr = std::unique_ptr<font_face_set>;

// FT_Stroker wrapper
class stroker : util::noncopyable
{
public:
    explicit stroker(FT_Stroker s)
        : s_(s) {}
    ~stroker();

    void init(double radius);
    FT_Stroker const& get() const { return s_; }
private:
    FT_Stroker s_;
};

} //ns mapnik

#endif // FACE_HPP
<|endoftext|>


<commit_before>//============================================================================
// MCKL/include/mckl/random/seed.hpp
//----------------------------------------------------------------------------
// MCKL: Monte Carlo Kernel Library
//----------------------------------------------------------------------------
// Copyright (c) 2013-2016, Yan Zhou
// 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.
//============================================================================

#ifndef MCKL_RANDOM_SEED_HPP
#define MCKL_RANDOM_SEED_HPP

#include <mckl/random/internal/common.hpp>
#include <mckl/random/counter.hpp>

/// \brief Default result type of Seed
/// \ingroup Config
#ifndef MCKL_SEED_RESULT_TYPE
#define MCKL_SEED_RESULT_TYPE unsigned
#endif

namespace mckl
{

/// \brief Seed generator
/// \ingroup Random
///
/// \details
/// The sequence of seeds are belongs to the equivalent class \f$s \mod D
/// \equiv R\f$ where \f$D > 0\f$, \f$R \ge 0\f$. The defaults are \f$1\f$ and
/// \f$0\f$ respectively. Each time `get()` is called, a new seed is returned.
///
/// The method `operator()(RNGType &rng)` is equivalent to
/// `rng.seed(static_cast<typename RNGType::result_type>(get()))`.
template <typename ID, typename ResultType = MCKL_SEED_RESULT_TYPE>
class SeedGenerator
{
    static_assert(std::is_unsigned<ResultType>::value,
        "**SeedGenerator** USED WITH ResultType OTHER THAN UNSIGEND INTEGER "
        "TYPES");

    public:
    using result_type = ResultType;

    SeedGenerator(const SeedGenerator<ID, ResultType> &) = delete;

    SeedGenerator<ID, ResultType> &operator=(
        const SeedGenerator<ID, ResultType> &) = delete;

    static SeedGenerator<ID, ResultType> &instance()
    {
        static SeedGenerator<ID, ResultType> seed;

        return seed;
    }

    /// \brief Seed a single RNG
    template <typename RNGType>
    void operator()(RNGType &rng)
    {
        rng.seed(static_cast<typename RNGType::result_type>(get()));
    }

    /// \brief Seed a sequence of RNGs
    template <typename OutputIter>
    OutputIter operator()(std::size_t n, OutputIter first)
    {
        using RNGType = typename std::iterator_traits<OutputIter>::value_type;

        for (std::size_t i = 0; i != n; ++i, ++first)
            first->seed(static_cast<typename RNGType::result_type>(get()));

        return first;
    }

    /// \brief Set the seed to `s % max() * divisor() + remainder()`
    void set(result_type s) { seed_ = s % max_; }

    /// \brief Get a seed
    result_type get()
    {
        result_type s = seed_.fetch_add(1);

        return (s % max_ + 1) * divisor_ + remainder_;
    }

    /// \brief The maximum of the seed
    result_type max() const { return max_; }

    /// \brief The divisor of the output seed
    result_type divisor() const { return divisor_; }

    /// \brief The remainder of the output seed
    result_type remainder() const { return remainder_; }

    /// \brief Set the divisor and the remainder
    void modulo(result_type divisor, result_type remainder)
    {
        runtime_assert(divisor > remainder,
            "**SeedGenerator::modulo** the "
            "remainder is not smaller than "
            "the divisor");

        result_type maxs = std::numeric_limits<result_type>::max() / divisor;
        runtime_assert(maxs > 1,
            "**SeedGenerator::modulo** the maximum of "
            "the internal seed will be no larger than 1");

        divisor_ = divisor;
        remainder_ = remainder;
        max_ = maxs;

        set(seed_);
    }

    template <typename CharT, typename Traits>
    friend std::basic_ostream<CharT, Traits> &operator<<(
        std::basic_ostream<CharT, Traits> &os,
        const SeedGenerator<ID, ResultType> &sg)
    {
        if (!os)
            return os;

        os << sg.seed_ << ' ';
        os << sg.max_ << ' ';
        os << sg.divisor_ << ' ';
        os << sg.remainder_ << ' ';

        return os;
    }

    template <typename CharT, typename Traits>
    friend std::basic_istream<CharT, Traits> &operator>>(
        std::basic_istream<CharT, Traits> &is,
        SeedGenerator<ID, ResultType> &sg)
    {
        if (!is)
            return is;

        result_type seed;
        result_type max;
        result_type divisor;
        result_type remainder;
        is >> std::ws >> seed;
        is >> std::ws >> max;
        is >> std::ws >> divisor;
        is >> std::ws >> remainder;

        if (is) {
            sg.seed_ = seed;
            sg.max_ = max;
            sg.divisor_ = divisor;
            sg.remainder_ = remainder;
        }

        return is;
    }

    private:
    std::atomic<result_type> seed_;
    result_type max_;
    result_type divisor_;
    result_type remainder_;

    SeedGenerator() : seed_(0), max_(0), divisor_(1), remainder_(0)
    {
        modulo(divisor_, remainder_);
    }
}; // class SeedGenerator

/// \brief The default Seed type
/// \ingroup Random
using Seed = SeedGenerator<NullType>;

} // namespace mckl

#endif // MCKL_RANDOM_SEED_HPP
<commit_msg>fix seed maximum case<commit_after>//============================================================================
// MCKL/include/mckl/random/seed.hpp
//----------------------------------------------------------------------------
// MCKL: Monte Carlo Kernel Library
//----------------------------------------------------------------------------
// Copyright (c) 2013-2016, Yan Zhou
// 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.
//============================================================================

#ifndef MCKL_RANDOM_SEED_HPP
#define MCKL_RANDOM_SEED_HPP

#include <mckl/random/internal/common.hpp>
#include <mckl/random/counter.hpp>

/// \brief Default result type of Seed
/// \ingroup Config
#ifndef MCKL_SEED_RESULT_TYPE
#define MCKL_SEED_RESULT_TYPE unsigned
#endif

namespace mckl
{

/// \brief Seed generator
/// \ingroup Random
///
/// \details
/// The sequence of seeds are belongs to the equivalent class \f$s \mod D
/// \equiv R\f$ where \f$D > 0\f$, \f$R \ge 0\f$. The defaults are \f$D = 1\f$
/// and \f$R = 0\f$. Each time `get()` is called, a new seed is returned.
///
/// The method `operator()(RNGType &rng)` is equivalent to
/// `rng.seed(static_cast<typename RNGType::result_type>(get()))`.
///
/// \note
/// If \f$D = 1\f$ (and \f$R = 0\f$), then there will be exactly two seeds
/// equal
/// to `1` in any sequence of length \f$2^N\f$, where \f$N\f$ is the number of
/// digits in the unsigned integer type. They are either one at the beginning
/// and one at the end, or consecutive.
template <typename ID, typename ResultType = MCKL_SEED_RESULT_TYPE>
class SeedGenerator
{
    static_assert(std::is_unsigned<ResultType>::value,
        "**SeedGenerator** used with ResultType other than unsigned integer "
        "types");

    public:
    using result_type = ResultType;

    SeedGenerator(const SeedGenerator<ID, ResultType> &) = delete;

    SeedGenerator<ID, ResultType> &operator=(
        const SeedGenerator<ID, ResultType> &) = delete;

    static SeedGenerator<ID, ResultType> &instance()
    {
        static SeedGenerator<ID, ResultType> seed;

        return seed;
    }

    /// \brief Seed a single RNG
    template <typename RNGType>
    void operator()(RNGType &rng)
    {
        rng.seed(static_cast<typename RNGType::result_type>(get()));
    }

    /// \brief Seed a sequence of RNGs
    template <typename OutputIter>
    OutputIter operator()(std::size_t n, OutputIter first)
    {
        using RNGType = typename std::iterator_traits<OutputIter>::value_type;

        for (std::size_t i = 0; i != n; ++i, ++first)
            first->seed(static_cast<typename RNGType::result_type>(get()));

        return first;
    }

    /// \brief Set the seed to `s % max() * divisor() + remainder()`
    void set(result_type s) { seed_ = s % max_; }

    /// \brief Get a seed
    result_type get()
    {
        result_type s = seed_.fetch_add(1);

        return (s % max_ + 1) * divisor_ + remainder_;
    }

    /// \brief The maximum of the seed
    result_type max() const { return max_; }

    /// \brief The divisor of the output seed
    result_type divisor() const { return divisor_; }

    /// \brief The remainder of the output seed
    result_type remainder() const { return remainder_; }

    /// \brief Set the divisor and the remainder
    void modulo(result_type divisor, result_type remainder)
    {
        runtime_assert(divisor > remainder,
            "**SeedGenerator::modulo** the remainder is not smaller than the "
            "divisor");

        result_type maxs =
            (std::numeric_limits<result_type>::max() - remainder) / divisor;
        runtime_assert(maxs > 1,
            "**SeedGenerator::modulo** the maximum of the internal seed will "
            "be no larger than 1");

        divisor_ = divisor;
        remainder_ = remainder;
        max_ = maxs;

        set(seed_);
    }

    template <typename CharT, typename Traits>
    friend std::basic_ostream<CharT, Traits> &operator<<(
        std::basic_ostream<CharT, Traits> &os,
        const SeedGenerator<ID, ResultType> &sg)
    {
        if (!os)
            return os;

        os << sg.seed_ << ' ';
        os << sg.max_ << ' ';
        os << sg.divisor_ << ' ';
        os << sg.remainder_ << ' ';

        return os;
    }

    template <typename CharT, typename Traits>
    friend std::basic_istream<CharT, Traits> &operator>>(
        std::basic_istream<CharT, Traits> &is,
        SeedGenerator<ID, ResultType> &sg)
    {
        if (!is)
            return is;

        result_type seed;
        result_type max;
        result_type divisor;
        result_type remainder;
        is >> std::ws >> seed;
        is >> std::ws >> max;
        is >> std::ws >> divisor;
        is >> std::ws >> remainder;

        if (is) {
            sg.seed_ = seed;
            sg.max_ = max;
            sg.divisor_ = divisor;
            sg.remainder_ = remainder;
        }

        return is;
    }

    private:
    std::atomic<result_type> seed_;
    result_type max_;
    result_type divisor_;
    result_type remainder_;

    SeedGenerator() : seed_(0), max_(0), divisor_(1), remainder_(0)
    {
        modulo(divisor_, remainder_);
    }
}; // class SeedGenerator

/// \brief The default Seed type
/// \ingroup Random
using Seed = SeedGenerator<NullType>;

} // namespace mckl

#endif // MCKL_RANDOM_SEED_HPP
<|endoftext|>


<commit_before>///
/// @file   pmath.hpp
/// @brief  Auxiliary math functions for primesieve.
///
/// Copyright (C) 2018 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PMATH_HPP
#define PMATH_HPP

#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <limits>
#include <type_traits>

namespace primesieve {

template <typename X, typename Y>
inline X ceilDiv(X x, Y y)
{
  return (X) ((x + y - 1) / y);
}

template <typename T>
inline bool isPow2(T x)
{
  return x != 0 && (x & (x - 1)) == 0;
}

template <typename T>
inline T numberOfBits(T)
{
  return (T) std::numeric_limits<
      typename std::make_unsigned<T>::type
          >::digits;
}

template <typename T>
inline T floorPow2(T x)
{
  for (T i = 1; i < numberOfBits(x); i += i)
    x |= (x >> i);

  return x - (x >> 1);
}

template <typename T>
inline T ilog2(T x)
{
  T bits = numberOfBits(x);
  T one = 1;
  T log2 = 0;

  for (T i = bits / 2; i > 0; i /= 2)
  {
    if (x >= (one << i))
    {
      x >>= i;
      log2 += i;
    }
  }

  return log2;
}

#if __cplusplus >= 201402L

/// C++14 compile time square root using binary search
template <typename T>
constexpr T ctSqrt(T x, T lo, T hi)
{
  if (lo == hi)
    return lo;

  const T mid = (lo + hi + 1) / 2;

  if (x / mid < mid)
    return ctSqrt<T>(x, lo, mid - 1);
  else
    return ctSqrt(x, mid, hi);
}

#else

#define MID ((lo + hi + 1) / 2)

/// C++11 compile time square root using binary search
template <typename T>
constexpr T ctSqrt(T x, T lo, T hi)
{
  return lo == hi ? lo : ((x / MID < MID)
      ? ctSqrt<T>(x, lo, MID - 1) : ctSqrt<T>(x, MID, hi));
}

#endif

template <typename T>
constexpr T ctSqrt(T x)
{
  return ctSqrt<T>(x, 0, x / 2 + 1);
}

template <typename T>
inline T isqrt(T x)
{
  T r = (T) std::sqrt((double) x);

  constexpr T maxSqrt = ctSqrt(std::numeric_limits<T>::max());
  r = std::min(r, maxSqrt);

  while (r * r > x)
    r--;
  while (x - r * r > r * 2)
    r++;

  return r;
}

/// Returns 2^64-1 if (x + y) > 2^64-1
inline uint64_t checkedAdd(uint64_t x, uint64_t y)
{
  if (x >= std::numeric_limits<uint64_t>::max() - y)
    return std::numeric_limits<uint64_t>::max();
  else
    return x + y;
}

/// Returns 0 if (x - y) < 0
inline uint64_t checkedSub(uint64_t x, uint64_t y)
{
  if (x > y)
    return x - y;
  else
    return 0;
}

template <typename A, typename B, typename C>
inline B inBetween(A min, B x, C max)
{
  using T = typename std::common_type<A, B, C>::type;

  if ((T) x < (T) min)
    return (B) min;
  if ((T) x > (T) max)
    return (B) max;

  return x;
}

/// primeCountApprox(x) >= pi(x)
inline std::size_t primeCountApprox(uint64_t start, uint64_t stop)
{
  if (start > stop)
    return 0;
  if (stop <= 10)
    return 4;

  // pi(x) <= x / (log(x) - 1.1) + 5, for x >= 4
  double x = (double) stop;
  double logx = std::log(x);
  double div = logx - 1.1;
  double pix = (stop - start) / div + 5;

  return (std::size_t) pix;
}

inline std::size_t primeCountApprox(uint64_t stop)
{
  return primeCountApprox(0, stop);
}

/// Approximation of the maximum prime gap near n
template <typename T>
inline T maxPrimeGap(T n)
{
  double x = (double) n;
  x = std::max(8.0, x);
  double logx = std::log(x);
  double prime_gap = logx * logx;

  return (T) prime_gap;
}

} // namespace

#endif
<commit_msg>constexpr numberOfBits()<commit_after>///
/// @file   pmath.hpp
/// @brief  Auxiliary math functions for primesieve.
///
/// Copyright (C) 2018 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PMATH_HPP
#define PMATH_HPP

#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <limits>
#include <type_traits>

namespace primesieve {

template <typename X, typename Y>
inline X ceilDiv(X x, Y y)
{
  return (X) ((x + y - 1) / y);
}

template <typename T>
inline bool isPow2(T x)
{
  return x != 0 && (x & (x - 1)) == 0;
}

template <typename T>
constexpr T numberOfBits(T)
{
  return (T) std::numeric_limits<
      typename std::make_unsigned<T>::type
          >::digits;
}

template <typename T>
inline T floorPow2(T x)
{
  for (T i = 1; i < numberOfBits(x); i += i)
    x |= (x >> i);

  return x - (x >> 1);
}

template <typename T>
inline T ilog2(T x)
{
  T bits = numberOfBits(x);
  T one = 1;
  T log2 = 0;

  for (T i = bits / 2; i > 0; i /= 2)
  {
    if (x >= (one << i))
    {
      x >>= i;
      log2 += i;
    }
  }

  return log2;
}

#if __cplusplus >= 201402L

/// C++14 compile time square root using binary search
template <typename T>
constexpr T ctSqrt(T x, T lo, T hi)
{
  if (lo == hi)
    return lo;

  const T mid = (lo + hi + 1) / 2;

  if (x / mid < mid)
    return ctSqrt<T>(x, lo, mid - 1);
  else
    return ctSqrt(x, mid, hi);
}

#else

#define MID ((lo + hi + 1) / 2)

/// C++11 compile time square root using binary search
template <typename T>
constexpr T ctSqrt(T x, T lo, T hi)
{
  return lo == hi ? lo : ((x / MID < MID)
      ? ctSqrt<T>(x, lo, MID - 1) : ctSqrt<T>(x, MID, hi));
}

#endif

template <typename T>
constexpr T ctSqrt(T x)
{
  return ctSqrt<T>(x, 0, x / 2 + 1);
}

template <typename T>
inline T isqrt(T x)
{
  T r = (T) std::sqrt((double) x);

  constexpr T maxSqrt = ctSqrt(std::numeric_limits<T>::max());
  r = std::min(r, maxSqrt);

  while (r * r > x)
    r--;
  while (x - r * r > r * 2)
    r++;

  return r;
}

/// Returns 2^64-1 if (x + y) > 2^64-1
inline uint64_t checkedAdd(uint64_t x, uint64_t y)
{
  if (x >= std::numeric_limits<uint64_t>::max() - y)
    return std::numeric_limits<uint64_t>::max();
  else
    return x + y;
}

/// Returns 0 if (x - y) < 0
inline uint64_t checkedSub(uint64_t x, uint64_t y)
{
  if (x > y)
    return x - y;
  else
    return 0;
}

template <typename A, typename B, typename C>
inline B inBetween(A min, B x, C max)
{
  using T = typename std::common_type<A, B, C>::type;

  if ((T) x < (T) min)
    return (B) min;
  if ((T) x > (T) max)
    return (B) max;

  return x;
}

/// primeCountApprox(x) >= pi(x)
inline std::size_t primeCountApprox(uint64_t start, uint64_t stop)
{
  if (start > stop)
    return 0;
  if (stop <= 10)
    return 4;

  // pi(x) <= x / (log(x) - 1.1) + 5, for x >= 4
  double x = (double) stop;
  double logx = std::log(x);
  double div = logx - 1.1;
  double pix = (stop - start) / div + 5;

  return (std::size_t) pix;
}

inline std::size_t primeCountApprox(uint64_t stop)
{
  return primeCountApprox(0, stop);
}

/// Approximation of the maximum prime gap near n
template <typename T>
inline T maxPrimeGap(T n)
{
  double x = (double) n;
  x = std::max(8.0, x);
  double logx = std::log(x);
  double prime_gap = logx * logx;

  return (T) prime_gap;
}

} // namespace

#endif
<|endoftext|>


<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "concurrency/watchable.hpp"

#include <functional>

#include "errors.hpp"
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>

#include "arch/timing.hpp"
#include "concurrency/cond_var.hpp"
#include "concurrency/wait_any.hpp"

template <class result_type, class outer_type, class callable_type>
class subview_watchable_t : public watchable_t<result_type> {
public:
    subview_watchable_t(const callable_type &l, watchable_t<outer_type> *p) :
        cache(new lensed_value_cache_t(l, p)) { }

    subview_watchable_t *clone() const {
        return new subview_watchable_t(cache);
    }

    result_type get() {
        return *cache->get();
    }

    virtual void apply_read(const std::function<void(const result_type*)> &read) {
        ASSERT_NO_CORO_WAITING;
        read(cache->get());
    }

    publisher_t<boost::function<void()> > *get_publisher() {
        return cache->get_publisher();
    }

    rwi_lock_assertion_t *get_rwi_lock_assertion() {
        return cache->parent->get_rwi_lock_assertion();
    }

private:
    // lensed_value_cache_t is a cache for the result of a lens applied to
    // a given parent watchable. It is implemented for incremental lenses only.
    // (`non_incremental_lens_wrapper_t` can be used to apply it to non-incremental
    // lenses as well).
    // The cached value is recomputed only after the parent has published a new
    // value.
    class lensed_value_cache_t : public home_thread_mixin_t {
    public:
        lensed_value_cache_t(const callable_type &l, watchable_t<outer_type> *p) :
            parent(p->clone()),
            lens(l),
            parent_subscription(boost::bind(
                &subview_watchable_t<result_type, outer_type, callable_type>::lensed_value_cache_t::on_parent_changed,
                this)) {
            typename watchable_t<outer_type>::freeze_t freeze(parent);
            ASSERT_FINITE_CORO_WAITING;
            compute_value();
            parent_subscription.reset(parent, &freeze);
        }

        ~lensed_value_cache_t() {
            assert_thread();
        }

        const result_type *get() {
            assert_thread();
            return &cached_value;
        }

        publisher_t<boost::function<void()> > *get_publisher() {
            assert_thread();
            return publisher_controller.get_publisher();
        }

        clone_ptr_t<watchable_t<outer_type> > parent;

    private:
        bool compute_value() {
            // The closure is to avoid copying the whole value from the parent.

            bool value_changed = false;
            struct op_closure_t {
                static void apply(callable_type *_lens,
                                  bool *_value_changed,
                                  result_type *_cached_value,
                                  const outer_type *val) {
                    *_value_changed = (*_lens)(*val, _cached_value);
                }
            };

            parent->apply_read(std::bind(&op_closure_t::apply,
                                         &lens,
                                         &value_changed,
                                         &cached_value,
                                         std::placeholders::_1));

            return value_changed;
        }

        void on_parent_changed() {
            assert_thread();
            const bool value_changed = compute_value();
            if (value_changed) {
                publisher_controller.publish(&call_function);
            }
        }

        callable_type lens;
        result_type cached_value;
        publisher_controller_t<boost::function<void()> > publisher_controller;
        typename watchable_t<outer_type>::subscription_t parent_subscription;
    };

    explicit subview_watchable_t(const boost::shared_ptr<lensed_value_cache_t> &_cache) :
        cache(_cache) { }

    // If you clone a subview_watchable_t, all clones share the same cache.
    // As a consequence, the lens is only applied once for the whole family
    // of clones, not once per instance of subview_watchable_t. This should save
    // some CPU and memory as well.
    boost::shared_ptr<lensed_value_cache_t> cache;
};

/* Given a non-incremental lens with the type signature
 * `result_type(input_type)`, `non_incremental_lens_wrapper_t` converts
 * it into an incremental lens with type signature
 * `bool(const input_type &, result_type *)` and otherwise equivalent semantics
 * (as much as possible). */
template<class outer_type, class callable_type>
class non_incremental_lens_wrapper_t {
public:
    typedef typename boost::result_of<callable_type(outer_type)>::type result_type;

    explicit non_incremental_lens_wrapper_t(const callable_type &_inner) :
        inner(_inner) {
    }

    bool operator()(const outer_type &input, result_type *current_out) {
        guarantee(current_out != NULL);
        result_type old_value = *current_out;
        *current_out = inner(input);
        return old_value != *current_out;
    }
private:
    callable_type inner;
};

template<class value_type>
template<class callable_type>
clone_ptr_t<watchable_t<typename callable_type::result_type> > watchable_t<value_type>::incremental_subview(const callable_type &lens) {
    assert_thread();
    return clone_ptr_t<watchable_t<typename callable_type::result_type> >(
        new subview_watchable_t<typename callable_type::result_type, value_type, callable_type>(lens, this));
}

template<class value_type>
template<class result_type, class callable_type>
clone_ptr_t<watchable_t<result_type> > watchable_t<value_type>::incremental_subview(const callable_type &lens) {
    assert_thread();
    return clone_ptr_t<watchable_t<result_type> >(
        new subview_watchable_t<result_type, value_type, callable_type>(lens, this));
}

template<class value_type>
template<class callable_type>
clone_ptr_t<watchable_t<typename boost::result_of<callable_type(value_type)>::type> > watchable_t<value_type>::subview(const callable_type &lens) {
    assert_thread();
    typedef non_incremental_lens_wrapper_t<value_type, callable_type> wrapped_callable_type;
    wrapped_callable_type wrapped_lens(lens);
    return clone_ptr_t<watchable_t<typename wrapped_callable_type::result_type> >(
        new subview_watchable_t<typename wrapped_callable_type::result_type, value_type, wrapped_callable_type>(wrapped_lens, this));
}

// These are helper functions for `run_until_satisfied()` and `run_until_satisfied_2()`
// that can be passed into a watchable's `apply_read()`. They simply apply the
// provided function `_fun` to the current value of the watchable(s) and pass out
// its boolean return value.
template<class value_type, class callable_type>
void run_until_satisfied_apply(const callable_type &_fun, const value_type *val,
        bool *is_done_out) {
    *is_done_out = _fun(*val);
}
template<class a_type, class b_type, class callable_type>
void run_until_satisfied_2_apply_inner(const callable_type &_fun,
        const a_type *a_val, const b_type *b_val, bool *is_done_out) {
    *is_done_out = _fun(*a_val, *b_val);
}
template<class a_type, class b_type, class callable_type>
void run_until_satisfied_2_apply_outer(const callable_type &_fun,
        const clone_ptr_t<watchable_t<b_type> > &_b, const a_type *a_val,
        bool *is_done_out) {
    _b->apply_read(std::bind(
        &run_until_satisfied_2_apply_inner<a_type, b_type, callable_type>, _fun, a_val,
        std::placeholders::_1, is_done_out));
}

template<class value_type>
template<class callable_type>
void watchable_t<value_type>::run_until_satisfied(const callable_type &fun,
        signal_t *interruptor, int64_t nap_before_retry_ms) THROWS_ONLY(interrupted_exc_t) {
    assert_thread();

    bool is_done = false;
    auto op = std::bind(&run_until_satisfied_apply<value_type, callable_type>,
                        fun,
                        std::placeholders::_1,
                        &is_done);

    clone_ptr_t<watchable_t<value_type> > clone_this(this->clone());
    while (true) {
        cond_t changed;
        typename watchable_t<value_type>::subscription_t subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        {
            typename watchable_t<value_type>::freeze_t freeze(clone_this);
            ASSERT_FINITE_CORO_WAITING;
            clone_this->apply_read(op);
            if (is_done) {
                return;
            }
            subs.reset(clone_this, &freeze);
        }
        // Nap a little so changes to the watchables can accumulate.
        // This is purely a performance optimization to save CPU cycles,
        // in case that applying `fun` is expensive.
        nap(nap_before_retry_ms, interruptor);
        wait_interruptible(&changed, interruptor);
    }
}

template<class a_type, class b_type, class callable_type>
void run_until_satisfied_2(
        const clone_ptr_t<watchable_t<a_type> > &a,
        const clone_ptr_t<watchable_t<b_type> > &b,
        const callable_type &fun,
        signal_t *interruptor,
        int64_t nap_before_retry_ms) THROWS_ONLY(interrupted_exc_t) {
    a->assert_thread();
    b->assert_thread();

    bool is_done = false;
    auto op = std::bind(&run_until_satisfied_2_apply_outer<a_type, b_type, callable_type>,
                        fun,
                        b,
                        std::placeholders::_1,
                        &is_done);

    while (true) {
        cond_t changed;
        typename watchable_t<a_type>::subscription_t a_subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        typename watchable_t<b_type>::subscription_t b_subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        {
            typename watchable_t<a_type>::freeze_t a_freeze(a);
            typename watchable_t<b_type>::freeze_t b_freeze(b);
            ASSERT_FINITE_CORO_WAITING;
            a->apply_read(op);
            if (is_done) {
                return;
            }
            a_subs.reset(a, &a_freeze);
            b_subs.reset(b, &b_freeze);
        }
        // Nap a little so changes to the watchables can accumulate.
        // This is purely a performance optimization to save CPU cycles,
        // in case that applying `fun` is expensive (which it is in our
        // applications in the reactors as of 12/10/2013).
        nap(nap_before_retry_ms, interruptor);
        wait_interruptible(&changed, interruptor);
    }
}
<commit_msg>Don't nap if nap time is 0.<commit_after>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "concurrency/watchable.hpp"

#include <functional>

#include "errors.hpp"
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>

#include "arch/timing.hpp"
#include "concurrency/cond_var.hpp"
#include "concurrency/wait_any.hpp"

template <class result_type, class outer_type, class callable_type>
class subview_watchable_t : public watchable_t<result_type> {
public:
    subview_watchable_t(const callable_type &l, watchable_t<outer_type> *p) :
        cache(new lensed_value_cache_t(l, p)) { }

    subview_watchable_t *clone() const {
        return new subview_watchable_t(cache);
    }

    result_type get() {
        return *cache->get();
    }

    virtual void apply_read(const std::function<void(const result_type*)> &read) {
        ASSERT_NO_CORO_WAITING;
        read(cache->get());
    }

    publisher_t<boost::function<void()> > *get_publisher() {
        return cache->get_publisher();
    }

    rwi_lock_assertion_t *get_rwi_lock_assertion() {
        return cache->parent->get_rwi_lock_assertion();
    }

private:
    // lensed_value_cache_t is a cache for the result of a lens applied to
    // a given parent watchable. It is implemented for incremental lenses only.
    // (`non_incremental_lens_wrapper_t` can be used to apply it to non-incremental
    // lenses as well).
    // The cached value is recomputed only after the parent has published a new
    // value.
    class lensed_value_cache_t : public home_thread_mixin_t {
    public:
        lensed_value_cache_t(const callable_type &l, watchable_t<outer_type> *p) :
            parent(p->clone()),
            lens(l),
            parent_subscription(boost::bind(
                &subview_watchable_t<result_type, outer_type, callable_type>::lensed_value_cache_t::on_parent_changed,
                this)) {
            typename watchable_t<outer_type>::freeze_t freeze(parent);
            ASSERT_FINITE_CORO_WAITING;
            compute_value();
            parent_subscription.reset(parent, &freeze);
        }

        ~lensed_value_cache_t() {
            assert_thread();
        }

        const result_type *get() {
            assert_thread();
            return &cached_value;
        }

        publisher_t<boost::function<void()> > *get_publisher() {
            assert_thread();
            return publisher_controller.get_publisher();
        }

        clone_ptr_t<watchable_t<outer_type> > parent;

    private:
        bool compute_value() {
            // The closure is to avoid copying the whole value from the parent.

            bool value_changed = false;
            struct op_closure_t {
                static void apply(callable_type *_lens,
                                  bool *_value_changed,
                                  result_type *_cached_value,
                                  const outer_type *val) {
                    *_value_changed = (*_lens)(*val, _cached_value);
                }
            };

            parent->apply_read(std::bind(&op_closure_t::apply,
                                         &lens,
                                         &value_changed,
                                         &cached_value,
                                         std::placeholders::_1));

            return value_changed;
        }

        void on_parent_changed() {
            assert_thread();
            const bool value_changed = compute_value();
            if (value_changed) {
                publisher_controller.publish(&call_function);
            }
        }

        callable_type lens;
        result_type cached_value;
        publisher_controller_t<boost::function<void()> > publisher_controller;
        typename watchable_t<outer_type>::subscription_t parent_subscription;
    };

    explicit subview_watchable_t(const boost::shared_ptr<lensed_value_cache_t> &_cache) :
        cache(_cache) { }

    // If you clone a subview_watchable_t, all clones share the same cache.
    // As a consequence, the lens is only applied once for the whole family
    // of clones, not once per instance of subview_watchable_t. This should save
    // some CPU and memory as well.
    boost::shared_ptr<lensed_value_cache_t> cache;
};

/* Given a non-incremental lens with the type signature
 * `result_type(input_type)`, `non_incremental_lens_wrapper_t` converts
 * it into an incremental lens with type signature
 * `bool(const input_type &, result_type *)` and otherwise equivalent semantics
 * (as much as possible). */
template<class outer_type, class callable_type>
class non_incremental_lens_wrapper_t {
public:
    typedef typename boost::result_of<callable_type(outer_type)>::type result_type;

    explicit non_incremental_lens_wrapper_t(const callable_type &_inner) :
        inner(_inner) {
    }

    bool operator()(const outer_type &input, result_type *current_out) {
        guarantee(current_out != NULL);
        result_type old_value = *current_out;
        *current_out = inner(input);
        return old_value != *current_out;
    }
private:
    callable_type inner;
};

template<class value_type>
template<class callable_type>
clone_ptr_t<watchable_t<typename callable_type::result_type> > watchable_t<value_type>::incremental_subview(const callable_type &lens) {
    assert_thread();
    return clone_ptr_t<watchable_t<typename callable_type::result_type> >(
        new subview_watchable_t<typename callable_type::result_type, value_type, callable_type>(lens, this));
}

template<class value_type>
template<class result_type, class callable_type>
clone_ptr_t<watchable_t<result_type> > watchable_t<value_type>::incremental_subview(const callable_type &lens) {
    assert_thread();
    return clone_ptr_t<watchable_t<result_type> >(
        new subview_watchable_t<result_type, value_type, callable_type>(lens, this));
}

template<class value_type>
template<class callable_type>
clone_ptr_t<watchable_t<typename boost::result_of<callable_type(value_type)>::type> > watchable_t<value_type>::subview(const callable_type &lens) {
    assert_thread();
    typedef non_incremental_lens_wrapper_t<value_type, callable_type> wrapped_callable_type;
    wrapped_callable_type wrapped_lens(lens);
    return clone_ptr_t<watchable_t<typename wrapped_callable_type::result_type> >(
        new subview_watchable_t<typename wrapped_callable_type::result_type, value_type, wrapped_callable_type>(wrapped_lens, this));
}

// These are helper functions for `run_until_satisfied()` and `run_until_satisfied_2()`
// that can be passed into a watchable's `apply_read()`. They simply apply the
// provided function `_fun` to the current value of the watchable(s) and pass out
// its boolean return value.
template<class value_type, class callable_type>
void run_until_satisfied_apply(const callable_type &_fun, const value_type *val,
        bool *is_done_out) {
    *is_done_out = _fun(*val);
}
template<class a_type, class b_type, class callable_type>
void run_until_satisfied_2_apply_inner(const callable_type &_fun,
        const a_type *a_val, const b_type *b_val, bool *is_done_out) {
    *is_done_out = _fun(*a_val, *b_val);
}
template<class a_type, class b_type, class callable_type>
void run_until_satisfied_2_apply_outer(const callable_type &_fun,
        const clone_ptr_t<watchable_t<b_type> > &_b, const a_type *a_val,
        bool *is_done_out) {
    _b->apply_read(std::bind(
        &run_until_satisfied_2_apply_inner<a_type, b_type, callable_type>, _fun, a_val,
        std::placeholders::_1, is_done_out));
}

template<class value_type>
template<class callable_type>
void watchable_t<value_type>::run_until_satisfied(const callable_type &fun,
        signal_t *interruptor, int64_t nap_before_retry_ms) THROWS_ONLY(interrupted_exc_t) {
    assert_thread();

    bool is_done = false;
    auto op = std::bind(&run_until_satisfied_apply<value_type, callable_type>,
                        fun,
                        std::placeholders::_1,
                        &is_done);

    clone_ptr_t<watchable_t<value_type> > clone_this(this->clone());
    while (true) {
        cond_t changed;
        typename watchable_t<value_type>::subscription_t subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        {
            typename watchable_t<value_type>::freeze_t freeze(clone_this);
            ASSERT_FINITE_CORO_WAITING;
            clone_this->apply_read(op);
            if (is_done) {
                return;
            }
            subs.reset(clone_this, &freeze);
        }
        // Nap a little so changes to the watchables can accumulate.
        // This is purely a performance optimization to save CPU cycles,
        // in case that applying `fun` is expensive.
        if (nap_before_retry_ms > 0) {
            nap(nap_before_retry_ms, interruptor);
        }
        wait_interruptible(&changed, interruptor);
    }
}

template<class a_type, class b_type, class callable_type>
void run_until_satisfied_2(
        const clone_ptr_t<watchable_t<a_type> > &a,
        const clone_ptr_t<watchable_t<b_type> > &b,
        const callable_type &fun,
        signal_t *interruptor,
        int64_t nap_before_retry_ms) THROWS_ONLY(interrupted_exc_t) {
    a->assert_thread();
    b->assert_thread();

    bool is_done = false;
    auto op = std::bind(&run_until_satisfied_2_apply_outer<a_type, b_type, callable_type>,
                        fun,
                        b,
                        std::placeholders::_1,
                        &is_done);

    while (true) {
        cond_t changed;
        typename watchable_t<a_type>::subscription_t a_subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        typename watchable_t<b_type>::subscription_t b_subs(boost::bind(&cond_t::pulse_if_not_already_pulsed, &changed));
        {
            typename watchable_t<a_type>::freeze_t a_freeze(a);
            typename watchable_t<b_type>::freeze_t b_freeze(b);
            ASSERT_FINITE_CORO_WAITING;
            a->apply_read(op);
            if (is_done) {
                return;
            }
            a_subs.reset(a, &a_freeze);
            b_subs.reset(b, &b_freeze);
        }
        // Nap a little so changes to the watchables can accumulate.
        // This is purely a performance optimization to save CPU cycles,
        // in case that applying `fun` is expensive (which it is in our
        // applications in the reactors as of 12/10/2013).
        if (nap_before_retry_ms > 0) {
            nap(nap_before_retry_ms, interruptor);
        }
        wait_interruptible(&changed, interruptor);
    }
}
<|endoftext|>


<commit_before>#include "condor_common.h"
#include "condor_config.h"
#include "condor_api.h"
#include "status_types.h"
#include "totals.h"

// global variables
AttrListPrintMask pm;
char 		*pool 	= NULL;
AdTypes		type 	= (AdTypes) -1;
ppOption	ppStyle	= PP_NOTSET;
int			wantTotals 	= 0;
int			summarySize = -1;
Mode		mode	= MODE_NOTSET;
int			diagnose = 0;
CondorQuery *query;
char		buffer[1024];
ClassAdList result;
Totals		totals;
char		*myName;

// function declarations
void usage 		();
void firstPass  (int, char *[]);
void secondPass (int, char *[]);
void prettyPrint(ClassAdList &);
int  matchPrefix(char *, char *);

extern "C" int SetSyscalls (int) {return 0;}
extern	void setPPstyle (ppOption, int, char *);
extern	void setType    (char *, int, char *);
extern	void setMode 	(Mode, int, char *);

int
main (int argc, char *argv[])
{
	// initialize to read from config file
	myName = argv[0];
	config ((ClassAd*)NULL);

	// The arguments take two passes to process --- the first pass
	// figures out the mode, after which we can instantiate the required
	// query object.  We add implied constraints from the command line in
	// the second pass.
	firstPass (argc, argv);

	// if the mode has not been set, it is NORMAL
	if (mode == MODE_NOTSET) {
		setMode (MODE_NORMAL, 0, "<default>");
	}

	// instantiate query object
	if (!(query = new CondorQuery (type))) {
		fprintf (stderr, "Error:  Out of memory\n");
		exit (1);
	}

	// set the constraint implied by the mode
	switch (mode) {
	  case MODE_NORMAL:
	  case MODE_CUSTOM:
		break;

	  case MODE_AVAIL:
		// **** Remeber to change to evaluating Requirements ****
		if (diagnose) {
			printf ("Adding constraint [%s]\n", "TARGET.START == True");
		}
		query->addConstraint ("TARGET.START == True");
		break;

	  case MODE_SUBMITTORS:
		sprintf (buffer,"TARGET.%s > 0 || TARGET.%s > 0", ATTR_IDLE_JOBS,
			ATTR_RUNNING_JOBS);
		if (diagnose) {
			printf ("Adding constraint [%s]\n", buffer);
		}
		query->addConstraint (buffer);
		break;

	  case MODE_RUN:
		sprintf (buffer, "TARGET.%s != \"NoJob\"", ATTR_STATE);
		if (diagnose) {
			printf ("Adding constraint [%s]\n", buffer);
		}
		query->addConstraint (buffer);
		break;
	}

	// second pass:  add regular parameters and constraints
	if (diagnose) {
		printf ("----------\n");
	}

	secondPass (argc, argv);

	// initialize the totals object
	if (wantTotals && summarySize == -1) {
		fprintf (stderr,"Error:  Want totals, but no total support for mode\n");
		exit (1);
	}
	totals.setSummarySize (summarySize);

	// fetch the query
	QueryResult q;

	// if diagnose was requested, just print the query ad
	if (diagnose) {
		ClassAd 	queryAd;

		// print diagnostic information about inferred internal state
		setMode ((Mode) 0, 0, NULL);
		setType (NULL, 0, NULL);
		setPPstyle ((ppOption) 0, 0, NULL);
		printf ("----------\n");

		q = query->getQueryAd (queryAd);
		queryAd.fPrint (stdout);

		printf ("----------\n");
		fprintf (stderr, "Result of making query ad was:  %d\n", q);
		exit (1);
	}

	if ((q = query->fetchAds (result, pool)) != Q_OK) {
		fprintf (stderr, "Error:  Could not fetch ads --- error %d\n", q);
		exit (1);
	}

	// output result
	prettyPrint (result);

	// be nice ...
	delete query;

	return 0;
}

void
usage ()
{
	fprintf (stderr,"Usage: %s [options]\n"
		"    where [options] are zero or more of\n"
		"\t[-avail]\t\tPrint information about available resources\n"
		"\t[-constraint <const>]\tAdd constraint on classads\n"
		"\t[-diagnose]\t\tPrint out query ad without performing query\n"
		"\t[-entity <type>]\tForce query on specified entity\n"
		"\t[-format <fmt> <attr>]\tRegister display format and attribute\n"
		"\t[-help]\t\t\tThis screen\n"
		"\t[-long]\t\t\tDisplay entire classads\n"
		"\t[-pool <poolname>]\tGet information from <poolname>\n"
		"\t[-run]\t\t\tPrint information about employed resources\n"
		"\t[-server]\t\tDisplay important attributes of resources\n"
		"\t[-submittors]\t\tObtain information about submittors\n"
		"\t[-total]\t\tDisplay totals only\n"
		"\t[-verbose]\t\tSame as -long\n",
		myName);
}

void
firstPass (int argc, char *argv[])
{
	// Process arguments:  there are dependencies between them
	// o -l/v and -serv are mutually exclusive
	// o -sub, -avail and -run are mutually exclusive
	// o -pool and -entity may be used at most once
	// o since -c can be processed only after the query has been instantiated,
	//   constraints are added on the second pass
	for (int i = 1; i < argc; i++) {
		if (matchPrefix (argv[i], "-avail")) {
			setMode (MODE_AVAIL, i, argv[i]);
		} else
		if (matchPrefix (argv[i], "-pool")) {
			if (pool == NULL) {
				pool = argv[++i];
			} else {
				fprintf (stderr, "At most one -pool argument may be used\n");
				exit (1);
			}
		} else
		if (matchPrefix (argv[i], "-format")) {
			setPPstyle (PP_CUSTOM, i, argv[i]);
			pm.registerFormat (argv[i+1], argv[i+2]);
			if (diagnose) {
				printf ("Arg %d --- register format [%s] for [%s]\n",
						i, argv[i+1], argv[i+2]);
			}
			i += 2;
		} else
		if (matchPrefix (argv[i], "-constraint")) {
			// can add constraints on second pass only
			i++;
		} else
		if (matchPrefix (argv[i], "-diagnose")) {
			diagnose = 1;
		} else
		if (matchPrefix (argv[i], "-help")) {
			usage ();
			exit (1);
		} else
		if (matchPrefix (argv[i],"-long") || matchPrefix (argv[i],"-verbose")) {
			setPPstyle (PP_VERBOSE, i, argv[i]);
		} else
		if (matchPrefix (argv[i], "-run")) {
			setMode (MODE_RUN, i, argv[i]);
		} else
		if (matchPrefix (argv[i], "-server")) {
			setPPstyle (PP_SERVER, i, argv[i]);
		} else
		if (matchPrefix (argv[i], "-submittors")) {
			setMode (MODE_SUBMITTORS, i, argv[i]);
		} else
		if (matchPrefix (argv[i], "-total")) {
			wantTotals = 1;
		} else
		if (matchPrefix (argv[i], "-entity")) {
			setMode (MODE_CUSTOM, i, argv[i]);
			setType (argv[i+1], i, argv[i]);
		} else
		if (*argv[i] == '-') {
			fprintf (stderr, "Error:  Unknown option %s\n", argv[i]);
			usage ();
			exit (1);
		}
	}
}

void
secondPass (int argc, char *argv[])
{
	for (int i = 1; i < argc; i++) {
		// omit parameters which qualify switches
		if (matchPrefix (argv[i], "-pool")) {
			i++;
			continue;
		}
		if (matchPrefix (argv[i], "-entity")) {
			i++;
			continue;
		}
		if (matchPrefix (argv[i], "-format")) {
			i += 2;
			continue;
		}

		// figure out what the other parameters should do
		if (*argv[i] != '-') {
			// display extra information for diagnosis
			if (diagnose) {
				printf ("Arg %d (%s) --- adding constraint", i, argv[i]);
			}

			switch (mode) {
			  case MODE_NORMAL:
    		  case MODE_AVAIL:
    		  case MODE_SUBMITTORS:
				sprintf (buffer, "TARGET.%s == \"%s\"", ATTR_NAME, argv[i]);
				if (diagnose) {
					printf ("[%s]\n", buffer);
				}
				query->addConstraint (buffer);
				break;

    		  case MODE_RUN:
				sprintf (buffer,"TARGET.%s == \"%s\"",ATTR_REMOTE_USER,argv[i]);
				if (diagnose) {
					printf ("[%s]\n", buffer);
				}
				query->addConstraint (buffer);
				break;

    		  case MODE_CUSTOM:
				if (diagnose) {
					printf ("[%s]\n", buffer);
				}
				query->addConstraint (argv[i]);
				break;

			  default:
				fprintf(stderr,"Error: Don't know how to process %s\n",argv[i]);
			}
		} else
		if (matchPrefix (argv[i], "-constraint")) {
			if (diagnose) {
				printf ("[%s]\n", argv[i+1]);
			}
			query->addConstraint (argv[i+1]);
			i++;
		}
	}
}

int
matchPrefix (char *s1, char *s2)
{
	int lenS1 = strlen (s1);
	int lenS2 = strlen (s2);
	int len = (lenS1 < lenS2) ? lenS1 : lenS2;

	return (strncmp (s1, s2, len) == 0);
}
<commit_msg>Added a better error message on query failure.  Also fixed bug with -pool option, which previously used the string "-pool" as the target collector instead of the option which followed it.<commit_after>#include "condor_common.h"
#include "condor_config.h"
#include "condor_api.h"
#include "status_types.h"
#include "totals.h"

// global variables
AttrListPrintMask pm;
char 		*pool 	= NULL;
AdTypes		type 	= (AdTypes) -1;
ppOption	ppStyle	= PP_NOTSET;
int			wantTotals 	= 0;
int			summarySize = -1;
Mode		mode	= MODE_NOTSET;
int			diagnose = 0;
CondorQuery *query;
char		buffer[1024];
ClassAdList result;
Totals		totals;
char		*myName;

// function declarations
void usage 		();
void firstPass  (int, char *[]);
void secondPass (int, char *[]);
void prettyPrint(ClassAdList &);
int  matchPrefix(char *, char *);

extern "C" int SetSyscalls (int) {return 0;}
extern	void setPPstyle (ppOption, int, char *);
extern	void setType    (char *, int, char *);
extern	void setMode 	(Mode, int, char *);

int
main (int argc, char *argv[])
{
	// initialize to read from config file
	myName = argv[0];
	config ((ClassAd*)NULL);

	// The arguments take two passes to process --- the first pass
	// figures out the mode, after which we can instantiate the required
	// query object.  We add implied constraints from the command line in
	// the second pass.
	firstPass (argc, argv);

	// if the mode has not been set, it is NORMAL
	if (mode == MODE_NOTSET) {
		setMode (MODE_NORMAL, 0, "<default>");
	}

	// instantiate query object
	if (!(query = new CondorQuery (type))) {
		fprintf (stderr, "Error:  Out of memory\n");
		exit (1);
	}

	// set the constraint implied by the mode
	switch (mode) {
	  case MODE_NORMAL:
	  case MODE_CUSTOM:
		break;

	  case MODE_AVAIL:
		// **** Remeber to change to evaluating Requirements ****
		if (diagnose) {
			printf ("Adding constraint [%s]\n", "TARGET.START == True");
		}
		query->addConstraint ("TARGET.START == True");
		break;

	  case MODE_SUBMITTORS:
		sprintf (buffer,"TARGET.%s > 0 || TARGET.%s > 0", ATTR_IDLE_JOBS,
			ATTR_RUNNING_JOBS);
		if (diagnose) {
			printf ("Adding constraint [%s]\n", buffer);
		}
		query->addConstraint (buffer);
		break;

	  case MODE_RUN:
		sprintf (buffer, "TARGET.%s != \"NoJob\"", ATTR_STATE);
		if (diagnose) {
			printf ("Adding constraint [%s]\n", buffer);
		}
		query->addConstraint (buffer);
		break;
	}

	// second pass:  add regular parameters and constraints
	if (diagnose) {
		printf ("----------\n");
	}

	secondPass (argc, argv);

	// initialize the totals object
	if (wantTotals && summarySize == -1) {
		fprintf (stderr,"Error:  Want totals, but no total support for mode\n");
		exit (1);
	}
	totals.setSummarySize (summarySize);

	// fetch the query
	QueryResult q;

	// if diagnose was requested, just print the query ad
	if (diagnose) {
		ClassAd 	queryAd;

		// print diagnostic information about inferred internal state
		setMode ((Mode) 0, 0, NULL);
		setType (NULL, 0, NULL);
		setPPstyle ((ppOption) 0, 0, NULL);
		printf ("----------\n");

		q = query->getQueryAd (queryAd);
		queryAd.fPrint (stdout);

		printf ("----------\n");
		fprintf (stderr, "Result of making query ad was:  %d\n", q);
		exit (1);
	}

	if ((q = query->fetchAds (result, pool)) != Q_OK) {
		fprintf (stderr, "Error:  Could not fetch ads --- error %s\n",
					StrQueryResult[q]);
		exit (1);
	}

	// output result
	prettyPrint (result);

	// be nice ...
	delete query;

	return 0;
}

void
usage ()
{
	fprintf (stderr,"Usage: %s [options]\n"
		"    where [options] are zero or more of\n"
		"\t[-avail]\t\tPrint information about available resources\n"
		"\t[-constraint <const>]\tAdd constraint on classads\n"
		"\t[-diagnose]\t\tPrint out query ad without performing query\n"
		"\t[-entity <type>]\tForce query on specified entity\n"
		"\t[-format <fmt> <attr>]\tRegister display format and attribute\n"
		"\t[-help]\t\t\tThis screen\n"
		"\t[-long]\t\t\tDisplay entire classads\n"
		"\t[-pool <poolname>]\tGet information from <poolname>\n"
		"\t[-run]\t\t\tPrint information about employed resources\n"
		"\t[-server]\t\tDisplay important attributes of resources\n"
		"\t[-submittors]\t\tObtain information about submittors\n"
		"\t[-total]\t\tDisplay totals only\n"
		"\t[-verbose]\t\tSame as -long\n",
		myName);
}

void
firstPass (int argc, char *argv[])
{
	// Process arguments:  there are dependencies between them
	// o -l/v and -serv are mutually exclusive
	// o -sub, -avail and -run are mutually exclusive
	// o -pool and -entity may be used at most once
	// o since -c can be processed only after the query has been instantiated,
	//   constraints are added on the second pass
	for (int i = 1; i < argc; i++) {
		if (matchPrefix (argv[i], "-avail")) {
			setMode (MODE_AVAIL, i, argv[i]);
		} else
		if (matchPrefix (argv[i], "-pool")) {
			if (pool == NULL) {
				pool = argv[++i];
			} else {
				fprintf (stderr, "At most one -pool argument may be used\n");
				exit (1);
			}
		} else
		if (matchPrefix (argv[i], "-format")) {
			setPPstyle (PP_CUSTOM, i, argv[i]);
			pm.registerFormat (argv[i+1], argv[i+2]);
			if (diagnose) {
				printf ("Arg %d --- register format [%s] for [%s]\n",
						i, argv[i+1], argv[i+2]);
			}
			i += 2;
		} else
		if (matchPrefix (argv[i], "-constraint")) {
			// can add constraints on second pass only
			i++;
		} else
		if (matchPrefix (argv[i], "-diagnose")) {
			diagnose = 1;
		} else
		if (matchPrefix (argv[i], "-help")) {
			usage ();
			exit (1);
		} else
		if (matchPrefix (argv[i],"-long") || matchPrefix (argv[i],"-verbose")) {
			setPPstyle (PP_VERBOSE, i, argv[i]);
		} else
		if (matchPrefix (argv[i], "-run")) {
			setMode (MODE_RUN, i, argv[i]);
		} else
		if (matchPrefix (argv[i], "-server")) {
			setPPstyle (PP_SERVER, i, argv[i]);
		} else
		if (matchPrefix (argv[i], "-submittors")) {
			setMode (MODE_SUBMITTORS, i, argv[i]);
		} else
		if (matchPrefix (argv[i], "-total")) {
			wantTotals = 1;
		} else
		if (matchPrefix (argv[i], "-entity")) {
			setMode (MODE_CUSTOM, i, argv[i]);
			setType (argv[i+1], i, argv[i]);
		} else
		if (*argv[i] == '-') {
			fprintf (stderr, "Error:  Unknown option %s\n", argv[i]);
			usage ();
			exit (1);
		}
	}
}

void
secondPass (int argc, char *argv[])
{
	for (int i = 1; i < argc; i++) {
		// omit parameters which qualify switches
		if (matchPrefix (argv[i], "-pool")) {
			i++;
			continue;
		}
		if (matchPrefix (argv[i], "-entity")) {
			i++;
			continue;
		}
		if (matchPrefix (argv[i], "-format")) {
			i += 2;
			continue;
		}

		// figure out what the other parameters should do
		if (*argv[i] != '-') {
			// display extra information for diagnosis
			if (diagnose) {
				printf ("Arg %d (%s) --- adding constraint", i, argv[i]);
			}

			switch (mode) {
			  case MODE_NORMAL:
    		  case MODE_AVAIL:
    		  case MODE_SUBMITTORS:
				sprintf (buffer, "TARGET.%s == \"%s\"", ATTR_NAME, argv[i]);
				if (diagnose) {
					printf ("[%s]\n", buffer);
				}
				query->addConstraint (buffer);
				break;

    		  case MODE_RUN:
				sprintf (buffer,"TARGET.%s == \"%s\"",ATTR_REMOTE_USER,argv[i]);
				if (diagnose) {
					printf ("[%s]\n", buffer);
				}
				query->addConstraint (buffer);
				break;

    		  case MODE_CUSTOM:
				if (diagnose) {
					printf ("[%s]\n", buffer);
				}
				query->addConstraint (argv[i]);
				break;

			  default:
				fprintf(stderr,"Error: Don't know how to process %s\n",argv[i]);
			}
		} else
		if (matchPrefix (argv[i], "-constraint")) {
			if (diagnose) {
				printf ("[%s]\n", argv[i+1]);
			}
			query->addConstraint (argv[i+1]);
			i++;
		}
	}
}

int
matchPrefix (char *s1, char *s2)
{
	int lenS1 = strlen (s1);
	int lenS2 = strlen (s2);
	int len = (lenS1 < lenS2) ? lenS1 : lenS2;

	return (strncmp (s1, s2, len) == 0);
}
<|endoftext|>


<commit_before><commit_msg>Create 1190 - Right Area.cpp<commit_after><|endoftext|>