<commit_before>// ======================================================================== //
// Copyright 2009-2016 Intel Corporation                                    //
//                                                                          //
// 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.                                           //
// ======================================================================== //

//ospray
#include "ospray/common/Data.h"
#include "ospray/common/Core.h"
#include "ospray/common/Library.h"
#include "ospray/volume/StructuredVolume.h"
#include "GridAccelerator_ispc.h"
#include "StructuredVolume_ispc.h"

// stl
#include <map>

namespace ospray {

StructuredVolume::StructuredVolume() :
  finished(false),
  voxelRange(FLT_MAX, -FLT_MAX)
{
}

StructuredVolume::~StructuredVolume() {}

std::string StructuredVolume::toString() const
{
  return("ospray::StructuredVolume<" + voxelType + ">");
}

void StructuredVolume::commit()
{
  // Some parameters can be changed after the volume has been allocated and
  // filled.
    updateEditableParameters();

    // Set the grid origin, default to (0,0,0).
    this->gridOrigin = getParam3f("gridOrigin", vec3f(0.f));

    // Get the volume dimensions.
    this->dimensions = getParam3i("dimensions", vec3i(0));
    exitOnCondition(reduce_min(this->dimensions) <= 0,
                    "invalid volume dimensions");

    // Set the grid spacing, default to (1,1,1).
    this->gridSpacing = getParam3f("gridSpacing", vec3f(1.f));

    ispc::StructuredVolume_setGridOrigin(ispcEquivalent,
                                         (const ispc::vec3f&)this->gridOrigin);
    ispc::StructuredVolume_setGridSpacing(ispcEquivalent,
                                         (const ispc::vec3f&)this->gridSpacing);

    // Complete volume initialization (only on first commit).
    if (!finished) {
      finish();
      finished = true;
    }
  }

  void StructuredVolume::buildAccelerator()
  {
    // Create instance of volume accelerator.
    void *accel = ispc::StructuredVolume_createAccelerator(ispcEquivalent);

    vec3i brickCount;
    brickCount.x = ispc::GridAccelerator_getBrickCount_x(accel);
    brickCount.y = ispc::GridAccelerator_getBrickCount_y(accel);
    brickCount.z = ispc::GridAccelerator_getBrickCount_z(accel);

    // Build volume accelerator.
    const int NTASKS = brickCount.x * brickCount.y * brickCount.z;
    parallel_for(NTASKS, [&](int taskIndex){
      ispc::GridAccelerator_buildAccelerator(ispcEquivalent, taskIndex);
    });
  }

  void StructuredVolume::finish()
  {
    // Make the voxel value range visible to the application.
    if (findParam("voxelRange") == NULL)
      set("voxelRange", voxelRange);
    else
      voxelRange = getParam2f("voxelRange", voxelRange);

    buildAccelerator();

    // Volume finish actions.
    Volume::finish();
  }

  OSPDataType StructuredVolume::getVoxelType() const
  {
    // Separate out the base type and vector width.
    char* kind = (char*)alloca(voxelType.size());
    unsigned int width = 1;
    sscanf(voxelType.c_str(), "%[^0-9]%u", kind, &width);

    OSPDataType res = OSP_UNKNOWN;

    // Unsigned 8-bit scalar integer.
    if (!strcmp(kind, "uchar") && width == 1)
      res = OSP_UCHAR;

    // Single precision scalar floating point.
    if (!strcmp(kind, "float") && width == 1)
      res = OSP_FLOAT;

    // Double precision scalar floating point.
    if (!strcmp(kind, "double") && width == 1)
      res = OSP_DOUBLE;

    return res;
  }

} // ::ospray

<commit_msg>formatting<commit_after>// ======================================================================== //
// Copyright 2009-2016 Intel Corporation                                    //
//                                                                          //
// 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.                                           //
// ======================================================================== //

//ospray
#include "ospray/common/Data.h"
#include "ospray/common/Core.h"
#include "ospray/common/Library.h"
#include "ospray/volume/StructuredVolume.h"
#include "GridAccelerator_ispc.h"
#include "StructuredVolume_ispc.h"

// stl
#include <map>

namespace ospray {

  StructuredVolume::StructuredVolume() :
    finished(false),
    voxelRange(FLT_MAX, -FLT_MAX)
  {
  }

  StructuredVolume::~StructuredVolume() {}

  std::string StructuredVolume::toString() const
  {
    return("ospray::StructuredVolume<" + voxelType + ">");
  }

  void StructuredVolume::commit()
  {
    // Some parameters can be changed after the volume has been allocated and
    // filled.
    updateEditableParameters();

    // Set the grid origin, default to (0,0,0).
    this->gridOrigin = getParam3f("gridOrigin", vec3f(0.f));

    // Get the volume dimensions.
    this->dimensions = getParam3i("dimensions", vec3i(0));
    exitOnCondition(reduce_min(this->dimensions) <= 0,
                    "invalid volume dimensions");

    // Set the grid spacing, default to (1,1,1).
    this->gridSpacing = getParam3f("gridSpacing", vec3f(1.f));

    ispc::StructuredVolume_setGridOrigin(ispcEquivalent,
                                         (const ispc::vec3f&)this->gridOrigin);
    ispc::StructuredVolume_setGridSpacing(ispcEquivalent,
                                         (const ispc::vec3f&)this->gridSpacing);

    // Complete volume initialization (only on first commit).
    if (!finished) {
      finish();
      finished = true;
    }
  }

  void StructuredVolume::buildAccelerator()
  {
    // Create instance of volume accelerator.
    void *accel = ispc::StructuredVolume_createAccelerator(ispcEquivalent);

    vec3i brickCount;
    brickCount.x = ispc::GridAccelerator_getBrickCount_x(accel);
    brickCount.y = ispc::GridAccelerator_getBrickCount_y(accel);
    brickCount.z = ispc::GridAccelerator_getBrickCount_z(accel);

    // Build volume accelerator.
    const int NTASKS = brickCount.x * brickCount.y * brickCount.z;
    parallel_for(NTASKS, [&](int taskIndex){
      ispc::GridAccelerator_buildAccelerator(ispcEquivalent, taskIndex);
    });
  }

  void StructuredVolume::finish()
  {
    // Make the voxel value range visible to the application.
    if (findParam("voxelRange") == NULL)
      set("voxelRange", voxelRange);
    else
      voxelRange = getParam2f("voxelRange", voxelRange);

    buildAccelerator();

    // Volume finish actions.
    Volume::finish();
  }

  OSPDataType StructuredVolume::getVoxelType() const
  {
    // Separate out the base type and vector width.
    char* kind = (char*)alloca(voxelType.size());
    unsigned int width = 1;
    sscanf(voxelType.c_str(), "%[^0-9]%u", kind, &width);

    OSPDataType res = OSP_UNKNOWN;

    // Unsigned 8-bit scalar integer.
    if (!strcmp(kind, "uchar") && width == 1)
      res = OSP_UCHAR;

    // Single precision scalar floating point.
    if (!strcmp(kind, "float") && width == 1)
      res = OSP_FLOAT;

    // Double precision scalar floating point.
    if (!strcmp(kind, "double") && width == 1)
      res = OSP_DOUBLE;

    return res;
  }

} // ::ospray

<|endoftext|>


<commit_before>/*
 * opencog/util/Logger.cc
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * Copyright (C) 2008 by OpenCog Foundation
 * Copyright (C) 2009, 2011 Linas Vepstas
 * Copyright (C) 2010 OpenCog Foundation
 * All Rights Reserved
 *
 * Written by Andre Senna <senna@vettalabs.com>
 *            Gustavo Gama <gama@vettalabs.com>
 *            Linas Vepstas <linasvepstas@gmail.com>
 *            Joel Pitt <joel@opencog.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "Logger.h"
#include "Config.h"

#ifndef CYGWIN
#include <cxxabi.h>
#include <execinfo.h>
#endif

#include <iostream>
#include <sstream>

#include <sched.h>
#include <stdarg.h>
#include <stdlib.h>
#include <time.h>

#ifdef WIN32_NOT_UNIX
#include <winsock2.h>
#undef ERROR
#undef DEBUG
#else
#include <sys/time.h>
#endif

#ifdef HAVE_VALGRIND
#include <valgrind/drd.h>
#endif

#include <opencog/util/backtrace-symbols.h>
#include <opencog/util/platform.h>

using namespace opencog;

// messages greater than this will be truncated
#define MAX_PRINTF_STYLE_MESSAGE_SIZE (1<<15)
const char* levelStrings[] = {"NONE", "ERROR", "WARN", "INFO", "DEBUG", "FINE"};

#ifndef CYGWIN /// @todo backtrace and backtrace_symbols is UNIX, we
              /// may need a WIN32 version
static void prt_backtrace(std::ostringstream& oss)
{
#define BT_BUFSZ 50
	void *bt_buf[BT_BUFSZ];

	int stack_depth = backtrace(bt_buf, BT_BUFSZ);
#ifdef HAVE_BFD
	char **syms = oc_backtrace_symbols(bt_buf, stack_depth);
#else
	char **syms = backtrace_symbols(bt_buf, stack_depth);
#endif

	// Start printing at a bit into the stack, so as to avoid recording
	// the logger functions in the stack trace.
	oss << "\tStack Trace:\n";
	for (int i=2; i < stack_depth; i++)
	{
		// Most things we'll print are mangled C++ names,
		// So demangle them, get them to pretty-print.
#ifdef HAVE_BFD
		// The standard and the heck versions differ slightly in layout.
		char * begin = strstr(syms[i], "_ZN");
		char * end = strchr(syms[i], '(');
		if (!(begin && end) || end <= begin)
		{
			// Failed to pull apart the symbol names
			oss << "\t" << i << ": " << syms[i] << "\n";
		}
		else
		{
			*begin = 0x0;
			oss << "\t" << i << ": " << syms[i] << "  ";
			*begin = '_';
			size_t sz = 250;
			int status;
			char *fname = (char *) malloc(sz);
			*end = 0x0;
			char *rv = abi::__cxa_demangle(begin, fname, &sz, &status);
			if (rv) fname = rv; // might have re-alloced
			oss << fname << std::endl;
			free(fname);
		}
#else
		char * begin = strchr(syms[i], '(');
		char * end = strchr(syms[i], '+');
		if (!(begin && end) || end <= begin)
		{
			// Failed to pull apart the symbol names
			oss << "\t" << i << ": " << syms[i] << "\n";
		}
		else
		{
			*begin = 0x0;
			oss << "\t" << i << ": " << syms[i] << " ";
			*begin = '(';
			size_t sz = 250;
			int status;
			char *fname = (char *) malloc(sz);
			*end = 0x0;
			char *rv = abi::__cxa_demangle(begin+1, fname, &sz, &status);
			*end = '+';
			if (rv) fname = rv; // might have re-alloced
			oss << "(" << fname << " " << end << std::endl;
			free(fname);
		}
#endif
	}
	oss << std::endl;
	free(syms);
}
#endif

Logger::~Logger()
{
    // Wait for queue to empty
    flush();
    stopWriteLoop();

    if (f != NULL) fclose(f);
}

void Logger::startWriteLoop()
{
    std::unique_lock<std::mutex> lock(the_mutex);
    if (!writingLoopActive)
    {
        writingLoopActive = true;
        writer_thread = std::thread(&Logger::writingLoop, this);
    }
}

void Logger::stopWriteLoop()
{
    std::unique_lock<std::mutex> lock(the_mutex);
    msg_queue.cancel();
    // rejoin thread
    writer_thread.join();
    writingLoopActive = false;
}

void Logger::writingLoop()
{
    try
    {
        while (true)
        {
            // The pending_write flag prevents Logger::flush()
            // from returning prematurely.
            std::string* msg = msg_queue.pop();
            pending_write = true;
            writeMsg(*msg);
            pending_write = false;
            delete msg;
        }
    }
    catch (concurrent_queue< std::string* >::Canceled &e)
    {
        return;
    }
}

void Logger::flush()
{
    // Perhaps we could do this with semaphors, but this is not
    // really critical code, so a busy-wait is good enough.
    while (pending_write or not msg_queue.is_empty())
    {
        sched_yield();
        usleep(100);
    }
}

void Logger::writeMsg(std::string &msg)
{
    std::unique_lock<std::mutex> lock(the_mutex);
    // Delay opening the file until the first logging statement is issued;
    // this allows us to set the main logger's filename without creating
    // a useless log file with the default filename.
    if (f == NULL)
    {
        if ((f = fopen(fileName.c_str(), "a")) == NULL)
        {
            fprintf(stderr, "[ERROR] Unable to open log file \"%s\"\n",
                    fileName.c_str());
            lock.unlock();
            disable();
            return;
        }

        enable();

        // Log the config file location. We do that here, because
        // we can't do it any earlier, because the config file
        // specifies the log location.
        if (INFO <= currentLevel)
        {
            fprintf(f, "[INFO] Using config file found at: %s\n",
                   config().path_where_found().c_str());

            if (printToStdout)
                printf("[INFO] Using config file found at: %s\n",
                       config().path_where_found().c_str());
        }
    }

    // Write to file.
    fprintf(f, "%s", msg.c_str());
    fflush(f);

    // Stdout writing ust be unlocked.
    lock.unlock();

    // Write to stdout.
    if (printToStdout)
    {
        std::cout << msg;
        std::cout.flush();
    }
}

Logger::Logger(const std::string &fname, Logger::Level level, bool tsEnabled)
    : error(*this), warn(*this), info(*this), debug(*this), fine(*this)
{
    this->fileName.assign(fname);
    this->currentLevel = level;
    this->backTraceLevel = getLevelFromString(opencog::config()["BACK_TRACE_LOG_LEVEL"]);
    this->timestampEnabled = tsEnabled;
    this->printToStdout = false;

    this->logEnabled = true;
#ifdef HAVE_VALGRIND
    DRD_IGNORE_VAR(this->logEnabled);
    DRD_IGNORE_VAR(this->msg_queue);
#endif
    this->f = NULL;
    this->pending_write = false;
    this->writingLoopActive = false;

    startWriteLoop();
}

Logger::Logger(const Logger& log)
    : error(*this), warn(*this), info(*this), debug(*this), fine(*this)
{
    set(log);
}

Logger& Logger::operator=(const Logger& log)
{
    this->stopWriteLoop();
    msg_queue.cancel_reset();
    this->set(log);
    return *this;
}

void Logger::set(const Logger& log)
{
    std::unique_lock<std::mutex> lock(the_mutex);
    this->fileName.assign(log.fileName);
    this->currentLevel = log.currentLevel;
    this->backTraceLevel = log.backTraceLevel;
    this->timestampEnabled = log.timestampEnabled;
    this->printToStdout = log.printToStdout;

    this->logEnabled = log.logEnabled;
    this->f = log.f;
    lock.unlock();

    startWriteLoop();
}

// ***********************************************/
// API

