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

#ifndef _UNOTOOLS_CALENDARWRAPPER_HXX
#define _UNOTOOLS_CALENDARWRAPPER_HXX

#ifndef _DATETIME_HXX
#include <tools/datetime.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_I18N_CALENDAR_HPP_
#include <com/sun/star/i18n/Calendar.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_
#include <com/sun/star/lang/Locale.hpp>
#endif

namespace com { namespace sun { namespace star {
    namespace lang {
        class XMultiServiceFactory;
    }
    namespace i18n {
        class XCalendar;
    }
}}}

class CalendarWrapper
{
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr;
    ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XCalendar >   xC;

            DateTime            aEpochStart;        // 1Jan1970

public:
                                CalendarWrapper(
                                    const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF
                                    );
                                ~CalendarWrapper();

    // wrapper implementations of XCalendar

    void loadDefaultCalendar( const ::com::sun::star::lang::Locale& rLocale );
    void loadCalendar( const ::rtl::OUString& rUniqueID, const ::com::sun::star::lang::Locale& rLocale );
    ::com::sun::star::i18n::Calendar getLoadedCalendar() const;
    ::com::sun::star::uno::Sequence< ::rtl::OUString > getAllCalendars( const ::com::sun::star::lang::Locale& rLocale ) const;
    ::rtl::OUString getUniqueID() const;
    void setDateTime( double nTimeInDays );
    double getDateTime() const;
    void setValue( sal_Int16 nFieldIndex, sal_Int16 nValue );
    sal_Bool isValid() const;
    sal_Int16 getValue( sal_Int16 nFieldIndex ) const;
    void addValue( sal_Int16 nFieldIndex, sal_Int32 nAmount );
    sal_Int16 getFirstDayOfWeek() const;
    void setFirstDayOfWeek( sal_Int16 nDay );
    void setMinimumNumberOfDaysForFirstWeek( sal_Int16 nDays );
    sal_Int16 getMinimumNumberOfDaysForFirstWeek() const;
    sal_Int16 getNumberOfMonthsInYear() const;
    sal_Int16 getNumberOfDaysInWeek() const;
    ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > getMonths() const;
    ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > getDays() const;
    String getDisplayName( sal_Int16 nCalendarDisplayIndex, sal_Int16 nIdx, sal_Int16 nNameType ) const;

    // convenience methods

    /// set a gregorian DateTime
    inline  void                setGregorianDateTime( const DateTime& rDateTime )
                                    { setDateTime( rDateTime - aEpochStart ); }

    /// get the DateTime as a gregorian DateTime
    inline  DateTime            getGregorianDateTime() const
                                    { return aEpochStart + getDateTime(); }

};

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

#ifndef _UNOTOOLS_CALENDARWRAPPER_HXX
#define _UNOTOOLS_CALENDARWRAPPER_HXX

#ifndef _DATETIME_HXX
#include <tools/datetime.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_I18N_CALENDAR_HPP_
#include <com/sun/star/i18n/Calendar.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_
#include <com/sun/star/lang/Locale.hpp>
#endif

namespace com { namespace sun { namespace star {
    namespace lang {
        class XMultiServiceFactory;
    }
    namespace i18n {
        class XCalendar;
    }
}}}

class CalendarWrapper
{
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr;
    ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XCalendar >   xC;

            DateTime            aEpochStart;        // 1Jan1970

public:
                                CalendarWrapper(
                                    const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & xSF
                                    );
                                ~CalendarWrapper();

    // wrapper implementations of XCalendar

    void loadDefaultCalendar( const ::com::sun::star::lang::Locale& rLocale );
    void loadCalendar( const ::rtl::OUString& rUniqueID, const ::com::sun::star::lang::Locale& rLocale );
    ::com::sun::star::i18n::Calendar getLoadedCalendar() const;
    ::com::sun::star::uno::Sequence< ::rtl::OUString > getAllCalendars( const ::com::sun::star::lang::Locale& rLocale ) const;
    ::rtl::OUString getUniqueID() const;
    void setDateTime( double nTimeInDays );
    double getDateTime() const;
    void setValue( sal_Int16 nFieldIndex, sal_Int16 nValue );
    sal_Bool isValid() const;
    sal_Int16 getValue( sal_Int16 nFieldIndex ) const;
    void addValue( sal_Int16 nFieldIndex, sal_Int32 nAmount );
    sal_Int16 getFirstDayOfWeek() const;
    void setFirstDayOfWeek( sal_Int16 nDay );
    void setMinimumNumberOfDaysForFirstWeek( sal_Int16 nDays );
    sal_Int16 getMinimumNumberOfDaysForFirstWeek() const;
    sal_Int16 getNumberOfMonthsInYear() const;
    sal_Int16 getNumberOfDaysInWeek() const;
    ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > getMonths() const;
    ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > getDays() const;
    String getDisplayName( sal_Int16 nCalendarDisplayIndex, sal_Int16 nIdx, sal_Int16 nNameType ) const;

    // convenience methods

    /// get epoch start (should be 01Jan1970)
    inline  const DateTime&     getEpochStart() const
                                    { return aEpochStart; }

    /// set a gregorian DateTime
    inline  void                setGregorianDateTime( const DateTime& rDateTime )
                                    { setDateTime( rDateTime - aEpochStart ); }

    /// get the DateTime as a gregorian DateTime
    inline  DateTime            getGregorianDateTime() const
                                    { return aEpochStart + getDateTime(); }

};

#endif
<|endoftext|>


<commit_before>/*********************************************************************
 *
 * Copyright 2011 Intel Corporation
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *********************************************************************/

#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>

#include <iostream>

#include "os_string.hpp"
#include "os_process.hpp"
#include "os_version.hpp"

#include "cli.hpp"
#include "cli_resources.hpp"

#if defined(__APPLE__)
#define TRACE_VARIABLE "DYLD_FRAMEWORK_PATH"
#define GL_TRACE_WRAPPER  "OpenGL.framework/OpenGL"
#elif defined(_WIN32)
#define GL_TRACE_WRAPPER  "opengl32.dll"
#else
#define TRACE_VARIABLE "LD_PRELOAD"
#define GL_TRACE_WRAPPER  "glxtrace.so"
#define EGL_TRACE_WRAPPER  "egltrace.so"
#endif

static inline bool
copyWrapper(const os::String & wrapperPath,
            const char *programPath,
            bool verbose)
{
    os::String wrapperFilename(wrapperPath);
    wrapperFilename.trimDirectory();

    os::String tmpWrapper(programPath);
    tmpWrapper.trimFilename();
    tmpWrapper.join(wrapperFilename);

    if (verbose) {
        std::cerr << wrapperPath << " -> " << tmpWrapper << "\n";
    }

    if (tmpWrapper.exists()) {
        std::cerr << "error: not overwriting " << tmpWrapper << "\n";
        return false;
    }

    if (!os::copyFile(wrapperPath, tmpWrapper, false)) {
        std::cerr << "error: failed to copy " << wrapperPath << " into " << tmpWrapper << "\n";
        return false;
    }

    return true;
}

static int
traceProgram(trace::API api,
             char * const *argv,
             const char *output,
             bool verbose,
             bool debug)
{
    const char *wrapperFilename;
    std::vector<const char *> args;
    int status = 1;

    /*
     * TODO: simplify code
     */

    bool useInject = false;
    switch (api) {
    case trace::API_GL:
        wrapperFilename = GL_TRACE_WRAPPER;
        break;
#ifdef EGL_TRACE_WRAPPER
    case trace::API_EGL:
        wrapperFilename = EGL_TRACE_WRAPPER;
        break;
#endif
#ifdef _WIN32
    case trace::API_D3D7:
        wrapperFilename = "ddraw.dll";
        break;
    case trace::API_D3D8:
        wrapperFilename = "d3d8.dll";
        break;
    case trace::API_D3D9:
        wrapperFilename = "d3d9.dll";
        break;
    case trace::API_DXGI:
        wrapperFilename = "dxgitrace.dll";
        useInject = true;
        break;
    case trace::API_D2D1:
        wrapperFilename = "d2d1trace.dll";
        useInject = true;
        break;
#endif
    default:
        std::cerr << "error: unsupported API\n";
        return 1;
    }

    os::String wrapperPath = findWrapper(wrapperFilename, verbose);
    if (!wrapperPath.length()) {
        std::cerr << "error: failed to find " << wrapperFilename << " wrapper (rerun with -v option for more details)\n";
        goto exit;
    }

#if defined(_WIN32)
    /*
     * Use DLL injection method on Windows, even for APIs that don't stricly
     * need it.
     */
    useInject = true;

    if (useInject) {
        args.push_back("inject");
        args.push_back(wrapperPath);
    } else {
        /* On Windows copy the wrapper to the program directory.
         */
        if (!copyWrapper(wrapperPath, argv[0], verbose)) {
            goto exit;
        }
    }
#else  /* !_WIN32 */
    (void)useInject;
#endif /* !_WIN32 */

#if defined(__APPLE__)
    /* On Mac OS X, using DYLD_LIBRARY_PATH, we actually set the
     * parent directory, not the file. */
    wrapperPath.trimFilename();
    wrapperPath.trimFilename();
#endif

    /*
     * Spawn child process.
     */

    {
#if defined(TRACE_VARIABLE)
        const char *oldEnvVarValue = getenv(TRACE_VARIABLE);
        if (oldEnvVarValue) {
            wrapperPath.append(OS_PATH_SEP);
            wrapperPath.append(oldEnvVarValue);
        }

        if (debug) {
            std::string ex("set exec-wrapper env " TRACE_VARIABLE "=");
            ex.append(wrapperPath.str());

            args.push_back("gdb");
            args.push_back("--ex");
            args.push_back(ex.c_str());
            args.push_back("--args");

            os::unsetEnvironment(TRACE_VARIABLE);
        } else {
            /* FIXME: Don't modify our (ie parent) environment */
            os::setEnvironment(TRACE_VARIABLE, wrapperPath.str());
        }

        if (verbose) {
            std::cerr << TRACE_VARIABLE << "=" << wrapperPath.str() << "\n";
        }
#endif /* TRACE_VARIABLE */

        if (output) {
            os::setEnvironment("TRACE_FILE", output);
        }

        for (char * const * arg = argv; *arg; ++arg) {
            args.push_back(*arg);
        }

        if (verbose) {
            const char *sep = "";
            for (unsigned i = 0; i < args.size(); ++i) {
                const char *quote;
                if (strchr(args[i], ' ') != NULL) {
                    quote = "\"";
                } else {
                    quote = "";
                }
                std::cerr << sep << quote << args[i] << quote;
                sep = " ";
            }
            std::cerr << "\n";
        }

        args.push_back(NULL);

        status = os::execute((char * const *)&args[0]);

#if defined(TRACE_VARIABLE)
        if (oldEnvVarValue) {
            os::setEnvironment(TRACE_VARIABLE, oldEnvVarValue);
        } else {
            os::unsetEnvironment(TRACE_VARIABLE);
        }
#endif
    }

exit:
#if defined(_WIN32)
    if (!useInject) {
        os::String tmpWrapper(argv[0]);
        tmpWrapper.trimFilename();
        tmpWrapper.join(wrapperFilename);
        os::removeFile(tmpWrapper);
    }
#endif

    if (output) {
        os::unsetEnvironment("TRACE_FILE");
    }

    return status;

}

