<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

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

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

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

#include <fstream>
#include <iostream>
#include <Core/Algorithms/DataIO/ReadMatrix.h>
#include <Core/Datatypes/DenseMatrix.h>
#include <Core/Datatypes/SparseRowMatrix.h>
#include <Core/Datatypes/MatrixIO.h>
#include <Core/Algorithms/DataIO/EigenMatrixFromScirunAsciiFormatConverter.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <boost/filesystem.hpp>
#include <boost/thread.hpp>

using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::DataIO;
using namespace SCIRun::Core::Datatypes;

namespace SCIRun {
  namespace Core {
    namespace Algorithms {
      namespace DataIO {

        class ReadMatrixAlgorithmPrivate
        {
        public:
          static boost::mutex fileCheckMutex_;
        };

        boost::mutex ReadMatrixAlgorithmPrivate::fileCheckMutex_;
      }}}}

ReadMatrixAlgorithm::ReadMatrixAlgorithm()
{
  addParameter(Variables::Filename, std::string(""));
}

ReadMatrixAlgorithm::Outputs ReadMatrixAlgorithm::run(const ReadMatrixAlgorithm::Parameters& filename) const
{
  {
    //BOOST FILESYSTEM BUG: it is not thread-safe. TODO: need to meld this locking code into the ENSURE_FILE_EXISTS macro.
    boost::lock_guard<boost::mutex> guard(ReadMatrixAlgorithmPrivate::fileCheckMutex_);
    ENSURE_FILE_EXISTS(filename);
  }

  if (boost::filesystem::extension(filename) == ".txt")
  {
    std::ifstream reader(filename.c_str());
    DenseMatrixHandle matrix(boost::make_shared<DenseMatrix>());
    reader >> *matrix;

    //std::cout << "ALGO OUTPUT:\n" << *matrix << std::endl;

    return matrix;
  }
  else if (boost::filesystem::extension(filename) == ".mat")
  {
    status("FOUND .mat file: assuming is SCIRUNv4 Matrix format.");

    PiostreamPtr stream = auto_istream(filename);
    if (!stream)
    {
      THROW_ALGORITHM_PROCESSING_ERROR("Error reading file '" + filename + "'.");
    }

    MatrixHandle matrix;
    Pio(*stream, matrix);
    if (!matrix)
      THROW_ALGORITHM_PROCESSING_ERROR("Import failed.");
    return matrix;
  }
  THROW_ALGORITHM_INPUT_ERROR("Unknown matrix file format");
}

AlgorithmOutput ReadMatrixAlgorithm::run_generic(const AlgorithmInput& input) const
{
  auto filename = get(Variables::Filename).getString();
  auto file = run(filename);
  AlgorithmOutput output;
  output[Variables::MatrixLoaded] = file;
  return output;
}
<commit_msg>Temporary bug fix<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

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

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

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

#include <fstream>
#include <iostream>
#include <Core/Algorithms/DataIO/ReadMatrix.h>
#include <Core/Datatypes/DenseMatrix.h>
#include <Core/Datatypes/SparseRowMatrix.h>
#include <Core/Datatypes/MatrixIO.h>
#include <Core/Algorithms/DataIO/EigenMatrixFromScirunAsciiFormatConverter.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <boost/filesystem.hpp>
#include <boost/thread.hpp>

using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::DataIO;
using namespace SCIRun::Core::Datatypes;

namespace SCIRun {
  namespace Core {
    namespace Algorithms {
      namespace DataIO {

        class ReadMatrixAlgorithmPrivate
        {
        public:
          static boost::mutex fileCheckMutex_;
        };

        boost::mutex ReadMatrixAlgorithmPrivate::fileCheckMutex_;
      }}}}

ReadMatrixAlgorithm::ReadMatrixAlgorithm()
{
  addParameter(Variables::Filename, std::string(""));
}

ReadMatrixAlgorithm::Outputs ReadMatrixAlgorithm::run(const ReadMatrixAlgorithm::Parameters& filename) const
{
  {
    std::cout << "locking mutex " << filename << std::endl; //TODO: I think putting this here avoids a deadlock/crash...but it will be moot once boost is upgraded.
    //BOOST FILESYSTEM BUG: it is not thread-safe. TODO: need to meld this locking code into the ENSURE_FILE_EXISTS macro.
    boost::lock_guard<boost::mutex> guard(ReadMatrixAlgorithmPrivate::fileCheckMutex_);
    ENSURE_FILE_EXISTS(filename);
  }

  if (boost::filesystem::extension(filename) == ".txt")
  {
    std::ifstream reader(filename.c_str());
    DenseMatrixHandle matrix(boost::make_shared<DenseMatrix>());
    reader >> *matrix;

    //std::cout << "ALGO OUTPUT:\n" << *matrix << std::endl;

    return matrix;
  }
  else if (boost::filesystem::extension(filename) == ".mat")
  {
    status("FOUND .mat file: assuming is SCIRUNv4 Matrix format.");

    PiostreamPtr stream = auto_istream(filename);
    if (!stream)
    {
      THROW_ALGORITHM_PROCESSING_ERROR("Error reading file '" + filename + "'.");
    }

    MatrixHandle matrix;
    Pio(*stream, matrix);
    if (!matrix)
      THROW_ALGORITHM_PROCESSING_ERROR("Import failed.");
    return matrix;
  }
  THROW_ALGORITHM_INPUT_ERROR("Unknown matrix file format");
}

AlgorithmOutput ReadMatrixAlgorithm::run_generic(const AlgorithmInput& input) const
{
  auto filename = get(Variables::Filename).getString();
  auto file = run(filename);
  AlgorithmOutput output;
  output[Variables::MatrixLoaded] = file;
  return output;
}
<|endoftext|>


<commit_before><commit_msg>removed double definition of default template in sub_block<commit_after><|endoftext|>


<commit_before>#include <chrono>
#include <thread>

#include "SDL.h"

#include "app.h"

using namespace app;

void App::mainLoop()
{
     int i = 0;
     bool finished = false;
     bool leftMouseButtonDown = false;

     SDL_Event event = SDL_Event({ 0 });

     std::chrono::system_clock::time_point now, frameEnd;
     std::chrono::microseconds frameTime =
          std::chrono::microseconds((long)(1000000.0/60.0));

     while (!finished) {
          now = std::chrono::system_clock::now();
          frameEnd = now + std::chrono::microseconds(frameTime);

          SDL_UpdateTexture(texture, NULL, pixels, 640 * sizeof(Uint32));

          while (SDL_PollEvent(&event)) {
               switch(event.type) {
               case SDL_QUIT:
                    finished = true;
                    break;
               case SDL_KEYDOWN:
                    switch(event.key.keysym.sym) {
                    case SDLK_ESCAPE:
                         finished = true;
                         break;
                    }
               case SDL_MOUSEBUTTONUP:
                    if (event.button.button == SDL_BUTTON_LEFT)
                         leftMouseButtonDown = false;
                    break;
               case SDL_MOUSEBUTTONDOWN:
                    if (event.button.button == SDL_BUTTON_LEFT)
                         leftMouseButtonDown = true;
               case SDL_MOUSEMOTION:
                    if (leftMouseButtonDown)
                    {
                         int mouseX = event.motion.x;
                         int mouseY = event.motion.y;
                         pixels[mouseY * 640 + mouseX] = 0;
                    }
                    break;
               }
          }

          SDL_RenderClear(renderer);
          SDL_RenderCopy(renderer, texture, NULL, NULL);
          SDL_RenderPresent(renderer);

          std::this_thread::sleep_until(frameEnd);
     }
}
<commit_msg>Removed frame timer for performance<commit_after>#include <chrono>
#include <thread>

#include "SDL.h"

#include "app.h"

using namespace app;

void App::mainLoop()
{
     int i = 0;
     bool finished = false;
     bool leftMouseButtonDown = false;

     SDL_Event event = SDL_Event({ 0 });

     std::chrono::system_clock::time_point now, frameEnd;
     std::chrono::microseconds frameTime =
          std::chrono::microseconds((long)(1000000.0/60.0));

     while (!finished) {
          now = std::chrono::system_clock::now();
          frameEnd = now + std::chrono::microseconds(frameTime);

          SDL_UpdateTexture(texture, NULL, pixels, 640 * sizeof(Uint32));

          while (SDL_PollEvent(&event)) {
               switch(event.type) {
               case SDL_QUIT:
                    finished = true;
                    break;
               case SDL_KEYDOWN:
                    switch(event.key.keysym.sym) {
                    case SDLK_ESCAPE:
                         finished = true;
                         break;
                    }
               case SDL_MOUSEBUTTONUP:
                    if (event.button.button == SDL_BUTTON_LEFT)
                         leftMouseButtonDown = false;
                    break;
               case SDL_MOUSEBUTTONDOWN:
                    if (event.button.button == SDL_BUTTON_LEFT)
                         leftMouseButtonDown = true;
               case SDL_MOUSEMOTION:
                    if (leftMouseButtonDown)
                    {
                         int mouseX = event.motion.x;
                         int mouseY = event.motion.y;
                         pixels[mouseY * 640 + mouseX] = 0;
                    }
                    break;
               }
          }

          SDL_RenderClear(renderer);
          SDL_RenderCopy(renderer, texture, NULL, NULL);
          SDL_RenderPresent(renderer);

          //std::this_thread::sleep_until(frameEnd);
     }
}
<|endoftext|>


<commit_before>#include <rendering/texture_2d.h>

#include <unordered_map>

namespace rendering {

namespace {

struct texture_format_traits {
    GLint internalformat;
    GLenum format;
    GLenum type;
};

std::unordered_map<texture_2d::texture_format, texture_format_traits> format_traits = {
    { texture_2d::TEXTURE_FORMAT_RGBA8, {GL_RGBA8, GL_RGBA, GL_BYTE}},
    { texture_2d::TEXTURE_FORMAT_RG16F, {GL_RG16F, GL_RG, GL_HALF_FLOAT}},
    { texture_2d::TEXTURE_FORMAT_R8I, {GL_R8I, GL_RED_INTEGER, GL_BYTE}}
};

} // unnamed namespace

texture_2d::texture_2d(const util::extent& extent, texture_format format, const void *data)
{
    glGenTextures(1, &tex);
    glActiveTexture(GL_TEXTURE5);
    glBindTexture(GL_TEXTURE_2D, tex);
    auto traits = format_traits[format];
    glTexImage2D(GL_TEXTURE_2D, 0, format, GLsizei(extent.width), GLsizei(extent.height), 0, traits.format, traits.type, data);
    GL_CHECK();
    glActiveTexture(GL_TEXTURE0);
}

} // namespace rendering
<commit_msg>use format traits to determine internalformat<commit_after>#include <rendering/texture_2d.h>