void Logger::setLevel(Logger::Level newLevel)
{
    currentLevel = newLevel;
}

Logger::Level Logger::getLevel() const
{
    return currentLevel;
}

void Logger::setBackTraceLevel(Logger::Level newLevel)
{
    backTraceLevel = newLevel;
}

Logger::Level Logger::getBackTraceLevel() const
{
    return backTraceLevel;
}

void Logger::setFilename(const std::string& s)
{
    fileName.assign(s);

    std::unique_lock<std::mutex> lock(the_mutex);
    if (f != NULL) fclose(f);
    f = NULL;
    lock.unlock();

    enable();
}

const std::string& Logger::getFilename()
{
    return fileName;
}

void Logger::setTimestampFlag(bool flag)
{
    timestampEnabled = flag;
}

void Logger::setPrintToStdoutFlag(bool flag)
{
    printToStdout = flag;
}

void Logger::setPrintErrorLevelStdout()
{
    setPrintToStdoutFlag(true);
    setLevel(Logger::ERROR);
}

void Logger::enable()
{
    logEnabled = true;
}

void Logger::disable()
{
    logEnabled = false;
}

void Logger::log(Logger::Level level, const std::string &txt)
{
    static const unsigned int max_queue_size_allowed = 1024;
    // Don't log if not enabled, or level is too low.
    if (!logEnabled) return;
    if (level > currentLevel) return;

    std::ostringstream oss;
    if (timestampEnabled)
    {
        struct timeval stv;
        struct tm stm;
        char timestamp[64];
        char timestampStr[256];

        ::gettimeofday(&stv, NULL);
        time_t t = stv.tv_sec;
        gmtime_r(&t, &stm);
        strftime(timestamp, sizeof(timestamp), "%F %T", &stm);
        snprintf(timestampStr, sizeof(timestampStr),
                "[%s:%03ld] ",timestamp, stv.tv_usec / 1000);
        oss << timestampStr;
    }

    oss << "[" << getLevelString(level) << "] " << txt << std::endl;

    if (level <= backTraceLevel)
    {
#ifndef CYGWIN
        prt_backtrace(oss);
#endif
    }

    msg_queue.push(new std::string(oss.str()));

    // If the queue gets too full, block until it's flushed to file or
    // stdout. This can sometimes happen, if some component is spewing
    // lots of debugging messages in a tight loop.
    if (msg_queue.size() > max_queue_size_allowed) {
        flush();
    }
}

void Logger::logva(Logger::Level level, const char *fmt, va_list args)
{
    if (level <= currentLevel) {
        char buffer[MAX_PRINTF_STYLE_MESSAGE_SIZE];
        vsnprintf(buffer, sizeof(buffer), fmt, args);
        std::string msg = buffer;
        log(level, msg);
    }
}

void Logger::log(Logger::Level level, const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(level, fmt, args); va_end(args);
}

void Logger::Error::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(ERROR, fmt, args); va_end(args);
}

void Logger::Warn::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(WARN,  fmt, args); va_end(args);
}

void Logger::Info::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(INFO,  fmt, args); va_end(args);
}

void Logger::Debug::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(DEBUG, fmt, args); va_end(args);
}

void Logger::Fine::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(FINE,  fmt, args); va_end(args);
}

const char* Logger::getLevelString(const Logger::Level level)
{
    if (level == BAD_LEVEL)
        return "Bad level";
    else
        return levelStrings[level];
}

const Logger::Level Logger::getLevelFromString(const std::string& levelStr)
{
    unsigned int nLevels = sizeof(levelStrings) / sizeof(levelStrings[0]);
    for (unsigned int i = 0; i < nLevels; ++i) {
        if (0 == levelStr.compare(levelStrings[i]))
            return (Logger::Level) i;
    }
    return BAD_LEVEL;
}

// create and return the single instance
Logger& opencog::logger()
{
    static Logger instance;
    return instance;
}
<commit_msg>Oops, fix bug introduced in previous patch.<commit_after>/*
 * opencog/util/Logger.cc
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * Copyright (C) 2008 by OpenCog Foundation
 * Copyright (C) 2009, 2011 Linas Vepstas
 * Copyright (C) 2010 OpenCog Foundation
 * All Rights Reserved
 *
 * Written by Andre Senna <senna@vettalabs.com>
 *            Gustavo Gama <gama@vettalabs.com>
 *            Linas Vepstas <linasvepstas@gmail.com>
 *            Joel Pitt <joel@opencog.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef CYGWIN
#include <cxxabi.h>
#include <execinfo.h>
#endif

#include <iostream>
#include <sstream>

#include <sched.h>
#include <stdarg.h>
#include <stdlib.h>
#include <strings.h>
#include <time.h>

#ifdef WIN32_NOT_UNIX
#include <winsock2.h>
#undef ERROR
#undef DEBUG
#else
#include <sys/time.h>
#endif

#ifdef HAVE_VALGRIND
#include <valgrind/drd.h>
#endif

#include <opencog/util/backtrace-symbols.h>
#include <opencog/util/platform.h>

#include "Logger.h"
#include "Config.h"

using namespace opencog;

// messages greater than this will be truncated
#define MAX_PRINTF_STYLE_MESSAGE_SIZE (1<<15)
const char* levelStrings[] = {"NONE", "ERROR", "WARN", "INFO", "DEBUG", "FINE"};

#ifndef CYGWIN /// @todo backtrace and backtrace_symbols is UNIX, we
              /// may need a WIN32 version
static void prt_backtrace(std::ostringstream& oss)
{
#define BT_BUFSZ 50
	void *bt_buf[BT_BUFSZ];

	int stack_depth = backtrace(bt_buf, BT_BUFSZ);
#ifdef HAVE_BFD
	char **syms = oc_backtrace_symbols(bt_buf, stack_depth);
#else
	char **syms = backtrace_symbols(bt_buf, stack_depth);
#endif

	// Start printing at a bit into the stack, so as to avoid recording
	// the logger functions in the stack trace.
	oss << "\tStack Trace:\n";
	for (int i=2; i < stack_depth; i++)
	{
		// Most things we'll print are mangled C++ names,
		// So demangle them, get them to pretty-print.
#ifdef HAVE_BFD
		// The standard and the heck versions differ slightly in layout.
		char * begin = strstr(syms[i], "_ZN");
		char * end = strchr(syms[i], '(');
		if (!(begin && end) || end <= begin)
		{
			// Failed to pull apart the symbol names
			oss << "\t" << i << ": " << syms[i] << "\n";
		}
		else
		{
			*begin = 0x0;
			oss << "\t" << i << ": " << syms[i] << "  ";
			*begin = '_';
			size_t sz = 250;
			int status;
			char *fname = (char *) malloc(sz);
			*end = 0x0;
			char *rv = abi::__cxa_demangle(begin, fname, &sz, &status);
			if (rv) fname = rv; // might have re-alloced
			oss << fname << std::endl;
			free(fname);
		}
#else
		char * begin = strchr(syms[i], '(');
		char * end = strchr(syms[i], '+');
		if (!(begin && end) || end <= begin)
		{
			// Failed to pull apart the symbol names
			oss << "\t" << i << ": " << syms[i] << "\n";
		}
		else
		{
			*begin = 0x0;
			oss << "\t" << i << ": " << syms[i] << " ";
			*begin = '(';
			size_t sz = 250;
			int status;
			char *fname = (char *) malloc(sz);
			*end = 0x0;
			char *rv = abi::__cxa_demangle(begin+1, fname, &sz, &status);
			*end = '+';
			if (rv) fname = rv; // might have re-alloced
			oss << "(" << fname << " " << end << std::endl;
			free(fname);
		}
#endif
	}
	oss << std::endl;
	free(syms);
}
#endif

Logger::~Logger()
{
    // Wait for queue to empty
    flush();
    stopWriteLoop();

    if (f != NULL) fclose(f);
}

void Logger::startWriteLoop()
{
    std::unique_lock<std::mutex> lock(the_mutex);
    if (!writingLoopActive)
    {
        writingLoopActive = true;
        writer_thread = std::thread(&Logger::writingLoop, this);
    }
}

void Logger::stopWriteLoop()
{
    std::unique_lock<std::mutex> lock(the_mutex);
    msg_queue.cancel();
    // rejoin thread
    writer_thread.join();
    writingLoopActive = false;
}

void Logger::writingLoop()
{
    try
    {
        while (true)
        {
            // The pending_write flag prevents Logger::flush()
            // from returning prematurely.
            std::string* msg = msg_queue.pop();
            pending_write = true;
            writeMsg(*msg);
            pending_write = false;
            delete msg;
        }
    }
    catch (concurrent_queue< std::string* >::Canceled &e)
    {
        return;
    }
}

void Logger::flush()
{
    // Perhaps we could do this with semaphors, but this is not
    // really critical code, so a busy-wait is good enough.
    while (pending_write or not msg_queue.is_empty())
    {
        sched_yield();
        usleep(100);
    }
}

void Logger::writeMsg(std::string &msg)
{
    std::unique_lock<std::mutex> lock(the_mutex);
    // Delay opening the file until the first logging statement is issued;
    // this allows us to set the main logger's filename without creating
    // a useless log file with the default filename.
    if (f == NULL)
    {
        if ((f = fopen(fileName.c_str(), "a")) == NULL)
        {
            fprintf(stderr, "[ERROR] Unable to open log file \"%s\"\n",
                    fileName.c_str());
            lock.unlock();
            disable();
            return;
        }

        enable();

        // Log the config file location. We do that here, because
        // we can't do it any earlier, because the config file
        // specifies the log location.
        if (INFO <= currentLevel)
        {
            fprintf(f, "[INFO] Using config file found at: %s\n",
                   config().path_where_found().c_str());

            if (printToStdout)
                printf("[INFO] Using config file found at: %s\n",
                       config().path_where_found().c_str());
        }
    }

    // Write to file.
    fprintf(f, "%s", msg.c_str());
    fflush(f);

    // Stdout writing ust be unlocked.
    lock.unlock();

    // Write to stdout.
    if (printToStdout)
    {
        std::cout << msg;
        std::cout.flush();
    }
}

Logger::Logger(const std::string &fname, Logger::Level level, bool tsEnabled)
    : error(*this), warn(*this), info(*this), debug(*this), fine(*this)
{
    this->fileName.assign(fname);
    this->currentLevel = level;
    this->backTraceLevel = getLevelFromString(opencog::config()["BACK_TRACE_LOG_LEVEL"]);

    this->timestampEnabled = tsEnabled;
    this->printToStdout = false;

    this->logEnabled = true;
#ifdef HAVE_VALGRIND
    DRD_IGNORE_VAR(this->logEnabled);
    DRD_IGNORE_VAR(this->msg_queue);
#endif
    this->f = NULL;
    this->pending_write = false;
    this->writingLoopActive = false;

    startWriteLoop();
}

Logger::Logger(const Logger& log)
    : error(*this), warn(*this), info(*this), debug(*this), fine(*this)
{
    set(log);
}

Logger& Logger::operator=(const Logger& log)
{
    this->stopWriteLoop();
    msg_queue.cancel_reset();
    this->set(log);
    return *this;
}

void Logger::set(const Logger& log)
{
    std::unique_lock<std::mutex> lock(the_mutex);
    this->fileName.assign(log.fileName);
    this->currentLevel = log.currentLevel;
    this->backTraceLevel = log.backTraceLevel;
    this->timestampEnabled = log.timestampEnabled;
    this->printToStdout = log.printToStdout;

    this->logEnabled = log.logEnabled;
    this->f = log.f;
    lock.unlock();

    startWriteLoop();
}

// ***********************************************/
// API