static const char *synopsis = "Generate a new trace by executing the given program.";

static void
usage(void)
{
    std::cout << "usage: apitrace trace [OPTIONS] PROGRAM [ARGS ...]\n"
        << synopsis << "\n"
        "\n"
        "    The given program will be executed with the given arguments.\n"
        "    During execution, all OpenGL calls will be captured to a trace\n"
        "    file. That trace file can then be used\n"
        "    with other apitrace utilities for replay or analysis.\n"
        "\n"
        "    -v, --verbose       verbose output\n"
        "    -a, --api=API       specify API to trace ("
#ifdef _WIN32
                                                      "gl, d3d7, d3d8, d3d9, or dxgi (for d3d10 and higher) "
#else
                                                      "gl or egl"
#endif
                                                      ");\n"
        "                        default is `gl`\n"
        "    -o, --output=TRACE  specify output trace file;\n"
        "                        default is `PROGRAM.trace`\n"
#ifdef TRACE_VARIABLE
        "    -d,  --debug        debug with gdb\n"
#endif
    ;
}

const static char *
shortOptions = "+hva:o:d";

const static struct option
longOptions[] = {
    {"help", no_argument, 0, 'h'},
    {"verbose", no_argument, 0, 'v'},
    {"api", required_argument, 0, 'a'},
    {"output", required_argument, 0, 'o'},
    {"debug", no_argument, 0, 'd'},
    {0, 0, 0, 0}
};

static int
command(int argc, char *argv[])
{
    bool verbose = false;
    trace::API api = trace::API_GL;
    const char *output = NULL;
    bool debug = false;

    int opt;
    while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) {
        switch (opt) {
        case 'h':
            usage();
            return 0;
        case 'v':
            verbose = true;
            break;
        case 'a':
            if (strcmp(optarg, "gl") == 0) {
                api = trace::API_GL;
            } else if (strcmp(optarg, "egl") == 0) {
                api = trace::API_EGL;
            } else if (strcmp(optarg, "d3d7") == 0) {
                api = trace::API_D3D7;
            } else if (strcmp(optarg, "d3d8") == 0) {
                api = trace::API_D3D8;
            } else if (strcmp(optarg, "d3d9") == 0) {
                api = trace::API_D3D9;
            } else if (strcmp(optarg, "dxgi") == 0 ||
                       strcmp(optarg, "d3d10") == 0 ||
                       strcmp(optarg, "d3d10_1") == 0 ||
                       strcmp(optarg, "d3d11") == 0 ||
                       strcmp(optarg, "d3d11_1") == 0) {
                api = trace::API_DXGI;
            } else if (strcmp(optarg, "d2d") == 0 ||
                       strcmp(optarg, "d2d1") == 0) {
                api = trace::API_D2D1;
            } else {
                std::cerr << "error: unknown API `" << optarg << "`\n";
                usage();
                return 1;
            }
            break;
        case 'o':
            output = optarg;
            break;
        case 'd':
            debug = true;
            break;
        default:
            std::cerr << "error: unexpected option `" << (char)opt << "`\n";
            usage();
            return 1;
        }
    }

    if (optind == argc) {
        std::cerr << "error: no command specified\n";
        usage();
        return 1;
    }

    assert(argv[argc] == 0);
    return traceProgram(api, argv + optind, output, verbose, debug);
}

const Command trace_command = {
    "trace",
    synopsis,
    usage,
    command
};
<commit_msg>cli: Use LLDB on MacOSX when tracing inside debugger.<commit_after>/*********************************************************************
 *
 * Copyright 2011 Intel Corporation
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *********************************************************************/

#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>

#include <iostream>
#include <fstream>

#include "os_string.hpp"
#include "os_process.hpp"
#include "os_version.hpp"

#include "cli.hpp"
#include "cli_resources.hpp"

#if defined(__APPLE__)
#define TRACE_VARIABLE "DYLD_FRAMEWORK_PATH"
#define GL_TRACE_WRAPPER  "OpenGL.framework/OpenGL"
#elif defined(_WIN32)
#define GL_TRACE_WRAPPER  "opengl32.dll"
#else
#define TRACE_VARIABLE "LD_PRELOAD"
#define GL_TRACE_WRAPPER  "glxtrace.so"
#define EGL_TRACE_WRAPPER  "egltrace.so"
#endif

static inline bool
copyWrapper(const os::String & wrapperPath,
            const char *programPath,
            bool verbose)
{
    os::String wrapperFilename(wrapperPath);
    wrapperFilename.trimDirectory();

    os::String tmpWrapper(programPath);
    tmpWrapper.trimFilename();
    tmpWrapper.join(wrapperFilename);

    if (verbose) {
        std::cerr << wrapperPath << " -> " << tmpWrapper << "\n";
    }

    if (tmpWrapper.exists()) {
        std::cerr << "error: not overwriting " << tmpWrapper << "\n";
        return false;
    }

    if (!os::copyFile(wrapperPath, tmpWrapper, false)) {
        std::cerr << "error: failed to copy " << wrapperPath << " into " << tmpWrapper << "\n";
        return false;
    }

    return true;
}

static int
traceProgram(trace::API api,
             char * const *argv,
             const char *output,
             bool verbose,
             bool debug)
{
    const char *wrapperFilename;
    std::vector<const char *> args;
    int status = 1;

    /*
     * TODO: simplify code
     */

    bool useInject = false;
    switch (api) {
    case trace::API_GL:
        wrapperFilename = GL_TRACE_WRAPPER;
        break;
#ifdef EGL_TRACE_WRAPPER
    case trace::API_EGL:
        wrapperFilename = EGL_TRACE_WRAPPER;
        break;
#endif
#ifdef _WIN32
    case trace::API_D3D7:
        wrapperFilename = "ddraw.dll";
        break;
    case trace::API_D3D8:
        wrapperFilename = "d3d8.dll";
        break;
    case trace::API_D3D9:
        wrapperFilename = "d3d9.dll";
        break;
    case trace::API_DXGI:
        wrapperFilename = "dxgitrace.dll";
        useInject = true;
        break;
    case trace::API_D2D1:
        wrapperFilename = "d2d1trace.dll";
        useInject = true;
        break;
#endif
    default:
        std::cerr << "error: unsupported API\n";
        return 1;
    }

    os::String wrapperPath = findWrapper(wrapperFilename, verbose);
    if (!wrapperPath.length()) {
        std::cerr << "error: failed to find " << wrapperFilename << " wrapper (rerun with -v option for more details)\n";
        goto exit;
    }

#if defined(_WIN32)
    /*
     * Use DLL injection method on Windows, even for APIs that don't stricly
     * need it.
     */
    useInject = true;

    if (useInject) {
        args.push_back("inject");
        args.push_back(wrapperPath);
    } else {
        /* On Windows copy the wrapper to the program directory.
         */
        if (!copyWrapper(wrapperPath, argv[0], verbose)) {
            goto exit;
        }
    }
#else  /* !_WIN32 */
    (void)useInject;
#endif /* !_WIN32 */

#if defined(__APPLE__)
    /* On Mac OS X, using DYLD_LIBRARY_PATH, we actually set the
     * parent directory, not the file. */
    wrapperPath.trimFilename();
    wrapperPath.trimFilename();
#endif

    /*
     * Spawn child process.
     */

    {
#if defined(TRACE_VARIABLE)
        const char *oldEnvVarValue = getenv(TRACE_VARIABLE);
        if (oldEnvVarValue) {
            wrapperPath.append(OS_PATH_SEP);
            wrapperPath.append(oldEnvVarValue);
        }

        if (debug) {
#if defined(__APPLE__)
            bool lldb = true;
#else
            bool lldb = false;
#endif

            if (lldb) {
                /*
                 * Debug with LLDB.
                 *
                 * See also http://lldb.llvm.org/lldb-gdb.html
                 */

                char scriptFileName[] = "/tmp/apitrace.XXXXXX";
                if (mktemp(scriptFileName) == NULL) {
                    std::cerr << "error: failed to create temporary lldb script file\n";
                    exit(1);
                }

                {
                    std::ofstream scriptStream(scriptFileName);
                    scriptStream << "env " TRACE_VARIABLE "='" << wrapperPath.str() << "'\n";
                }

                args.push_back("lldb");
                args.push_back("-s");
                args.push_back(scriptFileName);
                args.push_back("--");
            } else {
                /*
                 * Debug with GDB.
                 */

                std::string ex("set exec-wrapper env " TRACE_VARIABLE "='");
                ex.append(wrapperPath.str());
                ex.append("'");

                args.push_back("gdb");
                args.push_back("--ex");
                args.push_back(ex.c_str());
                args.push_back("--args");
            }

            os::unsetEnvironment(TRACE_VARIABLE);
        } else {
            /* FIXME: Don't modify our (ie parent) environment */
            os::setEnvironment(TRACE_VARIABLE, wrapperPath.str());
        }

        if (verbose) {
            std::cerr << TRACE_VARIABLE << "=" << wrapperPath.str() << "\n";
        }
#endif /* TRACE_VARIABLE */

        if (output) {
            os::setEnvironment("TRACE_FILE", output);
        }

        for (char * const * arg = argv; *arg; ++arg) {
            args.push_back(*arg);
        }

        if (verbose) {
            const char *sep = "";
            for (unsigned i = 0; i < args.size(); ++i) {
                const char *quote;
                if (strchr(args[i], ' ') != NULL) {
                    quote = "\"";
                } else {
                    quote = "";
                }
                std::cerr << sep << quote << args[i] << quote;
                sep = " ";
            }
            std::cerr << "\n";
        }

        args.push_back(NULL);

        status = os::execute((char * const *)&args[0]);

#if defined(TRACE_VARIABLE)
        if (oldEnvVarValue) {
            os::setEnvironment(TRACE_VARIABLE, oldEnvVarValue);
        } else {
            os::unsetEnvironment(TRACE_VARIABLE);
        }
#endif
    }

exit:
#if defined(_WIN32)
    if (!useInject) {
        os::String tmpWrapper(argv[0]);
        tmpWrapper.trimFilename();
        tmpWrapper.join(wrapperFilename);
        os::removeFile(tmpWrapper);
    }
#endif

    if (output) {
        os::unsetEnvironment("TRACE_FILE");
    }

    return status;

}