#include <unordered_map>

namespace rendering {

namespace {

struct texture_format_traits {
    GLint internalformat;
    GLenum format;
    GLenum type;
};

std::unordered_map<texture_2d::texture_format, texture_format_traits> format_traits = {
    { texture_2d::TEXTURE_FORMAT_RGBA8, {GL_RGBA8, GL_RGBA, GL_BYTE}},
    { texture_2d::TEXTURE_FORMAT_RG16F, {GL_RG16F, GL_RG, GL_HALF_FLOAT}},
    { texture_2d::TEXTURE_FORMAT_R8I, {GL_R8I, GL_RED_INTEGER, GL_BYTE}}
};

} // unnamed namespace

texture_2d::texture_2d(const util::extent& extent, texture_format format, const void *data)
{
    glGenTextures(1, &tex);
    glActiveTexture(GL_TEXTURE5);
    glBindTexture(GL_TEXTURE_2D, tex);
    auto traits = format_traits[format];
    glTexImage2D(GL_TEXTURE_2D, 0, traits.internalformat, GLsizei(extent.width), GLsizei(extent.height), 0, traits.format, traits.type, data);
    GL_CHECK();
    glActiveTexture(GL_TEXTURE0);
}

} // namespace rendering
<|endoftext|>


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

#include "dp_misc.h"
#include "rtl/uri.hxx"
#include "rtl/digest.h"
#include "osl/file.hxx"
#include "osl/pipe.hxx"
#include "com/sun/star/util/XMacroExpander.hpp"

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using ::rtl::OUString;