void Logger::setLevel(Logger::Level newLevel)
{
    currentLevel = newLevel;
}

Logger::Level Logger::getLevel() const
{
    return currentLevel;
}

void Logger::setBackTraceLevel(Logger::Level newLevel)
{
    backTraceLevel = newLevel;
}

Logger::Level Logger::getBackTraceLevel() const
{
    return backTraceLevel;
}

void Logger::setFilename(const std::string& s)
{
    fileName.assign(s);

    std::unique_lock<std::mutex> lock(the_mutex);
    if (f != NULL) fclose(f);
    f = NULL;
    lock.unlock();

    enable();
}

const std::string& Logger::getFilename()
{
    return fileName;
}

void Logger::setTimestampFlag(bool flag)
{
    timestampEnabled = flag;
}

void Logger::setPrintToStdoutFlag(bool flag)
{
    printToStdout = flag;
}

void Logger::setPrintErrorLevelStdout()
{
    setPrintToStdoutFlag(true);
    setLevel(Logger::ERROR);
}

void Logger::enable()
{
    logEnabled = true;
}

void Logger::disable()
{
    logEnabled = false;
}

void Logger::log(Logger::Level level, const std::string &txt)
{
    static const unsigned int max_queue_size_allowed = 1024;
    // Don't log if not enabled, or level is too low.
    if (!logEnabled) return;
    if (level > currentLevel) return;

    std::ostringstream oss;
    if (timestampEnabled)
    {
        struct timeval stv;
        struct tm stm;
        char timestamp[64];
        char timestampStr[256];

        ::gettimeofday(&stv, NULL);
        time_t t = stv.tv_sec;
        gmtime_r(&t, &stm);
        strftime(timestamp, sizeof(timestamp), "%F %T", &stm);
        snprintf(timestampStr, sizeof(timestampStr),
                "[%s:%03ld] ",timestamp, stv.tv_usec / 1000);
        oss << timestampStr;
    }

    oss << "[" << getLevelString(level) << "] " << txt << std::endl;

    if (level <= backTraceLevel)
    {
#ifndef CYGWIN
        prt_backtrace(oss);
#endif
    }

    msg_queue.push(new std::string(oss.str()));

    // If the queue gets too full, block until it's flushed to file or
    // stdout. This can sometimes happen, if some component is spewing
    // lots of debugging messages in a tight loop.
    if (msg_queue.size() > max_queue_size_allowed) {
        flush();
    }
}

void Logger::logva(Logger::Level level, const char *fmt, va_list args)
{
    if (level <= currentLevel) {
        char buffer[MAX_PRINTF_STYLE_MESSAGE_SIZE];
        vsnprintf(buffer, sizeof(buffer), fmt, args);
        std::string msg = buffer;
        log(level, msg);
    }
}

void Logger::log(Logger::Level level, const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(level, fmt, args); va_end(args);
}

void Logger::Error::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(ERROR, fmt, args); va_end(args);
}

void Logger::Warn::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(WARN,  fmt, args); va_end(args);
}

void Logger::Info::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(INFO,  fmt, args); va_end(args);
}

void Logger::Debug::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(DEBUG, fmt, args); va_end(args);
}

void Logger::Fine::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(FINE,  fmt, args); va_end(args);
}

const char* Logger::getLevelString(const Logger::Level level)
{
    if (level == BAD_LEVEL)
        return "Bad level";
    else
        return levelStrings[level];
}

const Logger::Level Logger::getLevelFromString(const std::string& levelStr)
{
    unsigned int nLevels = sizeof(levelStrings) / sizeof(levelStrings[0]);
    const char* lstr = levelStr.c_str();
    for (unsigned int i = 0; i < nLevels; ++i) {
        if (0 == strcasecmp(lstr, levelStrings[i]))
            return (Logger::Level) i;
    }
    return BAD_LEVEL;
}

// create and return the single instance
Logger& opencog::logger()
{
    static Logger instance;
    return instance;
}
<|endoftext|>


<commit_before>/*
 * opencog/util/Logger.cc
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * Copyright (C) 2008 by OpenCog Foundation
 * Copyright (C) 2009, 2011 Linas Vepstas
 * Copyright (C) 2010 OpenCog Foundation
 * All Rights Reserved
 *
 * Written by Andre Senna <senna@vettalabs.com>
 *            Gustavo Gama <gama@vettalabs.com>
 *            Joel Pitt <joel@opencog.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "Logger.h"
#include "Config.h"

#ifndef WIN32
#include <cxxabi.h>
#include <execinfo.h>
#endif

#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <sstream>

#ifdef WIN32_NOT_UNIX
#include <winsock2.h>
#undef ERROR
#undef DEBUG
#else
#include <sys/time.h>
#endif

#include <boost/algorithm/string.hpp>

#include <opencog/util/platform.h>

using namespace opencog;

// messages greater than this will be truncated
#define MAX_PRINTF_STYLE_MESSAGE_SIZE (1<<15)
const char* levelStrings[] = {"NONE", "ERROR", "WARN", "INFO", "DEBUG", "FINE"};

#ifndef WIN32 /// @todo backtrace and backtrace_symbols is UNIX, we
              /// may need a WIN32 version
static void prt_backtrace(std::ostringstream& oss)
{
#define BT_BUFSZ 50
	void *bt_buf[BT_BUFSZ];

	int stack_depth = backtrace(bt_buf, BT_BUFSZ);
	char **syms = backtrace_symbols(bt_buf, stack_depth);

	// Start printing at a bit into the stack, so as to avoid recording
	// the logger functions in the stack trace.
	oss << "\tStack Trace:\n";
	for (int i=2; i < stack_depth; i++)
	{
		// Most things we'll print are mangled C++ names,
		// So demangle them, get them to pretty-print.
		char * begin = strchr(syms[i], '(');
		char * end = strchr(syms[i], '+');
		if (!(begin && end) || end <= begin)
		{
			// Failed to pull apart the symbol names
            oss << "\t" << i << ": " << syms[i] << "\n";
		}
		else
		{
			*begin = 0x0;
			oss << "\t" << i << ": " << syms[i] << " ";
			*begin = '(';
			size_t sz = 250;
			int status;
			char *fname = (char *) malloc(sz);
			*end = 0x0;
			char *rv = abi::__cxa_demangle(begin+1, fname, &sz, &status);
			*end = '+';
			if (rv) fname = rv; // might have re-alloced
			oss << "(" << fname << " " << end << std::endl;
			free(fname);
		}
	}
	oss << std::endl;
	free(syms);
}
#endif

Logger::~Logger()
{
#ifdef ASYNC_LOGGING
    // Wait for queue to empty
    flush();
    stopWriteLoop();
#endif

    if (f != NULL) fclose(f);
}

#ifdef ASYNC_LOGGING
void Logger::startWriteLoop()
{
    pthread_mutex_lock(&lock);
    if (!writingLoopActive) {
        writingLoopActive = true;
        m_Thread = boost::thread(&Logger::writingLoop, this);
    }
    pthread_mutex_unlock(&lock);
}

void Logger::stopWriteLoop()
{
    pthread_mutex_lock(&lock);
    pendingMessagesToWrite.cancel();
    // rejoin thread
    m_Thread.join();
    writingLoopActive = false;
    pthread_mutex_unlock(&lock);
}

void Logger::writingLoop()
{
    try {
        while (true) {
            std::string* msg;
            pendingMessagesToWrite.wait_and_pop(msg);
            writeMsg(*msg);
            delete msg;
        }
    } catch (concurrent_queue< std::string* >::Canceled &e) {
        return;
    }
}

void Logger::flush()
{
    while (!pendingMessagesToWrite.empty()) usleep(100);
}
#endif

void Logger::writeMsg(std::string &msg)
{
    pthread_mutex_lock(&lock);
    // delay opening the file until the first logging statement is issued;
    // this allows us to set the main logger's filename without creating
    // a useless log file with the default filename
    if (f == NULL) {
        if ((f = fopen(fileName.c_str(), "a")) == NULL) {
            fprintf(stderr, "[ERROR] Unable to open log file \"%s\"\n", fileName.c_str());
            disable();
            return;
        } else enable();
    }
    // write to file
    fprintf(f, "%s", msg.c_str());
    fflush(f);
    pthread_mutex_unlock(&lock);
    // write to stdout
    if (printToStdout) {
        std::cout << msg;
        std::cout.flush();
    }

}

Logger::Logger(const std::string &fileName, Logger::Level level, bool timestampEnabled)
{
    this->fileName.assign(fileName);
    this->currentLevel = level;
    this->backTraceLevel = getLevelFromString(opencog::config()["BACK_TRACE_LOG_LEVEL"]);
    this->timestampEnabled = timestampEnabled;
    this->printToStdout = false;

    this->logEnabled = true;
    this->f = NULL;

    pthread_mutex_init(&lock, NULL);
#ifdef ASYNC_LOGGING
    this->writingLoopActive = false;
    startWriteLoop();
#endif // ASYNC_LOGGING
}

Logger::Logger(const Logger& log) {
    pthread_mutex_init(&lock, NULL);
    set(log);
}

Logger& Logger::operator=(const Logger& log)
{
#ifdef ASYNC_LOGGING
    this->stopWriteLoop();
    pendingMessagesToWrite.cancel_reset();
#endif // ASYNC_LOGGING
    this->set(log);
    return *this;
}

void Logger::set(const Logger& log) {
    this->fileName.assign(log.fileName);
    this->currentLevel = log.currentLevel;
    this->backTraceLevel = log.backTraceLevel;
    this->timestampEnabled = log.timestampEnabled;
    this->printToStdout = log.printToStdout;

    this->logEnabled = log.logEnabled;
    this->f = log.f;

#ifdef ASYNC_LOGGING
    startWriteLoop();
#endif // ASYNC_LOGGING
}

// ***********************************************/
// API