static const char *synopsis = "Generate a new trace by executing the given program.";

static void
usage(void)
{
    std::cout << "usage: apitrace trace [OPTIONS] PROGRAM [ARGS ...]\n"
        << synopsis << "\n"
        "\n"
        "    The given program will be executed with the given arguments.\n"
        "    During execution, all OpenGL calls will be captured to a trace\n"
        "    file. That trace file can then be used\n"
        "    with other apitrace utilities for replay or analysis.\n"
        "\n"
        "    -v, --verbose       verbose output\n"
        "    -a, --api=API       specify API to trace ("
#ifdef _WIN32
                                                      "gl, d3d7, d3d8, d3d9, or dxgi (for d3d10 and higher) "
#else
                                                      "gl or egl"
#endif
                                                      ");\n"
        "                        default is `gl`\n"
        "    -o, --output=TRACE  specify output trace file;\n"
        "                        default is `PROGRAM.trace`\n"
#ifdef TRACE_VARIABLE
        "    -d,  --debug        run inside debugger (gdb/lldb)\n"
#endif
    ;
}

const static char *
shortOptions = "+hva:o:d";

const static struct option
longOptions[] = {
    {"help", no_argument, 0, 'h'},
    {"verbose", no_argument, 0, 'v'},
    {"api", required_argument, 0, 'a'},
    {"output", required_argument, 0, 'o'},
    {"debug", no_argument, 0, 'd'},
    {0, 0, 0, 0}
};

static int
command(int argc, char *argv[])
{
    bool verbose = false;
    trace::API api = trace::API_GL;
    const char *output = NULL;
    bool debug = false;

    int opt;
    while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) {
        switch (opt) {
        case 'h':
            usage();
            return 0;
        case 'v':
            verbose = true;
            break;
        case 'a':
            if (strcmp(optarg, "gl") == 0) {
                api = trace::API_GL;
            } else if (strcmp(optarg, "egl") == 0) {
                api = trace::API_EGL;
            } else if (strcmp(optarg, "d3d7") == 0) {
                api = trace::API_D3D7;
            } else if (strcmp(optarg, "d3d8") == 0) {
                api = trace::API_D3D8;
            } else if (strcmp(optarg, "d3d9") == 0) {
                api = trace::API_D3D9;
            } else if (strcmp(optarg, "dxgi") == 0 ||
                       strcmp(optarg, "d3d10") == 0 ||
                       strcmp(optarg, "d3d10_1") == 0 ||
                       strcmp(optarg, "d3d11") == 0 ||
                       strcmp(optarg, "d3d11_1") == 0) {
                api = trace::API_DXGI;
            } else if (strcmp(optarg, "d2d") == 0 ||
                       strcmp(optarg, "d2d1") == 0) {
                api = trace::API_D2D1;
            } else {
                std::cerr << "error: unknown API `" << optarg << "`\n";
                usage();
                return 1;
            }
            break;
        case 'o':
            output = optarg;
            break;
        case 'd':
            debug = true;
            break;
        default:
            std::cerr << "error: unexpected option `" << (char)opt << "`\n";
            usage();
            return 1;
        }
    }

    if (optind == argc) {
        std::cerr << "error: no command specified\n";
        usage();
        return 1;
    }

    assert(argv[argc] == 0);
    return traceProgram(api, argv + optind, output, verbose, debug);
}

const Command trace_command = {
    "trace",
    synopsis,
    usage,
    command
};
<|endoftext|>