namespace dp_misc
{

//==============================================================================
OUString expand_reg_url(
    OUString const & url, Reference< XComponentContext > const & xContext )
{
    Reference< util::XMacroExpander > xMacroExpander(
        xContext->getValueByName(
            OUSTR("/singletons/com.sun.star.util.theMacroExpander") ),
        UNO_QUERY_THROW );
    if (url.matchIgnoreAsciiCaseAsciiL(
            RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") ))
    {
        // cut protocol:
        OUString macro( url.copy( sizeof ("vnd.sun.star.expand:") -1 ) );
        // decode uric class chars:
        macro = ::rtl::Uri::decode(
            macro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
        // expand macro string:
        OUString ret( xMacroExpander->expandMacros( macro ) );
// #if OSL_DEBUG_LEVEL > 1
//         {
//         OUStringBuffer buf( 128 );
//         buf.appendAscii(
//             RTL_CONSTASCII_STRINGPARAM(__FILE__" expand_reg_url(): ") );
//         buf.append( url );
//         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" => ") );
//         buf.append( macro );
//         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" => ") );
//         buf.append( ret );
//         OString cstr(
//             OUStringToOString(
//                 buf.makeStringAndClear(), osl_getThreadTextEncoding() ) );
//         OSL_TRACE( "%s", cstr.getStr() );
//         }
// #endif
        return ret;
    }
    else
    {
        return url;
    }
}

enum t_status { RUNNING, NOT_RUNNING, INIT_ME };
//==============================================================================
bool office_is_running( Reference< XComponentContext > const & xContext )
{
    static t_status s_status = INIT_ME;
    if (s_status == INIT_ME)
    {
        Reference< util::XMacroExpander > xMacroExpander(
            xContext->getValueByName(
                OUSTR("/singletons/com.sun.star.util.theMacroExpander") ),
            UNO_QUERY_THROW );
        OUString user_path(
            xMacroExpander->expandMacros( OUSTR( "${$SYSBINDIR/"
                                                 SAL_CONFIGFILE("bootstrap")
                                                 ":UserInstallation}") ) );
        // normalize path:
        ::osl::FileStatus status( FileStatusMask_FileURL );
        ::osl::DirectoryItem dirItem;
        if (::osl::DirectoryItem::get( user_path, dirItem )
            != ::osl::DirectoryItem::E_None ||
            dirItem.getFileStatus( status )
            != ::osl::DirectoryItem::E_None ||
            !status.isValid( FileStatusMask_FileURL ) ||
            ::osl::FileBase::getAbsoluteFileURL(
                OUString(), status.getFileURL(), user_path )
            != ::osl::FileBase::E_None)
        {
            throw RuntimeException(
                OUSTR("Cannot normalize path ") + user_path, 0 );
        }

        rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
        if (digest <= 0)
        {
            throw RuntimeException(
                OUSTR("cannot get digest rtl_Digest_AlgorithmMD5!"), 0 );
        }

        sal_uInt8 const * data =
            reinterpret_cast< sal_uInt8 const * >(user_path.getStr());
        sal_Size size = (user_path.getLength() * sizeof (sal_Unicode));
        sal_uInt32 md5_key_len = rtl_digest_queryLength( digest );
        sal_uInt8 * md5_buf = new sal_uInt8 [ md5_key_len ];

        rtl_digest_init( digest, data, static_cast< sal_uInt32 >(size) );
        rtl_digest_update( digest, data, static_cast< sal_uInt32 >(size) );
        rtl_digest_get( digest, md5_buf, md5_key_len );
        rtl_digest_destroy( digest );

        // create hex-value string from the MD5 value to keep
        // the string size minimal
        ::rtl::OUStringBuffer buf;
        buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("SingleOfficeIPC_") );
        for ( sal_uInt32 i = 0; i < md5_key_len; ++i )
            buf.append( static_cast< sal_Int32 >(md5_buf[ i ]), 0x10 );

        delete [] md5_buf;

        OUString pipe_id( buf.makeStringAndClear() );
        ::osl::Security sec;
        ::osl::Pipe pipe( pipe_id, osl_Pipe_OPEN, sec );
        s_status = (pipe.is() ? RUNNING : NOT_RUNNING);
    }
    return (s_status == RUNNING);
}

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

#include "dp_misc.h"
#include "rtl/uri.hxx"
#include "rtl/digest.h"
#include "osl/file.hxx"
#include "osl/pipe.hxx"
#include "com/sun/star/util/XMacroExpander.hpp"

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using ::rtl::OUString;

namespace dp_misc
{

//==============================================================================
OUString expand_reg_url(
    OUString const & url, Reference< XComponentContext > const & xContext )
{
    Reference< util::XMacroExpander > xMacroExpander(
        xContext->getValueByName(
            OUSTR("/singletons/com.sun.star.util.theMacroExpander") ),
        UNO_QUERY_THROW );
    if (url.matchIgnoreAsciiCaseAsciiL(
            RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") ))
    {
        // cut protocol:
        OUString macro( url.copy( sizeof ("vnd.sun.star.expand:") -1 ) );
        // decode uric class chars:
        macro = ::rtl::Uri::decode(
            macro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
        // expand macro string:
        OUString ret( xMacroExpander->expandMacros( macro ) );
// #if OSL_DEBUG_LEVEL > 1
//         {
//         OUStringBuffer buf( 128 );
//         buf.appendAscii(
//             RTL_CONSTASCII_STRINGPARAM(__FILE__" expand_reg_url(): ") );
//         buf.append( url );
//         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" => ") );
//         buf.append( macro );
//         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" => ") );
//         buf.append( ret );
//         OString cstr(
//             OUStringToOString(
//                 buf.makeStringAndClear(), osl_getThreadTextEncoding() ) );
//         OSL_TRACE( "%s", cstr.getStr() );
//         }
// #endif
        return ret;
    }
    else
    {
        return url;
    }
}

enum t_status { RUNNING, NOT_RUNNING, INIT_ME };
//==============================================================================
bool office_is_running( Reference< XComponentContext > const & xContext )
{
    static t_status s_status = INIT_ME;
    if (s_status == INIT_ME)
    {
        Reference< util::XMacroExpander > xMacroExpander(
            xContext->getValueByName(
                OUSTR("/singletons/com.sun.star.util.theMacroExpander") ),
            UNO_QUERY_THROW );
        OUString user_path(
            xMacroExpander->expandMacros( OUSTR( "${$SYSBINDIR/"
                                                 SAL_CONFIGFILE("bootstrap")
                                                 ":UserInstallation}") ) );
        // normalize path:
        ::osl::FileStatus status( FileStatusMask_FileURL );
        ::osl::DirectoryItem dirItem;
        if (::osl::DirectoryItem::get( user_path, dirItem )
            != ::osl::DirectoryItem::E_None ||
            dirItem.getFileStatus( status )
            != ::osl::DirectoryItem::E_None ||
            !status.isValid( FileStatusMask_FileURL ) ||
            ::osl::FileBase::getAbsoluteFileURL(
                OUString(), status.getFileURL(), user_path )
            != ::osl::FileBase::E_None)
        {
            return false;
        }

        rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
        if (digest <= 0)
        {
            throw RuntimeException(
                OUSTR("cannot get digest rtl_Digest_AlgorithmMD5!"), 0 );
        }

        sal_uInt8 const * data =
            reinterpret_cast< sal_uInt8 const * >(user_path.getStr());
        sal_Size size = (user_path.getLength() * sizeof (sal_Unicode));
        sal_uInt32 md5_key_len = rtl_digest_queryLength( digest );
        sal_uInt8 * md5_buf = new sal_uInt8 [ md5_key_len ];

        rtl_digest_init( digest, data, static_cast< sal_uInt32 >(size) );
        rtl_digest_update( digest, data, static_cast< sal_uInt32 >(size) );
        rtl_digest_get( digest, md5_buf, md5_key_len );
        rtl_digest_destroy( digest );

        // create hex-value string from the MD5 value to keep
        // the string size minimal
        ::rtl::OUStringBuffer buf;
        buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("SingleOfficeIPC_") );
        for ( sal_uInt32 i = 0; i < md5_key_len; ++i )
            buf.append( static_cast< sal_Int32 >(md5_buf[ i ]), 0x10 );

        delete [] md5_buf;

        OUString pipe_id( buf.makeStringAndClear() );
        ::osl::Security sec;
        ::osl::Pipe pipe( pipe_id, osl_Pipe_OPEN, sec );
        s_status = (pipe.is() ? RUNNING : NOT_RUNNING);
    }
    return (s_status == RUNNING);
}

}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2011-2012, John Haddon. All rights reserved.
//  Copyright (c) 2011-2013, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp" // must be the first include

#include <fstream>

#include "IECorePython/Wrapper.h"
#include "IECorePython/RunTimeTypedBinding.h"
#include "IECorePython/ScopedGILLock.h"

#include "Gaffer/ScriptNode.h"
#include "Gaffer/Context.h"
#include "Gaffer/ApplicationRoot.h"
#include "Gaffer/StandardSet.h"
#include "Gaffer/CompoundDataPlug.h"

#include "GafferBindings/ScriptNodeBinding.h"
#include "GafferBindings/SignalBinding.h"
#include "GafferBindings/NodeBinding.h"

using namespace boost::python;
using namespace Gaffer;

namespace GafferBindings
{

/// The ScriptNodeWrapper class implements the scripting
/// components of the ScriptNode base class. In this way
/// scripting is available provided that the ScriptNode was
/// created from python.
class ScriptNodeWrapper : public NodeWrapper<ScriptNode>
{

	public :

		ScriptNodeWrapper( PyObject *self, const std::string &name )
			:	NodeWrapper<ScriptNode>( self, name )
		{
		}

		virtual ~ScriptNodeWrapper()
		{
		}

		virtual void execute( const std::string &pythonScript, Node *parent = 0 )
		{
			IECorePython::ScopedGILLock gilLock;
			object e = executionDict( parent );
			exec( pythonScript.c_str(), e, e );
			scriptExecutedSignal()( this, pythonScript );
		}

		void executeFile( const std::string &pythonFile, Node *parent = 0 )
		{
			const std::string pythonScript = readFile( pythonFile );
			execute( pythonScript, parent );
		}

		virtual PyObject *evaluate( const std::string &pythonExpression, Node *parent = 0 )
		{
			IECorePython::ScopedGILLock gilLock;
			object e = executionDict( parent );
			object result = eval( pythonExpression.c_str(), e, e );
			scriptEvaluatedSignal()( this, pythonExpression, result.ptr() );

			// make a reference to keep the result alive - the caller then
			// assumes responsibility for dealing with this
			Py_XINCREF( result.ptr() );
			return result.ptr();
		}

		virtual std::string serialise( const Node *parent = 0, const Set *filter = 0 ) const
		{
			Serialisation serialisation( parent ? parent : this, "parent", filter );
			return serialisation.result();
		}

		virtual void serialiseToFile( const std::string &fileName, const Node *parent, const Set *filter ) const
		{
			std::string s = serialise( parent, filter );

			std::ofstream f( fileName.c_str() );
			if( !f.good() )
			{
				throw IECore::IOException( "Unable to open file \"" + fileName + "\"" );
			}

			f << s;

			if( !f.good() )
			{
				throw IECore::IOException( "Failed to write to \"" + fileName + "\"" );
			}
		}

		virtual void load()
		{
			const std::string s = readFile( fileNamePlug()->getValue() );

			deleteNodes();
			variablesPlug()->clearChildren();

			execute( s );

			UndoContext undoDisabled( this, UndoContext::Disabled );
			unsavedChangesPlug()->setValue( false );
		}

		virtual void save() const
		{
			serialiseToFile( fileNamePlug()->getValue(), 0, 0 );
			UndoContext undoDisabled( const_cast<ScriptNodeWrapper *>( this ), UndoContext::Disabled );
			const_cast<BoolPlug *>( unsavedChangesPlug() )->setValue( false );
		}

	private :

		std::string readFile( const std::string &fileName )
		{
			std::ifstream f( fileName.c_str() );
			if( !f.good() )
			{
				throw IECore::IOException( "Unable to open file \"" + fileName + "\"" );
			}

			std::string s;
			while( !f.eof() )
			{
				if( !f.good() )
				{
					throw IECore::IOException( "Failed to read from \"" + fileName + "\"" );
				}

				std::string line;
				std::getline( f, line );
				s += line + "\n";
			}

			return s;
		}

		// the dict returned will form both the locals and the globals for the execute()
		// and evaluate() methods. it's not possible to have a separate locals
		// and globals dictionary and have things work as intended. see
		// ScriptNodeTest.testClassScope() for an example, and
		// http://bugs.python.org/issue991196 for an explanation.
		object executionDict( Node *parent )
		{
			dict result;

			object builtIn = import( "__builtin__" );
			result["__builtins__"] = builtIn;

			object gafferModule = import( "Gaffer" );
			result["Gaffer"] = gafferModule;

			result["script"] = object( ScriptNodePtr( this ) );
			result["parent"] = object( NodePtr( parent ? parent : this ) );

			return result;
		}

};

IE_CORE_DECLAREPTR( ScriptNodeWrapper )

struct ScriptEvaluatedSlotCaller
{
	boost::signals::detail::unusable operator()( boost::python::object slot, ScriptNodePtr node, const std::string script, PyObject *result )
	{
		try
		{
			boost::python::object o( handle<>( borrowed( result ) ) );
			slot( node, script, o );
		}
		catch( const error_already_set &e )
		{
			PyErr_PrintEx( 0 ); // clears error status
		}
		return boost::signals::detail::unusable();
	}
};

static ContextPtr context( ScriptNode &s )
{
	return s.context();
}

static ApplicationRootPtr applicationRoot( ScriptNode &s )
{
	return s.applicationRoot();
}

static StandardSetPtr selection( ScriptNode &s )
{
	return s.selection();
}

class ScriptNodeSerialiser : public NodeSerialiser
{

	virtual bool childNeedsSerialisation( const Gaffer::GraphComponent *child ) const
	{
		if( child->isInstanceOf( Node::staticTypeId() ) )
		{
			return true;
		}
		return NodeSerialiser::childNeedsSerialisation( child );
	}

	virtual bool childNeedsConstruction( const Gaffer::GraphComponent *child ) const
	{
		if( child->isInstanceOf( Node::staticTypeId() ) )
		{
			return true;
		}
		return NodeSerialiser::childNeedsConstruction( child );
	}

};

struct ActionSlotCaller
{

	boost::signals::detail::unusable operator()( boost::python::object slot, ScriptNodePtr script, ConstActionPtr action, Action::Stage stage )
	{
		try
		{
			slot( script, IECore::constPointerCast<Action>( action ), stage );
		}
		catch( const error_already_set &e )
		{
			PyErr_PrintEx( 0 ); // clears the error status
		}
		return boost::signals::detail::unusable();
	}

};

struct UndoAddedSlotCaller
{

	boost::signals::detail::unusable operator()( boost::python::object slot, ScriptNodePtr script )
	{
		try
		{
			slot( script );
		}
		catch( const error_already_set &e )
		{
			PyErr_PrintEx( 0 ); // clears the error status
		}
		return boost::signals::detail::unusable();
	}

};

void bindScriptNode()
{
	scope s = NodeClass<ScriptNode, ScriptNodeWrapperPtr>()
		.def( "applicationRoot", &applicationRoot )
		.def( "selection", &selection )
		.def( "undoAvailable", &ScriptNode::undoAvailable )
		.def( "undo", &ScriptNode::undo )
		.def( "redoAvailable", &ScriptNode::redoAvailable )
		.def( "redo", &ScriptNode::redo )
		.def( "currentActionStage", &ScriptNode::currentActionStage )
		.def( "actionSignal", &ScriptNode::actionSignal, return_internal_reference<1>() )
		.def( "undoAddedSignal", &ScriptNode::undoAddedSignal, return_internal_reference<1>() )
		.def( "copy", &ScriptNode::copy, ( arg_( "parent" ) = object(), arg_( "filter" ) = object() ) )
		.def( "cut", &ScriptNode::cut, ( arg_( "parent" ) = object(), arg_( "filter" ) = object() ) )
		.def( "paste", &ScriptNode::paste, ( arg_( "parent" ) = object() ) )
		.def( "deleteNodes", &ScriptNode::deleteNodes, ( arg_( "parent" ) = object(), arg_( "filter" ) = object(), arg_( "reconnect" ) = true ) )
		.def( "execute", &ScriptNode::execute, ( arg_( "parent" ) = object() ) )
		.def( "executeFile", &ScriptNode::executeFile, ( arg_( "fileName" ), arg_( "parent" ) = object() ) )
		.def( "evaluate", &ScriptNode::evaluate, ( arg_( "parent" ) = object() ) )
		.def( "scriptExecutedSignal", &ScriptNode::scriptExecutedSignal, return_internal_reference<1>() )
		.def( "scriptEvaluatedSignal", &ScriptNode::scriptEvaluatedSignal, return_internal_reference<1>() )
		.def( "serialise", &ScriptNode::serialise, ( arg_( "parent" ) = object(), arg_( "filter" ) = object() ) )
		.def( "serialiseToFile", &ScriptNode::serialiseToFile, ( arg_( "fileName" ), arg_( "parent" ) = object(), arg_( "filter" ) = object() ) )
		.def( "save", &ScriptNode::save )
		.def( "load", &ScriptNode::load )
		.def( "context", &context )
	;

	SignalBinder<ScriptNode::ActionSignal, DefaultSignalCaller<ScriptNode::ActionSignal>, ActionSlotCaller>::bind( "ActionSignal" );
	SignalBinder<ScriptNode::UndoAddedSignal, DefaultSignalCaller<ScriptNode::UndoAddedSignal>, UndoAddedSlotCaller>::bind( "UndoAddedSignal" );

	SignalBinder<ScriptNode::ScriptExecutedSignal>::bind( "ScriptExecutedSignal" );
	SignalBinder<ScriptNode::ScriptEvaluatedSignal, DefaultSignalCaller<ScriptNode::ScriptEvaluatedSignal>, ScriptEvaluatedSlotCaller>::bind( "ScriptEvaluatedSignal" );

	Serialisation::registerSerialiser( ScriptNode::staticTypeId(), new ScriptNodeSerialiser );

}

} // namespace GafferBindings
<commit_msg>put a gil release in the python bindings for ScriptNode::deleteNodes in case it triggers a python evaluation<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2011-2012, John Haddon. All rights reserved.
//  Copyright (c) 2011-2013, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp" // must be the first include

#include <fstream>

#include "IECorePython/Wrapper.h"
#include "IECorePython/RunTimeTypedBinding.h"
#include "IECorePython/ScopedGILLock.h"
#include "IECorePython/ScopedGILRelease.h"

#include "Gaffer/ScriptNode.h"
#include "Gaffer/Context.h"
#include "Gaffer/ApplicationRoot.h"
#include "Gaffer/StandardSet.h"
#include "Gaffer/CompoundDataPlug.h"

#include "GafferBindings/ScriptNodeBinding.h"
#include "GafferBindings/SignalBinding.h"
#include "GafferBindings/NodeBinding.h"

using namespace boost::python;
using namespace Gaffer;

namespace GafferBindings
{

/// The ScriptNodeWrapper class implements the scripting
/// components of the ScriptNode base class. In this way
/// scripting is available provided that the ScriptNode was
/// created from python.
class ScriptNodeWrapper : public NodeWrapper<ScriptNode>
{

	public :

		ScriptNodeWrapper( PyObject *self, const std::string &name )
			:	NodeWrapper<ScriptNode>( self, name )
		{
		}

		virtual ~ScriptNodeWrapper()
		{
		}

		virtual void execute( const std::string &pythonScript, Node *parent = 0 )
		{
			IECorePython::ScopedGILLock gilLock;
			object e = executionDict( parent );
			exec( pythonScript.c_str(), e, e );
			scriptExecutedSignal()( this, pythonScript );
		}

		void executeFile( const std::string &pythonFile, Node *parent = 0 )
		{
			const std::string pythonScript = readFile( pythonFile );
			execute( pythonScript, parent );
		}

		virtual PyObject *evaluate( const std::string &pythonExpression, Node *parent = 0 )
		{
			IECorePython::ScopedGILLock gilLock;
			object e = executionDict( parent );
			object result = eval( pythonExpression.c_str(), e, e );
			scriptEvaluatedSignal()( this, pythonExpression, result.ptr() );

			// make a reference to keep the result alive - the caller then
			// assumes responsibility for dealing with this
			Py_XINCREF( result.ptr() );
			return result.ptr();
		}

		virtual std::string serialise( const Node *parent = 0, const Set *filter = 0 ) const
		{
			Serialisation serialisation( parent ? parent : this, "parent", filter );
			return serialisation.result();
		}

		virtual void serialiseToFile( const std::string &fileName, const Node *parent, const Set *filter ) const
		{
			std::string s = serialise( parent, filter );

			std::ofstream f( fileName.c_str() );
			if( !f.good() )
			{
				throw IECore::IOException( "Unable to open file \"" + fileName + "\"" );
			}

			f << s;

			if( !f.good() )
			{
				throw IECore::IOException( "Failed to write to \"" + fileName + "\"" );
			}
		}

		virtual void load()
		{
			const std::string s = readFile( fileNamePlug()->getValue() );

			deleteNodes();
			variablesPlug()->clearChildren();

			execute( s );

			UndoContext undoDisabled( this, UndoContext::Disabled );
			unsavedChangesPlug()->setValue( false );
		}

		virtual void save() const
		{
			serialiseToFile( fileNamePlug()->getValue(), 0, 0 );
			UndoContext undoDisabled( const_cast<ScriptNodeWrapper *>( this ), UndoContext::Disabled );
			const_cast<BoolPlug *>( unsavedChangesPlug() )->setValue( false );
		}

	private :

		std::string readFile( const std::string &fileName )
		{
			std::ifstream f( fileName.c_str() );
			if( !f.good() )
			{
				throw IECore::IOException( "Unable to open file \"" + fileName + "\"" );
			}

			std::string s;
			while( !f.eof() )
			{
				if( !f.good() )
				{
					throw IECore::IOException( "Failed to read from \"" + fileName + "\"" );
				}

				std::string line;
				std::getline( f, line );
				s += line + "\n";
			}

			return s;
		}

		// the dict returned will form both the locals and the globals for the execute()
		// and evaluate() methods. it's not possible to have a separate locals
		// and globals dictionary and have things work as intended. see
		// ScriptNodeTest.testClassScope() for an example, and
		// http://bugs.python.org/issue991196 for an explanation.
		object executionDict( Node *parent )
		{
			dict result;

			object builtIn = import( "__builtin__" );
			result["__builtins__"] = builtIn;

			object gafferModule = import( "Gaffer" );
			result["Gaffer"] = gafferModule;

			result["script"] = object( ScriptNodePtr( this ) );
			result["parent"] = object( NodePtr( parent ? parent : this ) );

			return result;
		}

};

IE_CORE_DECLAREPTR( ScriptNodeWrapper )

struct ScriptEvaluatedSlotCaller
{
	boost::signals::detail::unusable operator()( boost::python::object slot, ScriptNodePtr node, const std::string script, PyObject *result )
	{
		try
		{
			boost::python::object o( handle<>( borrowed( result ) ) );
			slot( node, script, o );
		}
		catch( const error_already_set &e )
		{
			PyErr_PrintEx( 0 ); // clears error status
		}
		return boost::signals::detail::unusable();
	}
};

static ContextPtr context( ScriptNode &s )
{
	return s.context();
}

static ApplicationRootPtr applicationRoot( ScriptNode &s )
{
	return s.applicationRoot();
}

static StandardSetPtr selection( ScriptNode &s )
{
	return s.selection();
}

static void deleteNodes( ScriptNode &s, Node *parent, const Set *filter, bool reconnect )
{
	IECorePython::ScopedGILRelease r;
	s.deleteNodes( parent, filter, reconnect );
}

class ScriptNodeSerialiser : public NodeSerialiser
{

	virtual bool childNeedsSerialisation( const Gaffer::GraphComponent *child ) const
	{
		if( child->isInstanceOf( Node::staticTypeId() ) )
		{
			return true;
		}
		return NodeSerialiser::childNeedsSerialisation( child );
	}

	virtual bool childNeedsConstruction( const Gaffer::GraphComponent *child ) const
	{
		if( child->isInstanceOf( Node::staticTypeId() ) )
		{
			return true;
		}
		return NodeSerialiser::childNeedsConstruction( child );
	}

};

struct ActionSlotCaller
{

	boost::signals::detail::unusable operator()( boost::python::object slot, ScriptNodePtr script, ConstActionPtr action, Action::Stage stage )
	{
		try
		{
			slot( script, IECore::constPointerCast<Action>( action ), stage );
		}
		catch( const error_already_set &e )
		{
			PyErr_PrintEx( 0 ); // clears the error status
		}
		return boost::signals::detail::unusable();
	}

};

struct UndoAddedSlotCaller
{

	boost::signals::detail::unusable operator()( boost::python::object slot, ScriptNodePtr script )
	{
		try
		{
			slot( script );
		}
		catch( const error_already_set &e )
		{
			PyErr_PrintEx( 0 ); // clears the error status
		}
		return boost::signals::detail::unusable();
	}

};

void bindScriptNode()
{
	scope s = NodeClass<ScriptNode, ScriptNodeWrapperPtr>()
		.def( "applicationRoot", &applicationRoot )
		.def( "selection", &selection )
		.def( "undoAvailable", &ScriptNode::undoAvailable )
		.def( "undo", &ScriptNode::undo )
		.def( "redoAvailable", &ScriptNode::redoAvailable )
		.def( "redo", &ScriptNode::redo )
		.def( "currentActionStage", &ScriptNode::currentActionStage )
		.def( "actionSignal", &ScriptNode::actionSignal, return_internal_reference<1>() )
		.def( "undoAddedSignal", &ScriptNode::undoAddedSignal, return_internal_reference<1>() )
		.def( "copy", &ScriptNode::copy, ( arg_( "parent" ) = object(), arg_( "filter" ) = object() ) )
		.def( "cut", &ScriptNode::cut, ( arg_( "parent" ) = object(), arg_( "filter" ) = object() ) )
		.def( "paste", &ScriptNode::paste, ( arg_( "parent" ) = object() ) )
		.def( "deleteNodes", &deleteNodes, ( arg_( "parent" ) = object(), arg_( "filter" ) = object(), arg_( "reconnect" ) = true ) )
		.def( "execute", &ScriptNode::execute, ( arg_( "parent" ) = object() ) )
		.def( "executeFile", &ScriptNode::executeFile, ( arg_( "fileName" ), arg_( "parent" ) = object() ) )
		.def( "evaluate", &ScriptNode::evaluate, ( arg_( "parent" ) = object() ) )
		.def( "scriptExecutedSignal", &ScriptNode::scriptExecutedSignal, return_internal_reference<1>() )
		.def( "scriptEvaluatedSignal", &ScriptNode::scriptEvaluatedSignal, return_internal_reference<1>() )
		.def( "serialise", &ScriptNode::serialise, ( arg_( "parent" ) = object(), arg_( "filter" ) = object() ) )
		.def( "serialiseToFile", &ScriptNode::serialiseToFile, ( arg_( "fileName" ), arg_( "parent" ) = object(), arg_( "filter" ) = object() ) )
		.def( "save", &ScriptNode::save )
		.def( "load", &ScriptNode::load )
		.def( "context", &context )
	;

	SignalBinder<ScriptNode::ActionSignal, DefaultSignalCaller<ScriptNode::ActionSignal>, ActionSlotCaller>::bind( "ActionSignal" );
	SignalBinder<ScriptNode::UndoAddedSignal, DefaultSignalCaller<ScriptNode::UndoAddedSignal>, UndoAddedSlotCaller>::bind( "UndoAddedSignal" );

	SignalBinder<ScriptNode::ScriptExecutedSignal>::bind( "ScriptExecutedSignal" );
	SignalBinder<ScriptNode::ScriptEvaluatedSignal, DefaultSignalCaller<ScriptNode::ScriptEvaluatedSignal>, ScriptEvaluatedSlotCaller>::bind( "ScriptEvaluatedSignal" );

	Serialisation::registerSerialiser( ScriptNode::staticTypeId(), new ScriptNodeSerialiser );

}

} // namespace GafferBindings
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2018, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"

#include "ParallelAlgoBinding.h"

#include "GafferBindings/SignalBinding.h"

#include "Gaffer/BackgroundTask.h"
#include "Gaffer/ParallelAlgo.h"
#include "Gaffer/Plug.h"

#include "IECorePython/ExceptionAlgo.h"
#include "IECorePython/ScopedGILRelease.h"

using namespace Gaffer;
using namespace GafferBindings;
using namespace boost::python;

namespace
{

BackgroundTask *backgroundTaskConstructor( const Plug *subject, object f )
{
	auto fPtr = std::make_shared<boost::python::object>( f );
	return new BackgroundTask(
		subject,
		[fPtr]( const IECore::Canceller &canceller ) mutable {
			IECorePython::ScopedGILLock gilLock;
			try
			{
				(*fPtr)( boost::ref( canceller ) );
				// We are likely to be the last owner of the python
				// function object. Make sure we release it while we
				// still hold the GIL.
				fPtr.reset();
			}
			catch( boost::python::error_already_set &e )
			{
				fPtr.reset();
				IECorePython::ExceptionAlgo::translatePythonException();
			}
		}
	);
}

void backgroundTaskCancel( BackgroundTask &b )
{
	IECorePython::ScopedGILRelease gilRelease;
	b.cancel();
}

void backgroundTaskWait( BackgroundTask &b )
{
	IECorePython::ScopedGILRelease gilRelease;
	b.wait();
}

bool backgroundTaskWaitFor( BackgroundTask &b, float seconds )
{
	IECorePython::ScopedGILRelease gilRelease;
	return b.waitFor( seconds );
}

void backgroundTaskCancelAndWait( BackgroundTask &b )
{
	IECorePython::ScopedGILRelease gilRelease;
	b.cancelAndWait();
}

BackgroundTask::Status backgroundTaskStatus( const BackgroundTask &b )
{
	IECorePython::ScopedGILRelease gilRelease;
	return b.status();
}

struct GILReleaseUIThreadFunction
{

	GILReleaseUIThreadFunction( ParallelAlgo::UIThreadFunction function )
		:	m_function( function )
	{
	}

	void operator()()
	{
		IECorePython::ScopedGILRelease gilRelease;
		m_function();
	}

	private :

		ParallelAlgo::UIThreadFunction m_function;

};

void callOnUIThread( boost::python::object f )
{
	auto fPtr = std::make_shared<boost::python::object>( f );

	IECorePython::ScopedGILRelease gilRelease;

	Gaffer::ParallelAlgo::callOnUIThread(
		[fPtr]() mutable {
			IECorePython::ScopedGILLock gilLock;
			try
			{
				(*fPtr)();
				// We are likely to be the last owner of the python
				// function object. Make sure we release it while we
				// still hold the GIL.
				fPtr.reset();
			}
			catch( boost::python::error_already_set &e )
			{
				fPtr.reset();
				IECorePython::ExceptionAlgo::translatePythonException();
			}
		}
	);
}

void pushUIThreadCallHandler( boost::python::object handler )
{
	// The lambda below needs to own a reference to `handler`,
	// and in turn will be owned by the ParallelAlgo C++ API.
	// Wrap `handler` so we acquire the GIL when the lambda is
	// destroyed from C++.
	auto handlerPtr = std::shared_ptr<boost::python::object>(
		new boost::python::object( handler ),
		[]( boost::python::object *o ) {
			IECorePython::ScopedGILLock gilLock;
			delete o;
		}
	);

	IECorePython::ScopedGILRelease gilRelease;

	Gaffer::ParallelAlgo::pushUIThreadCallHandler(
		[handlerPtr] ( const ParallelAlgo::UIThreadFunction &function ) {
			IECorePython::ScopedGILLock gilLock;
			boost::python::object pythonFunction = make_function(
				GILReleaseUIThreadFunction( function ),
				boost::python::default_call_policies(),
				boost::mpl::vector<void>()
			);
			(*handlerPtr)( pythonFunction );
		}
	);
}

std::shared_ptr<BackgroundTask> callOnBackgroundThread( const Plug *subject, boost::python::object f )
{
	// The BackgroundTask we return will own the python function we
	// pass to it. Wrap the function so that the GIL is acquired
	// before the python object is destroyed.
	auto fPtr = std::shared_ptr<boost::python::object>(
		new boost::python::object( f ),
		[]( boost::python::object *o ) {
			IECorePython::ScopedGILLock gilLock;
			delete o;
		}
	);

	auto backgroundTask = ParallelAlgo::callOnBackgroundThread(
		subject,
		[fPtr]() mutable {
			IECorePython::ScopedGILLock gilLock;
			try
			{
				(*fPtr)();
			}
			catch( boost::python::error_already_set &e )
			{
				IECorePython::ExceptionAlgo::translatePythonException();
			}
		}
	);

	return std::shared_ptr<BackgroundTask>(
		backgroundTask.release(),
		// Custom deleter. We need to release
		// the GIL when deleting, because the destructor
		// waits on the background task, and the background
		// task might need the GIL in order to complete.
		[]( BackgroundTask *t ) {
			IECorePython::ScopedGILRelease gilRelease;
			delete t;
		}
	);
}

} // namespace

void GafferModule::bindParallelAlgo()
{

	{
		scope s = class_<BackgroundTask, boost::noncopyable>( "BackgroundTask", no_init )
			.def( "__init__", make_constructor( &backgroundTaskConstructor, default_call_policies() ) )
			.def( "cancel", &backgroundTaskCancel )
			.def( "wait", &backgroundTaskWait )
			.def( "waitFor", &backgroundTaskWaitFor )
			.def( "cancelAndWait", &backgroundTaskCancelAndWait )
			.def( "status", &backgroundTaskStatus )
		;

		enum_<BackgroundTask::Status>( "Status" )
			.value( "Pending", BackgroundTask::Pending )
			.value( "Running", BackgroundTask::Running )
			.value( "Completed", BackgroundTask::Completed )
			.value( "Cancelled", BackgroundTask::Cancelled )
			.value( "Errored", BackgroundTask::Errored )
		;
	}

	register_ptr_to_python<std::shared_ptr<BackgroundTask>>();

	object module( borrowed( PyImport_AddModule( "Gaffer.ParallelAlgo" ) ) );
	scope().attr( "ParallelAlgo" ) = module;
	scope moduleScope( module );

	def( "callOnUIThread", &callOnUIThread );
	def( "pushUIThreadCallHandler", &pushUIThreadCallHandler );
	def( "popUIThreadCallHandler", &ParallelAlgo::popUIThreadCallHandler );
	def( "callOnBackgroundThread", &callOnBackgroundThread );

}
<commit_msg>ParallelAlgoBinding : Release GIL in `popUIThreadCallHandler()`<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2018, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"

#include "ParallelAlgoBinding.h"

#include "GafferBindings/SignalBinding.h"

#include "Gaffer/BackgroundTask.h"
#include "Gaffer/ParallelAlgo.h"
#include "Gaffer/Plug.h"

#include "IECorePython/ExceptionAlgo.h"
#include "IECorePython/ScopedGILRelease.h"

using namespace Gaffer;
using namespace GafferBindings;
using namespace boost::python;

namespace
{

BackgroundTask *backgroundTaskConstructor( const Plug *subject, object f )
{
	auto fPtr = std::make_shared<boost::python::object>( f );
	return new BackgroundTask(
		subject,
		[fPtr]( const IECore::Canceller &canceller ) mutable {
			IECorePython::ScopedGILLock gilLock;
			try
			{
				(*fPtr)( boost::ref( canceller ) );
				// We are likely to be the last owner of the python
				// function object. Make sure we release it while we
				// still hold the GIL.
				fPtr.reset();
			}
			catch( boost::python::error_already_set &e )
			{
				fPtr.reset();
				IECorePython::ExceptionAlgo::translatePythonException();
			}
		}
	);
}

void backgroundTaskCancel( BackgroundTask &b )
{
	IECorePython::ScopedGILRelease gilRelease;
	b.cancel();
}

void backgroundTaskWait( BackgroundTask &b )
{
	IECorePython::ScopedGILRelease gilRelease;
	b.wait();
}

bool backgroundTaskWaitFor( BackgroundTask &b, float seconds )
{
	IECorePython::ScopedGILRelease gilRelease;
	return b.waitFor( seconds );
}

void backgroundTaskCancelAndWait( BackgroundTask &b )
{
	IECorePython::ScopedGILRelease gilRelease;
	b.cancelAndWait();
}

BackgroundTask::Status backgroundTaskStatus( const BackgroundTask &b )
{
	IECorePython::ScopedGILRelease gilRelease;
	return b.status();
}

struct GILReleaseUIThreadFunction
{

	GILReleaseUIThreadFunction( ParallelAlgo::UIThreadFunction function )
		:	m_function( function )
	{
	}

	void operator()()
	{
		IECorePython::ScopedGILRelease gilRelease;
		m_function();
	}

	private :

		ParallelAlgo::UIThreadFunction m_function;

};

void callOnUIThread( boost::python::object f )
{
	auto fPtr = std::make_shared<boost::python::object>( f );

	IECorePython::ScopedGILRelease gilRelease;

	Gaffer::ParallelAlgo::callOnUIThread(
		[fPtr]() mutable {
			IECorePython::ScopedGILLock gilLock;
			try
			{
				(*fPtr)();
				// We are likely to be the last owner of the python
				// function object. Make sure we release it while we
				// still hold the GIL.
				fPtr.reset();
			}
			catch( boost::python::error_already_set &e )
			{
				fPtr.reset();
				IECorePython::ExceptionAlgo::translatePythonException();
			}
		}
	);
}

void pushUIThreadCallHandler( boost::python::object handler )
{
	// The lambda below needs to own a reference to `handler`,
	// and in turn will be owned by the ParallelAlgo C++ API.
	// Wrap `handler` so we acquire the GIL when the lambda is
	// destroyed from C++.
	auto handlerPtr = std::shared_ptr<boost::python::object>(
		new boost::python::object( handler ),
		[]( boost::python::object *o ) {
			IECorePython::ScopedGILLock gilLock;
			delete o;
		}
	);

	IECorePython::ScopedGILRelease gilRelease;

	Gaffer::ParallelAlgo::pushUIThreadCallHandler(
		[handlerPtr] ( const ParallelAlgo::UIThreadFunction &function ) {
			IECorePython::ScopedGILLock gilLock;
			boost::python::object pythonFunction = make_function(
				GILReleaseUIThreadFunction( function ),
				boost::python::default_call_policies(),
				boost::mpl::vector<void>()
			);
			(*handlerPtr)( pythonFunction );
		}
	);
}

void popUIThreadCallHandler()
{
	IECorePython::ScopedGILRelease gilRelease;
	ParallelAlgo::popUIThreadCallHandler();
}

std::shared_ptr<BackgroundTask> callOnBackgroundThread( const Plug *subject, boost::python::object f )
{
	// The BackgroundTask we return will own the python function we
	// pass to it. Wrap the function so that the GIL is acquired
	// before the python object is destroyed.
	auto fPtr = std::shared_ptr<boost::python::object>(
		new boost::python::object( f ),
		[]( boost::python::object *o ) {
			IECorePython::ScopedGILLock gilLock;
			delete o;
		}
	);

	auto backgroundTask = ParallelAlgo::callOnBackgroundThread(
		subject,
		[fPtr]() mutable {
			IECorePython::ScopedGILLock gilLock;
			try
			{
				(*fPtr)();
			}
			catch( boost::python::error_already_set &e )
			{
				IECorePython::ExceptionAlgo::translatePythonException();
			}
		}
	);

	return std::shared_ptr<BackgroundTask>(
		backgroundTask.release(),
		// Custom deleter. We need to release
		// the GIL when deleting, because the destructor
		// waits on the background task, and the background
		// task might need the GIL in order to complete.
		[]( BackgroundTask *t ) {
			IECorePython::ScopedGILRelease gilRelease;
			delete t;
		}
	);
}

} // namespace

void GafferModule::bindParallelAlgo()
{

	{
		scope s = class_<BackgroundTask, boost::noncopyable>( "BackgroundTask", no_init )
			.def( "__init__", make_constructor( &backgroundTaskConstructor, default_call_policies() ) )
			.def( "cancel", &backgroundTaskCancel )
			.def( "wait", &backgroundTaskWait )
			.def( "waitFor", &backgroundTaskWaitFor )
			.def( "cancelAndWait", &backgroundTaskCancelAndWait )
			.def( "status", &backgroundTaskStatus )
		;

		enum_<BackgroundTask::Status>( "Status" )
			.value( "Pending", BackgroundTask::Pending )
			.value( "Running", BackgroundTask::Running )
			.value( "Completed", BackgroundTask::Completed )
			.value( "Cancelled", BackgroundTask::Cancelled )
			.value( "Errored", BackgroundTask::Errored )
		;
	}

	register_ptr_to_python<std::shared_ptr<BackgroundTask>>();

	object module( borrowed( PyImport_AddModule( "Gaffer.ParallelAlgo" ) ) );
	scope().attr( "ParallelAlgo" ) = module;
	scope moduleScope( module );

	def( "callOnUIThread", &callOnUIThread );
	def( "pushUIThreadCallHandler", &pushUIThreadCallHandler );
	def( "popUIThreadCallHandler", &popUIThreadCallHandler );
	def( "callOnBackgroundThread", &callOnBackgroundThread );

}
<|endoftext|>


<commit_before>// ===============================
//  PC-BSD REST API Server
// Available under the 3-clause BSD License
// Written by: Ken Moore <ken@pcbsd.org> 2015-2016
// =================================
#include "EventWatcher.h"

#include "globals.h"

// === PUBLIC ===
EventWatcher::EventWatcher(){
  qRegisterMetaType<EventWatcher::EVENT_TYPE>("EventWatcher::EVENT_TYPE");

  starting = true;
  LPlog_pos = LPrep_pos = LPerr_pos = 0; //no pos yet
  watcher = new QFileSystemWatcher(this);
  filechecktimer = new QTimer(this);
    filechecktimer->setSingleShot(false);
    filechecktimer->setInterval(3600000); //1-hour checks (also run on new event notices)
  connect(watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(WatcherUpdate(const QString&)) );
  connect(watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(WatcherUpdate(const QString&)) );
  connect(filechecktimer, SIGNAL(timeout()), this, SLOT( CheckLogFiles()) );
}

EventWatcher::~EventWatcher(){
}

void EventWatcher::start(){
  // - DISPATCH Events
  starting = true;
  //if(!QFile::exists(DISPATCHWORKING)){ QProcess::execute("touch "+DISPATCHWORKING); }
  //qDebug() << " Dispatcher Events:" << DISPATCHWORKING;
  //WatcherUpdate(DISPATCHWORKING); //load it initially (will also add it to the watcher)
  // - Life Preserver Events
  WatcherUpdate(LPLOG); //load it initially (will also add it to the watcher);
  WatcherUpdate(LPERRLOG); //load it initially (will also add it to the watcher);

  filechecktimer->start();
  starting = false;
}

EventWatcher::EVENT_TYPE EventWatcher::typeFromString(QString typ){
  if(typ=="dispatcher"){ return DISPATCHER; }
  else if(typ=="life-preserver"){ return LIFEPRESERVER; }
  else{ return BADEVENT; }
}

QJsonValue EventWatcher::lastEvent(EVENT_TYPE type){
  if(HASH.contains(type)){ return HASH.value(type); }
  else{ qDebug() << "No saved event:" << type; return QJsonValue(); }
}

// === PRIVATE ===

void EventWatcher::sendLPEvent(QString system, int priority, QString msg){
  QJsonObject obj;
  obj.insert("message",msg);
  obj.insert("priority", DisplayPriority(priority) );
  obj.insert("class" , system);
  HASH.insert(LIFEPRESERVER, obj);
  //qDebug() << "New LP Event Object:" << obj;
  LogManager::log(LogManager::EV_LP, obj);
  if(!starting){ emit NewEvent(LIFEPRESERVER, obj); }
}

// === General Purpose Functions
QString EventWatcher::readFile(QString path){
  QFile file(path);
  if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ return ""; }
  QTextStream in(&file);
  QString contents = in.readAll();
  file.close();
  if(contents.endsWith("\n")){ contents.chop(1); }
  return contents;
}

double EventWatcher::displayToDoubleK(QString displayNumber){
  QStringList labels;
    labels << "K" << "M" << "G" << "T" << "P" << "E";
  QString clab = displayNumber.right(1); //last character is the size label
	displayNumber.chop(1); //remove the label from the number
  double num = displayNumber.toDouble();
  //Now format the number properly
  bool ok = false;
  clab = clab.toUpper();
  for(int i=0; i<labels.length(); i++){
    if(labels[i] == clab){ ok = true; break; }
    else{ num = num*1024; } //get ready for the next size
  }
  if(!ok){ num = -1; } //could not determine the size
  return num;
}

// === PUBLIC SLOTS ===
//Slots for the global Dispatcher to connect to
void EventWatcher::DispatchStarting(QString ID){
  QJsonObject obj;
  obj.insert("process_id", ID);
  obj.insert("state", "running");
  LogManager::log(LogManager::EV_DISPATCH, obj);
  emit NewEvent(DISPATCHER, obj);
}

void EventWatcher::DispatchFinished(QJsonObject obj){
  LogManager::log(LogManager::EV_DISPATCH, obj);
  emit NewEvent(DISPATCHER, obj);
}

// === PRIVATE SLOTS ===
void EventWatcher::WatcherUpdate(const QString &path){
  if(!starting){ qDebug() << "Event Watcher Update:" << path; }
  if(path==LPLOG){
    //Main Life Preserver Log File
    ReadLPLogFile();
  }else if(path==LPERRLOG){
    //Life Preserver Error log
    ReadLPErrFile();
  }else if(path==tmpLPRepFile){
    //Life Preserver Replication Log (currently-running replication)
    ReadLPRepFile();
  }else{
    //This file should no longer be watched (old replication file?)
    if(watcher->files().contains(path) || watcher->directories().contains(path)){
      watcher->removePath(path);
    }
  }
  CheckLogFiles(); //check for any other missing files
}

void EventWatcher::CheckLogFiles(){
  //Make sure all the proper files are being watched
  QStringList watched; watched << watcher->files() << watcher->directories();
  if(!watched.contains(LPLOG) && QFile::exists(LPLOG)){ watcher->addPath(LPLOG); }
  if(!watched.contains(LPERRLOG) && QFile::exists(LPERRLOG)){ watcher->addPath(LPERRLOG); }
  if(!watched.contains(tmpLPRepFile) && QFile::exists(tmpLPRepFile)){ watcher->addPath(tmpLPRepFile); }
  //qDebug() << "watched:" << watcher->files() << watcher->directories();
}

// == Life Preserver Event Functions
void EventWatcher::ReadLPLogFile(){
  //Open/Read any new info in the file
  QFile LPlogfile(LPLOG);
  if( !LPlogfile.open(QIODevice::ReadOnly) ){ return; } //could not open file
  QTextStream STREAM(&LPlogfile);
  if(LPlog_pos>0){ STREAM.seek(LPlog_pos); }
  QStringList info = STREAM.readAll().split("\n");
  LPlog_pos = STREAM.pos();
  LPlogfile.close();
  //Now parse the new info line-by-line
  for(int i=0; i<info.length(); i++){
    if(info[i].isEmpty()){ continue; }
    QString log = info[i];
    if(!starting){ qDebug() << "Read LP Log File Line:" << log; }
    //Divide up the log into it's sections
    QString timestamp = log.section(":",0,2).simplified();
    QString time = timestamp.section(" ",3,3).simplified();
    QString message = log.section(":",3,3).toLower().simplified();
    QString dev = log.section(":",4,4).simplified(); //dataset/snapshot/nothing

    //Now decide what to do/show because of the log message
    if(message.contains("creating snapshot", Qt::CaseInsensitive)){
      dev = message.section(" ",-1).simplified();
      QString msg = QString(tr("New snapshot of %1")).arg(dev);
      //Setup the status of the message
      HASH.insert(110,"SNAPCREATED");
      HASH.insert(111,dev); //dataset
      HASH.insert(112, msg ); //summary
      HASH.insert(113, QString(tr("Creating snapshot for %1")).arg(dev) );
      HASH.insert(114, timestamp); //full timestamp
      HASH.insert(115, time); // time only
      sendLPEvent("snapshot", 1, timestamp+": "+msg);
    }else if(message.contains("Starting replication", Qt::CaseInsensitive)){
      //Setup the file watcher for this new log file
      //qDebug() << " - Found Rep Start:" << dev << message;
      tmpLPRepFile = dev;
       LPrep_pos = 0; //reset file position
      dev = message.section(" on ",1,1,QString::SectionSkipEmpty);
      //qDebug() << " - New Dev:" << dev << "Valid Pools:" << reppools;
      //Make sure the device is currently setup for replication
      //if( !reppools.contains(dev) ){ FILE_REPLICATION.clear(); continue; }
      QString msg = QString(tr("Starting replication for %1")).arg(dev);
        //Set the appropriate status variables
        HASH.insert(120,"STARTED");
        HASH.insert(121, dev); //zpool
        HASH.insert(122, tr("Replication Starting") ); //summary
        HASH.insert(123, msg ); //Full message
        HASH.insert(124, timestamp); //full timestamp
        HASH.insert(125, time); // time only
        HASH.insert(126,tr("Replication Log")+" <"+tmpLPRepFile+">"); //log file
        sendLPEvent("replication", 1, timestamp+": "+msg);
    }else if(message.contains("finished replication task", Qt::CaseInsensitive)){
      //Done with this replication - close down the rep file watcher
        tmpLPRepFile.clear();
	LPrep_pos = 0; //reset file position
      dev = message.section(" -> ",0,0).section(" ",-1).simplified();
      //Make sure the device is currently setup for replication
      //if( reppools.contains(dev) ){
	QString msg = QString(tr("Finished replication for %1")).arg(dev);
        //Now set the status of the process
        HASH.insert(120,"FINISHED");
        HASH.insert(121,dev); //dataset
        HASH.insert(122, tr("Finished Replication") ); //summary
        HASH.insert(123, msg );
        HASH.insert(124, timestamp); //full timestamp
        HASH.insert(125, time); // time only
        HASH.insert(126, ""); //clear the log file entry
        sendLPEvent("replication", 1, timestamp+": "+msg);
    }else if( message.contains("FAILED replication", Qt::CaseInsensitive) ){
        tmpLPRepFile.clear();
	LPrep_pos = 0; //reset file position
      //Now set the status of the process
      dev = message.section(" -> ",0,0).section(" ",-1).simplified();
      //Make sure the device is currently setup for replication
	//Update the HASH
        QString file = log.section("LOGFILE:",1,1).simplified();
        QString tt = QString(tr("Replication Failed for %1")).arg(dev) +"\n"+ QString(tr("Logfile available at: %1")).arg(file);
        HASH.insert(120,"ERROR");
        HASH.insert(121,dev); //dataset
        HASH.insert(122, tr("Replication Failed") ); //summary
        HASH.insert(123, tt );
        HASH.insert(124, timestamp); //full timestamp
        HASH.insert(125, time); // time only
        HASH.insert(126, tr("Replication Error Log")+" <"+file+">" );
        sendLPEvent("replication", 7, timestamp+": "+tt);
    }

  }
}

void EventWatcher::ReadLPErrFile(){

}

void EventWatcher::ReadLPRepFile(){
  static QString stat = "";
  static QString repTotK = "";
  static QString lastSize = "";
 //Open/Read any new info in the file
  QFile LPlogfile(LPLOG);
  if( !LPlogfile.open(QIODevice::ReadOnly) ){ return; } //could not open file
  QTextStream STREAM(&LPlogfile);
  if(LPrep_pos<=0 || !STREAM.seek(LPrep_pos) ){
    //New file location
    stat.clear();
    repTotK.clear();
    lastSize.clear();
  }
  QStringList info = STREAM.readAll().split("\n");
  LPrep_pos = STREAM.pos();
  LPlogfile.close();
  //Now parse the new info line-by-line
  for(int i=0; i<info.length(); i++){
    QString line = info[i];
    if(line.contains("estimated size is")){ repTotK = line.section("size is ",1,1,QString::SectionSkipEmpty).simplified(); } //save the total size to replicate
    else if(line.startsWith("send from ")){}
    else if(line.startsWith("TIME ")){}
    else if(line.startsWith("warning: ")){} //start of an error
    else{ stat = line; } //only save the relevant/latest status line
  }
  if(!stat.isEmpty()){
    //qDebug() << "New Status Message:" << stat;
    //Divide up the status message into sections
    stat.replace("\t"," ");
    QString dataset = stat.section(" ",2,2,QString::SectionSkipEmpty).section("/",0,0).simplified();
    QString cSize = stat.section(" ",1,1,QString::SectionSkipEmpty);
    //Now Setup the tooltip
    if(cSize != lastSize){ //don't update the info if the same size info
      QString percent;
      if(!repTotK.isEmpty() && repTotK!="??"){
        //calculate the percentage
        double tot = displayToDoubleK(repTotK);
        double c = displayToDoubleK(cSize);
        if( tot!=-1 & c!=-1){
          double p = (c*100)/tot;
	  p = int(p*10)/10.0; //round to 1 decimel places
	  percent = QString::number(p) + "%";
        }
      }
      if(repTotK.isEmpty()){ repTotK = "??"; }
      //Format the info string
      QString status = cSize+"/"+repTotK;
      if(!percent.isEmpty()){ status.append(" ("+percent+")"); }
      QString txt = QString(tr("Replicating %1: %2")).arg(dataset, status);
      lastSize = cSize; //save the current size for later
      //Now set the current process status
      HASH.insert(120,"RUNNING");
      HASH.insert(121,dataset);
      HASH.insert(122,txt);
      HASH.insert(123,txt);
      emit sendLPEvent("replication", 0, txt);
    }
  }
}
<commit_msg>Make sure the event file watcher checks for new watched files on a more regular basis. This will check every time a client asks for the latest logs, and will automatically load/parse any new file which appears.<commit_after>// ===============================
//  PC-BSD REST API Server
// Available under the 3-clause BSD License
// Written by: Ken Moore <ken@pcbsd.org> 2015-2016
// =================================
#include "EventWatcher.h"

#include "globals.h"

// === PUBLIC ===
EventWatcher::EventWatcher(){
  qRegisterMetaType<EventWatcher::EVENT_TYPE>("EventWatcher::EVENT_TYPE");

  starting = true;
  LPlog_pos = LPrep_pos = LPerr_pos = 0; //no pos yet
  watcher = new QFileSystemWatcher(this);
  filechecktimer = new QTimer(this);
    filechecktimer->setSingleShot(false);
    filechecktimer->setInterval(3600000); //1-hour checks (also run on new event notices)
  connect(watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(WatcherUpdate(const QString&)) );
  connect(watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(WatcherUpdate(const QString&)) );
  connect(filechecktimer, SIGNAL(timeout()), this, SLOT( CheckLogFiles()) );
}

EventWatcher::~EventWatcher(){
}

void EventWatcher::start(){
  // - DISPATCH Events
  starting = true;
  //if(!QFile::exists(DISPATCHWORKING)){ QProcess::execute("touch "+DISPATCHWORKING); }
  //qDebug() << " Dispatcher Events:" << DISPATCHWORKING;
  //WatcherUpdate(DISPATCHWORKING); //load it initially (will also add it to the watcher)
  // - Life Preserver Events
  WatcherUpdate(LPLOG); //load it initially (will also add it to the watcher);
  WatcherUpdate(LPERRLOG); //load it initially (will also add it to the watcher);

  filechecktimer->start();
  starting = false;
}

EventWatcher::EVENT_TYPE EventWatcher::typeFromString(QString typ){
  if(typ=="dispatcher"){ return DISPATCHER; }
  else if(typ=="life-preserver"){ return LIFEPRESERVER; }
  else{ return BADEVENT; }
}

QJsonValue EventWatcher::lastEvent(EVENT_TYPE type){
  CheckLogFiles();
  if(HASH.contains(type)){ return HASH.value(type); }
  else{ qDebug() << "No saved event:" << type; return QJsonValue(); }
}

// === PRIVATE ===

void EventWatcher::sendLPEvent(QString system, int priority, QString msg){
  QJsonObject obj;
  obj.insert("message",msg);
  obj.insert("priority", DisplayPriority(priority) );
  obj.insert("class" , system);
  HASH.insert(LIFEPRESERVER, obj);
  //qDebug() << "New LP Event Object:" << obj;
  LogManager::log(LogManager::EV_LP, obj);
  if(!starting){ emit NewEvent(LIFEPRESERVER, obj); }
}

// === General Purpose Functions
QString EventWatcher::readFile(QString path){
  QFile file(path);
  if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ return ""; }
  QTextStream in(&file);
  QString contents = in.readAll();
  file.close();
  if(contents.endsWith("\n")){ contents.chop(1); }
  return contents;
}

double EventWatcher::displayToDoubleK(QString displayNumber){
  QStringList labels;
    labels << "K" << "M" << "G" << "T" << "P" << "E";
  QString clab = displayNumber.right(1); //last character is the size label
	displayNumber.chop(1); //remove the label from the number
  double num = displayNumber.toDouble();
  //Now format the number properly
  bool ok = false;
  clab = clab.toUpper();
  for(int i=0; i<labels.length(); i++){
    if(labels[i] == clab){ ok = true; break; }
    else{ num = num*1024; } //get ready for the next size
  }
  if(!ok){ num = -1; } //could not determine the size
  return num;
}

// === PUBLIC SLOTS ===
//Slots for the global Dispatcher to connect to
void EventWatcher::DispatchStarting(QString ID){
  QJsonObject obj;
  obj.insert("process_id", ID);
  obj.insert("state", "running");
  LogManager::log(LogManager::EV_DISPATCH, obj);
  emit NewEvent(DISPATCHER, obj);
}

void EventWatcher::DispatchFinished(QJsonObject obj){
  LogManager::log(LogManager::EV_DISPATCH, obj);
  emit NewEvent(DISPATCHER, obj);
}

// === PRIVATE SLOTS ===
void EventWatcher::WatcherUpdate(const QString &path){
  if(!starting){ qDebug() << "Event Watcher Update:" << path; }
  if(path==LPLOG){
    //Main Life Preserver Log File
    ReadLPLogFile();
  }else if(path==LPERRLOG){
    //Life Preserver Error log
    ReadLPErrFile();
  }else if(path==tmpLPRepFile){
    //Life Preserver Replication Log (currently-running replication)
    ReadLPRepFile();
  }else{
    //This file should no longer be watched (old replication file?)
    if(watcher->files().contains(path) || watcher->directories().contains(path)){
      watcher->removePath(path);
    }
  }
  QTimer::singleShot(10,this, SLOT(CheckLogFiles()) ); //check for any other missing files
}

void EventWatcher::CheckLogFiles(){
  //Make sure all the proper files are being watched
  QStringList watched; watched << watcher->files() << watcher->directories();
  if(!watched.contains(LPLOG) && QFile::exists(LPLOG)){ watcher->addPath(LPLOG); WatcherUpdate(LPLOG); }
  if(!watched.contains(LPERRLOG) && QFile::exists(LPERRLOG)){ watcher->addPath(LPERRLOG); WatcherUpdate(LPERRLOG); }
  if(!watched.contains(tmpLPRepFile) && QFile::exists(tmpLPRepFile)){ watcher->addPath(tmpLPRepFile);  WatcherUpdate(tmpLPRepFile); }
  //qDebug() << "watched:" << watcher->files() << watcher->directories();
}

// == Life Preserver Event Functions
void EventWatcher::ReadLPLogFile(){
  //Open/Read any new info in the file
  QFile LPlogfile(LPLOG);
  if( !LPlogfile.open(QIODevice::ReadOnly) ){ return; } //could not open file
  QTextStream STREAM(&LPlogfile);
  if(LPlog_pos>0){ STREAM.seek(LPlog_pos); }
  QStringList info = STREAM.readAll().split("\n");
  LPlog_pos = STREAM.pos();
  LPlogfile.close();
  //Now parse the new info line-by-line
  for(int i=0; i<info.length(); i++){
    if(info[i].isEmpty()){ continue; }
    QString log = info[i];
    if(!starting){ qDebug() << "Read LP Log File Line:" << log; }
    //Divide up the log into it's sections
    QString timestamp = log.section(":",0,2).simplified();
    QString time = timestamp.section(" ",3,3).simplified();
    QString message = log.section(":",3,3).toLower().simplified();
    QString dev = log.section(":",4,4).simplified(); //dataset/snapshot/nothing

    //Now decide what to do/show because of the log message
    if(message.contains("creating snapshot", Qt::CaseInsensitive)){
      dev = message.section(" ",-1).simplified();
      QString msg = QString(tr("New snapshot of %1")).arg(dev);
      //Setup the status of the message
      HASH.insert(110,"SNAPCREATED");
      HASH.insert(111,dev); //dataset
      HASH.insert(112, msg ); //summary
      HASH.insert(113, QString(tr("Creating snapshot for %1")).arg(dev) );
      HASH.insert(114, timestamp); //full timestamp
      HASH.insert(115, time); // time only
      sendLPEvent("snapshot", 1, timestamp+": "+msg);
    }else if(message.contains("Starting replication", Qt::CaseInsensitive)){
      //Setup the file watcher for this new log file
      //qDebug() << " - Found Rep Start:" << dev << message;
      tmpLPRepFile = dev;
       LPrep_pos = 0; //reset file position
      dev = message.section(" on ",1,1,QString::SectionSkipEmpty);
      //qDebug() << " - New Dev:" << dev << "Valid Pools:" << reppools;
      //Make sure the device is currently setup for replication
      //if( !reppools.contains(dev) ){ FILE_REPLICATION.clear(); continue; }
      QString msg = QString(tr("Starting replication for %1")).arg(dev);
        //Set the appropriate status variables
        HASH.insert(120,"STARTED");
        HASH.insert(121, dev); //zpool
        HASH.insert(122, tr("Replication Starting") ); //summary
        HASH.insert(123, msg ); //Full message
        HASH.insert(124, timestamp); //full timestamp
        HASH.insert(125, time); // time only
        HASH.insert(126,tr("Replication Log")+" <"+tmpLPRepFile+">"); //log file
        sendLPEvent("replication", 1, timestamp+": "+msg);
    }else if(message.contains("finished replication task", Qt::CaseInsensitive)){
      //Done with this replication - close down the rep file watcher
        tmpLPRepFile.clear();
	LPrep_pos = 0; //reset file position
      dev = message.section(" -> ",0,0).section(" ",-1).simplified();
      //Make sure the device is currently setup for replication
      //if( reppools.contains(dev) ){
	QString msg = QString(tr("Finished replication for %1")).arg(dev);
        //Now set the status of the process
        HASH.insert(120,"FINISHED");
        HASH.insert(121,dev); //dataset
        HASH.insert(122, tr("Finished Replication") ); //summary
        HASH.insert(123, msg );
        HASH.insert(124, timestamp); //full timestamp
        HASH.insert(125, time); // time only
        HASH.insert(126, ""); //clear the log file entry
        sendLPEvent("replication", 1, timestamp+": "+msg);
    }else if( message.contains("FAILED replication", Qt::CaseInsensitive) ){
        tmpLPRepFile.clear();
	LPrep_pos = 0; //reset file position
      //Now set the status of the process
      dev = message.section(" -> ",0,0).section(" ",-1).simplified();
      //Make sure the device is currently setup for replication
	//Update the HASH
        QString file = log.section("LOGFILE:",1,1).simplified();
        QString tt = QString(tr("Replication Failed for %1")).arg(dev) +"\n"+ QString(tr("Logfile available at: %1")).arg(file);
        HASH.insert(120,"ERROR");
        HASH.insert(121,dev); //dataset
        HASH.insert(122, tr("Replication Failed") ); //summary
        HASH.insert(123, tt );
        HASH.insert(124, timestamp); //full timestamp
        HASH.insert(125, time); // time only
        HASH.insert(126, tr("Replication Error Log")+" <"+file+">" );
        sendLPEvent("replication", 7, timestamp+": "+tt);
    }

  }
}

void EventWatcher::ReadLPErrFile(){

}

void EventWatcher::ReadLPRepFile(){
  static QString stat = "";
  static QString repTotK = "";
  static QString lastSize = "";
 //Open/Read any new info in the file
  QFile LPlogfile(LPLOG);
  if( !LPlogfile.open(QIODevice::ReadOnly) ){ return; } //could not open file
  QTextStream STREAM(&LPlogfile);
  if(LPrep_pos<=0 || !STREAM.seek(LPrep_pos) ){
    //New file location
    stat.clear();
    repTotK.clear();
    lastSize.clear();
  }
  QStringList info = STREAM.readAll().split("\n");
  LPrep_pos = STREAM.pos();
  LPlogfile.close();
  //Now parse the new info line-by-line
  for(int i=0; i<info.length(); i++){
    QString line = info[i];
    if(line.contains("estimated size is")){ repTotK = line.section("size is ",1,1,QString::SectionSkipEmpty).simplified(); } //save the total size to replicate
    else if(line.startsWith("send from ")){}
    else if(line.startsWith("TIME ")){}
    else if(line.startsWith("warning: ")){} //start of an error
    else{ stat = line; } //only save the relevant/latest status line
  }
  if(!stat.isEmpty()){
    //qDebug() << "New Status Message:" << stat;
    //Divide up the status message into sections
    stat.replace("\t"," ");
    QString dataset = stat.section(" ",2,2,QString::SectionSkipEmpty).section("/",0,0).simplified();
    QString cSize = stat.section(" ",1,1,QString::SectionSkipEmpty);
    //Now Setup the tooltip
    if(cSize != lastSize){ //don't update the info if the same size info
      QString percent;
      if(!repTotK.isEmpty() && repTotK!="??"){
        //calculate the percentage
        double tot = displayToDoubleK(repTotK);
        double c = displayToDoubleK(cSize);
        if( tot!=-1 & c!=-1){
          double p = (c*100)/tot;
	  p = int(p*10)/10.0; //round to 1 decimel places
	  percent = QString::number(p) + "%";
        }
      }
      if(repTotK.isEmpty()){ repTotK = "??"; }
      //Format the info string
      QString status = cSize+"/"+repTotK;
      if(!percent.isEmpty()){ status.append(" ("+percent+")"); }
      QString txt = QString(tr("Replicating %1: %2")).arg(dataset, status);
      lastSize = cSize; //save the current size for later
      //Now set the current process status
      HASH.insert(120,"RUNNING");
      HASH.insert(121,dataset);
      HASH.insert(122,txt);
      HASH.insert(123,txt);
      emit sendLPEvent("replication", 0, txt);
    }
  }
}
<|endoftext|>


<commit_before>/*
 * PoolConn.cpp
 *
 *  Created on: Apr 7, 2009
 *      Author: rasmussn
 */

#include "PoolConn.hpp"
#include <assert.h>
#include <string.h>

namespace PV {

PoolConn::PoolConn(const char * name,
                   HyPerCol * hc, HyPerLayer * pre, HyPerLayer * post, int channel)
{
   this->connId = hc->numberOfConnections();
   this->name   = strdup(name);
   this->parent = hc;

   this->numAxonalArborLists = 1;

   initialize(NULL, pre, post, channel);

   hc->addConnection(this);
}

int PoolConn::initializeWeights(const char * filename)
{
   if (filename == NULL) {
      PVParams * params = parent->parameters();
      const float strength = params->value(name, "strength");

      const int xScale = pre->clayer->xScale;
      const int yScale = pre->clayer->yScale;

      int nfPre = pre->clayer->numFeatures;

      const int arbor = 0;
      const int numPatches = numberOfWeightPatches(arbor);
      for (int i = 0; i < numPatches; i++) {
         int fPre = i % nfPre;
         poolWeights(wPatches[arbor][i], fPre, xScale, yScale, strength);
      }
   }
   else {
      fprintf(stderr, "Initializing weights from a file not implemented for RuleConn\n");
      exit(1);
   } // end if for filename

   return 0;
}

int PoolConn::poolWeights(PVPatch * wp, int fPre, int xScale, int yScale, float strength)
{
   pvdata_t * w = wp->data;

   const int nx = (int) wp->nx;
   const int ny = (int) wp->ny;
   const int nf = (int) wp->nf;

   // strides
   const int sx = (int) wp->sx;  assert(sx == nf);
   const int sy = (int) wp->sy;  assert(sy == nf*nx);
   const int sf = (int) wp->sf;  assert(sf == 1);

   assert(fPre >= 0 && fPre <= 15);
   assert(nx == 1);
   assert(ny == 1);
   assert(nf == 2);

   // initialize connections of OFF and ON cells to 0
   for (int f = 0; f < nf; f++) {
      for (int j = 0; j < ny; j++) {
         for (int i = 0; i < nx; i++) {
            w[i*sx + j*sy + f*sf] = 0;
         }
      }
   }

   // connect an OFF cells to all OFF cells (and vice versa)

   for (int f = (fPre % 2); f < nf; f += 2) {
      w[0*sx + 0*sy + f*sf] = 1;
   }

   for (int f = 0; f < nf; f++) {
      float factor = strength;
      for (int i = 0; i < nx*ny; i++) w[f + i*nf] *= factor;
   }

   return 0;
}

} // namespace PV
<commit_msg>Simplified constructors and unified initialization.<commit_after>/*
 * PoolConn.cpp
 *
 *  Created on: Apr 7, 2009
 *      Author: rasmussn
 */

#include "PoolConn.hpp"
#include <assert.h>
#include <string.h>

namespace PV {

PoolConn::PoolConn(const char * name,
                   HyPerCol * hc, HyPerLayer * pre, HyPerLayer * post, int channel)
        : HyPerConn(name, hc, pre, post, channel, PROTECTED_NUMBER)
{
   this->numAxonalArborLists = 1;
   initialize();
   hc->addConnection(this);
}

int PoolConn::initializeWeights(const char * filename)
{
   if (filename == NULL) {
      PVParams * params = parent->parameters();
      const float strength = params->value(name, "strength");

      const int xScale = pre->clayer->xScale;
      const int yScale = pre->clayer->yScale;

      int nfPre = pre->clayer->numFeatures;

      const int arbor = 0;
      const int numPatches = numberOfWeightPatches(arbor);
      for (int i = 0; i < numPatches; i++) {
         int fPre = i % nfPre;
         poolWeights(wPatches[arbor][i], fPre, xScale, yScale, strength);
      }
   }
   else {
      fprintf(stderr, "Initializing weights from a file not implemented for RuleConn\n");
      exit(1);
   } // end if for filename

   return 0;
}

int PoolConn::poolWeights(PVPatch * wp, int fPre, int xScale, int yScale, float strength)
{
   pvdata_t * w = wp->data;

   const int nx = (int) wp->nx;
   const int ny = (int) wp->ny;
   const int nf = (int) wp->nf;

   // strides
   const int sx = (int) wp->sx;  assert(sx == nf);
   const int sy = (int) wp->sy;  assert(sy == nf*nx);
   const int sf = (int) wp->sf;  assert(sf == 1);

   assert(fPre >= 0 && fPre <= 15);
   assert(nx == 1);
   assert(ny == 1);
   assert(nf == 2);

   // initialize connections of OFF and ON cells to 0
   for (int f = 0; f < nf; f++) {
      for (int j = 0; j < ny; j++) {
         for (int i = 0; i < nx; i++) {
            w[i*sx + j*sy + f*sf] = 0;
         }
      }
   }

   // connect an OFF cells to all OFF cells (and vice versa)

   for (int f = (fPre % 2); f < nf; f += 2) {
      w[0*sx + 0*sy + f*sf] = 1;
   }

   for (int f = 0; f < nf; f++) {
      float factor = strength;
      for (int i = 0; i < nx*ny; i++) w[f + i*nf] *= factor;
   }

   return 0;
}

} // namespace PV
<|endoftext|>