void Logger::setLevel(Logger::Level newLevel)
{
    currentLevel = newLevel;
}

Logger::Level Logger::getLevel() const
{
    return currentLevel;
}

void Logger::setBackTraceLevel(Logger::Level newLevel)
{
    backTraceLevel = newLevel;
}

Logger::Level Logger::getBackTraceLevel() const
{
    return backTraceLevel;
}

void Logger::setFilename(const std::string& s)
{
    fileName.assign(s);

    pthread_mutex_lock(&lock);
    if (f != NULL) fclose(f);
    f = NULL;
    pthread_mutex_unlock(&lock);

    enable();
}

const std::string& Logger::getFilename()
{
    return fileName;
}

void Logger::setTimestampFlag(bool flag)
{
    timestampEnabled = flag;
}

void Logger::setPrintToStdoutFlag(bool flag)
{
    printToStdout = flag;
}

void Logger::setPrintErrorLevelStdout() {
    setPrintToStdoutFlag(true);
    setLevel(Logger::ERROR);
}

void Logger::enable()
{
    logEnabled = true;
}

void Logger::disable()
{
    logEnabled = false;
}

void Logger::log(Logger::Level level, const std::string &txt)
{
#ifdef ASYNC_LOGGING
    static const unsigned int max_queue_size_allowed = 1024;
#endif
    static char timestamp[64];
    static char timestampStr[256];
    if (!logEnabled) return;

    if (level <= currentLevel) {
        std::ostringstream oss;
        if (timestampEnabled) {
            struct timeval stv;
            struct tm stm;

            ::gettimeofday(&stv, NULL);
            time_t t = stv.tv_sec;
            gmtime_r(&t, &stm);
            strftime(timestamp, sizeof(timestamp), "%F %T", &stm);
            snprintf(timestampStr, sizeof(timestampStr),
                    "[%s:%03ld] ",timestamp, stv.tv_usec / 1000);
            oss << timestampStr;
        }

        oss << "[" << getLevelString(level) << "] " << txt << std::endl;

        if (level <= backTraceLevel)
        {
#ifndef WIN32
            prt_backtrace(oss);
#endif
        }
#ifdef ASYNC_LOGGING
        pendingMessagesToWrite.push(new std::string(oss.str()));

        // If the queue gets too full, block until it's flushed to file or
        // stdout
        if (pendingMessagesToWrite.approx_size() > max_queue_size_allowed) {
            flush();
        }
#else
        std::string temp(oss.str());
        writeMsg(temp);
#endif
    }
}
void Logger::error(const std::string &txt)
{
    log(ERROR, txt);
}
void Logger::warn (const std::string &txt)
{
    log(WARN,  txt);
}
void Logger::info (const std::string &txt)
{
    log(INFO,  txt);
}
void Logger::debug(const std::string &txt)
{
    log(DEBUG, txt);
}
void Logger::fine (const std::string &txt)
{
    log(FINE,  txt);
}

void Logger::logva(Logger::Level level, const char *fmt, va_list args)
{
    if (level <= currentLevel) {
        char buffer[MAX_PRINTF_STYLE_MESSAGE_SIZE];
        vsnprintf(buffer, sizeof(buffer), fmt, args);
        std::string msg = buffer;
        log(level, msg);
    }
}

void Logger::log(Logger::Level level, const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(level, fmt, args); va_end(args);
}
void Logger::error(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(ERROR, fmt, args); va_end(args);
}
void Logger::warn (const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(WARN,  fmt, args); va_end(args);
}
void Logger::info (const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(INFO,  fmt, args); va_end(args);
}
void Logger::debug(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(DEBUG, fmt, args); va_end(args);
}
void Logger::fine (const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(FINE,  fmt, args); va_end(args);
}

bool Logger::isEnabled(Level level) const
{
    return level <= currentLevel;
}

bool Logger::isErrorEnabled() const
{
    return ERROR <= currentLevel;
}

bool Logger::isWarnEnabled() const
{
    return WARN <= currentLevel;
}

bool Logger::isInfoEnabled() const
{
    return INFO <= currentLevel;
}

bool Logger::isDebugEnabled() const
{
    return DEBUG <= currentLevel;
}

bool Logger::isFineEnabled() const
{
    return FINE <= currentLevel;
}

const char* Logger::getLevelString(const Logger::Level level)
{
    if (level == BAD_LEVEL)
        return "Bad level";
    else
        return levelStrings[level];
}

const Logger::Level Logger::getLevelFromString(const std::string& levelStr)
{
    unsigned int nLevels = sizeof(levelStrings) / sizeof(levelStrings[0]);
    for (unsigned int i = 0; i < nLevels; ++i) {
        if (boost::iequals(levelStrings[i], levelStr))
            return (Logger::Level) i;
    }
    return BAD_LEVEL;
}

// create and return the single instance
static Logger instance;
Logger& opencog::logger()
{
    return instance;
}
<commit_msg>minor: whitespace formatting.<commit_after>/*
 * opencog/util/Logger.cc
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * Copyright (C) 2008 by OpenCog Foundation
 * Copyright (C) 2009, 2011 Linas Vepstas
 * Copyright (C) 2010 OpenCog Foundation
 * All Rights Reserved
 *
 * Written by Andre Senna <senna@vettalabs.com>
 *            Gustavo Gama <gama@vettalabs.com>
 *            Joel Pitt <joel@opencog.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "Logger.h"
#include "Config.h"

#ifndef WIN32
#include <cxxabi.h>
#include <execinfo.h>
#endif

#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <sstream>

#ifdef WIN32_NOT_UNIX
#include <winsock2.h>
#undef ERROR
#undef DEBUG
#else
#include <sys/time.h>
#endif

#include <boost/algorithm/string.hpp>

#include <opencog/util/platform.h>

using namespace opencog;

// messages greater than this will be truncated
#define MAX_PRINTF_STYLE_MESSAGE_SIZE (1<<15)
const char* levelStrings[] = {"NONE", "ERROR", "WARN", "INFO", "DEBUG", "FINE"};

#ifndef WIN32 /// @todo backtrace and backtrace_symbols is UNIX, we
              /// may need a WIN32 version
static void prt_backtrace(std::ostringstream& oss)
{
#define BT_BUFSZ 50
	void *bt_buf[BT_BUFSZ];

	int stack_depth = backtrace(bt_buf, BT_BUFSZ);
	char **syms = backtrace_symbols(bt_buf, stack_depth);

	// Start printing at a bit into the stack, so as to avoid recording
	// the logger functions in the stack trace.
	oss << "\tStack Trace:\n";
	for (int i=2; i < stack_depth; i++)
	{
		// Most things we'll print are mangled C++ names,
		// So demangle them, get them to pretty-print.
		char * begin = strchr(syms[i], '(');
		char * end = strchr(syms[i], '+');
		if (!(begin && end) || end <= begin)
		{
			// Failed to pull apart the symbol names
            oss << "\t" << i << ": " << syms[i] << "\n";
		}
		else
		{
			*begin = 0x0;
			oss << "\t" << i << ": " << syms[i] << " ";
			*begin = '(';
			size_t sz = 250;
			int status;
			char *fname = (char *) malloc(sz);
			*end = 0x0;
			char *rv = abi::__cxa_demangle(begin+1, fname, &sz, &status);
			*end = '+';
			if (rv) fname = rv; // might have re-alloced
			oss << "(" << fname << " " << end << std::endl;
			free(fname);
		}
	}
	oss << std::endl;
	free(syms);
}
#endif

Logger::~Logger()
{
#ifdef ASYNC_LOGGING
    // Wait for queue to empty
    flush();
    stopWriteLoop();
#endif

    if (f != NULL) fclose(f);
}

#ifdef ASYNC_LOGGING
void Logger::startWriteLoop()
{
    pthread_mutex_lock(&lock);
    if (!writingLoopActive)
    {
        writingLoopActive = true;
        m_Thread = boost::thread(&Logger::writingLoop, this);
    }
    pthread_mutex_unlock(&lock);
}

void Logger::stopWriteLoop()
{
    pthread_mutex_lock(&lock);
    pendingMessagesToWrite.cancel();
    // rejoin thread
    m_Thread.join();
    writingLoopActive = false;
    pthread_mutex_unlock(&lock);
}

void Logger::writingLoop()
{
    try
    {
        while (true)
        {
            std::string* msg;
            pendingMessagesToWrite.wait_and_pop(msg);
            writeMsg(*msg);
            delete msg;
        }
    }
    catch (concurrent_queue< std::string* >::Canceled &e)
    {
        return;
    }
}

void Logger::flush()
{
    while (!pendingMessagesToWrite.empty())
        usleep(100);
}
#endif

void Logger::writeMsg(std::string &msg)
{
    pthread_mutex_lock(&lock);
    // delay opening the file until the first logging statement is issued;
    // this allows us to set the main logger's filename without creating
    // a useless log file with the default filename
    if (f == NULL)
    {
        if ((f = fopen(fileName.c_str(), "a")) == NULL)
        {
            fprintf(stderr, "[ERROR] Unable to open log file \"%s\"\n",
                    fileName.c_str());
            disable();
            return;
        }
        else
            enable();
    }

    // write to file
    fprintf(f, "%s", msg.c_str());
    fflush(f);
    pthread_mutex_unlock(&lock);

    // write to stdout
    if (printToStdout)
    {
        std::cout << msg;
        std::cout.flush();
    }
}

Logger::Logger(const std::string &fname, Logger::Level level, bool tsEnabled)
{
    this->fileName.assign(fname);
    this->currentLevel = level;
    this->backTraceLevel = getLevelFromString(opencog::config()["BACK_TRACE_LOG_LEVEL"]);
    this->timestampEnabled = tsEnabled;
    this->printToStdout = false;

    this->logEnabled = true;
    this->f = NULL;

    pthread_mutex_init(&lock, NULL);
#ifdef ASYNC_LOGGING
    this->writingLoopActive = false;
    startWriteLoop();
#endif // ASYNC_LOGGING
}

Logger::Logger(const Logger& log)
{
    pthread_mutex_init(&lock, NULL);
    set(log);
}

Logger& Logger::operator=(const Logger& log)
{
#ifdef ASYNC_LOGGING
    this->stopWriteLoop();
    pendingMessagesToWrite.cancel_reset();
#endif // ASYNC_LOGGING
    this->set(log);
    return *this;
}

void Logger::set(const Logger& log)
{
    this->fileName.assign(log.fileName);
    this->currentLevel = log.currentLevel;
    this->backTraceLevel = log.backTraceLevel;
    this->timestampEnabled = log.timestampEnabled;
    this->printToStdout = log.printToStdout;

    this->logEnabled = log.logEnabled;
    this->f = log.f;

#ifdef ASYNC_LOGGING
    startWriteLoop();
#endif // ASYNC_LOGGING
}

// ***********************************************/
// API