<commit_before>/* Copyright (C) 2003 MySQL AB

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

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <ndb_global.h>
#include <SimpleProperties.hpp>
#include <NdbOut.hpp>
#include <NdbTCP.h>
#include <UtilBuffer.hpp>

bool
SimpleProperties::Writer::first(){
  return reset();
}

bool
SimpleProperties::Writer::add(Uint16 key, Uint32 value){
  Uint32 head = Uint32Value;
  head <<= 16;
  head += key;
  if(!putWord(htonl(head)))
    return false;

  return putWord(htonl(value));
}

bool
SimpleProperties::Writer::add(const char * value, int len){
  const Uint32 valLen = (len + 3) / 4;

  if ((len % 4) == 0)
    return putWords((Uint32*)value, valLen);

  const Uint32 putLen= valLen - 1;
  if (!putWords((Uint32*)value, putLen))
    return false;

  // Special handling of last bytes
  union {
    Uint32 lastWord;
    char lastBytes[4];
  };
  memcpy(lastBytes,
         value + putLen*4,
         len - putLen*4);
  return putWord(lastWord);
}

bool
SimpleProperties::Writer::add(Uint16 key, const char * value){
  Uint32 head = StringValue;
  head <<= 16;
  head += key;
  if(!putWord(htonl(head)))
    return false;
  Uint32 strLen = strlen(value) + 1; // Including NULL-byte
  if(!putWord(htonl(strLen)))
    return false;

  return add(value, (int)strLen);

}

bool
SimpleProperties::Writer::add(Uint16 key, const void* value, int len){
  Uint32 head = BinaryValue;
  head <<= 16;
  head += key;
  if(!putWord(htonl(head)))
    return false;
  if(!putWord(htonl(len)))
    return false;

  return add((const char*)value, len);
}

SimpleProperties::Reader::Reader(){
  m_itemLen = 0;
}

bool
SimpleProperties::Reader::first(){
  reset();
  m_itemLen = 0;
  return readValue();
}

bool
SimpleProperties::Reader::next(){
  return readValue();
}

bool
SimpleProperties::Reader::valid() const {
  return m_type != InvalidValue;
}

Uint16
SimpleProperties::Reader::getKey() const{
  return m_key;
}

Uint16
SimpleProperties::Reader::getValueLen() const {
  switch(m_type){
  case Uint32Value:
    return 4;
  case StringValue:
  case BinaryValue:
    return m_strLen;
  case InvalidValue:
    return 0;
  }
  return 0;
}

SimpleProperties::ValueType
SimpleProperties::Reader::getValueType() const {
  return m_type;
}

Uint32
SimpleProperties::Reader::getUint32() const {
  return m_ui32_value;
}

char *
SimpleProperties::Reader::getString(char * dst) const {
  if(peekWords((Uint32*)dst, m_itemLen))
    return dst;
  return 0;
}

bool
SimpleProperties::Reader::readValue(){
  if(!step(m_itemLen)){
    m_type = InvalidValue;
    return false;
  }

  Uint32 tmp;
  if(!getWord(&tmp)){
    m_type = InvalidValue;
    return false;
  }

  tmp = ntohl(tmp);
  m_key = tmp & 0xFFFF;
  m_type = (SimpleProperties::ValueType)(tmp >> 16);
  switch(m_type){
  case Uint32Value:
    m_itemLen = 1;
    if(!peekWord(&m_ui32_value))
      return false;
    m_ui32_value = ntohl(m_ui32_value);
    return true;
  case StringValue:
  case BinaryValue:
    if(!getWord(&tmp))
      return false;
    m_strLen = ntohl(tmp);
    m_itemLen = (m_strLen + 3)/4;
    return true;
  default:
    m_itemLen = 0;
    m_type = InvalidValue;
    return false;
  }
}

SimpleProperties::UnpackStatus
SimpleProperties::unpack(Reader & it, void * dst,
			 const SP2StructMapping _map[], Uint32 mapSz,
			 bool ignoreMinMax,
			 bool ignoreUnknownKeys){
  do {
    if(!it.valid())
      break;

    bool found = false;
    Uint16 key = it.getKey();
    for(Uint32 i = 0; i<mapSz; i++){
      if(key == _map[i].Key){
	found = true;
	if(_map[i].Type == InvalidValue)
	  return Break;
	if(_map[i].Type != it.getValueType())
	  return TypeMismatch;

	char * _dst = (char *)dst;
	_dst += _map[i].Offset;

	switch(it.getValueType()){
	case Uint32Value:{
	  const Uint32 val = it.getUint32();
	  if(!ignoreMinMax){
	    if(val < _map[i].minValue)
	      return ValueTooLow;
	    if(val > _map[i].maxValue)
	      return ValueTooHigh;
	  }
	  * ((Uint32 *)_dst) = val;
	  break;
        }
	case BinaryValue:
        case StringValue:{
	  unsigned len = it.getValueLen();
	  if(len < _map[i].minValue)
	    return ValueTooLow;
	  if(len > _map[i].maxValue)
	    return ValueTooHigh;
          it.getString(_dst);
          break;
	}
	default:
	  abort();
	}
	break;
      }
    }
    if(!found && !ignoreUnknownKeys)
      return UnknownKey;
  } while(it.next());

  return Eof;
}

SimpleProperties::UnpackStatus
SimpleProperties::pack(Writer & it, const void * __src,
		       const SP2StructMapping _map[], Uint32 mapSz,
		       bool ignoreMinMax){

  const char * _src = (const char *)__src;

  for(Uint32 i = 0; i<mapSz; i++){
    bool ok = false;
    const char * src = _src + _map[i].Offset;
    switch(_map[i].Type){
    case SimpleProperties::InvalidValue:
      ok = true;
      break;
    case SimpleProperties::Uint32Value:{
      Uint32 val = * ((Uint32*)src);
      if(!ignoreMinMax){
	if(val < _map[i].minValue)
	  return ValueTooLow;
	if(val > _map[i].maxValue)
	  return ValueTooHigh;
      }
      ok = it.add(_map[i].Key, val);
    }
      break;
    case SimpleProperties::BinaryValue:{
      const char * src_len = _src + _map[i].Length_Offset;
      Uint32 len = *((Uint32*)src_len);
      if(!ignoreMinMax){
	if(len == _map[i].maxValue)
	  return ValueTooHigh;
      }
      ok = it.add(_map[i].Key, src, len);
      break;
    }
    case SimpleProperties::StringValue:
      if(!ignoreMinMax){
	size_t len = strlen(src);
	if(len == _map[i].maxValue)
	  return ValueTooHigh;
      }
      ok = it.add(_map[i].Key, src);
      break;
    }
    if(!ok)
      return OutOfMemory;
  }

  return Eof;
}

void
SimpleProperties::Reader::printAll(NdbOut& ndbout){
  char tmp[1024];
  for(first(); valid(); next()){
    switch(getValueType()){
    case SimpleProperties::Uint32Value:
      ndbout << "Key: " << getKey()
             << " value(" << getValueLen() << ") : "
             << getUint32() << endl;
      break;
    case SimpleProperties::BinaryValue:
    case SimpleProperties::StringValue:
      if(getValueLen() < 1024){
	getString(tmp);
	ndbout << "Key: " << getKey()
	       << " value(" << getValueLen() << ") : "
	       << "\"" << tmp << "\"" << endl;
      } else {
	ndbout << "Key: " << getKey()
	       << " value(" << getValueLen() << ") : "
	       << "\"" << "<TOO LONG>" << "\"" << endl;

      }
      break;
    default:
      ndbout << "Unknown type for key: " << getKey()
             << " type: " << (Uint32)getValueType() << endl;
    }
  }
}

SimplePropertiesLinearReader::SimplePropertiesLinearReader
(const Uint32 * src, Uint32 len){
  m_src = src;
  m_len = len;
  m_pos = 0;
  first();
}

void
SimplePropertiesLinearReader::reset() {
  m_pos = 0;
}

bool
SimplePropertiesLinearReader::step(Uint32 len){
  m_pos += len;
  return m_pos < m_len;
}

bool
SimplePropertiesLinearReader::getWord(Uint32 * dst) {
  if(m_pos<m_len){
    * dst = m_src[m_pos++];
    return true;
  }
  return false;
}

bool
SimplePropertiesLinearReader::peekWord(Uint32 * dst) const {
  if(m_pos<m_len){
    * dst = m_src[m_pos];
    return true;
  }
  return false;
}

bool
SimplePropertiesLinearReader::peekWords(Uint32 * dst, Uint32 len) const {
  if(m_pos + len <= m_len){
    memcpy(dst, &m_src[m_pos], 4 * len);
    return true;
  }
  return false;
}

LinearWriter::LinearWriter(Uint32 * src, Uint32 len){
  m_src = src;
  m_len = len;
  reset();
}

bool LinearWriter::reset() { m_pos = 0; return m_len > 0;}

bool
LinearWriter::putWord(Uint32 val){
  if(m_pos < m_len){
    m_src[m_pos++] = val;
    return true;
  }
  return false;
}

bool
LinearWriter::putWords(const Uint32 * src, Uint32 len){
  if(m_pos + len <= m_len){
    memcpy(&m_src[m_pos], src, 4 * len);
    m_pos += len;
    return true;
  }
  return false;
}

Uint32
LinearWriter::getWordsUsed() const { return m_pos;}

UtilBufferWriter::UtilBufferWriter(UtilBuffer & b)
  : m_buf(b)
{
  reset();
}

bool UtilBufferWriter::reset() { m_buf.clear(); return true;}

bool
UtilBufferWriter::putWord(Uint32 val){
  return (m_buf.append(&val, 4) == 0);
}

bool
UtilBufferWriter::putWords(const Uint32 * src, Uint32 len){
  return (m_buf.append(src, 4 * len) == 0);
}

Uint32
UtilBufferWriter::getWordsUsed() const { return m_buf.length() / 4;}

#if 0
LinearPagesReader::LinearPagesReader(const Uint32 * base,
				     Uint32 pageSize,
				     Uint32 headerSize,
				     Uint32 noOfPages,
				     Uint32 len){
  m_base = base;
  m_pageSz = pageSize;
  m_noOfPages = noOfPages;
  m_pageHeaderSz = headerSize;
  m_len = len;
  reset();
}

void
LinearPagesReader::reset() { m_pos = 0;}

bool
LinearPagesReader::step(Uint32 len){
  m_pos += len;
  return m_pos < m_len;
}

bool
LinearPagesReader::getWord(Uint32 * dst) {
  if(m_pos<m_len){
    * dst = m_base[getPos(m_pos++)];
    return true;
  }
  return false;
}

bool
LinearPagesReader::peekWord(Uint32 * dst) const {
  if(m_pos<m_len){
    * dst = m_base[getPos(m_pos)];
    return true;
  }
  return false;
}

bool
LinearPagesReader::peekWords(Uint32 * dst, Uint32 len) const {
  if(m_pos + len <= m_len){
    for(Uint32 i = 0; i<len; i++)
      * (dst + i) = m_base[getPos(m_pos + i)];
    return true;
  }
  return false;
}

Uint32
LinearPagesReader::getPos(Uint32 pos) const {
  const Uint32 sz = (m_pageSz - m_pageHeaderSz);
  Uint32 no = pos / sz;
  Uint32 in = pos % sz;
  return no * m_pageSz + m_pageHeaderSz + in;
}

LinearPagesWriter::LinearPagesWriter(Uint32 * base,
				     Uint32 pageSize,
				     Uint32 noOfPages,
				     Uint32 headerSize){
  m_base = base;
  m_pageSz = pageSize;
  m_noOfPages = noOfPages;
  m_pageHeaderSz = headerSize;
  m_len = noOfPages * (pageSize - headerSize);
  reset();
}

bool
LinearPagesWriter::putWord(Uint32 val){
  if(m_pos < m_len){
    m_base[getPos(m_pos++)] = val;
    return true;
  }
  return false;
}

bool
LinearPagesWriter::putWords(const Uint32 * src, Uint32 len){
  if(m_pos + len <= m_len){
    for(Uint32 i = 0; i<len; i++)
      m_base[getPos(m_pos++)] = src[i];
    return true;
  }
  return false;
}

#if 0
Uint32
LinearPagesWriter::getWordsUsed() const {
  return getPos(m_pos);
}
#endif

Uint32
LinearPagesWriter::getPagesUsed() const {
  return m_pos / (m_pageSz - m_pageHeaderSz);
}

Uint32
LinearPagesWriter::getPos(Uint32 pos) const {
  const Uint32 sz = (m_pageSz - m_pageHeaderSz);
  Uint32 no = pos / sz;
  Uint32 in = pos % sz;
  return no * m_pageSz + m_pageHeaderSz + in;
}
#endif
<commit_msg>ndb -   Fix compile error with gcc296<commit_after>/* Copyright (C) 2003 MySQL AB

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

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <ndb_global.h>
#include <SimpleProperties.hpp>
#include <NdbOut.hpp>
#include <NdbTCP.h>
#include <UtilBuffer.hpp>

bool
SimpleProperties::Writer::first(){
  return reset();
}

bool
SimpleProperties::Writer::add(Uint16 key, Uint32 value){
  Uint32 head = Uint32Value;
  head <<= 16;
  head += key;
  if(!putWord(htonl(head)))
    return false;

  return putWord(htonl(value));
}

bool
SimpleProperties::Writer::add(const char * value, int len){
  const Uint32 valLen = (len + 3) / 4;

  if ((len % 4) == 0)
    return putWords((Uint32*)value, valLen);

  const Uint32 putLen= valLen - 1;
  if (!putWords((Uint32*)value, putLen))
    return false;

  // Special handling of last bytes
  union {
    Uint32 lastWord;
    char lastBytes[4];
  } tmp;
  tmp.lastWord =0 ;
  memcpy(tmp.lastBytes,
         value + putLen*4,
         len - putLen*4);
  return putWord(tmp.lastWord);
}

bool
SimpleProperties::Writer::add(Uint16 key, const char * value){
  Uint32 head = StringValue;
  head <<= 16;
  head += key;
  if(!putWord(htonl(head)))
    return false;
  Uint32 strLen = strlen(value) + 1; // Including NULL-byte
  if(!putWord(htonl(strLen)))
    return false;

  return add(value, (int)strLen);

}

bool
SimpleProperties::Writer::add(Uint16 key, const void* value, int len){
  Uint32 head = BinaryValue;
  head <<= 16;
  head += key;
  if(!putWord(htonl(head)))
    return false;
  if(!putWord(htonl(len)))
    return false;

  return add((const char*)value, len);
}

SimpleProperties::Reader::Reader(){
  m_itemLen = 0;
}

bool
SimpleProperties::Reader::first(){
  reset();
  m_itemLen = 0;
  return readValue();
}

bool
SimpleProperties::Reader::next(){
  return readValue();
}

bool
SimpleProperties::Reader::valid() const {
  return m_type != InvalidValue;
}

Uint16
SimpleProperties::Reader::getKey() const{
  return m_key;
}

Uint16
SimpleProperties::Reader::getValueLen() const {
  switch(m_type){
  case Uint32Value:
    return 4;
  case StringValue:
  case BinaryValue:
    return m_strLen;
  case InvalidValue:
    return 0;
  }
  return 0;
}

SimpleProperties::ValueType
SimpleProperties::Reader::getValueType() const {
  return m_type;
}

Uint32
SimpleProperties::Reader::getUint32() const {
  return m_ui32_value;
}

char *
SimpleProperties::Reader::getString(char * dst) const {
  if(peekWords((Uint32*)dst, m_itemLen))
    return dst;
  return 0;
}

bool
SimpleProperties::Reader::readValue(){
  if(!step(m_itemLen)){
    m_type = InvalidValue;
    return false;
  }

  Uint32 tmp;
  if(!getWord(&tmp)){
    m_type = InvalidValue;
    return false;
  }

  tmp = ntohl(tmp);
  m_key = tmp & 0xFFFF;
  m_type = (SimpleProperties::ValueType)(tmp >> 16);
  switch(m_type){
  case Uint32Value:
    m_itemLen = 1;
    if(!peekWord(&m_ui32_value))
      return false;
    m_ui32_value = ntohl(m_ui32_value);
    return true;
  case StringValue:
  case BinaryValue:
    if(!getWord(&tmp))
      return false;
    m_strLen = ntohl(tmp);
    m_itemLen = (m_strLen + 3)/4;
    return true;
  default:
    m_itemLen = 0;
    m_type = InvalidValue;
    return false;
  }
}

SimpleProperties::UnpackStatus
SimpleProperties::unpack(Reader & it, void * dst,
			 const SP2StructMapping _map[], Uint32 mapSz,
			 bool ignoreMinMax,
			 bool ignoreUnknownKeys){
  do {
    if(!it.valid())
      break;

    bool found = false;
    Uint16 key = it.getKey();
    for(Uint32 i = 0; i<mapSz; i++){
      if(key == _map[i].Key){
	found = true;
	if(_map[i].Type == InvalidValue)
	  return Break;
	if(_map[i].Type != it.getValueType())
	  return TypeMismatch;

	char * _dst = (char *)dst;
	_dst += _map[i].Offset;

	switch(it.getValueType()){
	case Uint32Value:{
	  const Uint32 val = it.getUint32();
	  if(!ignoreMinMax){
	    if(val < _map[i].minValue)
	      return ValueTooLow;
	    if(val > _map[i].maxValue)
	      return ValueTooHigh;
	  }
	  * ((Uint32 *)_dst) = val;
	  break;
        }
	case BinaryValue:
        case StringValue:{
	  unsigned len = it.getValueLen();
	  if(len < _map[i].minValue)
	    return ValueTooLow;
	  if(len > _map[i].maxValue)
	    return ValueTooHigh;
          it.getString(_dst);
          break;
	}
	default:
	  abort();
	}
	break;
      }
    }
    if(!found && !ignoreUnknownKeys)
      return UnknownKey;
  } while(it.next());

  return Eof;
}

SimpleProperties::UnpackStatus
SimpleProperties::pack(Writer & it, const void * __src,
		       const SP2StructMapping _map[], Uint32 mapSz,
		       bool ignoreMinMax){

  const char * _src = (const char *)__src;

  for(Uint32 i = 0; i<mapSz; i++){
    bool ok = false;
    const char * src = _src + _map[i].Offset;
    switch(_map[i].Type){
    case SimpleProperties::InvalidValue:
      ok = true;
      break;
    case SimpleProperties::Uint32Value:{
      Uint32 val = * ((Uint32*)src);
      if(!ignoreMinMax){
	if(val < _map[i].minValue)
	  return ValueTooLow;
	if(val > _map[i].maxValue)
	  return ValueTooHigh;
      }
      ok = it.add(_map[i].Key, val);
    }
      break;
    case SimpleProperties::BinaryValue:{
      const char * src_len = _src + _map[i].Length_Offset;
      Uint32 len = *((Uint32*)src_len);
      if(!ignoreMinMax){
	if(len == _map[i].maxValue)
	  return ValueTooHigh;
      }
      ok = it.add(_map[i].Key, src, len);
      break;
    }
    case SimpleProperties::StringValue:
      if(!ignoreMinMax){
	size_t len = strlen(src);
	if(len == _map[i].maxValue)
	  return ValueTooHigh;
      }
      ok = it.add(_map[i].Key, src);
      break;
    }
    if(!ok)
      return OutOfMemory;
  }

  return Eof;
}

void
SimpleProperties::Reader::printAll(NdbOut& ndbout){
  char tmp[1024];
  for(first(); valid(); next()){
    switch(getValueType()){
    case SimpleProperties::Uint32Value:
      ndbout << "Key: " << getKey()
             << " value(" << getValueLen() << ") : "
             << getUint32() << endl;
      break;
    case SimpleProperties::BinaryValue:
    case SimpleProperties::StringValue:
      if(getValueLen() < 1024){
	getString(tmp);
	ndbout << "Key: " << getKey()
	       << " value(" << getValueLen() << ") : "
	       << "\"" << tmp << "\"" << endl;
      } else {
	ndbout << "Key: " << getKey()
	       << " value(" << getValueLen() << ") : "
	       << "\"" << "<TOO LONG>" << "\"" << endl;

      }
      break;
    default:
      ndbout << "Unknown type for key: " << getKey()
             << " type: " << (Uint32)getValueType() << endl;
    }
  }
}

SimplePropertiesLinearReader::SimplePropertiesLinearReader
(const Uint32 * src, Uint32 len){
  m_src = src;
  m_len = len;
  m_pos = 0;
  first();
}

void
SimplePropertiesLinearReader::reset() {
  m_pos = 0;
}

bool
SimplePropertiesLinearReader::step(Uint32 len){
  m_pos += len;
  return m_pos < m_len;
}

bool
SimplePropertiesLinearReader::getWord(Uint32 * dst) {
  if(m_pos<m_len){
    * dst = m_src[m_pos++];
    return true;
  }
  return false;
}

bool
SimplePropertiesLinearReader::peekWord(Uint32 * dst) const {
  if(m_pos<m_len){
    * dst = m_src[m_pos];
    return true;
  }
  return false;
}

bool
SimplePropertiesLinearReader::peekWords(Uint32 * dst, Uint32 len) const {
  if(m_pos + len <= m_len){
    memcpy(dst, &m_src[m_pos], 4 * len);
    return true;
  }
  return false;
}

LinearWriter::LinearWriter(Uint32 * src, Uint32 len){
  m_src = src;
  m_len = len;
  reset();
}

bool LinearWriter::reset() { m_pos = 0; return m_len > 0;}

bool
LinearWriter::putWord(Uint32 val){
  if(m_pos < m_len){
    m_src[m_pos++] = val;
    return true;
  }
  return false;
}

bool
LinearWriter::putWords(const Uint32 * src, Uint32 len){
  if(m_pos + len <= m_len){
    memcpy(&m_src[m_pos], src, 4 * len);
    m_pos += len;
    return true;
  }
  return false;
}

Uint32
LinearWriter::getWordsUsed() const { return m_pos;}

UtilBufferWriter::UtilBufferWriter(UtilBuffer & b)
  : m_buf(b)
{
  reset();
}

bool UtilBufferWriter::reset() { m_buf.clear(); return true;}

bool
UtilBufferWriter::putWord(Uint32 val){
  return (m_buf.append(&val, 4) == 0);
}

bool
UtilBufferWriter::putWords(const Uint32 * src, Uint32 len){
  return (m_buf.append(src, 4 * len) == 0);
}

Uint32
UtilBufferWriter::getWordsUsed() const { return m_buf.length() / 4;}

#if 0
LinearPagesReader::LinearPagesReader(const Uint32 * base,
				     Uint32 pageSize,
				     Uint32 headerSize,
				     Uint32 noOfPages,
				     Uint32 len){
  m_base = base;
  m_pageSz = pageSize;
  m_noOfPages = noOfPages;
  m_pageHeaderSz = headerSize;
  m_len = len;
  reset();
}

void
LinearPagesReader::reset() { m_pos = 0;}

bool
LinearPagesReader::step(Uint32 len){
  m_pos += len;
  return m_pos < m_len;
}

bool
LinearPagesReader::getWord(Uint32 * dst) {
  if(m_pos<m_len){
    * dst = m_base[getPos(m_pos++)];
    return true;
  }
  return false;
}

bool
LinearPagesReader::peekWord(Uint32 * dst) const {
  if(m_pos<m_len){
    * dst = m_base[getPos(m_pos)];
    return true;
  }
  return false;
}

bool
LinearPagesReader::peekWords(Uint32 * dst, Uint32 len) const {
  if(m_pos + len <= m_len){
    for(Uint32 i = 0; i<len; i++)
      * (dst + i) = m_base[getPos(m_pos + i)];
    return true;
  }
  return false;
}

Uint32
LinearPagesReader::getPos(Uint32 pos) const {
  const Uint32 sz = (m_pageSz - m_pageHeaderSz);
  Uint32 no = pos / sz;
  Uint32 in = pos % sz;
  return no * m_pageSz + m_pageHeaderSz + in;
}

LinearPagesWriter::LinearPagesWriter(Uint32 * base,
				     Uint32 pageSize,
				     Uint32 noOfPages,
				     Uint32 headerSize){
  m_base = base;
  m_pageSz = pageSize;
  m_noOfPages = noOfPages;
  m_pageHeaderSz = headerSize;
  m_len = noOfPages * (pageSize - headerSize);
  reset();
}

bool
LinearPagesWriter::putWord(Uint32 val){
  if(m_pos < m_len){
    m_base[getPos(m_pos++)] = val;
    return true;
  }
  return false;
}

bool
LinearPagesWriter::putWords(const Uint32 * src, Uint32 len){
  if(m_pos + len <= m_len){
    for(Uint32 i = 0; i<len; i++)
      m_base[getPos(m_pos++)] = src[i];
    return true;
  }
  return false;
}

#if 0
Uint32
LinearPagesWriter::getWordsUsed() const {
  return getPos(m_pos);
}
#endif

Uint32
LinearPagesWriter::getPagesUsed() const {
  return m_pos / (m_pageSz - m_pageHeaderSz);
}

Uint32
LinearPagesWriter::getPos(Uint32 pos) const {
  const Uint32 sz = (m_pageSz - m_pageHeaderSz);
  Uint32 no = pos / sz;
  Uint32 in = pos % sz;
  return no * m_pageSz + m_pageHeaderSz + in;
}
#endif
<|endoftext|>


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

#include "PoolObjectSQL.h"
#include "PoolObjectAuth.h"
#include "SSLTools.h"
#include "Nebula.h"
#include "Clusterable.h"

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

string& PoolObjectSQL::to_xml64(string &xml64)
{
    string *str64;

    to_xml(xml64);

    str64 = SSLTools::base64_encode(xml64);

    xml64 = *str64;

    delete str64;

    return xml64;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::select(SqlDB *db)
{
    ostringstream   oss;
    int             rc;
    int             boid;

    set_callback(
            static_cast<Callbackable::Callback>(&PoolObjectSQL::select_cb));

    oss << "SELECT body FROM " << table << " WHERE oid = " << oid;

    boid = oid;
    oid  = -1;

    rc = db->exec(oss, this);

    unset_callback();

    if ((rc != 0) || (oid != boid ))
    {
        return -1;
    }

    return 0;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::select(SqlDB *db, const string& _name, int _uid)
{
    ostringstream oss;

    int rc;
    char * sql_name;

    sql_name = db->escape_str(_name.c_str());

    if ( sql_name == 0 )
    {
        return -1;
    }

    set_callback(
            static_cast<Callbackable::Callback>(&PoolObjectSQL::select_cb));

    oss << "SELECT body FROM " << table << " WHERE name = '" << sql_name << "'";

    if ( _uid != -1 )
    {
        oss << " AND uid = " << _uid;
    }

    name  = "";
    uid   = -1;

    rc = db->exec(oss, this);

    unset_callback();

    db->free_str(sql_name);

    if ((rc != 0) || (_name != name) || (_uid != -1 && _uid != uid))
    {
        return -1;
    }

    return 0;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::drop(SqlDB *db)
{
    ostringstream oss;
    int rc;

    oss << "DELETE FROM " << table << " WHERE oid=" << oid;

    rc = db->exec(oss);

    if ( rc == 0 )
    {
        set_valid(false);
    }

    return rc;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

const char * PoolObjectSQL::error_attribute_name = "ERROR";

void PoolObjectSQL::set_template_error_message(const string& message)
{
    VectorAttribute *  attr;
    map<string,string> error_value;

    char   str[26];
    time_t the_time;

    the_time = time(NULL);

#ifdef SOLARIS
    ctime_r(&(the_time),str,sizeof(char)*26);
#else
    ctime_r(&(the_time),str);
#endif

    str[24] = '\0'; // Get rid of final enter character

    error_value.insert(make_pair("TIMESTAMP",str));
    error_value.insert(make_pair("MESSAGE",message));

    //Replace previous error message and insert the new one

    attr = new VectorAttribute(error_attribute_name,error_value);

    obj_template->erase(error_attribute_name);
    obj_template->set(attr);
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::replace_template(const string& tmpl_str, string& error)
{
    Template * new_tmpl  = get_new_template();

    if ( new_tmpl == 0 )
    {
        error = "Cannot allocate a new template";
        return -1;
    }

    if ( new_tmpl->parse_str_or_xml(tmpl_str, error) != 0 )
    {
        delete new_tmpl;
        return -1;
    }

    if ( obj_template != 0 )
    {
        delete obj_template;
    }

    obj_template = new_tmpl;

    return 0;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

string& PoolObjectSQL::perms_to_xml(string& xml) const
{
    ostringstream   oss;

    oss <<
        "<PERMISSIONS>" <<
            "<OWNER_U>" << owner_u << "</OWNER_U>"  <<
            "<OWNER_M>" << owner_m << "</OWNER_M>"  <<
            "<OWNER_A>" << owner_a << "</OWNER_A>"  <<
            "<GROUP_U>" << group_u << "</GROUP_U>"  <<
            "<GROUP_M>" << group_m << "</GROUP_M>"  <<
            "<GROUP_A>" << group_a << "</GROUP_A>"  <<
            "<OTHER_U>" << other_u << "</OTHER_U>"  <<
            "<OTHER_M>" << other_m << "</OTHER_M>"  <<
            "<OTHER_A>" << other_a << "</OTHER_A>"  <<
        "</PERMISSIONS>";

    xml = oss.str();
    return xml;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::perms_from_xml()
{
    int rc = 0;

    rc += xpath(owner_u, "/*/PERMISSIONS/OWNER_U", 0);
    rc += xpath(owner_m, "/*/PERMISSIONS/OWNER_M", 0);
    rc += xpath(owner_a, "/*/PERMISSIONS/OWNER_A", 0);

    rc += xpath(group_u, "/*/PERMISSIONS/GROUP_U", 0);
    rc += xpath(group_m, "/*/PERMISSIONS/GROUP_M", 0);
    rc += xpath(group_a, "/*/PERMISSIONS/GROUP_A", 0);

    rc += xpath(other_u, "/*/PERMISSIONS/OTHER_U", 0);
    rc += xpath(other_m, "/*/PERMISSIONS/OTHER_M", 0);
    rc += xpath(other_a, "/*/PERMISSIONS/OTHER_A", 0);

    return rc;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void PoolObjectSQL::get_permissions(PoolObjectAuth& auth)
{
    auth.obj_type = obj_type;

    auth.oid = oid;
    auth.uid = uid;
    auth.gid = gid;

    auth.owner_u = owner_u;
    auth.owner_m = owner_m;
    auth.owner_a = owner_a;

    auth.group_u = group_u;
    auth.group_m = group_m;
    auth.group_a = group_a;

    auth.other_u = other_u;
    auth.other_m = other_m;
    auth.other_a = other_a;

    Clusterable* cl = dynamic_cast<Clusterable*>(this);

    if(cl != 0)
    {
        auth.cid = cl->get_cluster_id();
    }
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::set_permissions( int _owner_u,
                                    int _owner_m,
                                    int _owner_a,
                                    int _group_u,
                                    int _group_m,
                                    int _group_a,
                                    int _other_u,
                                    int _other_m,
                                    int _other_a,
                                    string& error_str)
{
    if ( _owner_u < -1 || _owner_u > 1 ) goto error_value;
    if ( _owner_m < -1 || _owner_m > 1 ) goto error_value;
    if ( _owner_a < -1 || _owner_a > 1 ) goto error_value;
    if ( _group_u < -1 || _group_u > 1 ) goto error_value;
    if ( _group_m < -1 || _group_m > 1 ) goto error_value;
    if ( _group_a < -1 || _group_a > 1 ) goto error_value;
    if ( _other_u < -1 || _other_u > 1 ) goto error_value;
    if ( _other_m < -1 || _other_m > 1 ) goto error_value;
    if ( _other_a < -1 || _other_a > 1 ) goto error_value;

    set_perm(owner_u, _owner_u);
    set_perm(owner_m, _owner_m);
    set_perm(owner_a, _owner_a);
    set_perm(group_u, _group_u);
    set_perm(group_m, _group_m);
    set_perm(group_a, _group_a);
    set_perm(other_u, _other_u);
    set_perm(other_m, _other_m);
    set_perm(other_a, _other_a);

    return 0;

error_value:
    error_str = "New permission values must be -1, 0 or 1";
    return -1;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void PoolObjectSQL::set_umask(int umask)
{
    int perms;
    bool enable_other;

    Nebula::instance().get_configuration_attribute(
            "ENABLE_OTHER_PERMISSIONS", enable_other);

    if (uid == 0 || gid == 0)
    {
        perms = 0777;
    }
    else if (enable_other)
    {
        perms = 0666;
    }
    else
    {
        perms = 0660;
    }

    perms = perms & ~umask;

    owner_u = ( (perms & 0400) != 0 ) ? 1 : 0;
    owner_m = ( (perms & 0200) != 0 ) ? 1 : 0;
    owner_a = ( (perms & 0100) != 0 ) ? 1 : 0;
    group_u = ( (perms & 0040) != 0 ) ? 1 : 0;
    group_m = ( (perms & 0020) != 0 ) ? 1 : 0;
    group_a = ( (perms & 0010) != 0 ) ? 1 : 0;
    other_u = ( (perms & 0004) != 0 ) ? 1 : 0;
    other_m = ( (perms & 0002) != 0 ) ? 1 : 0;
    other_a = ( (perms & 0001) != 0 ) ? 1 : 0;

}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
<commit_msg>feature #1664: Error messages as single attribute in templates<commit_after>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs        */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

#include "PoolObjectSQL.h"
#include "PoolObjectAuth.h"
#include "SSLTools.h"
#include "Nebula.h"
#include "Clusterable.h"

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

string& PoolObjectSQL::to_xml64(string &xml64)
{
    string *str64;

    to_xml(xml64);

    str64 = SSLTools::base64_encode(xml64);

    xml64 = *str64;

    delete str64;

    return xml64;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::select(SqlDB *db)
{
    ostringstream   oss;
    int             rc;
    int             boid;

    set_callback(
            static_cast<Callbackable::Callback>(&PoolObjectSQL::select_cb));

    oss << "SELECT body FROM " << table << " WHERE oid = " << oid;

    boid = oid;
    oid  = -1;

    rc = db->exec(oss, this);

    unset_callback();

    if ((rc != 0) || (oid != boid ))
    {
        return -1;
    }

    return 0;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::select(SqlDB *db, const string& _name, int _uid)
{
    ostringstream oss;

    int rc;
    char * sql_name;

    sql_name = db->escape_str(_name.c_str());

    if ( sql_name == 0 )
    {
        return -1;
    }

    set_callback(
            static_cast<Callbackable::Callback>(&PoolObjectSQL::select_cb));

    oss << "SELECT body FROM " << table << " WHERE name = '" << sql_name << "'";

    if ( _uid != -1 )
    {
        oss << " AND uid = " << _uid;
    }

    name  = "";
    uid   = -1;

    rc = db->exec(oss, this);

    unset_callback();

    db->free_str(sql_name);

    if ((rc != 0) || (_name != name) || (_uid != -1 && _uid != uid))
    {
        return -1;
    }

    return 0;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::drop(SqlDB *db)
{
    ostringstream oss;
    int rc;

    oss << "DELETE FROM " << table << " WHERE oid=" << oid;

    rc = db->exec(oss);

    if ( rc == 0 )
    {
        set_valid(false);
    }

    return rc;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

const char * PoolObjectSQL::error_attribute_name = "ERROR";

void PoolObjectSQL::set_template_error_message(const string& message)
{
    SingleAttribute * attr;
    ostringstream     error_value;

    char   str[26];
    time_t the_time;

    the_time = time(NULL);

#ifdef SOLARIS
    ctime_r(&(the_time),str,sizeof(char)*26);
#else
    ctime_r(&(the_time),str);
#endif

    str[24] = '\0'; // Get rid of final enter character

    error_value << str << " : " << message;

    //Replace previous error message and insert the new one

    attr = new SingleAttribute(error_attribute_name, error_value.str());

    obj_template->erase(error_attribute_name);
    obj_template->set(attr);
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::replace_template(const string& tmpl_str, string& error)
{
    Template * new_tmpl  = get_new_template();

    if ( new_tmpl == 0 )
    {
        error = "Cannot allocate a new template";
        return -1;
    }

    if ( new_tmpl->parse_str_or_xml(tmpl_str, error) != 0 )
    {
        delete new_tmpl;
        return -1;
    }

    if ( obj_template != 0 )
    {
        delete obj_template;
    }

    obj_template = new_tmpl;

    return 0;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

string& PoolObjectSQL::perms_to_xml(string& xml) const
{
    ostringstream   oss;

    oss <<
        "<PERMISSIONS>" <<
            "<OWNER_U>" << owner_u << "</OWNER_U>"  <<
            "<OWNER_M>" << owner_m << "</OWNER_M>"  <<
            "<OWNER_A>" << owner_a << "</OWNER_A>"  <<
            "<GROUP_U>" << group_u << "</GROUP_U>"  <<
            "<GROUP_M>" << group_m << "</GROUP_M>"  <<
            "<GROUP_A>" << group_a << "</GROUP_A>"  <<
            "<OTHER_U>" << other_u << "</OTHER_U>"  <<
            "<OTHER_M>" << other_m << "</OTHER_M>"  <<
            "<OTHER_A>" << other_a << "</OTHER_A>"  <<
        "</PERMISSIONS>";

    xml = oss.str();
    return xml;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::perms_from_xml()
{
    int rc = 0;

    rc += xpath(owner_u, "/*/PERMISSIONS/OWNER_U", 0);
    rc += xpath(owner_m, "/*/PERMISSIONS/OWNER_M", 0);
    rc += xpath(owner_a, "/*/PERMISSIONS/OWNER_A", 0);

    rc += xpath(group_u, "/*/PERMISSIONS/GROUP_U", 0);
    rc += xpath(group_m, "/*/PERMISSIONS/GROUP_M", 0);
    rc += xpath(group_a, "/*/PERMISSIONS/GROUP_A", 0);

    rc += xpath(other_u, "/*/PERMISSIONS/OTHER_U", 0);
    rc += xpath(other_m, "/*/PERMISSIONS/OTHER_M", 0);
    rc += xpath(other_a, "/*/PERMISSIONS/OTHER_A", 0);

    return rc;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void PoolObjectSQL::get_permissions(PoolObjectAuth& auth)
{
    auth.obj_type = obj_type;

    auth.oid = oid;
    auth.uid = uid;
    auth.gid = gid;

    auth.owner_u = owner_u;
    auth.owner_m = owner_m;
    auth.owner_a = owner_a;

    auth.group_u = group_u;
    auth.group_m = group_m;
    auth.group_a = group_a;

    auth.other_u = other_u;
    auth.other_m = other_m;
    auth.other_a = other_a;

    Clusterable* cl = dynamic_cast<Clusterable*>(this);

    if(cl != 0)
    {
        auth.cid = cl->get_cluster_id();
    }
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolObjectSQL::set_permissions( int _owner_u,
                                    int _owner_m,
                                    int _owner_a,
                                    int _group_u,
                                    int _group_m,
                                    int _group_a,
                                    int _other_u,
                                    int _other_m,
                                    int _other_a,
                                    string& error_str)
{
    if ( _owner_u < -1 || _owner_u > 1 ) goto error_value;
    if ( _owner_m < -1 || _owner_m > 1 ) goto error_value;
    if ( _owner_a < -1 || _owner_a > 1 ) goto error_value;
    if ( _group_u < -1 || _group_u > 1 ) goto error_value;
    if ( _group_m < -1 || _group_m > 1 ) goto error_value;
    if ( _group_a < -1 || _group_a > 1 ) goto error_value;
    if ( _other_u < -1 || _other_u > 1 ) goto error_value;
    if ( _other_m < -1 || _other_m > 1 ) goto error_value;
    if ( _other_a < -1 || _other_a > 1 ) goto error_value;

    set_perm(owner_u, _owner_u);
    set_perm(owner_m, _owner_m);
    set_perm(owner_a, _owner_a);
    set_perm(group_u, _group_u);
    set_perm(group_m, _group_m);
    set_perm(group_a, _group_a);
    set_perm(other_u, _other_u);
    set_perm(other_m, _other_m);
    set_perm(other_a, _other_a);

    return 0;

error_value:
    error_str = "New permission values must be -1, 0 or 1";
    return -1;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void PoolObjectSQL::set_umask(int umask)
{
    int perms;
    bool enable_other;

    Nebula::instance().get_configuration_attribute(
            "ENABLE_OTHER_PERMISSIONS", enable_other);

    if (uid == 0 || gid == 0)
    {
        perms = 0777;
    }
    else if (enable_other)
    {
        perms = 0666;
    }
    else
    {
        perms = 0660;
    }

    perms = perms & ~umask;

    owner_u = ( (perms & 0400) != 0 ) ? 1 : 0;
    owner_m = ( (perms & 0200) != 0 ) ? 1 : 0;
    owner_a = ( (perms & 0100) != 0 ) ? 1 : 0;
    group_u = ( (perms & 0040) != 0 ) ? 1 : 0;
    group_m = ( (perms & 0020) != 0 ) ? 1 : 0;
    group_a = ( (perms & 0010) != 0 ) ? 1 : 0;
    other_u = ( (perms & 0004) != 0 ) ? 1 : 0;
    other_m = ( (perms & 0002) != 0 ) ? 1 : 0;
    other_a = ( (perms & 0001) != 0 ) ? 1 : 0;

}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
<|endoftext|>


<commit_before>/** @file
 *
 * @ingroup dspFunctionLib
 *
 * @brief #TTFreeHandFunction Unit for Jamoms DSP
 *
 * @details A piecewise function unit that allows to load a function unit per defined domain. @n
 * The default configuration is a linear function for X[0::1], Y[0::1] domain. @n
 * Setup the curveList attribute to change the configuration. @n
 * For example setting curveList to the < 0.3 0.6 exponential base 0.5 1. 1. logarithm base 0.8 > value @n
 * you will imply the following behavior :
 *  -  if x belongs to [0::0.3] domain, it will use the exponential function and the result will belong to [0.::0.6] domain.
 *  -  if x belongs to ]0.3::1.] domain, it will use the logarithm function and the result will belong to  ]0.6::1.] domain.
 *
 * @authors Théo de la Hogue, Trond Lossius
 *
 * @copyright Copyright © 2013 by Théo de la Hogue @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTFreeHandFunction.h"
#include <math.h>

#define thisTTClass			TTFreeHandFunction
#define thisTTClassName		"freehand"
#define thisTTClassTags		"dspFunctionLib, audio, processor, function"

TT_AUDIO_CONSTRUCTOR
{
    registerAttribute(TTSymbol("curveList"), kTypeLocalValue, NULL, (TTGetterMethod)&TTFreeHandFunction::getCurveList, (TTSetterMethod)&TTFreeHandFunction::setCurveList);

	setProcessMethod(processAudio);
	setCalculateMethod(calculateValue);

    Clear();
}

TTFreeHandFunction::~TTFreeHandFunction()
{
	;
}

TTErr TTFreeHandFunction::getCurveList(TTValue& value)
{
    TTObject    aFunction;
    TTValue     v, attributeNames;
    TTSymbol    aName;
    TTUInt8     i;
    TTBoolean   firstFunction = YES;

    mFunctions.begin();

    // for each point
    for (mPoints.begin(); mPoints.end(); mPoints.next()) {

        // append the point coordinate
        value.append(mPoints.current());

        // the first function is always an exponential base 1. function
        if (firstFunction) {

            value.append(TTSymbol("exponential"));
            value.append(TTSymbol("base"));
            value.append(1.);

            firstFunction = NO;
            continue;
        }

        // append function info
        if (mFunctions.end()) {

            aFunction = mFunctions.current()[0];

            if (aFunction.valid()) {

                // append function name
                value.append(aFunction.name());

                // for all attributes
                aFunction.attributes(attributeNames);

                for (i = 0; i < attributeNames.size(); i++) {

                    aName = attributeNames[i];
                    if (aName == kTTSym_bypass || aName == TTSymbol("mute") || aName == kTTSym_maxNumChannels || aName == kTTSym_sampleRate)
                        continue;										// don't publish these datas

                    // append attribute name and value
                    aFunction.get(aName, v);
                    value.append(attributeNames[i]);
                    value.append(v);
                }
            }

            mFunctions.next();
        }
    }

    return kTTErrNone;
}

TTErr TTFreeHandFunction::setCurveList(const TTValue& value)
{
    TTUInt8     curveId;
    TTUInt32    i, next, size;
    TTFloat64   x, y;
    TTSymbol    function, parameterName;
    TTObject    aFunction;
    TTValue     v;
    TTErr       err = kTTErrNone;

    locked = YES;

    // clear all existing points
    mPoints.clear();

    // clear all existing functions
    mFunctions.clear();

    // set all points and curves
    size = value.size();
    curveId = 0;
    for (i = 0; i < size; i = i + next) {

        // check size
        if (i+1 >= size)
            err = kTTErrGeneric;

        // append a point : x y
        if (value[i].type() == kTypeFloat64 && value[i+1].type() == kTypeFloat64) {

            x = value[i];
            y = value[i+1];

            v = TTValue(x);
            v.append(y);
            mPoints.append(v);

            next = 2;
        }
        else
            err = kTTErrGeneric;

        // create a function
        aFunction = NULL;

        // check size
        if (i+2 >= size) {
            aFunction = TTObject("linear", 1);      // 1 is the numChannel

            // set function type
        } else if (value[i+2].type() == kTypeSymbol) {

            function = value[i+2];
            aFunction = TTObject(function, 1);      // 1 is the numChannel

            next = 3;

            // check size
            if (i+5 > size)
                ;

            // set function parameter
            else if (value[i+3].type() == kTypeSymbol) {

                parameterName = value[i+3];

                v.copyRange(value, i+4, i+5);
                aFunction.set(parameterName, v);

                next = 5;
            }
            else
                err = kTTErrGeneric;
        }
        else
            aFunction = TTObject("linear", 1);      // 1 is the numChannel

        // for the first point : release the function
        if (!curveId)
            aFunction = TTObject();

        // append the function
        else
            mFunctions.append(aFunction);

        curveId++;
    }

    locked = NO;

    return err;
}

TTErr TTFreeHandFunction::Clear()
{
    TTValue init;

    init.append(0.);
    init.append(0.);

    init.append(1.);
    init.append(1.);

    return setCurveList(init);
}

TTErr TTFreeHandFunction::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt data)
{
    TTFloat64   lastX, lastY;
    TTFloat64   currentX, currentY;
    TTFloat64   scaledX, scaledY;
    TTObject    aFunction;
    TTErr       err;

    if (locked)
        return kTTErrGeneric;

    if (mPoints.isEmpty())
        return kTTErrNone;

    mPoints.begin();
    lastX = mPoints.current()[0];
    lastY = mPoints.current()[1];

    if (x < lastX) {
        y = lastY;
        return kTTErrNone;
    }

     mPoints.next();

    // select the function to use
    for (mFunctions.begin(); mFunctions.end(); mFunctions.next()) {

        currentX = mPoints.current()[0];
        currentY = mPoints.current()[1];

        if (x < currentX) {

            aFunction = mFunctions.current()[0];

            // scale x
            scaledX = (x - lastX) / (currentX - lastX);

            // use function
            err = TTAudioObjectBasePtr(aFunction.instance())->calculate(scaledX, scaledY);

            // scale y
            y = (currentY - lastY) * scaledY + lastY;

            return err;
        }

        lastX = currentX;
        lastY = currentY;
        mPoints.next();
    }

    y = lastY;

	return kTTErrNone;
}

TTErr TTFreeHandFunction::processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	TT_WRAP_CALCULATE_METHOD(calculateValue);
}

<commit_msg>Cleaning get curve list accessor<commit_after>/** @file
 *
 * @ingroup dspFunctionLib
 *
 * @brief #TTFreeHandFunction Unit for Jamoms DSP
 *
 * @details A piecewise function unit that allows to load a function unit per defined domain. @n
 * The default configuration is a linear function for X[0::1], Y[0::1] domain. @n
 * Setup the curveList attribute to change the configuration. @n
 * For example setting curveList to the < 0.3 0.6 exponential base 0.5 1. 1. logarithm base 0.8 > value @n
 * you will imply the following behavior :
 *  -  if x belongs to [0::0.3] domain, it will use the exponential function and the result will belong to [0.::0.6] domain.
 *  -  if x belongs to ]0.3::1.] domain, it will use the logarithm function and the result will belong to  ]0.6::1.] domain.
 *
 * @authors Théo de la Hogue, Trond Lossius
 *
 * @copyright Copyright © 2013 by Théo de la Hogue @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTFreeHandFunction.h"
#include <math.h>

#define thisTTClass			TTFreeHandFunction
#define thisTTClassName		"freehand"
#define thisTTClassTags		"dspFunctionLib, audio, processor, function"

TT_AUDIO_CONSTRUCTOR
{
    registerAttribute(TTSymbol("curveList"), kTypeLocalValue, NULL, (TTGetterMethod)&TTFreeHandFunction::getCurveList, (TTSetterMethod)&TTFreeHandFunction::setCurveList);

	setProcessMethod(processAudio);
	setCalculateMethod(calculateValue);

    Clear();
}

TTFreeHandFunction::~TTFreeHandFunction()
{
	;
}

TTErr TTFreeHandFunction::getCurveList(TTValue& value)
{
    TTBoolean   firstFunction = YES;

    mFunctions.begin();

    // for each point
    for (mPoints.begin(); mPoints.end(); mPoints.next()) {

        // append the point coordinate
        value.append(mPoints.current());

        // the first function is always an exponential base 1. function
        if (firstFunction) {

            value.append(TTSymbol("exponential"));
            value.append(TTSymbol("base"));
            value.append(1.);

            firstFunction = NO;
            continue;
        }

        // append function info
        if (mFunctions.end()) {

            TTObject aFunction = mFunctions.current()[0];

            if (aFunction.valid()) {

                TTValue attributeNames;
                TTUInt8 i;

                // append function name
                value.append(aFunction.name());

                // for all attributes
                aFunction.attributes(attributeNames);

                for (i = 0; i < attributeNames.size(); i++) {

                    TTSymbol aName = attributeNames[i];

                    if (aName == kTTSym_bypass || aName == TTSymbol("mute") || aName == kTTSym_maxNumChannels || aName == kTTSym_sampleRate)
                        continue;										// don't publish these datas

                    // append attribute name
                    value.append(aName);

                    // append attribute value
                    TTValue v;
                    aFunction.get(aName, v);
                    value.append(v);
                }
            }

            mFunctions.next();
        }
    }

    return kTTErrNone;
}

TTErr TTFreeHandFunction::setCurveList(const TTValue& value)
{
    TTUInt8     curveId;
    TTUInt32    i, next, size;
    TTFloat64   x, y;
    TTSymbol    function, parameterName;
    TTObject    aFunction;
    TTValue     v;
    TTErr       err = kTTErrNone;

    locked = YES;

    // clear all existing points
    mPoints.clear();

    // clear all existing functions
    mFunctions.clear();

    // set all points and curves
    size = value.size();
    curveId = 0;
    for (i = 0; i < size; i = i + next) {

        // check size
        if (i+1 >= size)
            err = kTTErrGeneric;

        // append a point : x y
        if (value[i].type() == kTypeFloat64 && value[i+1].type() == kTypeFloat64) {

            x = value[i];
            y = value[i+1];

            v = TTValue(x);
            v.append(y);
            mPoints.append(v);

            next = 2;
        }
        else
            err = kTTErrGeneric;

        // create a function
        aFunction = NULL;

        // check size
        if (i+2 >= size) {
            aFunction = TTObject("linear", 1);      // 1 is the numChannel

            // set function type
        } else if (value[i+2].type() == kTypeSymbol) {

            function = value[i+2];
            aFunction = TTObject(function, 1);      // 1 is the numChannel

            next = 3;

            // check size
            if (i+5 > size)
                ;

            // set function parameter
            else if (value[i+3].type() == kTypeSymbol) {

                parameterName = value[i+3];

                v.copyRange(value, i+4, i+5);
                aFunction.set(parameterName, v);

                next = 5;
            }
            else
                err = kTTErrGeneric;
        }
        else
            aFunction = TTObject("linear", 1);      // 1 is the numChannel

        // for the first point : release the function
        if (!curveId)
            aFunction = TTObject();

        // append the function
        else
            mFunctions.append(aFunction);

        curveId++;
    }

    locked = NO;

    return err;
}

TTErr TTFreeHandFunction::Clear()
{
    TTValue init;

    init.append(0.);
    init.append(0.);

    init.append(1.);
    init.append(1.);

    return setCurveList(init);
}

TTErr TTFreeHandFunction::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt data)
{
    TTFloat64   lastX, lastY;
    TTFloat64   currentX, currentY;
    TTFloat64   scaledX, scaledY;
    TTObject    aFunction;
    TTErr       err;

    if (locked)
        return kTTErrGeneric;

    if (mPoints.isEmpty())
        return kTTErrNone;

    mPoints.begin();
    lastX = mPoints.current()[0];
    lastY = mPoints.current()[1];

    if (x < lastX) {
        y = lastY;
        return kTTErrNone;
    }

     mPoints.next();

    // select the function to use
    for (mFunctions.begin(); mFunctions.end(); mFunctions.next()) {

        currentX = mPoints.current()[0];
        currentY = mPoints.current()[1];

        if (x < currentX) {

            aFunction = mFunctions.current()[0];

            // scale x
            scaledX = (x - lastX) / (currentX - lastX);

            // use function
            err = TTAudioObjectBasePtr(aFunction.instance())->calculate(scaledX, scaledY);

            // scale y
            y = (currentY - lastY) * scaledY + lastY;

            return err;
        }

        lastX = currentX;
        lastY = currentY;
        mPoints.next();
    }

    y = lastY;

	return kTTErrNone;
}

TTErr TTFreeHandFunction::processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	TT_WRAP_CALCULATE_METHOD(calculateValue);
}

<|endoftext|>