void Logger::setLevel(Logger::Level newLevel)
{
    currentLevel = newLevel;
}

Logger::Level Logger::getLevel() const
{
    return currentLevel;
}

void Logger::setBackTraceLevel(Logger::Level newLevel)
{
    backTraceLevel = newLevel;
}

Logger::Level Logger::getBackTraceLevel() const
{
    return backTraceLevel;
}

void Logger::setFilename(const std::string& s)
{
    fileName.assign(s);

    pthread_mutex_lock(&lock);
    if (f != NULL) fclose(f);
    f = NULL;
    pthread_mutex_unlock(&lock);

    enable();
}

const std::string& Logger::getFilename()
{
    return fileName;
}

void Logger::setTimestampFlag(bool flag)
{
    timestampEnabled = flag;
}

void Logger::setPrintToStdoutFlag(bool flag)
{
    printToStdout = flag;
}

void Logger::setPrintErrorLevelStdout() {
    setPrintToStdoutFlag(true);
    setLevel(Logger::ERROR);
}

void Logger::enable()
{
    logEnabled = true;
}

void Logger::disable()
{
    logEnabled = false;
}

void Logger::log(Logger::Level level, const std::string &txt)
{
#ifdef ASYNC_LOGGING
    static const unsigned int max_queue_size_allowed = 1024;
#endif
    static char timestamp[64];
    static char timestampStr[256];
    if (!logEnabled) return;

    if (level <= currentLevel) {
        std::ostringstream oss;
        if (timestampEnabled) {
            struct timeval stv;
            struct tm stm;

            ::gettimeofday(&stv, NULL);
            time_t t = stv.tv_sec;
            gmtime_r(&t, &stm);
            strftime(timestamp, sizeof(timestamp), "%F %T", &stm);
            snprintf(timestampStr, sizeof(timestampStr),
                    "[%s:%03ld] ",timestamp, stv.tv_usec / 1000);
            oss << timestampStr;
        }

        oss << "[" << getLevelString(level) << "] " << txt << std::endl;

        if (level <= backTraceLevel)
        {
#ifndef WIN32
            prt_backtrace(oss);
#endif
        }
#ifdef ASYNC_LOGGING
        pendingMessagesToWrite.push(new std::string(oss.str()));

        // If the queue gets too full, block until it's flushed to file or
        // stdout
        if (pendingMessagesToWrite.approx_size() > max_queue_size_allowed) {
            flush();
        }
#else
        std::string temp(oss.str());
        writeMsg(temp);
#endif
    }
}
void Logger::error(const std::string &txt)
{
    log(ERROR, txt);
}
void Logger::warn (const std::string &txt)
{
    log(WARN,  txt);
}
void Logger::info (const std::string &txt)
{
    log(INFO,  txt);
}
void Logger::debug(const std::string &txt)
{
    log(DEBUG, txt);
}
void Logger::fine (const std::string &txt)
{
    log(FINE,  txt);
}

void Logger::logva(Logger::Level level, const char *fmt, va_list args)
{
    if (level <= currentLevel) {
        char buffer[MAX_PRINTF_STYLE_MESSAGE_SIZE];
        vsnprintf(buffer, sizeof(buffer), fmt, args);
        std::string msg = buffer;
        log(level, msg);
    }
}

void Logger::log(Logger::Level level, const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(level, fmt, args); va_end(args);
}
void Logger::error(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(ERROR, fmt, args); va_end(args);
}
void Logger::warn (const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(WARN,  fmt, args); va_end(args);
}
void Logger::info (const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(INFO,  fmt, args); va_end(args);
}
void Logger::debug(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(DEBUG, fmt, args); va_end(args);
}
void Logger::fine (const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(FINE,  fmt, args); va_end(args);
}

bool Logger::isEnabled(Level level) const
{
    return level <= currentLevel;
}

bool Logger::isErrorEnabled() const
{
    return ERROR <= currentLevel;
}

bool Logger::isWarnEnabled() const
{
    return WARN <= currentLevel;
}

bool Logger::isInfoEnabled() const
{
    return INFO <= currentLevel;
}

bool Logger::isDebugEnabled() const
{
    return DEBUG <= currentLevel;
}

bool Logger::isFineEnabled() const
{
    return FINE <= currentLevel;
}

const char* Logger::getLevelString(const Logger::Level level)
{
    if (level == BAD_LEVEL)
        return "Bad level";
    else
        return levelStrings[level];
}

const Logger::Level Logger::getLevelFromString(const std::string& levelStr)
{
    unsigned int nLevels = sizeof(levelStrings) / sizeof(levelStrings[0]);
    for (unsigned int i = 0; i < nLevels; ++i) {
        if (boost::iequals(levelStrings[i], levelStr))
            return (Logger::Level) i;
    }
    return BAD_LEVEL;
}

// create and return the single instance
static Logger instance;
Logger& opencog::logger()
{
    return instance;
}
<|endoftext|>


<commit_before>## This file is a template.  The comment below is emitted
## into the rendered file; feel free to edit this file.
// WARNING: Generated header. Do not edit!
<%
import re
from collections import defaultdict
from sdbusplus.namedelement import NamedElement
objects = settingsDict.keys()
sdbusplus_includes = []
props = defaultdict(list)
validators = defaultdict(tuple)

def get_setting_sdbusplus_type(setting_intf):
    setting = "sdbusplus::" + setting_intf.replace('.', '::')
    i = setting.rfind('::')
    setting = setting[:i] + '::server::' + setting[i+2:]
    return setting

def get_setting_type(path):
    path = path[1:]
    path = path.replace('/', '::')
    return path
%>\
#pragma once

% for object in objects:
    % for item in settingsDict[object]:
<%
    include = item['Interface']
    include = include.replace('.', '/')
    include = include + "/server.hpp"
    sdbusplus_includes.append(include)
%>\
    % endfor
% endfor
#include <cereal/archives/json.hpp>
#include <cereal/types/vector.hpp>
#include <fstream>
#include <utility>
#include <experimental/filesystem>
#include <regex>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include "config.h"
#include <xyz/openbmc_project/Common/error.hpp>
using namespace phosphor::logging;

% for i in set(sdbusplus_includes):
#include "${i}"
% endfor

namespace phosphor
{
namespace settings
{

namespace fs = std::experimental::filesystem;

namespace persistent
{

// A setting d-bus object /foo/bar/baz is persisted in the filesystem with the
// same path. This eases re-construction of settings objects when we restore
// from the filesystem. This can be a problem though when you have two objects
// such as - /foo/bar and /foo/bar/baz. This is because 'bar' will be treated as
// a file in the first case, and a subdir in the second. To solve this, suffix
// files with a trailing __. The __ is a safe character sequence to use, because
// we won't have d-bus object paths ending with this.
// With this the objects would be persisted as - /foo/bar__ and /foo/bar/baz__.
constexpr auto fileSuffix = "__";

}

% for object in objects:
<%
   ns = object.split('/')
   ns.pop(0)
%>\
% for n in ns:
namespace ${n}
{
% endfor
<%
    interfaces = []
    aliases = []
    for item in settingsDict[object]:
        interfaces.append(item['Interface'])
        for name, meta in item['Properties'].items():
            if 'Validation' in meta:
                dict = meta['Validation']
                if dict['Type'] == "range":
                    validators[name] = (dict['Type'], dict['Validator'], dict['Unit'])
                else:
                    validators[name] = (dict['Type'], dict['Validator'])
%>
% for index, intf in enumerate(interfaces):
using Iface${index} = ${get_setting_sdbusplus_type(intf)};
<% aliases.append("Iface" + str(index)) %>\
% endfor
<%
    parent = "sdbusplus::server::object::object" + "<" + ", ".join(aliases) + ">"
%>\
using Parent = ${parent};

class Impl : public Parent
{
    public:
        Impl(sdbusplus::bus::bus& bus, const char* path):
            Parent(bus, path, true),
            path(path)
        {
        }
        virtual ~Impl() = default;

% for index, item in enumerate(settingsDict[object]):
    % for propName, metaDict in item['Properties'].items():
<% t = NamedElement(name=propName).camelCase %>\
<% fname = "validate" + propName %>\
        decltype(std::declval<Iface${index}>().${t}()) ${t}(decltype(std::declval<Iface${index}>().${t}()) value) override
        {
            auto result = Iface${index}::${t}();
            if (value != result)
            {
            % if propName in validators:
                if (!${fname}(value))
                {
                    namespace error =
                        sdbusplus::xyz::openbmc_project::Common::Error;
                    namespace metadata =
                        phosphor::logging::xyz::openbmc_project::Common;
                    phosphor::logging::report<error::InvalidArgument>(
                        metadata::InvalidArgument::ARGUMENT_NAME("${t}"),
                    % if validators[propName][0] != "regex":
                        metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str()));
                    % else:
                        metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str()));
                    % endif
                    return result;
                }
             % endif
                fs::path p(SETTINGS_PERSIST_PATH);
                p /= path;
                p += persistent::fileSuffix;
                fs::create_directories(p.parent_path());
                std::ofstream os(p.c_str(), std::ios::binary);
                cereal::JSONOutputArchive oarchive(os);
                result = Iface${index}::${t}(value);
                oarchive(*this);
            }
            return result;
        }
        using Iface${index}::${t};

    % endfor
% endfor
    private:
        fs::path path;
% for index, item in enumerate(settingsDict[object]):
  % for propName, metaDict in item['Properties'].items():
<% t = NamedElement(name=propName).camelCase %>\
<% fname = "validate" + propName %>\
    % if propName in validators:

        bool ${fname}(decltype(std::declval<Iface${index}>().${t}()) value)
        {
            bool matched = false;
        % if (validators[propName][0] == 'regex'):
            std::regex regexToCheck("${validators[propName][1]}");
            matched = std::regex_search(value, regexToCheck);
            if (!matched)
            {
                std::string err = "Input parameter for ${propName} is invalid "
                    "Input: " + value + " not in the format of this regex: "
                    "${validators[propName][1]}";
                using namespace phosphor::logging;
                log<level::ERR>(err.c_str());
            }
        % elif (validators[propName][0] == 'range'):
<% lowhigh = re.split('\.\.', validators[propName][1]) %>\
            if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]}))
            {
                matched = true;
            }
            else
            {
                std::string err = "Input parameter for ${propName} is invalid "
                    "Input: " + std::to_string(value) + "in uint: "
                    "${validators[propName][2]} is not in range:${validators[propName][1]}";
                using namespace phosphor::logging;
                log<level::ERR>(err.c_str());
            }
        % else:
            <% assert("Unknown validation type: propName") %>\
        % endif
            return matched;
        }
    % endif
  % endfor
% endfor
};

template<class Archive>
void save(Archive& a,
          const Impl& setting,
          const std::uint32_t version)
{
<%
props = []
for index, item in enumerate(settingsDict[object]):
    intfProps = ["setting." + NamedElement(name=propName).camelCase + "()" for \
                    propName, metaDict in item['Properties'].items()]
    props.extend(intfProps)
props = ', '.join(props)
%>\
    a(${props});
}

template<class Archive>
void load(Archive& a,
          Impl& setting,
          const std::uint32_t version)
{
<% props = [] %>\
% for index, item in enumerate(settingsDict[object]):
  % for  prop, metaDict in item['Properties'].items():
<%
    t = "setting." + NamedElement(name=prop).camelCase + "()"
    props.append(prop)
%>\
    decltype(${t}) ${prop}{};
  % endfor
% endfor
<% props = ', '.join(props) %>
    a(${props});
<% props = [] %>
% for index, item in enumerate(settingsDict[object]):
  % for  prop, metaDict in item['Properties'].items():
<%
    t = "setting." + NamedElement(name=prop).camelCase + "(" + prop + ")"
%>\
    ${t};
  % endfor
% endfor
}

% for n in reversed(ns):
} // namespace ${n}
% endfor

% endfor

/** @class Manager
 *
 *  @brief Compose settings objects and put them on the bus.
 */
class Manager
{
    public:
        Manager() = delete;
        Manager(const Manager&) = delete;
        Manager& operator=(const Manager&) = delete;
        Manager(Manager&&) = delete;
        Manager& operator=(Manager&&) = delete;
        virtual ~Manager() = default;

        /** @brief Constructor to put settings objects on to the bus.
         *  @param[in] bus - Bus to attach to.
         */
        Manager(sdbusplus::bus::bus& bus)
        {
            fs::path path{};
            settings =
                std::make_tuple(
% for index, path in enumerate(objects):
<% type = get_setting_type(path) + "::Impl" %>\
                    std::make_unique<${type}>(
                        bus,
  % if index < len(settingsDict) - 1:
                        "${path}"),
  % else:
                        "${path}"));
  % endif
% endfor

% for index, path in enumerate(objects):
            path = fs::path(SETTINGS_PERSIST_PATH) / "${path}";
            path += persistent::fileSuffix;
            auto initSetting${index} = [&]()
            {
  % for item in settingsDict[path]:
    % for propName, metaDict in item['Properties'].items():
<% p = NamedElement(name=propName).camelCase %>\
<% defaultValue = metaDict['Default'] %>\
% if isinstance(defaultValue, str) and  not \
    defaultValue.startswith('"') and '::' in defaultValue:
<% ns = get_setting_sdbusplus_type(item['Interface'])
i = ns.rfind('::')
defaultValue = "{}::{}".format(ns[:i], defaultValue)
%>\
% endif
                std::get<${index}>(settings)->
                  ${get_setting_sdbusplus_type(item['Interface'])}::${p}(${defaultValue});
  % endfor
% endfor
            };

            try
            {
                if (fs::exists(path))
                {
                    std::ifstream is(path.c_str(), std::ios::in);
                    cereal::JSONInputArchive iarchive(is);
                    iarchive(*std::get<${index}>(settings));
                }
                else
                {
                    initSetting${index}();
                }
            }
            catch (cereal::Exception& e)
            {
                log<level::ERR>(e.what());
                fs::remove(path);
                initSetting${index}();
            }
            std::get<${index}>(settings)->emit_object_added();

% endfor
        }

    private:
        /* @brief Composition of settings objects. */
        std::tuple<
% for index, path in enumerate(objects):
<% type = get_setting_type(path) + "::Impl" %>\
  % if index < len(settingsDict) - 1:
            std::unique_ptr<${type}>,
  % else:
            std::unique_ptr<${type}>> settings;
  % endif
% endfor
};

} // namespace settings
} // namespace phosphor

// Now register the class version with Cereal
% for object in objects:
<%
   classname = "phosphor::settings"
   ns = object.split('/')
   ns.pop(0)
%>\
% for n in ns:
<%
    classname += "::" + n
%>\
% endfor
CEREAL_CLASS_VERSION(${classname + "::Impl"}, CLASS_VERSION);
% endfor
<commit_msg>catch exceptions as const<commit_after>## This file is a template.  The comment below is emitted
## into the rendered file; feel free to edit this file.
// WARNING: Generated header. Do not edit!
<%
import re
from collections import defaultdict
from sdbusplus.namedelement import NamedElement
objects = settingsDict.keys()
sdbusplus_includes = []
props = defaultdict(list)
validators = defaultdict(tuple)

def get_setting_sdbusplus_type(setting_intf):
    setting = "sdbusplus::" + setting_intf.replace('.', '::')
    i = setting.rfind('::')
    setting = setting[:i] + '::server::' + setting[i+2:]
    return setting

def get_setting_type(path):
    path = path[1:]
    path = path.replace('/', '::')
    return path
%>\
#pragma once

% for object in objects:
    % for item in settingsDict[object]:
<%
    include = item['Interface']
    include = include.replace('.', '/')
    include = include + "/server.hpp"
    sdbusplus_includes.append(include)
%>\
    % endfor
% endfor
#include <cereal/archives/json.hpp>
#include <cereal/types/vector.hpp>
#include <fstream>
#include <utility>
#include <experimental/filesystem>
#include <regex>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include "config.h"
#include <xyz/openbmc_project/Common/error.hpp>
using namespace phosphor::logging;

% for i in set(sdbusplus_includes):
#include "${i}"
% endfor

namespace phosphor
{
namespace settings
{

namespace fs = std::experimental::filesystem;

namespace persistent
{

// A setting d-bus object /foo/bar/baz is persisted in the filesystem with the
// same path. This eases re-construction of settings objects when we restore
// from the filesystem. This can be a problem though when you have two objects
// such as - /foo/bar and /foo/bar/baz. This is because 'bar' will be treated as
// a file in the first case, and a subdir in the second. To solve this, suffix
// files with a trailing __. The __ is a safe character sequence to use, because
// we won't have d-bus object paths ending with this.
// With this the objects would be persisted as - /foo/bar__ and /foo/bar/baz__.
constexpr auto fileSuffix = "__";

}

% for object in objects:
<%
   ns = object.split('/')
   ns.pop(0)
%>\
% for n in ns:
namespace ${n}
{
% endfor
<%
    interfaces = []
    aliases = []
    for item in settingsDict[object]:
        interfaces.append(item['Interface'])
        for name, meta in item['Properties'].items():
            if 'Validation' in meta:
                dict = meta['Validation']
                if dict['Type'] == "range":
                    validators[name] = (dict['Type'], dict['Validator'], dict['Unit'])
                else:
                    validators[name] = (dict['Type'], dict['Validator'])
%>
% for index, intf in enumerate(interfaces):
using Iface${index} = ${get_setting_sdbusplus_type(intf)};
<% aliases.append("Iface" + str(index)) %>\
% endfor
<%
    parent = "sdbusplus::server::object::object" + "<" + ", ".join(aliases) + ">"
%>\
using Parent = ${parent};

class Impl : public Parent
{
    public:
        Impl(sdbusplus::bus::bus& bus, const char* path):
            Parent(bus, path, true),
            path(path)
        {
        }
        virtual ~Impl() = default;

% for index, item in enumerate(settingsDict[object]):
    % for propName, metaDict in item['Properties'].items():
<% t = NamedElement(name=propName).camelCase %>\
<% fname = "validate" + propName %>\
        decltype(std::declval<Iface${index}>().${t}()) ${t}(decltype(std::declval<Iface${index}>().${t}()) value) override
        {
            auto result = Iface${index}::${t}();
            if (value != result)
            {
            % if propName in validators:
                if (!${fname}(value))
                {
                    namespace error =
                        sdbusplus::xyz::openbmc_project::Common::Error;
                    namespace metadata =
                        phosphor::logging::xyz::openbmc_project::Common;
                    phosphor::logging::report<error::InvalidArgument>(
                        metadata::InvalidArgument::ARGUMENT_NAME("${t}"),
                    % if validators[propName][0] != "regex":
                        metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str()));
                    % else:
                        metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str()));
                    % endif
                    return result;
                }
             % endif
                fs::path p(SETTINGS_PERSIST_PATH);
                p /= path;
                p += persistent::fileSuffix;
                fs::create_directories(p.parent_path());
                std::ofstream os(p.c_str(), std::ios::binary);
                cereal::JSONOutputArchive oarchive(os);
                result = Iface${index}::${t}(value);
                oarchive(*this);
            }
            return result;
        }
        using Iface${index}::${t};

    % endfor
% endfor
    private:
        fs::path path;
% for index, item in enumerate(settingsDict[object]):
  % for propName, metaDict in item['Properties'].items():
<% t = NamedElement(name=propName).camelCase %>\
<% fname = "validate" + propName %>\
    % if propName in validators:

        bool ${fname}(decltype(std::declval<Iface${index}>().${t}()) value)
        {
            bool matched = false;
        % if (validators[propName][0] == 'regex'):
            std::regex regexToCheck("${validators[propName][1]}");
            matched = std::regex_search(value, regexToCheck);
            if (!matched)
            {
                std::string err = "Input parameter for ${propName} is invalid "
                    "Input: " + value + " not in the format of this regex: "
                    "${validators[propName][1]}";
                using namespace phosphor::logging;
                log<level::ERR>(err.c_str());
            }
        % elif (validators[propName][0] == 'range'):
<% lowhigh = re.split('\.\.', validators[propName][1]) %>\
            if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]}))
            {
                matched = true;
            }
            else
            {
                std::string err = "Input parameter for ${propName} is invalid "
                    "Input: " + std::to_string(value) + "in uint: "
                    "${validators[propName][2]} is not in range:${validators[propName][1]}";
                using namespace phosphor::logging;
                log<level::ERR>(err.c_str());
            }
        % else:
            <% assert("Unknown validation type: propName") %>\
        % endif
            return matched;
        }
    % endif
  % endfor
% endfor
};

template<class Archive>
void save(Archive& a,
          const Impl& setting,
          const std::uint32_t version)
{
<%
props = []
for index, item in enumerate(settingsDict[object]):
    intfProps = ["setting." + NamedElement(name=propName).camelCase + "()" for \
                    propName, metaDict in item['Properties'].items()]
    props.extend(intfProps)
props = ', '.join(props)
%>\
    a(${props});
}

template<class Archive>
void load(Archive& a,
          Impl& setting,
          const std::uint32_t version)
{
<% props = [] %>\
% for index, item in enumerate(settingsDict[object]):
  % for  prop, metaDict in item['Properties'].items():
<%
    t = "setting." + NamedElement(name=prop).camelCase + "()"
    props.append(prop)
%>\
    decltype(${t}) ${prop}{};
  % endfor
% endfor
<% props = ', '.join(props) %>
    a(${props});
<% props = [] %>
% for index, item in enumerate(settingsDict[object]):
  % for  prop, metaDict in item['Properties'].items():
<%
    t = "setting." + NamedElement(name=prop).camelCase + "(" + prop + ")"
%>\
    ${t};
  % endfor
% endfor
}

% for n in reversed(ns):
} // namespace ${n}
% endfor

% endfor

/** @class Manager
 *
 *  @brief Compose settings objects and put them on the bus.
 */
class Manager
{
    public:
        Manager() = delete;
        Manager(const Manager&) = delete;
        Manager& operator=(const Manager&) = delete;
        Manager(Manager&&) = delete;
        Manager& operator=(Manager&&) = delete;
        virtual ~Manager() = default;

        /** @brief Constructor to put settings objects on to the bus.
         *  @param[in] bus - Bus to attach to.
         */
        Manager(sdbusplus::bus::bus& bus)
        {
            fs::path path{};
            settings =
                std::make_tuple(
% for index, path in enumerate(objects):
<% type = get_setting_type(path) + "::Impl" %>\
                    std::make_unique<${type}>(
                        bus,
  % if index < len(settingsDict) - 1:
                        "${path}"),
  % else:
                        "${path}"));
  % endif
% endfor

% for index, path in enumerate(objects):
            path = fs::path(SETTINGS_PERSIST_PATH) / "${path}";
            path += persistent::fileSuffix;
            auto initSetting${index} = [&]()
            {
  % for item in settingsDict[path]:
    % for propName, metaDict in item['Properties'].items():
<% p = NamedElement(name=propName).camelCase %>\
<% defaultValue = metaDict['Default'] %>\
% if isinstance(defaultValue, str) and  not \
    defaultValue.startswith('"') and '::' in defaultValue:
<% ns = get_setting_sdbusplus_type(item['Interface'])
i = ns.rfind('::')
defaultValue = "{}::{}".format(ns[:i], defaultValue)
%>\
% endif
                std::get<${index}>(settings)->
                  ${get_setting_sdbusplus_type(item['Interface'])}::${p}(${defaultValue});
  % endfor
% endfor
            };

            try
            {
                if (fs::exists(path))
                {
                    std::ifstream is(path.c_str(), std::ios::in);
                    cereal::JSONInputArchive iarchive(is);
                    iarchive(*std::get<${index}>(settings));
                }
                else
                {
                    initSetting${index}();
                }
            }
            catch (const cereal::Exception& e)
            {
                log<level::ERR>(e.what());
                fs::remove(path);
                initSetting${index}();
            }
            std::get<${index}>(settings)->emit_object_added();

% endfor
        }

    private:
        /* @brief Composition of settings objects. */
        std::tuple<
% for index, path in enumerate(objects):
<% type = get_setting_type(path) + "::Impl" %>\
  % if index < len(settingsDict) - 1:
            std::unique_ptr<${type}>,
  % else:
            std::unique_ptr<${type}>> settings;
  % endif
% endfor
};

} // namespace settings
} // namespace phosphor

// Now register the class version with Cereal
% for object in objects:
<%
   classname = "phosphor::settings"
   ns = object.split('/')
   ns.pop(0)
%>\
% for n in ns:
<%
    classname += "::" + n
%>\
% endfor
CEREAL_CLASS_VERSION(${classname + "::Impl"}, CLASS_VERSION);
% endfor
<|endoftext|>


<commit_before>/*
 * The BENG request struct.  This is only used by the handlers
 * (handler.c, file-handler.c etc.).
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "request.hxx"
#include "bp_connection.hxx"
#include "bp_instance.hxx"
#include "session.hxx"
#include "session_manager.hxx"
#include "http_server.hxx"
#include "cookie_server.hxx"
#include "transformation.hxx"
#include "args.hxx"
#include "bot.h"
#include "dpool.h"
#include "pbuffer.hxx"
#include "strmap.h"
#include "istream.h"
#include "crc.h"
#include "format.h"

#include <daemon/log.h>

bool
request_processor_enabled(const struct request *request)
{
    const struct transformation *transformation;

    for (transformation = request->translate.response->views->transformation;
         transformation != nullptr;
         transformation = transformation->next)
        if (transformation->type == transformation::TRANSFORMATION_PROCESS)
            return true;

    return false;
}

void
request_discard_body(struct request *request)
{
    if (request->body != nullptr) {
        struct istream *body = request->body;
        request->body = nullptr;
        istream_close_unused(body);
    }
}

void
request_args_parse(struct request *request)
{
    assert(request != nullptr);
    assert(request->args == nullptr);

    if (strref_is_empty(&request->uri.args)) {
        request->args = nullptr;
        request->translate.request.param = nullptr;
        request->translate.request.session = nullptr;
        return;
    }

    request->args = args_parse(request->request->pool,
                               request->uri.args.data, request->uri.args.length);
    request->translate.request.param = strmap_remove(request->args, "translate");
    request->translate.request.session = nullptr;
}

static const struct strmap *
request_get_cookies(struct request *request)
{
    const char *cookie;

    if (request->cookies != nullptr)
        return request->cookies;

    cookie = strmap_get(request->request->headers, "cookie");
    if (cookie == nullptr)
        return nullptr;

    request->cookies = strmap_new(request->request->pool, 8);
    cookie_map_parse(request->cookies, cookie, request->request->pool);

    return request->cookies;
}

static struct session *
request_load_session(struct request *request, const char *session_id)
{
    struct session *session;

    assert(request != nullptr);
    assert(!request->stateless);
    assert(!session_id_is_defined(request->session_id));
    assert(session_id != nullptr);

    if (!session_id_parse(session_id, &request->session_id))
        return nullptr;

    session = request_get_session(request);
    if (session == nullptr)
        return nullptr;

    if (!session->translate.IsNull())
        request->translate.request.session = DupBuffer(request->request->pool,
                                                       session->translate);

    if (!session->cookie_sent)
        request->send_session_cookie = true;

    session->is_new = false;

    return session;
}

static const char *
build_session_cookie_name(struct pool *pool, const struct config *config,
                          const struct strmap *headers)
{
    if (headers == nullptr || !config->dynamic_session_cookie)
        return config->session_cookie;

    const char *host = strmap_get(headers, "host");
    if (host == nullptr || *host == 0)
        return config->session_cookie;

    size_t length = strlen(config->session_cookie);
    char *name = PoolAlloc<char>(pool, length + 5);
    memcpy(name, config->session_cookie, length);
    format_uint16_hex_fixed(name + length, crc16_string(0, host));
    name[length + 4] = 0;
    return name;
}

static const char *
request_get_uri_session_id(const struct request *request)
{
    assert(request != nullptr);
    assert(!request->stateless);

    return strmap_get_checked(request->args, "session");
}

static const char *
request_get_cookie_session_id(struct request *request)
{
    assert(request != nullptr);
    assert(!request->stateless);
    assert(request->session_cookie != nullptr);

    const struct strmap *cookies = request_get_cookies(request);

    return strmap_get_checked(cookies, request->session_cookie);
}

void
request_determine_session(struct request *request)
{
    const char *user_agent;
    const char *session_id;
    bool cookie_received = false;
    struct session *session;

    assert(request != nullptr);

    request->session_realm = nullptr;

    user_agent = strmap_get(request->request->headers, "user-agent");
    request->stateless = user_agent == nullptr ||
        user_agent_is_bot(user_agent);
    if (request->stateless)
        return;

    request->session_cookie =
        build_session_cookie_name(request->request->pool,
                                  &request->connection->instance->config,
                                  request->request->headers);

    session_id = request_get_uri_session_id(request);
    if (session_id == nullptr || *session_id == 0) {
        session_id = request_get_cookie_session_id(request);
        if (session_id == nullptr)
            return;

        cookie_received = true;
    }

    session = request_load_session(request, session_id);
    if (session == nullptr) {
        if (!cookie_received && request->args != nullptr)
            /* remove invalid session id from URI args */
            strmap_remove(request->args, "session");

        return;
    }

    if (!cookie_received) {
        const char *p = request_get_cookie_session_id(request);
        if (p != nullptr && strcmp(p, session_id) == 0)
            cookie_received = true;
    }

    if (cookie_received) {
        session->cookie_received = true;

        if (request->args != nullptr)
            /* we're using cookies, and we can safely remove the
               session id from the args */
            strmap_remove(request->args, "session");
    }

    request->session_realm = p_strdup(request->request->pool, session->realm);

    session_put(session);
}

struct session *
request_make_session(struct request *request)
{
    struct session *session;

    assert(request != nullptr);

    if (request->stateless)
        return nullptr;

    session = request_get_session(request);
    if (session != nullptr)
        return session;

    session = session_new();
    if (session == nullptr) {
        daemon_log(1, "Failed to allocate a session\n");
        return nullptr;
    }

    session->realm = d_strdup(session->pool, request->realm);

    request->session_id = session->id;
    request->send_session_cookie = true;

    if (request->args == nullptr)
        request->args = strmap_new(request->request->pool, 4);
    strmap_set(request->args, "session",
               session_id_format(request->session_id,
                                 &request->session_id_string));

    return session;
}

void
request_ignore_session(struct request *request)
{
    assert(request != nullptr);

    if (!session_id_is_defined(request->session_id))
        return;

    assert(!request->stateless);

    if (request->args != nullptr)
        strmap_remove(request->args, "session");

    session_id_clear(&request->session_id);
}

void
request_discard_session(struct request *request)
{
    assert(request != nullptr);

    if (!session_id_is_defined(request->session_id))
        return;

    assert(!request->stateless);

    if (request->args != nullptr)
        strmap_remove(request->args, "session");

    session_delete(request->session_id);
    session_id_clear(&request->session_id);
}
<commit_msg>request: use widget_view_has_processor() in _processor_enabled()<commit_after>/*
 * The BENG request struct.  This is only used by the handlers
 * (handler.c, file-handler.c etc.).
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "request.hxx"
#include "bp_connection.hxx"
#include "bp_instance.hxx"
#include "session.hxx"
#include "session_manager.hxx"
#include "http_server.hxx"
#include "cookie_server.hxx"
#include "transformation.hxx"
#include "args.hxx"
#include "bot.h"
#include "dpool.h"
#include "pbuffer.hxx"
#include "strmap.h"
#include "istream.h"
#include "crc.h"
#include "format.h"

#include <daemon/log.h>

bool
request_processor_enabled(const struct request *request)
{
    return widget_view_has_processor(request->translate.response->views);
}

void
request_discard_body(struct request *request)
{
    if (request->body != nullptr) {
        struct istream *body = request->body;
        request->body = nullptr;
        istream_close_unused(body);
    }
}

void
request_args_parse(struct request *request)
{
    assert(request != nullptr);
    assert(request->args == nullptr);

    if (strref_is_empty(&request->uri.args)) {
        request->args = nullptr;
        request->translate.request.param = nullptr;
        request->translate.request.session = nullptr;
        return;
    }

    request->args = args_parse(request->request->pool,
                               request->uri.args.data, request->uri.args.length);
    request->translate.request.param = strmap_remove(request->args, "translate");
    request->translate.request.session = nullptr;
}

static const struct strmap *
request_get_cookies(struct request *request)
{
    const char *cookie;

    if (request->cookies != nullptr)
        return request->cookies;

    cookie = strmap_get(request->request->headers, "cookie");
    if (cookie == nullptr)
        return nullptr;

    request->cookies = strmap_new(request->request->pool, 8);
    cookie_map_parse(request->cookies, cookie, request->request->pool);

    return request->cookies;
}

static struct session *
request_load_session(struct request *request, const char *session_id)
{
    struct session *session;

    assert(request != nullptr);
    assert(!request->stateless);
    assert(!session_id_is_defined(request->session_id));
    assert(session_id != nullptr);

    if (!session_id_parse(session_id, &request->session_id))
        return nullptr;

    session = request_get_session(request);
    if (session == nullptr)
        return nullptr;

    if (!session->translate.IsNull())
        request->translate.request.session = DupBuffer(request->request->pool,
                                                       session->translate);

    if (!session->cookie_sent)
        request->send_session_cookie = true;

    session->is_new = false;

    return session;
}

static const char *
build_session_cookie_name(struct pool *pool, const struct config *config,
                          const struct strmap *headers)
{
    if (headers == nullptr || !config->dynamic_session_cookie)
        return config->session_cookie;

    const char *host = strmap_get(headers, "host");
    if (host == nullptr || *host == 0)
        return config->session_cookie;

    size_t length = strlen(config->session_cookie);
    char *name = PoolAlloc<char>(pool, length + 5);
    memcpy(name, config->session_cookie, length);
    format_uint16_hex_fixed(name + length, crc16_string(0, host));
    name[length + 4] = 0;
    return name;
}

static const char *
request_get_uri_session_id(const struct request *request)
{
    assert(request != nullptr);
    assert(!request->stateless);

    return strmap_get_checked(request->args, "session");
}

static const char *
request_get_cookie_session_id(struct request *request)
{
    assert(request != nullptr);
    assert(!request->stateless);
    assert(request->session_cookie != nullptr);

    const struct strmap *cookies = request_get_cookies(request);

    return strmap_get_checked(cookies, request->session_cookie);
}

void
request_determine_session(struct request *request)
{
    const char *user_agent;
    const char *session_id;
    bool cookie_received = false;
    struct session *session;

    assert(request != nullptr);

    request->session_realm = nullptr;

    user_agent = strmap_get(request->request->headers, "user-agent");
    request->stateless = user_agent == nullptr ||
        user_agent_is_bot(user_agent);
    if (request->stateless)
        return;

    request->session_cookie =
        build_session_cookie_name(request->request->pool,
                                  &request->connection->instance->config,
                                  request->request->headers);

    session_id = request_get_uri_session_id(request);
    if (session_id == nullptr || *session_id == 0) {
        session_id = request_get_cookie_session_id(request);
        if (session_id == nullptr)
            return;

        cookie_received = true;
    }

    session = request_load_session(request, session_id);
    if (session == nullptr) {
        if (!cookie_received && request->args != nullptr)
            /* remove invalid session id from URI args */
            strmap_remove(request->args, "session");

        return;
    }

    if (!cookie_received) {
        const char *p = request_get_cookie_session_id(request);
        if (p != nullptr && strcmp(p, session_id) == 0)
            cookie_received = true;
    }

    if (cookie_received) {
        session->cookie_received = true;

        if (request->args != nullptr)
            /* we're using cookies, and we can safely remove the
               session id from the args */
            strmap_remove(request->args, "session");
    }

    request->session_realm = p_strdup(request->request->pool, session->realm);

    session_put(session);
}

struct session *
request_make_session(struct request *request)
{
    struct session *session;

    assert(request != nullptr);

    if (request->stateless)
        return nullptr;

    session = request_get_session(request);
    if (session != nullptr)
        return session;

    session = session_new();
    if (session == nullptr) {
        daemon_log(1, "Failed to allocate a session\n");
        return nullptr;
    }

    session->realm = d_strdup(session->pool, request->realm);

    request->session_id = session->id;
    request->send_session_cookie = true;

    if (request->args == nullptr)
        request->args = strmap_new(request->request->pool, 4);
    strmap_set(request->args, "session",
               session_id_format(request->session_id,
                                 &request->session_id_string));

    return session;
}

void
request_ignore_session(struct request *request)
{
    assert(request != nullptr);

    if (!session_id_is_defined(request->session_id))
        return;

    assert(!request->stateless);

    if (request->args != nullptr)
        strmap_remove(request->args, "session");

    session_id_clear(&request->session_id);
}

void
request_discard_session(struct request *request)
{
    assert(request != nullptr);

    if (!session_id_is_defined(request->session_id))
        return;

    assert(!request->stateless);

    if (request->args != nullptr)
        strmap_remove(request->args, "session");

    session_delete(request->session_id);
    session_id_clear(&request->session_id);
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////
//
//                             Pixie
//
// Copyright  1999 - 2003, Okan Arikan
//
// Contact: okan@cs.berkeley.edu
//
// This library 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 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
// General Public License for more details.
//
// You should have received a copy of the GNU 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
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
//  File				:	show.cpp
//  Classes				:	-
//  Description			:	The hardware visualizer
//
////////////////////////////////////////////////////////////////////////
#include "show.h"
#include "cache.h"
#include "renderer.h"
#include "error.h"
#include "fileResource.h"
#include "photonMap.h"
#include "texture3d.h"
#include "opengl/opengl.h"

// The static members of the CView class that visualizable classes derive from
void					*CView::handle			=	NULL;
TGlTrianglesFunction	CView::drawTriangles	=	NULL;
TGlPointsFunction		CView::drawPoints		=	NULL;

///////////////////////////////////////////////////////////////////////
// Class				:	CShow
// Method				:	CShow
// Description			:	Ctor
// Return Value			:	-
// Comments				:
// Date last edited		:	9/21/2006
CShow::CShow(COptions *o,CXform *x,SOCKET s) : CShadingContext(o,x,s,HIDER_NODISPLAY) {
	const char	*pixieHome	=	osEnvironment("PIXIEHOME");
	char		moduleFile[OS_MAX_PATH_LENGTH];

	// First, try to load the dynamic library
	CView::handle	=	NULL;
	if(currentRenderer->locateFileEx(moduleFile,"opengl",osModuleExtension,modulePath)) {
		CView::handle		=	osLoadModule(moduleFile);
	}

	if (CView::handle != NULL) {

		// Is this the library we were expecting ?
		TGlVisualizeFunction	visualize	=	(TGlVisualizeFunction) osResolve(CView::handle,"pglVisualize");
		CView					*view		=	NULL;

		if (visualize != NULL) {

			// Try to load the file
			const char	*fileName	=	hider + 5;
			FILE		*in			=	fopen(fileName,"rb");

			CView::drawTriangles	=	(TGlTrianglesFunction)	osResolve(CView::handle,"pglTriangles");
			CView::drawPoints		=	(TGlPointsFunction)		osResolve(CView::handle,"pglPoints");

			assert(CView::drawTriangles != NULL);
			assert(CView::drawPoints != NULL);

			if (in != NULL)	{
				unsigned int	magic	=	0;
				int				version[3],i;
				char			*t;

				fread(&magic,1,sizeof(int),in);

				if (magic == magicNumber) {
					fread(version,3,sizeof(int),in);

					if (!((version[0] == VERSION_RELEASE) || (version[1] == VERSION_BETA))) {
						error(CODE_VERSION,"File %s is from an incompatible version\n",fileName);
					} else {
						fread(&i,1,sizeof(int),in);
						t	=	(char *) alloca((i+1)*sizeof(char));
						fread(t,i+1,sizeof(char),in);

						info(CODE_LOG,"File:    %s\n",fileName);
						info(CODE_LOG,"Version: %d.%d.%d\n",version[0],version[1],version[2]);
						info(CODE_LOG,"Type:    %s\n",t);
						fclose(in);

						if (strcmp(t,filePhotonMap) == 0) {
							view	=	getPhotonMap(fileName);
						} else if (strcmp(t,fileIrradianceCache) == 0) {
							view	=	getCache(fileName,"R");
						} else if (strcmp(t,fileGatherCache) == 0) {
							view	=	getCache(fileName,"R");
						} else if (strcmp(t,filePointCloud) == 0) {

						} else if (strcmp(t,fileBrickMap) == 0) {
							view	=	getTexture3d(fileName,FALSE,NULL,NULL);
						}

						// Create / display the window
						if (view != NULL)	visualize(view);
					}
				} else {
					error(CODE_BADFILE,"File %s doesn't seem to be a Pixie file\n",fileName);
				}
			}
		}
	} else {
		error(CODE_SYSTEM,"Opengl wrapper not found...");
	}
}

///////////////////////////////////////////////////////////////////////
// Class				:	CShow
// Method				:	~CShow
// Description			:	Dtor
// Return Value			:	-
// Comments				:
// Date last edited		:	9/21/2006
CShow::~CShow() {
}
<commit_msg>fix feedback to print<commit_after>//////////////////////////////////////////////////////////////////////
//
//                             Pixie
//
// Copyright  1999 - 2003, Okan Arikan
//
// Contact: okan@cs.berkeley.edu
//
// This library 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 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
// General Public License for more details.
//
// You should have received a copy of the GNU 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
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
//  File				:	show.cpp
//  Classes				:	-
//  Description			:	The hardware visualizer
//
////////////////////////////////////////////////////////////////////////
#include "show.h"
#include "cache.h"
#include "renderer.h"
#include "error.h"
#include "fileResource.h"
#include "photonMap.h"
#include "texture3d.h"
#include "opengl/opengl.h"

// The static members of the CView class that visualizable classes derive from
void					*CView::handle			=	NULL;
TGlTrianglesFunction	CView::drawTriangles	=	NULL;
TGlPointsFunction		CView::drawPoints		=	NULL;

///////////////////////////////////////////////////////////////////////
// Class				:	CShow
// Method				:	CShow
// Description			:	Ctor
// Return Value			:	-
// Comments				:
// Date last edited		:	9/21/2006
CShow::CShow(COptions *o,CXform *x,SOCKET s) : CShadingContext(o,x,s,HIDER_NODISPLAY) {
	const char	*pixieHome	=	osEnvironment("PIXIEHOME");
	char		moduleFile[OS_MAX_PATH_LENGTH];

	// First, try to load the dynamic library
	CView::handle	=	NULL;
	if(currentRenderer->locateFileEx(moduleFile,"opengl",osModuleExtension,modulePath)) {
		CView::handle		=	osLoadModule(moduleFile);
	}

	if (CView::handle != NULL) {

		// Is this the library we were expecting ?
		TGlVisualizeFunction	visualize	=	(TGlVisualizeFunction) osResolve(CView::handle,"pglVisualize");
		CView					*view		=	NULL;

		if (visualize != NULL) {

			// Try to load the file
			const char	*fileName	=	hider + 5;
			FILE		*in			=	fopen(fileName,"rb");

			CView::drawTriangles	=	(TGlTrianglesFunction)	osResolve(CView::handle,"pglTriangles");
			CView::drawPoints		=	(TGlPointsFunction)		osResolve(CView::handle,"pglPoints");

			assert(CView::drawTriangles != NULL);
			assert(CView::drawPoints != NULL);

			if (in != NULL)	{
				unsigned int	magic	=	0;
				int				version[3],i;
				char			*t;

				fread(&magic,1,sizeof(int),in);

				if (magic == magicNumber) {
					fread(version,3,sizeof(int),in);

					if (!((version[0] == VERSION_RELEASE) || (version[1] == VERSION_BETA))) {
						error(CODE_VERSION,"File %s is from an incompatible version\n",fileName);
					} else {
						fread(&i,1,sizeof(int),in);
						t	=	(char *) alloca((i+1)*sizeof(char));
						fread(t,i+1,sizeof(char),in);

						info(CODE_PRINTF,"File:    %s\n",fileName);
						info(CODE_PRINTF,"Version: %d.%d.%d\n",version[0],version[1],version[2]);
						info(CODE_PRINTF,"Type:    %s\n",t);
						fclose(in);

						if (strcmp(t,filePhotonMap) == 0) {
							view	=	getPhotonMap(fileName);
						} else if (strcmp(t,fileIrradianceCache) == 0) {
							view	=	getCache(fileName,"R");
						} else if (strcmp(t,fileGatherCache) == 0) {
							view	=	getCache(fileName,"R");
						} else if (strcmp(t,filePointCloud) == 0) {

						} else if (strcmp(t,fileBrickMap) == 0) {
							view	=	getTexture3d(fileName,FALSE,NULL,NULL);
						}

						// Create / display the window
						if (view != NULL)	visualize(view);
					}
				} else {
					error(CODE_BADFILE,"File %s doesn't seem to be a Pixie file\n",fileName);
				}
			}
		}
	} else {
		error(CODE_SYSTEM,"Opengl wrapper not found...");
	}
}

///////////////////////////////////////////////////////////////////////
// Class				:	CShow
// Method				:	~CShow
// Description			:	Dtor
// Return Value			:	-
// Comments				:
// Date last edited		:	9/21/2006
CShow::~CShow() {
}
<|endoftext|>