<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2014 pl8787
 */

#include <shogun/base/init.h>
#include <shogun/statistics/HSIC.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/mathematics/Statistics.h>
#include <gtest/gtest.h>

using namespace shogun;

void create_fixed_data_kernel_small(CFeatures*& features_p,
		CFeatures*& features_q, CKernel*& kernel_p, CKernel*& kernel_q)
{
	index_t m=2;
	index_t d=3;

	SGMatrix<float64_t> p(d,2*m);
	for (index_t i=0; i<2*d*m; ++i)
		p.matrix[i]=i;

//	p.display_matrix("p");

	SGMatrix<float64_t> q(d,2*m);
	for (index_t i=0; i<2*d*m; ++i)
		q.matrix[i]=i+10;

//	q.display_matrix("q");

	features_p=new CDenseFeatures<float64_t>(p);
	features_q=new CDenseFeatures<float64_t>(q);

	float64_t sigma_x=2;
	float64_t sigma_y=3;
	float64_t sq_sigma_x_twice=sigma_x*sigma_x*2;
	float64_t sq_sigma_y_twice=sigma_y*sigma_y*2;

	/* shoguns kernel width is different */
	kernel_p=new CGaussianKernel(10, sq_sigma_x_twice);
	kernel_q=new CGaussianKernel(10, sq_sigma_y_twice);
}

void create_fixed_data_kernel_big(CFeatures*& features_p,
		CFeatures*& features_q, CKernel*& kernel_p, CKernel*& kernel_q)
{
	index_t m=10;
	index_t d=7;

	SGMatrix<float64_t> p(d,m);
	for (index_t i=0; i<d*m; ++i)
		p.matrix[i]=(i+8)%3;

//	p.display_matrix("p");

	SGMatrix<float64_t> q(d,m);
	for (index_t i=0; i<d*m; ++i)
		q.matrix[i]=((i+10)*(i%4+2))%4;

//	q.display_matrix("q");

	features_p=new CDenseFeatures<float64_t>(p);
	features_q=new CDenseFeatures<float64_t>(q);

	float64_t sigma_x=2;
	float64_t sigma_y=3;
	float64_t sq_sigma_x_twice=sigma_x*sigma_x*2;
	float64_t sq_sigma_y_twice=sigma_y*sigma_y*2;

	/* shoguns kernel width is different */
	kernel_p=new CGaussianKernel(10, sq_sigma_x_twice);
	kernel_q=new CGaussianKernel(10, sq_sigma_y_twice);
}

/** tests the hsic statistic for a single fixed data case and ensures
 * equality with sma implementation */
TEST(HSICTEST, hsic_fixed)
{
	CFeatures* features_p=NULL;
	CFeatures* features_q=NULL;
	CKernel* kernel_p=NULL;
	CKernel* kernel_q=NULL;
	create_fixed_data_kernel_small(features_p, features_q, kernel_p, kernel_q);

	index_t m=features_p->get_num_vectors();

	CHSIC* hsic=new CHSIC(kernel_p, kernel_q, features_p, features_q);

	/* assert matlab result, note that compute statistic computes m*hsic */
	float64_t difference=hsic->compute_statistic();
	//SG_SPRINT("hsic fixed: %f\n", difference);
	EXPECT_NEAR(difference, m*0.164761446385339, 1e-15);

	SG_UNREF(hsic);
}

TEST(HSICTEST, hsic_gamma)
{
	CFeatures* features_p=NULL;
	CFeatures* features_q=NULL;
	CKernel* kernel_p=NULL;
	CKernel* kernel_q=NULL;
	create_fixed_data_kernel_big(features_p, features_q, kernel_p, kernel_q);

	CHSIC* hsic=new CHSIC(kernel_p, kernel_q, features_p, features_q);

	hsic->set_null_approximation_method(HSIC_GAMMA);
	float64_t p=hsic->compute_p_value(0.05);
	//SG_SPRINT("p-value: %f\n", p);
	EXPECT_NEAR(p, 0.172182287884256, 1e-14);

	SG_UNREF(hsic);
}

TEST(HSICTEST, hsic_sample_null)
{
	CFeatures* features_p=NULL;
	CFeatures* features_q=NULL;
	CKernel* kernel_p=NULL;
	CKernel* kernel_q=NULL;
	create_fixed_data_kernel_big(features_p, features_q, kernel_p, kernel_q);

	CHSIC* hsic=new CHSIC(kernel_p, kernel_q, features_p, features_q);

	/* do sampling null */
	hsic->set_null_approximation_method(PERMUTATION);
	float64_t p=hsic->compute_p_value(0.05);
	//SG_SPRINT("p-value: %f\n", p);
	//EXPECT_NEAR(p, 0.576000, 1e-14);

	/* ensure that sampling null of hsic leads to same results as using
	 * CKernelIndependenceTest */
	CMath::init_random(1);
	float64_t mean1=CStatistics::mean(hsic->sample_null());
	float64_t var1=CStatistics::variance(hsic->sample_null());
	//SG_SPRINT("mean1=%f, var1=%f\n", mean1, var1);

	CMath::init_random(1);
	float64_t mean2=CStatistics::mean(
			hsic->CKernelIndependenceTest::sample_null());
	float64_t var2=CStatistics::variance(hsic->sample_null());
	//SG_SPRINT("mean2=%f, var2=%f\n", mean2, var2);

	/* assert than results are the same from bot sampling null impl. */
	EXPECT_NEAR(mean1, mean2, 1e-7);
	EXPECT_NEAR(var1, var2, 1e-7);

	SG_UNREF(hsic);
}

<commit_msg>Code format modify.<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2014 pl8787
 */

#include <shogun/base/init.h>
#include <shogun/statistics/HSIC.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/mathematics/Statistics.h>
#include <gtest/gtest.h>

using namespace shogun;

void create_fixed_data_kernel_small(CFeatures*& features_p,
		CFeatures*& features_q, CKernel*& kernel_p, CKernel*& kernel_q)
{
	index_t m=2;
	index_t d=3;

	SGMatrix<float64_t> p(d,2*m);
	for (index_t i=0; i<2*d*m; ++i)
		p.matrix[i]=i;

	SGMatrix<float64_t> q(d,2*m);
	for (index_t i=0; i<2*d*m; ++i)
		q.matrix[i]=i+10;

	features_p=new CDenseFeatures<float64_t>(p);
	features_q=new CDenseFeatures<float64_t>(q);

	float64_t sigma_x=2;
	float64_t sigma_y=3;
	float64_t sq_sigma_x_twice=sigma_x*sigma_x*2;
	float64_t sq_sigma_y_twice=sigma_y*sigma_y*2;

	/* shoguns kernel width is different */
	kernel_p=new CGaussianKernel(10, sq_sigma_x_twice);
	kernel_q=new CGaussianKernel(10, sq_sigma_y_twice);
}

void create_fixed_data_kernel_big(CFeatures*& features_p,
		CFeatures*& features_q, CKernel*& kernel_p, CKernel*& kernel_q)
{
	index_t m=10;
	index_t d=7;

	SGMatrix<float64_t> p(d,m);
	for (index_t i=0; i<d*m; ++i)
		p.matrix[i]=(i+8)%3;

	SGMatrix<float64_t> q(d,m);
	for (index_t i=0; i<d*m; ++i)
		q.matrix[i]=((i+10)*(i%4+2))%4;

	features_p=new CDenseFeatures<float64_t>(p);
	features_q=new CDenseFeatures<float64_t>(q);

	float64_t sigma_x=2;
	float64_t sigma_y=3;
	float64_t sq_sigma_x_twice=sigma_x*sigma_x*2;
	float64_t sq_sigma_y_twice=sigma_y*sigma_y*2;

	/* shoguns kernel width is different */
	kernel_p=new CGaussianKernel(10, sq_sigma_x_twice);
	kernel_q=new CGaussianKernel(10, sq_sigma_y_twice);
}

/** tests the hsic statistic for a single fixed data case and ensures
 * equality with sma implementation */
TEST(HSIC, hsic_fixed)
{
	CFeatures* features_p=NULL;
	CFeatures* features_q=NULL;
	CKernel* kernel_p=NULL;
	CKernel* kernel_q=NULL;
	create_fixed_data_kernel_small(features_p, features_q, kernel_p, kernel_q);

	index_t m=features_p->get_num_vectors();

	CHSIC* hsic=new CHSIC(kernel_p, kernel_q, features_p, features_q);

	/* assert matlab result, note that compute statistic computes m*hsic */
	float64_t difference=hsic->compute_statistic();

	EXPECT_NEAR(difference, m*0.164761446385339, 1e-15);

	SG_UNREF(hsic);
}

TEST(HSIC, hsic_gamma)
{
	CFeatures* features_p=NULL;
	CFeatures* features_q=NULL;
	CKernel* kernel_p=NULL;
	CKernel* kernel_q=NULL;
	create_fixed_data_kernel_big(features_p, features_q, kernel_p, kernel_q);

	CHSIC* hsic=new CHSIC(kernel_p, kernel_q, features_p, features_q);

	hsic->set_null_approximation_method(HSIC_GAMMA);
	float64_t p=hsic->compute_p_value(0.05);

	EXPECT_NEAR(p, 0.172182287884256, 1e-14);

	SG_UNREF(hsic);
}

TEST(HSIC, hsic_sample_null)
{
	CFeatures* features_p=NULL;
	CFeatures* features_q=NULL;
	CKernel* kernel_p=NULL;
	CKernel* kernel_q=NULL;
	create_fixed_data_kernel_big(features_p, features_q, kernel_p, kernel_q);

	CHSIC* hsic=new CHSIC(kernel_p, kernel_q, features_p, features_q);

	/* do sampling null */
	hsic->set_null_approximation_method(PERMUTATION);
	hsic->compute_p_value(0.05);

	/* ensure that sampling null of hsic leads to same results as using
	 * CKernelIndependenceTest */
	CMath::init_random(1);
	float64_t mean1=CStatistics::mean(hsic->sample_null());
	float64_t var1=CStatistics::variance(hsic->sample_null());

	CMath::init_random(1);
	float64_t mean2=CStatistics::mean(
			hsic->CKernelIndependenceTest::sample_null());
	float64_t var2=CStatistics::variance(hsic->sample_null());

	/* assert than results are the same from bot sampling null impl. */
	EXPECT_NEAR(mean1, mean2, 1e-7);
	EXPECT_NEAR(var1, var2, 1e-7);

	SG_UNREF(hsic);
}

<|endoftext|>


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

#ifndef STORE_WATCHER_HPP
#define STORE_WATCHER_HPP

#include <zippylog/zippylog.hpp>
#include <zippylog/device/device.hpp>
#include <zippylog/platform.hpp>
#include <zippylog/store.hpp>

#include <zmq.hpp>

namespace zippylog {

/// Parameters to instantiate a StoreWatcher class
class ZIPPYLOG_EXPORT StoreWatcherStartParams {
public:
    /// 0MQ context to use
    ::zmq::context_t *zctx;

    /// Store filesystem path to watch
    ::std::string store_path;

    /// 0MQ socket endpoint to send change notifications to
    ::std::string endpoint;

    /// 0MQ endpoint to send log messages to
    ::std::string logging_endpoint;

    /// Semaphore to control whether device should run
    ::zippylog::platform::ConditionalWait *active;
};

/// A directory watcher for file-based stores
///
/// This class watches the specified store directory for changes.
/// When changes are detected, it executes function callbacks, which
/// must be defined in an inherited class.
///
/// The directory watcher is currently designed to execute on its own
/// thread. Just instantiate a directory watcher and invoke Run(). This
/// function will block until the active semaphore contained in the start
/// parameters goes to false.
///
/// @todo move to device namespace
class ZIPPYLOG_EXPORT StoreWatcher : public ::zippylog::device::Device {
public:
    /// Instantiate a store watcher with the given parameters
    ///
    /// Will not actually start the store watcher. To do that, execute
    /// Run().
    ///
    /// @param params Parameters to construct watcher with
    StoreWatcher(StoreWatcherStartParams params);
    virtual ~StoreWatcher();

    /// Performs work
    ///
    /// @param timeout
    ::zippylog::device::PumpResult Pump(int32 timeout = 100000);

    ///@{
    /// Device hooks
    virtual void OnRunStart();
    virtual void OnRunFinish();
    ///@}

protected:
    // Function that performs actions when something is created
    //
    // Receives the path that was added as a store path (e.g.
    // "/bucket/store/20101107T1615") and a stat record that describes
    // the filesystem entity.
    virtual void HandleAdded(::std::string path, platform::FileStat &stat) = 0;

    /// Function that performs actions when something is deleted
    ///
    /// @param path The path that was deleted
    virtual void HandleDeleted(::std::string path) = 0;

    /// Performs actions when something (probably a stream) is modified
    ///
    /// @param path The path that was modified
    /// @param stat The result of a stat() on the modified path
    virtual void HandleModified(::std::string path, platform::FileStat &stat) = 0;

    /// Sends a change notification across the socket
    ///
    /// @param e Envelope to send
    void SendChangeMessage(Envelope &e);

    /// The store we are watching
    SimpleDirectoryStore * _store;

    /// 0MQ context
    ::zmq::context_t *_ctx;

    /// 0MQ endpoint to send notification messages to
    ::std::string _endpoint;

    /// 0MQ endpoint to send logging messages to
    ::std::string logging_endpoint;

    /// Unique identifier of this device
    ::std::string id;

    /// 0MQ socket we are sending notifications on
    ::zmq::socket_t * socket;

    /// 0MQ socket we are sending logging messages on
    ::zmq::socket_t * logging_sock;

    /// The underlying watcher looking for store changes
    platform::DirectoryWatcher watcher;

private:
    // we don't provide these
    StoreWatcher(StoreWatcher const &orig);
    StoreWatcher & operator=(StoreWatcher const &orig);

};

}

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

#ifndef STORE_WATCHER_HPP
#define STORE_WATCHER_HPP

#include <zippylog/zippylog.hpp>
#include <zippylog/device/device.hpp>
#include <zippylog/platform.hpp>
#include <zippylog/store.hpp>

#include <zmq.hpp>

namespace zippylog {

/// Parameters to instantiate a StoreWatcher class
class ZIPPYLOG_EXPORT StoreWatcherStartParams {
public:
    /// 0MQ context to use
    ::zmq::context_t *zctx;

    /// Store filesystem path to watch
    ::std::string store_path;

    /// 0MQ socket endpoint to send change notifications to
    ::std::string endpoint;

    /// 0MQ endpoint to send log messages to
    ::std::string logging_endpoint;

    /// Semaphore to control whether device should run
    ::zippylog::platform::ConditionalWait *active;
};

/// A directory watcher for file-based stores
///
/// This class watches the specified store directory for changes.
/// When changes are detected, it executes function callbacks, which
/// must be defined in an inherited class.
///
/// The directory watcher is currently designed to execute on its own
/// thread. Just instantiate a directory watcher and invoke Run(). This
/// function will block until the active semaphore contained in the start
/// parameters goes to false.
///
/// @todo move to device namespace
class ZIPPYLOG_EXPORT StoreWatcher : public ::zippylog::device::Device {
public:
    /// Instantiate a store watcher with the given parameters
    ///
    /// Will not actually start the store watcher. To do that, execute
    /// Run().
    ///
    /// @param params Parameters to construct watcher with
    StoreWatcher(StoreWatcherStartParams params);
    virtual ~StoreWatcher();

    /// Performs work
    ///
    /// @param timeout
    ::zippylog::device::PumpResult Pump(int32 timeout = 100000);

    ///@{
    /// Device hooks
    virtual void OnRunStart();
    virtual void OnRunFinish();
    ///@}

protected:
    /// Function that performs actions when something is created
    ///
    /// Receives the path that was added as a store path (e.g.
    /// "/bucket/store/20101107T1615") and a stat record that describes
    /// the filesystem entity.
    ///
    /// @param path Store path that was added
    /// @param stat Filesystem stat result of new path
    virtual void HandleAdded(::std::string path, platform::FileStat &stat) = 0;

    /// Function that performs actions when something is deleted
    ///
    /// @param path The path that was deleted
    virtual void HandleDeleted(::std::string path) = 0;

    /// Performs actions when something (probably a stream) is modified
    ///
    /// @param path The path that was modified
    /// @param stat The result of a stat() on the modified path
    virtual void HandleModified(::std::string path, platform::FileStat &stat) = 0;

    /// Sends a change notification across the socket
    ///
    /// @param e Envelope to send
    void SendChangeMessage(Envelope &e);

    /// The store we are watching
    SimpleDirectoryStore * _store;

    /// 0MQ context
    ::zmq::context_t *_ctx;

    /// 0MQ endpoint to send notification messages to
    ::std::string _endpoint;

    /// 0MQ endpoint to send logging messages to
    ::std::string logging_endpoint;

    /// Unique identifier of this device
    ::std::string id;

    /// 0MQ socket we are sending notifications on
    ::zmq::socket_t * socket;

    /// 0MQ socket we are sending logging messages on
    ::zmq::socket_t * logging_sock;

    /// The underlying watcher looking for store changes
    platform::DirectoryWatcher watcher;

private:
    // we don't provide these
    StoreWatcher(StoreWatcher const &orig);
    StoreWatcher & operator=(StoreWatcher const &orig);

};

}

#endif<|endoftext|>


<commit_before>/*-------------------------------------------------------

                        Spruce
            Filesystem Wrapper Library for C++11

    Copyright (c) 2014, Joseph Davis (@josephdavisco)
    All rights reserved. See LICENSE for license info.

---------------------------------------------------------*/
#include "spruce.hh"

#include <utility>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <cstdio>
extern "C" {
    #include <sys/stat.h>
}
/*-------------------------------------------------------

    Windows includes

---------------------------------------------------------
Notes:

POSIX functions named such as mkdir are deprecated on
Windows. Functions are prefixed with an underscore (_),
mkdir() becomes _mkdir().

"In Windows NT, both the (\) and (/) are valid path
delimiters in character strings in run-time routines."

http://msdn.microsoft.com/en-us/library/

---------------------------------------------------------*/
#if defined(_WIN32) || defined(_WIN64)
#define SPRUCE_WIN
#include <direct.h>
auto SPRUCE_CHDIR  = _chdir;
auto SPRUCE_GETCWD = _getcwd;
auto SPRUCE_RMDIR  = _rmdir;
auto SPRUCE_MKDIR  = _mkdir;
#else
/*-------------------------------------------------------

    Unix/Posix includes

---------------------------------------------------------*/
extern "C" {
    #include <sys/types.h>
    #include <unistd.h>
}
auto SPRUCE_CHDIR  = chdir;
auto SPRUCE_GETCWD = getcwd;
auto SPRUCE_RMDIR  = rmdir;
auto SPRUCE_MKDIR  = []( const char* pathTomake )
{
    return mkdir( pathTomake, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
};
#endif

/*-------------------------------------------------------
    class path default constructor
---------------------------------------------------------*/
spruce::path::path()
{
    path_str = "";
}

/*-------------------------------------------------------
    class path constructor
---------------------------------------------------------*/
spruce::path::path( std::string path_ ) : path_str( path_ )
{
    normalize();
}

/*-------------------------------------------------------
    class path destructor
---------------------------------------------------------*/
spruce::path::~path()
{
}

/*-------------------------------------------------------
    path.setStr
---------------------------------------------------------*/
void spruce::path::setStr( std::string path_ )
{
    path_str = path_;
    normalize();
}

/*-------------------------------------------------------
    path.getStr
---------------------------------------------------------*/
std::string spruce::path::getStr() const
{
    return path_str;
}

/*-------------------------------------------------------
    class path.split
---------------------------------------------------------*/
std::vector<std::string> spruce::path::split()
{
    std::vector<std::string> v;
    std::istringstream ss( path_str );
    while ( !ss.eof() )
    {
        std::string temp;
        std::getline( ss, temp, '/' );
        v.push_back( temp );
    }
    return v;
}

/*-------------------------------------------------------
    class path.extension
---------------------------------------------------------*/
std::string spruce::path::extension()
{
    size_t dot( path_str.rfind( '.' ) );

    if ( dot == std::string::npos )
    {
        return "";
    }

    return path_str.substr( dot );
}

void spruce::path::append(std::string const & str)
{
  if(isFile())
    return;
  std::string str_append;

  if(str.find('/') == 0)
    str_append = str.substr(1, str.length());
  else
    str_append = str;

  if(path_str.rfind('/') == path_str.length())
    path_str.append(str_append);
  else
    path_str.append("/" + str_append);
}

void spruce::path::setExtension(std::string const & str)
{
  size_t ext = path_str.rfind(extension());
  if(ext == std::string::npos)
    ext = path_str.length();
  path_str = path_str.substr(0, ext) + str;
}

/*-------------------------------------------------------
    class path.root
---------------------------------------------------------*/
std::string spruce::path::root()
{
    size_t position( path_str.rfind( '/' ) );

    if ( position == std::string::npos )
    {
        return "";
    }

    return path_str.substr( 0, position );
}

/*-------------------------------------------------------
    class path.isFile
---------------------------------------------------------*/
bool spruce::path::isFile() const
{
    if ( !exists() ) return false;

#ifdef SPRUCE_WIN

    struct _stat attributes;
    _stat( path_str.c_str(), &attributes );

#else

    struct stat attributes;
    stat( path_str.c_str(), &attributes );

#endif

    return S_ISREG( attributes.st_mode ) != 0;
}

/*-------------------------------------------------------
    class path.isDir
---------------------------------------------------------*/
bool spruce::path::isDir() const
{
    if ( !exists() ) return false;

#ifdef SPRUCE_WIN

    struct _stat attributes;
    _stat( path_str.c_str(), &attributes );

#else

    struct stat attributes;
    stat( path_str.c_str(), &attributes );

#endif

    return S_ISDIR( attributes.st_mode ) != 0;
}

/*-------------------------------------------------------
    class path.exists
---------------------------------------------------------*/
bool spruce::path::exists() const
{
#ifdef SPRUCE_WIN
    struct _stat attributes;
    return _stat( path_str.c_str(), &attributes ) == 0;
#else
    struct stat attributes;
    return stat( path_str.c_str(), &attributes ) == 0;
#endif
}

/*-------------------------------------------------------
    class path.setAsHome
---------------------------------------------------------*/
void spruce::path::setAsHome()
{
    char* home;
#ifdef SPRUCE_WIN
    home = std::getenv( "HOMEPATH" );
#else
    home = std::getenv( "HOME" );
#endif
    if ( home != NULL )
    {
        setStr( home );
    }
}

/*-------------------------------------------------------
    class path.setAsTemp
---------------------------------------------------------*/
void spruce::path::setAsTemp()
{
    char* cwd = std::getenv( "TMPDIR" );
    if ( !cwd ) cwd = std::getenv( "TEMPDIR" );
    if ( !cwd ) cwd = std::getenv( "TMP" );
    if ( !cwd ) cwd = std::getenv( "TEMP" );
    if ( !cwd )
    {
        setStr( "/tmp" );
    }
    else
    {
        setStr( cwd );
    }
}

/*-------------------------------------------------------
    class path.setAsCurrent
---------------------------------------------------------*/
void spruce::path::setAsCurrent()
{
    setStr( SPRUCE_GETCWD( NULL, 0 ) );
}

/*-------------------------------------------------------
    class path.normalize
---------------------------------------------------------*/
void spruce::path::normalize()
{
    std::replace( path_str.begin(), path_str.end(), '\\', '/' );

    if ( path_str.back() == '/' ) path_str = path_str.substr(0, path_str.length()-1);
}

/*-------------------------------------------------------
    ostream operator<< class path
---------------------------------------------------------*/
std::ostream& operator<<( std::ostream& output, const spruce::path& p )
{
    return output << p.getStr();
}

/*-------------------------------------------------------
    file::remove
---------------------------------------------------------*/
bool spruce::file::remove( const spruce::path& p )
{
    if ( !p.isFile() || ( std::remove( ( p.getStr() ).c_str() ) != 0 ) )
        return false;
    return true;
}

/*-------------------------------------------------------
    file::rename
---------------------------------------------------------*/
bool spruce::file::rename( const spruce::path& source, const spruce::path& dest )
{
    if ( std::rename( source.getStr().c_str(), dest.getStr().c_str() ) != 0 )
        return false;
    return true;
}

/*-------------------------------------------------------
    file::copy
---------------------------------------------------------*/
bool spruce::file::copy( const spruce::path& source, const spruce::path& dest )
{
    std::ifstream in( source.getStr(), std::ios::binary );
    std::ofstream out( dest.getStr(), std::ios::binary );

    out << in.rdbuf();
    if ( out.fail() )
    {
        return false;
    }
    return true;
}

/*-------------------------------------------------------
    file::readAsString
---------------------------------------------------------*/
bool spruce::file::readAsString( const spruce::path& p,
                                 std::string& readTo )
{

    std::ifstream file( p.getStr() );
    std::stringstream ss;

    if ( file.is_open() )
    {
        while ( !file.eof() )
        {
            ss << static_cast<char>( file.get() );
        }
        file.close();
    }
    else
    {
        return false;
    }

    readTo = ss.str();

    return true;
}

/*-------------------------------------------------------
    file::writeAsString
---------------------------------------------------------*/
bool spruce::file::writeAsString( const spruce::path& p,
                                  const std::string& content, bool append )
{

    std::ofstream out;

    if ( append )
    {
        out.open( ( p.getStr() ).c_str(),
                  std::ios_base::out | std::ios_base::app );
    }

    else
    {
        out.open( ( p.getStr() ).c_str() );
    }

    if ( out.fail() )
    {
        return false;
    }

    out << content;

    out.close();

    return true;
}

/*-------------------------------------------------------
    dir::mkdir
---------------------------------------------------------*/
bool spruce::dir::mkdir( const spruce::path& p )
{
    if ( SPRUCE_MKDIR( ( p.getStr() ).c_str() ) != 0 )
    {
        return false;
    }
    return true;
}

/*-------------------------------------------------------
    dir::mkdirAll
---------------------------------------------------------*/
bool spruce::dir::mkdirAll( const spruce::path& p )
{
    size_t pos = 1;
    std::string temp( p.getStr() );

    if ( temp == "" ) return false;

    while ( ( pos = temp.find( '/', pos + 1 ) ) != std::string::npos )
    {
        if ( ( path( temp.substr( 0, pos ) ) ).exists() ) continue;
        // if making a directory on the path fails we cannot continue
        if ( SPRUCE_MKDIR( ( temp.substr( 0, pos ) ).c_str() ) != 0 )
            return false;
    }

    if ( SPRUCE_MKDIR( temp.c_str() ) != 0 ) return false;

    return true;
}

/*-------------------------------------------------------
    dir::rmdir
---------------------------------------------------------*/
bool spruce::dir::rmdir( const spruce::path& p )
{
    if ( SPRUCE_RMDIR( ( p.getStr() ).c_str() ) != 0 )
    {
        return false;
    }
    return true;
}

/*-------------------------------------------------------
    dir::rename
---------------------------------------------------------*/
bool spruce::dir::rename( const spruce::path& source, const spruce::path& dest )
{
    // cstdio accepts the name of a file or directory
    return spruce::file::rename( source, dest );
}

/*-------------------------------------------------------
    dir::chdir
---------------------------------------------------------*/
bool spruce::dir::chdir( const spruce::path& p )
{
    if ( SPRUCE_CHDIR( ( p.getStr() ).c_str() ) != 0 ) return false;
    return true;
}

<commit_msg>added alternative preprocessor macros for to S_ISREG and S_ISDIR<commit_after>/*-------------------------------------------------------

                        Spruce
            Filesystem Wrapper Library for C++11

    Copyright (c) 2014, Joseph Davis (@josephdavisco)
    All rights reserved. See LICENSE for license info.

---------------------------------------------------------*/
#include "spruce.hh"

#include <utility>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <cstdio>
extern "C" {
    #include <sys/stat.h>
}
/*-------------------------------------------------------

    Windows includes

---------------------------------------------------------
Notes:

POSIX functions named such as mkdir are deprecated on
Windows. Functions are prefixed with an underscore (_),
mkdir() becomes _mkdir().

"In Windows NT, both the (\) and (/) are valid path
delimiters in character strings in run-time routines."

http://msdn.microsoft.com/en-us/library/

---------------------------------------------------------*/
#if defined(_WIN32) || defined(_WIN64)
#define SPRUCE_WIN
#include <direct.h>
auto SPRUCE_CHDIR  = _chdir;
auto SPRUCE_GETCWD = _getcwd;
auto SPRUCE_RMDIR  = _rmdir;
auto SPRUCE_MKDIR  = _mkdir;
#else
/*-------------------------------------------------------

    Unix/Posix includes

---------------------------------------------------------*/
extern "C" {
    #include <sys/types.h>
    #include <unistd.h>
}
auto SPRUCE_CHDIR  = chdir;
auto SPRUCE_GETCWD = getcwd;
auto SPRUCE_RMDIR  = rmdir;
auto SPRUCE_MKDIR  = []( const char* pathTomake )
{
    return mkdir( pathTomake, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
};
#endif

#ifndef S_ISDIR
#define S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
#endif

#ifndef S_ISREG
#define S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)
#endif

/*-------------------------------------------------------
    class path default constructor
---------------------------------------------------------*/
spruce::path::path()
{
    path_str = "";
}

/*-------------------------------------------------------
    class path constructor
---------------------------------------------------------*/
spruce::path::path( std::string path_ ) : path_str( path_ )
{
    normalize();
}

/*-------------------------------------------------------
    class path destructor
---------------------------------------------------------*/
spruce::path::~path()
{
}

/*-------------------------------------------------------
    path.setStr
---------------------------------------------------------*/
void spruce::path::setStr( std::string path_ )
{
    path_str = path_;
    normalize();
}

/*-------------------------------------------------------
    path.getStr
---------------------------------------------------------*/
std::string spruce::path::getStr() const
{
    return path_str;
}

/*-------------------------------------------------------
    class path.split
---------------------------------------------------------*/
std::vector<std::string> spruce::path::split()
{
    std::vector<std::string> v;
    std::istringstream ss( path_str );
    while ( !ss.eof() )
    {
        std::string temp;
        std::getline( ss, temp, '/' );
        v.push_back( temp );
    }
    return v;
}

/*-------------------------------------------------------
    class path.extension
---------------------------------------------------------*/
std::string spruce::path::extension()
{
    size_t dot( path_str.rfind( '.' ) );

    if ( dot == std::string::npos )
    {
        return "";
    }

    return path_str.substr( dot );
}

void spruce::path::append(std::string const & str)
{
  if(isFile())
    return;
  std::string str_append;

  if(str.find('/') == 0)
    str_append = str.substr(1, str.length());
  else
    str_append = str;

  if(path_str.rfind('/') == path_str.length())
    path_str.append(str_append);
  else
    path_str.append("/" + str_append);
}

void spruce::path::setExtension(std::string const & str)
{
  size_t ext = path_str.rfind(extension());
  if(ext == std::string::npos)
    ext = path_str.length();
  path_str = path_str.substr(0, ext) + str;
}

/*-------------------------------------------------------
    class path.root
---------------------------------------------------------*/
std::string spruce::path::root()
{
    size_t position( path_str.rfind( '/' ) );

    if ( position == std::string::npos )
    {
        return "";
    }

    return path_str.substr( 0, position );
}

/*-------------------------------------------------------
    class path.isFile
---------------------------------------------------------*/
bool spruce::path::isFile() const
{
    if ( !exists() ) return false;

#ifdef SPRUCE_WIN

    struct _stat attributes;
    _stat( path_str.c_str(), &attributes );

#else

    struct stat attributes;
    stat( path_str.c_str(), &attributes );

#endif

    return S_ISREG( attributes.st_mode ) != 0;
}

/*-------------------------------------------------------
    class path.isDir
---------------------------------------------------------*/
bool spruce::path::isDir() const
{
    if ( !exists() ) return false;

#ifdef SPRUCE_WIN

    struct _stat attributes;
    _stat( path_str.c_str(), &attributes );

#else

    struct stat attributes;
    stat( path_str.c_str(), &attributes );

#endif

    return S_ISDIR( attributes.st_mode ) != 0;
}

/*-------------------------------------------------------
    class path.exists
---------------------------------------------------------*/
bool spruce::path::exists() const
{
#ifdef SPRUCE_WIN
    struct _stat attributes;
    return _stat( path_str.c_str(), &attributes ) == 0;
#else
    struct stat attributes;
    return stat( path_str.c_str(), &attributes ) == 0;
#endif
}

/*-------------------------------------------------------
    class path.setAsHome
---------------------------------------------------------*/
void spruce::path::setAsHome()
{
    char* home;
#ifdef SPRUCE_WIN
    home = std::getenv( "HOMEPATH" );
#else
    home = std::getenv( "HOME" );
#endif
    if ( home != NULL )
    {
        setStr( home );
    }
}

/*-------------------------------------------------------
    class path.setAsTemp
---------------------------------------------------------*/
void spruce::path::setAsTemp()
{
    char* cwd = std::getenv( "TMPDIR" );
    if ( !cwd ) cwd = std::getenv( "TEMPDIR" );
    if ( !cwd ) cwd = std::getenv( "TMP" );
    if ( !cwd ) cwd = std::getenv( "TEMP" );
    if ( !cwd )
    {
        setStr( "/tmp" );
    }
    else
    {
        setStr( cwd );
    }
}

/*-------------------------------------------------------
    class path.setAsCurrent
---------------------------------------------------------*/
void spruce::path::setAsCurrent()
{
    setStr( SPRUCE_GETCWD( NULL, 0 ) );
}

/*-------------------------------------------------------
    class path.normalize
---------------------------------------------------------*/
void spruce::path::normalize()
{
    std::replace( path_str.begin(), path_str.end(), '\\', '/' );

    if ( path_str.back() == '/' ) path_str = path_str.substr(0, path_str.length()-1);
}

/*-------------------------------------------------------
    ostream operator<< class path
---------------------------------------------------------*/
std::ostream& operator<<( std::ostream& output, const spruce::path& p )
{
    return output << p.getStr();
}

/*-------------------------------------------------------
    file::remove
---------------------------------------------------------*/
bool spruce::file::remove( const spruce::path& p )
{
    if ( !p.isFile() || ( std::remove( ( p.getStr() ).c_str() ) != 0 ) )
        return false;
    return true;
}

/*-------------------------------------------------------
    file::rename
---------------------------------------------------------*/
bool spruce::file::rename( const spruce::path& source, const spruce::path& dest )
{
    if ( std::rename( source.getStr().c_str(), dest.getStr().c_str() ) != 0 )
        return false;
    return true;
}

/*-------------------------------------------------------
    file::copy
---------------------------------------------------------*/
bool spruce::file::copy( const spruce::path& source, const spruce::path& dest )
{
    std::ifstream in( source.getStr(), std::ios::binary );
    std::ofstream out( dest.getStr(), std::ios::binary );

    out << in.rdbuf();
    if ( out.fail() )
    {
        return false;
    }
    return true;
}

/*-------------------------------------------------------
    file::readAsString
---------------------------------------------------------*/
bool spruce::file::readAsString( const spruce::path& p,
                                 std::string& readTo )
{

    std::ifstream file( p.getStr() );
    std::stringstream ss;

    if ( file.is_open() )
    {
        while ( !file.eof() )
        {
            ss << static_cast<char>( file.get() );
        }
        file.close();
    }
    else
    {
        return false;
    }

    readTo = ss.str();

    return true;
}

/*-------------------------------------------------------
    file::writeAsString
---------------------------------------------------------*/
bool spruce::file::writeAsString( const spruce::path& p,
                                  const std::string& content, bool append )
{

    std::ofstream out;

    if ( append )
    {
        out.open( ( p.getStr() ).c_str(),
                  std::ios_base::out | std::ios_base::app );
    }

    else
    {
        out.open( ( p.getStr() ).c_str() );
    }

    if ( out.fail() )
    {
        return false;
    }

    out << content;

    out.close();

    return true;
}

/*-------------------------------------------------------
    dir::mkdir
---------------------------------------------------------*/
bool spruce::dir::mkdir( const spruce::path& p )
{
    if ( SPRUCE_MKDIR( ( p.getStr() ).c_str() ) != 0 )
    {
        return false;
    }
    return true;
}

/*-------------------------------------------------------
    dir::mkdirAll
---------------------------------------------------------*/
bool spruce::dir::mkdirAll( const spruce::path& p )
{
    size_t pos = 1;
    std::string temp( p.getStr() );

    if ( temp == "" ) return false;

    while ( ( pos = temp.find( '/', pos + 1 ) ) != std::string::npos )
    {
        if ( ( path( temp.substr( 0, pos ) ) ).exists() ) continue;
        // if making a directory on the path fails we cannot continue
        if ( SPRUCE_MKDIR( ( temp.substr( 0, pos ) ).c_str() ) != 0 )
            return false;
    }

    if ( SPRUCE_MKDIR( temp.c_str() ) != 0 ) return false;

    return true;
}

/*-------------------------------------------------------
    dir::rmdir
---------------------------------------------------------*/
bool spruce::dir::rmdir( const spruce::path& p )
{
    if ( SPRUCE_RMDIR( ( p.getStr() ).c_str() ) != 0 )
    {
        return false;
    }
    return true;
}

/*-------------------------------------------------------
    dir::rename
---------------------------------------------------------*/
bool spruce::dir::rename( const spruce::path& source, const spruce::path& dest )
{
    // cstdio accepts the name of a file or directory
    return spruce::file::rename( source, dest );
}

/*-------------------------------------------------------
    dir::chdir
---------------------------------------------------------*/
bool spruce::dir::chdir( const spruce::path& p )
{
    if ( SPRUCE_CHDIR( ( p.getStr() ).c_str() ) != 0 ) return false;
    return true;
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* libwps
 * Copyright (C) 2009, 2011 Alonso Laurent (alonso@loria.fr)
 * Copyright (C) 2006, 2007 Andrew Ziem
 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
 * Copyright (C) 2004 Marc Maurer (uwog@uwog.net)
 * Copyright (C) 2003-2005 William Lachance (william.lachance@sympatico.ca)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * For further information visit http://libwps.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */

#include <iomanip>
#include <sstream>

#include <libwpd/WPXBinaryData.h>
#include <libwpd-stream/WPXStream.h>

#include "WPSDebug.h"

#if defined(DEBUG_WITH_FILES)
namespace libwps
{
bool DebugFile::open(std::string const &filename)
{
	std::string name=Debug::flattenFileName(filename);
	name += ".ascii";
	m_file.open(name.c_str());
	return m_on = m_file.is_open();
}

void DebugFile::addPos(long pos)
{
	if (!m_on) return;
	m_actOffset = pos;
}

void DebugFile::addNote(char const *note)
{
	if (!m_on || note == 0L) return;

	size_t numNotes = m_notes.size();

	if (!numNotes || m_notes[numNotes-1].m_pos != m_actOffset)
	{
		std::string empty("");
		m_notes.push_back(NotePos(m_actOffset, empty));
		numNotes++;
	}

	m_notes[numNotes-1].m_text += std::string(note);
}

void DebugFile::addDelimiter(long pos, char c)
{
	if (!m_on) return;
	std::string s;
	s+=c;
	m_notes.push_back(NotePos(pos,s,false));
}

void DebugFile::sort()
{
	if (!m_on) return;
	size_t numNotes = m_notes.size();

	if (m_actOffset >= 0 && (numNotes == 0 || m_notes[numNotes-1].m_pos != m_actOffset))
	{
		std::string empty("");
		m_notes.push_back(NotePos(m_actOffset, empty));
		numNotes++;
	}

	NotePos::Map map;
	for (size_t i = 0; i < numNotes; i++) map[m_notes[i]] = 0;

	size_t i = 0;
	for (NotePos::Map::iterator it = map.begin(); it != map.end(); i++, it++)
		m_notes[i] = it->first;
	if (i != numNotes) m_notes.resize(i);

	Vec2i::MapX sMap;
	size_t numSkip = m_skipZones.size();
	for (size_t s = 0; s < numSkip; s++) sMap[m_skipZones[s]] = 0;

	i = 0;
	for (Vec2i::MapX::iterator it = sMap.begin();
	        it != sMap.end(); i++, it++)
		m_skipZones[i] = it->first;
}

void DebugFile::write()
{
	if (!m_on || m_input.get() == 0) return;

	sort();

	long readPos = m_input->tell();

	std::vector<NotePos>::const_iterator noteIter = m_notes.begin();

	//! write the notes which does not have any position
	while(noteIter != m_notes.end() && noteIter->m_pos < 0)
	{
		if (!noteIter->m_text.empty())
			std::cerr << "DebugFile::write: skipped: " << noteIter->m_text << std::endl;
		noteIter++;
	}

	long actualPos = 0;
	int numSkip = int(m_skipZones.size()), actSkip = (numSkip == 0) ? -1 : 0;
	long actualSkipEndPos = (numSkip == 0) ? -1 : m_skipZones[0].x();

	m_input->seek(0,WPX_SEEK_SET);
	m_file << std::hex << std::right << std::setfill('0') << std::setw(6) << 0 << " ";

	do
	{
		bool printAdr = false;
		bool stop = false;
		while (actualSkipEndPos != -1 && actualPos >= actualSkipEndPos)
		{
			printAdr = true;
			actualPos = m_skipZones[size_t(actSkip)].y()+1;
			m_file << "\nSkip : " << std::hex << std::setw(6) << actualSkipEndPos << "-"
			       << actualPos-1 << "\n\n";
			m_input->seek(actualPos, WPX_SEEK_SET);
			stop = m_input->atEOS();
			actSkip++;
			actualSkipEndPos = (actSkip < numSkip) ? m_skipZones[size_t(actSkip)].x() : -1;
		}
		if (stop) break;
		while(noteIter != m_notes.end() && noteIter->m_pos < actualPos)
		{
			if (!noteIter->m_text.empty())
				m_file << "Skipped: " << noteIter->m_text << std::endl;
			noteIter++;
		}
		bool printNote = noteIter != m_notes.end() && noteIter->m_pos == actualPos;
		if (printAdr || (printNote && noteIter->m_breaking))
			m_file << "\n" << std::setw(6) << actualPos << " ";
		while(noteIter != m_notes.end() && noteIter->m_pos == actualPos)
		{
			if (noteIter->m_text.empty())
			{
				noteIter++;
				continue;
			}
			if (noteIter->m_breaking)
				m_file << "[" << noteIter->m_text << "]";
			else
				m_file << noteIter->m_text;
			noteIter++;
		}

		long ch = libwps::readU8(m_input);
		m_file << std::setw(2) << ch;
		actualPos++;

	}
	while (!m_input->atEOS());

	m_file << "\n\n";

	m_input->seek(readPos,WPX_SEEK_SET);

	m_actOffset=-1;
	m_notes.resize(0);
}

////////////////////////////////////////////////////////////
//
// save WPXBinaryData in a file
//
////////////////////////////////////////////////////////////
namespace Debug
{
bool dumpFile(WPXBinaryData &data, char const *fileName)
{
	if (!fileName) return false;
	std::string fName = Debug::flattenFileName(fileName);
	FILE *file = fopen(fName.c_str(), "wb");
	if (!file) return false;

	WPXInputStream *tmpStream =
	    const_cast<WPXInputStream *>(data.getDataStream());
	while (!tmpStream->atEOS())
		fprintf(file, "%c", libwps::readU8(tmpStream));
	fclose(file);
	return true;
}

std::string flattenFileName(std::string const &name)
{
	std::string res;
	for (size_t i = 0; i < name.length(); i++)
	{
		char c = name[i];
		switch(c)
		{
		case '\0':
		case '/':
		case '\\':
		case ':': // potential file system separator
		case ' ':
		case '\t':
		case '\n': // potential text separator
			res += '_';
			break;
		default:
			if (c <= 28) res += '#'; // potential trouble potential char
			else res += c;
		}
	}
	return res;
}
}

}
#endif
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
<commit_msg>Add safeguards to prevent problem if we can not read a picture in debug mode...<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* libwps
 * Copyright (C) 2009, 2011 Alonso Laurent (alonso@loria.fr)
 * Copyright (C) 2006, 2007 Andrew Ziem
 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
 * Copyright (C) 2004 Marc Maurer (uwog@uwog.net)
 * Copyright (C) 2003-2005 William Lachance (william.lachance@sympatico.ca)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * For further information visit http://libwps.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */

#include <iomanip>
#include <sstream>

#include <libwpd/WPXBinaryData.h>
#include <libwpd-stream/WPXStream.h>

#include "WPSDebug.h"

#if defined(DEBUG_WITH_FILES)
namespace libwps
{
bool DebugFile::open(std::string const &filename)
{
	std::string name=Debug::flattenFileName(filename);
	name += ".ascii";
	m_file.open(name.c_str());
	return m_on = m_file.is_open();
}

void DebugFile::addPos(long pos)
{
	if (!m_on) return;
	m_actOffset = pos;
}

void DebugFile::addNote(char const *note)
{
	if (!m_on || note == 0L) return;

	size_t numNotes = m_notes.size();

	if (!numNotes || m_notes[numNotes-1].m_pos != m_actOffset)
	{
		std::string empty("");
		m_notes.push_back(NotePos(m_actOffset, empty));
		numNotes++;
	}

	m_notes[numNotes-1].m_text += std::string(note);
}

void DebugFile::addDelimiter(long pos, char c)
{
	if (!m_on) return;
	std::string s;
	s+=c;
	m_notes.push_back(NotePos(pos,s,false));
}

void DebugFile::sort()
{
	if (!m_on) return;
	size_t numNotes = m_notes.size();

	if (m_actOffset >= 0 && (numNotes == 0 || m_notes[numNotes-1].m_pos != m_actOffset))
	{
		std::string empty("");
		m_notes.push_back(NotePos(m_actOffset, empty));
		numNotes++;
	}

	NotePos::Map map;
	for (size_t i = 0; i < numNotes; i++) map[m_notes[i]] = 0;

	size_t i = 0;
	for (NotePos::Map::iterator it = map.begin(); it != map.end(); i++, it++)
		m_notes[i] = it->first;
	if (i != numNotes) m_notes.resize(i);

	Vec2i::MapX sMap;
	size_t numSkip = m_skipZones.size();
	for (size_t s = 0; s < numSkip; s++) sMap[m_skipZones[s]] = 0;

	i = 0;
	for (Vec2i::MapX::iterator it = sMap.begin();
	        it != sMap.end(); i++, it++)
		m_skipZones[i] = it->first;
}

void DebugFile::write()
{
	if (!m_on || m_input.get() == 0) return;

	sort();

	long readPos = m_input->tell();

	std::vector<NotePos>::const_iterator noteIter = m_notes.begin();

	//! write the notes which does not have any position
	while(noteIter != m_notes.end() && noteIter->m_pos < 0)
	{
		if (!noteIter->m_text.empty())
			std::cerr << "DebugFile::write: skipped: " << noteIter->m_text << std::endl;
		noteIter++;
	}

	long actualPos = 0;
	int numSkip = int(m_skipZones.size()), actSkip = (numSkip == 0) ? -1 : 0;
	long actualSkipEndPos = (numSkip == 0) ? -1 : m_skipZones[0].x();

	m_input->seek(0,WPX_SEEK_SET);
	m_file << std::hex << std::right << std::setfill('0') << std::setw(6) << 0 << " ";

	do
	{
		bool printAdr = false;
		bool stop = false;
		while (actualSkipEndPos != -1 && actualPos >= actualSkipEndPos)
		{
			printAdr = true;
			actualPos = m_skipZones[size_t(actSkip)].y()+1;
			m_file << "\nSkip : " << std::hex << std::setw(6) << actualSkipEndPos << "-"
			       << actualPos-1 << "\n\n";
			m_input->seek(actualPos, WPX_SEEK_SET);
			stop = m_input->atEOS();
			actSkip++;
			actualSkipEndPos = (actSkip < numSkip) ? m_skipZones[size_t(actSkip)].x() : -1;
		}
		if (stop) break;
		while(noteIter != m_notes.end() && noteIter->m_pos < actualPos)
		{
			if (!noteIter->m_text.empty())
				m_file << "Skipped: " << noteIter->m_text << std::endl;
			noteIter++;
		}
		bool printNote = noteIter != m_notes.end() && noteIter->m_pos == actualPos;
		if (printAdr || (printNote && noteIter->m_breaking))
			m_file << "\n" << std::setw(6) << actualPos << " ";
		while(noteIter != m_notes.end() && noteIter->m_pos == actualPos)
		{
			if (noteIter->m_text.empty())
			{
				noteIter++;
				continue;
			}
			if (noteIter->m_breaking)
				m_file << "[" << noteIter->m_text << "]";
			else
				m_file << noteIter->m_text;
			noteIter++;
		}

		long ch = libwps::readU8(m_input);
		m_file << std::setw(2) << ch;
		actualPos++;

	}
	while (!m_input->atEOS());

	m_file << "\n\n";

	m_input->seek(readPos,WPX_SEEK_SET);

	m_actOffset=-1;
	m_notes.resize(0);
}

////////////////////////////////////////////////////////////
//
// save WPXBinaryData in a file
//
////////////////////////////////////////////////////////////
namespace Debug
{
bool dumpFile(WPXBinaryData &data, char const *fileName)
{
	if (!fileName) return false;
	std::string fName = Debug::flattenFileName(fileName);
	FILE *file = fopen(fName.c_str(), "wb");
	if (!file) return false;

	WPXInputStream *tmpStream =
	    const_cast<WPXInputStream *>(data.getDataStream());
	if (!tmpStream) return false;
	while (!tmpStream->atEOS())
		fprintf(file, "%c", libwps::readU8(tmpStream));
	fclose(file);
	return true;
}

std::string flattenFileName(std::string const &name)
{
	std::string res;
	for (size_t i = 0; i < name.length(); i++)
	{
		char c = name[i];
		switch(c)
		{
		case '\0':
		case '/':
		case '\\':
		case ':': // potential file system separator
		case ' ':
		case '\t':
		case '\n': // potential text separator
			res += '_';
			break;
		default:
			if (c <= 28) res += '#'; // potential trouble potential char
			else res += c;
		}
	}
	return res;
}
}

}
#endif
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
<|endoftext|>


<commit_before>#include "types.hh"

#include <cstring>
#include <cstddef>
#include <cstdlib>

#include <unistd.h>
#include <signal.h>

namespace nix {

static void sigsegvHandler(int signo, siginfo_t * info, void * ctx)
{
    /* Detect stack overflows by comparing the faulting address with
       the stack pointer.  Unfortunately, getting the stack pointer is
       not portable. */
    bool haveSP = true;
    char * sp = 0;
#if defined(__x86_64__) && defined(REG_RSP)
    sp = (char *) ((ucontext_t *) ctx)->uc_mcontext.gregs[REG_RSP];
#elif defined(REG_ESP)
    sp = (char *) ((ucontext_t *) ctx)->uc_mcontext.gregs[REG_ESP];
#else
    haveSP = false;
#endif

    if (haveSP) {
        ptrdiff_t diff = (char *) info->si_addr - sp;
        if (diff < 0) diff = -diff;
        if (diff < 4096) {
            char msg[] = "error: stack overflow (possible infinite recursion)\n";
            [[gnu::unused]] auto res = write(2, msg, strlen(msg));
            _exit(1); // maybe abort instead?
        }
    }

    /* Restore default behaviour (i.e. segfault and dump core). */
    struct sigaction act;
    sigfillset(&act.sa_mask);
    act.sa_handler = SIG_DFL;
    act.sa_flags = 0;
    if (sigaction(SIGSEGV, &act, 0)) abort();
}

void detectStackOverflow()
{
#if defined(SA_SIGINFO) && defined (SA_ONSTACK)
    /* Install a SIGSEGV handler to detect stack overflows.  This
       requires an alternative stack, otherwise the signal cannot be
       delivered when we're out of stack space. */
    stack_t stack;
    stack.ss_size = 4096 * 4 + MINSIGSTKSZ;
    static auto stackBuf = std::make_unique<std::vector<char>>(stack.ss_size);
    stack.ss_sp = stackBuf->data();
    if (!stack.ss_sp) throw Error("cannot allocate alternative stack");
    stack.ss_flags = 0;
    if (sigaltstack(&stack, 0) == -1) throw SysError("cannot set alternative stack");

    struct sigaction act;
    sigfillset(&act.sa_mask);
    act.sa_sigaction = sigsegvHandler;
    act.sa_flags = SA_SIGINFO | SA_ONSTACK;
    if (sigaction(SIGSEGV, &act, 0))
        throw SysError("resetting SIGCHLD");
#endif
}

}
<commit_msg>Fix typo<commit_after>#include "types.hh"

#include <cstring>
#include <cstddef>
#include <cstdlib>

#include <unistd.h>
#include <signal.h>

namespace nix {

static void sigsegvHandler(int signo, siginfo_t * info, void * ctx)
{
    /* Detect stack overflows by comparing the faulting address with
       the stack pointer.  Unfortunately, getting the stack pointer is
       not portable. */
    bool haveSP = true;
    char * sp = 0;
#if defined(__x86_64__) && defined(REG_RSP)
    sp = (char *) ((ucontext_t *) ctx)->uc_mcontext.gregs[REG_RSP];
#elif defined(REG_ESP)
    sp = (char *) ((ucontext_t *) ctx)->uc_mcontext.gregs[REG_ESP];
#else
    haveSP = false;
#endif

    if (haveSP) {
        ptrdiff_t diff = (char *) info->si_addr - sp;
        if (diff < 0) diff = -diff;
        if (diff < 4096) {
            char msg[] = "error: stack overflow (possible infinite recursion)\n";
            [[gnu::unused]] auto res = write(2, msg, strlen(msg));
            _exit(1); // maybe abort instead?
        }
    }

    /* Restore default behaviour (i.e. segfault and dump core). */
    struct sigaction act;
    sigfillset(&act.sa_mask);
    act.sa_handler = SIG_DFL;
    act.sa_flags = 0;
    if (sigaction(SIGSEGV, &act, 0)) abort();
}

void detectStackOverflow()
{
#if defined(SA_SIGINFO) && defined (SA_ONSTACK)
    /* Install a SIGSEGV handler to detect stack overflows.  This
       requires an alternative stack, otherwise the signal cannot be
       delivered when we're out of stack space. */
    stack_t stack;
    stack.ss_size = 4096 * 4 + MINSIGSTKSZ;
    static auto stackBuf = std::make_unique<std::vector<char>>(stack.ss_size);
    stack.ss_sp = stackBuf->data();
    if (!stack.ss_sp) throw Error("cannot allocate alternative stack");
    stack.ss_flags = 0;
    if (sigaltstack(&stack, 0) == -1) throw SysError("cannot set alternative stack");

    struct sigaction act;
    sigfillset(&act.sa_mask);
    act.sa_sigaction = sigsegvHandler;
    act.sa_flags = SA_SIGINFO | SA_ONSTACK;
    if (sigaction(SIGSEGV, &act, 0))
        throw SysError("resetting SIGSEGV");
#endif
}

}
<|endoftext|>


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

// clfft.repo.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "repo.h"

using std::map;
using std::string;

//	Static initialization of the repo lock variable
lockRAII FFTRepo::lockRepo( _T( "FFTRepo" ) );

//	Static initialization of the plan count variable
size_t FFTRepo::planCount	= 1;

//	Handle/Address of the dynamic module that contains the timer, that we discover and load during runtime
void* FFTRepo::timerHandle	= NULL;
GpuStatTimer* FFTRepo::pStatTimer	= NULL;

clfftStatus FFTRepo::releaseResources( )
{
	scopedLock sLock( lockRepo, _T( "releaseResources" ) );

	//	Release all handles to Kernels
	//
	for(Kernel_iterator iKern = mapKernels.begin( ); iKern != mapKernels.end( ); ++iKern )
	{
		cl_kernel k = iKern->second.kernel_fwd;
		iKern->second.kernel_fwd = NULL;
		if (NULL != k)
			clReleaseKernel( k );
		k = iKern->second.kernel_back;
		iKern->second.kernel_back = NULL;
		if (NULL != k)
			clReleaseKernel( k );

		if (NULL != iKern->second.kernel_fwd_lock)
		{
			delete iKern->second.kernel_fwd_lock;
			iKern->second.kernel_fwd_lock = NULL;
		}

		if (NULL != iKern->second.kernel_back_lock)
		{
			delete iKern->second.kernel_back_lock;
			iKern->second.kernel_back_lock = NULL;
		}
	}
	mapKernels.clear( );

	//	Release all handles to programs
	//
	for (fftRepo_iterator iProg = mapFFTs.begin( ); iProg != mapFFTs.end( ); ++iProg )
	{
        if (iProg->first.data != NULL)
        {
            const_cast<FFTRepoKey*>(&iProg->first)->deleteData();
        }

		cl_program p = iProg->second.clProgram;
		iProg->second.clProgram = NULL;
		if (NULL != p)
			clReleaseProgram (p);
	}

	//	Free all memory allocated in the repoPlans; represents cached plans that were not destroyed by the client
	//
	for( repoPlansType::iterator iter = repoPlans.begin( ); iter != repoPlans.end( ); ++iter )
	{
		FFTPlan* plan	= iter->second.first;
		lockRAII* lock	= iter->second.second;
		if( plan != NULL )
		{
			delete plan;
		}
		if( lock != NULL )
		{
			delete lock;
		}
	}

	//	Reset the plan count to zero because we are guaranteed to have destroyed all plans
	planCount	= 1;

	//	Release all strings
	mapFFTs.clear( );

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::setProgramCode( const clfftGenerators gen, const FFTKernelSignatureHeader * data, const std::string& kernel, const cl_device_id &device, const cl_context& planContext )
{
	scopedLock sLock( lockRepo, _T( "setProgramCode" ) );

	FFTRepoKey key(gen, data, planContext, device);

    key.privatizeData();

	// Prefix copyright statement at the top of generated kernels
	std::stringstream ss;
	ss <<
		"/* ************************************************************************\n"
		" * Copyright 2013 Advanced Micro Devices, Inc.\n"
		" *\n"
		" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
		" * you may not use this file except in compliance with the License.\n"
		" * You may obtain a copy of the License at\n"
		" *\n"
		" * http://www.apache.org/licenses/LICENSE-2.0\n"
		" *\n"
		" * Unless required by applicable law or agreed to in writing, software\n"
		" * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
		" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
		" * See the License for the specific language governing permissions and\n"
		" * limitations under the License.\n"
		" * ************************************************************************/"
	<< std::endl << std::endl;

	std::string prefixCopyright = ss.str();

	mapFFTs[ key ].ProgramString = prefixCopyright + kernel;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::getProgramCode( const clfftGenerators gen, const FFTKernelSignatureHeader * data, std::string& kernel, const cl_device_id &device, const cl_context& planContext )
{
	scopedLock sLock( lockRepo, _T( "getProgramCode" ) );

	FFTRepoKey key(gen, data, planContext, device);

	fftRepo_iterator pos = mapFFTs.find( key);
	if( pos == mapFFTs.end( ) )
		return	CLFFT_FILE_NOT_FOUND;

  kernel = pos->second.ProgramString;
	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::setProgramEntryPoints( const clfftGenerators gen, const FFTKernelSignatureHeader * data,
	const char * kernel_fwd, const char * kernel_back, const cl_device_id &device, const cl_context& planContext  )
{
	scopedLock sLock( lockRepo, _T( "setProgramEntryPoints" ) );

	FFTRepoKey key(gen, data, planContext, device);

	fftRepoValue& fft  = mapFFTs[ key ];
	fft.EntryPoint_fwd  = kernel_fwd;
	fft.EntryPoint_back = kernel_back;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::getProgramEntryPoint( const clfftGenerators gen, const FFTKernelSignatureHeader * data,
			clfftDirection dir, std::string& kernel, const cl_device_id &device, const cl_context& planContext )
{
	scopedLock sLock( lockRepo, _T( "getProgramEntryPoint" ) );

	FFTRepoKey key(gen, data, planContext, device);

	fftRepo_iterator pos = mapFFTs.find( key );
	if( pos == mapFFTs.end( ) )
		return	CLFFT_FILE_NOT_FOUND;

	switch (dir) {
	case CLFFT_FORWARD:
		kernel = pos->second.EntryPoint_fwd;
		break;
	case CLFFT_BACKWARD:
		kernel = pos->second.EntryPoint_back;
		break;
	default:
		assert (false);
		return CLFFT_INVALID_ARG_VALUE;
	}

	if (0 == kernel.size())
		return	CLFFT_FILE_NOT_FOUND;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::setclProgram( const clfftGenerators gen, const FFTKernelSignatureHeader * data, const cl_program& prog, const cl_device_id &device, const cl_context& planContext )
{
	scopedLock sLock( lockRepo, _T( "setclProgram" ) );

 	FFTRepoKey key(gen, data, planContext, device);

	fftRepo_iterator pos = mapFFTs.find( key );
	if( pos == mapFFTs.end( ) )
	{
		key.privatizeData(); // the key owns the data
		mapFFTs[ key ].clProgram = prog;
	}
	else {
		cl_program p = pos->second.clProgram;
		assert (NULL == p);
		if (NULL != p)
			clReleaseProgram (p);
		pos->second.clProgram = prog;
	}

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::getclProgram( const clfftGenerators gen, const FFTKernelSignatureHeader * data, cl_program& prog, const cl_device_id &device, const cl_context& planContext  )
{
	scopedLock sLock( lockRepo, _T( "getclProgram" ) );

	FFTRepoKey key(gen, data, planContext, device);

	fftRepo_iterator pos = mapFFTs.find( key );
	if( pos == mapFFTs.end( ) )
		return	CLFFT_INVALID_PROGRAM;
	prog = pos->second.clProgram;
	if (NULL == prog)
		return	CLFFT_INVALID_PROGRAM;

  cl_context progContext;
  clGetProgramInfo(prog, CL_PROGRAM_CONTEXT, sizeof(cl_context), &progContext, NULL);
  if (planContext!=progContext)
    return	CLFFT_INVALID_PROGRAM;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::setclKernel( cl_program prog, clfftDirection dir, const cl_kernel& kernel )
{
	scopedLock sLock( lockRepo, _T( "setclKernel" ) );

	fftKernels & Kernels = mapKernels[ prog ];

	cl_kernel * pk;
	lockRAII ** kernelLock;

	switch (dir) {
	case CLFFT_FORWARD:
		pk = & Kernels.kernel_fwd;
		kernelLock = & Kernels.kernel_fwd_lock;
		break;
	case CLFFT_BACKWARD:
		pk = & Kernels.kernel_back;
		kernelLock = & Kernels.kernel_back_lock;
		break;
	default:
		assert (false);
		return CLFFT_INVALID_ARG_VALUE;
	}

	assert (NULL == *pk);
	if (NULL != *pk)
		clReleaseKernel( *pk );

	*pk = kernel;

	if (NULL != *kernelLock)
		 delete kernelLock;

	*kernelLock = new lockRAII;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::getclKernel( cl_program prog, clfftDirection dir, cl_kernel& kernel, lockRAII*& kernelLock)
{
	scopedLock sLock( lockRepo, _T( "getclKernel" ) );

	Kernel_iterator pos = mapKernels.find( prog );
	if (pos == mapKernels.end( ) )
		return	CLFFT_INVALID_KERNEL;

	switch (dir) {
	case CLFFT_FORWARD:
		kernel = pos->second.kernel_fwd;
		kernelLock = pos->second.kernel_fwd_lock;
		break;
	case CLFFT_BACKWARD:
		kernel = pos->second.kernel_back;
		kernelLock = pos->second.kernel_back_lock;
		break;
	default:
		assert (false);
		return CLFFT_INVALID_ARG_VALUE;
	}

	if (NULL == kernel)
		return	CLFFT_INVALID_KERNEL;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::createPlan( clfftPlanHandle* plHandle, FFTPlan*& fftPlan )
{
	scopedLock sLock( lockRepo, _T( "insertPlan" ) );

	//	We keep track of this memory in our own collection class, to make sure it's freed in releaseResources
	//	The lifetime of a plan is tracked by the client and is freed when the client calls ::clfftDestroyPlan()
	fftPlan	= new FFTPlan;

	//	We allocate a new lock here, and expect it to be freed in ::clfftDestroyPlan();
	//	The lifetime of the lock is the same as the lifetime of the plan
	lockRAII* lockPlan	= new lockRAII;

	//	Add and remember the fftPlan in our map
	repoPlans[ planCount ] = std::make_pair( fftPlan, lockPlan );

	//	Assign the user handle the plan count (unique identifier), and bump the count for the next plan
	*plHandle	= planCount++;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::getPlan( clfftPlanHandle plHandle, FFTPlan*& fftPlan, lockRAII*& planLock )
{
	scopedLock sLock( lockRepo, _T( "getPlan" ) );

	//	First, check if we have already created a plan with this exact same FFTPlan
	repoPlansType::iterator iter	= repoPlans.find( plHandle );
	if( iter == repoPlans.end( ) )
		return	CLFFT_INVALID_PLAN;

	//	If plan is valid, return fill out the output pointers
	fftPlan		= iter->second.first;
	planLock	= iter->second.second;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::deletePlan( clfftPlanHandle* plHandle )
{
	scopedLock sLock( lockRepo, _T( "deletePlan" ) );

	//	First, check if we have already created a plan with this exact same FFTPlan
	repoPlansType::iterator iter	= repoPlans.find( *plHandle );
	if( iter == repoPlans.end( ) )
		return	CLFFT_INVALID_PLAN;

	//	We lock the plan object while we are in the process of deleting it
	{
		scopedLock sLock( *iter->second.second, _T( "clfftDestroyPlan" ) );
		clReleaseContext( iter->second.first->context );

		//	Delete the FFTPlan
		delete iter->second.first;
	}

		//	Delete the lockRAII
	delete iter->second.second;

	//	Remove entry from our map object
	repoPlans.erase( iter );

	//	Clear the client's handle to signify that the plan is gone
	*plHandle = 0;

	return	CLFFT_SUCCESS;
}
<commit_msg>fixing a memory leak issue in key creation, fixes #172<commit_after>/* ************************************************************************
 * Copyright 2013 Advanced Micro Devices, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ************************************************************************/

// clfft.repo.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "repo.h"

using std::map;
using std::string;

//	Static initialization of the repo lock variable
lockRAII FFTRepo::lockRepo( _T( "FFTRepo" ) );

//	Static initialization of the plan count variable
size_t FFTRepo::planCount	= 1;

//	Handle/Address of the dynamic module that contains the timer, that we discover and load during runtime
void* FFTRepo::timerHandle	= NULL;
GpuStatTimer* FFTRepo::pStatTimer	= NULL;

clfftStatus FFTRepo::releaseResources( )
{
	scopedLock sLock( lockRepo, _T( "releaseResources" ) );

	//	Release all handles to Kernels
	//
	for(Kernel_iterator iKern = mapKernels.begin( ); iKern != mapKernels.end( ); ++iKern )
	{
		cl_kernel k = iKern->second.kernel_fwd;
		iKern->second.kernel_fwd = NULL;
		if (NULL != k)
			clReleaseKernel( k );
		k = iKern->second.kernel_back;
		iKern->second.kernel_back = NULL;
		if (NULL != k)
			clReleaseKernel( k );

		if (NULL != iKern->second.kernel_fwd_lock)
		{
			delete iKern->second.kernel_fwd_lock;
			iKern->second.kernel_fwd_lock = NULL;
		}

		if (NULL != iKern->second.kernel_back_lock)
		{
			delete iKern->second.kernel_back_lock;
			iKern->second.kernel_back_lock = NULL;
		}
	}
	mapKernels.clear( );

	//	Release all handles to programs
	//
	for (fftRepo_iterator iProg = mapFFTs.begin( ); iProg != mapFFTs.end( ); ++iProg )
	{
        if (iProg->first.data != NULL)
        {
            const_cast<FFTRepoKey*>(&iProg->first)->deleteData();
        }

		cl_program p = iProg->second.clProgram;
		iProg->second.clProgram = NULL;
		if (NULL != p)
			clReleaseProgram (p);
	}

	//	Free all memory allocated in the repoPlans; represents cached plans that were not destroyed by the client
	//
	for( repoPlansType::iterator iter = repoPlans.begin( ); iter != repoPlans.end( ); ++iter )
	{
		FFTPlan* plan	= iter->second.first;
		lockRAII* lock	= iter->second.second;
		if( plan != NULL )
		{
			delete plan;
		}
		if( lock != NULL )
		{
			delete lock;
		}
	}

	//	Reset the plan count to zero because we are guaranteed to have destroyed all plans
	planCount	= 1;

	//	Release all strings
	mapFFTs.clear( );

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::setProgramCode( const clfftGenerators gen, const FFTKernelSignatureHeader * data, const std::string& kernel, const cl_device_id &device, const cl_context& planContext )
{
	scopedLock sLock( lockRepo, _T( "setProgramCode" ) );

	FFTRepoKey key(gen, data, planContext, device);

    key.privatizeData();

	// Prefix copyright statement at the top of generated kernels
	std::stringstream ss;
	ss <<
		"/* ************************************************************************\n"
		" * Copyright 2013 Advanced Micro Devices, Inc.\n"
		" *\n"
		" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
		" * you may not use this file except in compliance with the License.\n"
		" * You may obtain a copy of the License at\n"
		" *\n"
		" * http://www.apache.org/licenses/LICENSE-2.0\n"
		" *\n"
		" * Unless required by applicable law or agreed to in writing, software\n"
		" * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
		" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
		" * See the License for the specific language governing permissions and\n"
		" * limitations under the License.\n"
		" * ************************************************************************/"
	<< std::endl << std::endl;

	std::string prefixCopyright = ss.str();

	fftRepoType::iterator it = mapFFTs.find(key);
	if (it == mapFFTs.end())
		mapFFTs[key].ProgramString = prefixCopyright + kernel;
	else
		key.deleteData();

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::getProgramCode( const clfftGenerators gen, const FFTKernelSignatureHeader * data, std::string& kernel, const cl_device_id &device, const cl_context& planContext )
{
	scopedLock sLock( lockRepo, _T( "getProgramCode" ) );

	FFTRepoKey key(gen, data, planContext, device);

	fftRepo_iterator pos = mapFFTs.find( key);
	if( pos == mapFFTs.end( ) )
		return	CLFFT_FILE_NOT_FOUND;

  kernel = pos->second.ProgramString;
	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::setProgramEntryPoints( const clfftGenerators gen, const FFTKernelSignatureHeader * data,
	const char * kernel_fwd, const char * kernel_back, const cl_device_id &device, const cl_context& planContext  )
{
	scopedLock sLock( lockRepo, _T( "setProgramEntryPoints" ) );

	FFTRepoKey key(gen, data, planContext, device);

	fftRepoValue& fft  = mapFFTs[ key ];
	fft.EntryPoint_fwd  = kernel_fwd;
	fft.EntryPoint_back = kernel_back;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::getProgramEntryPoint( const clfftGenerators gen, const FFTKernelSignatureHeader * data,
			clfftDirection dir, std::string& kernel, const cl_device_id &device, const cl_context& planContext )
{
	scopedLock sLock( lockRepo, _T( "getProgramEntryPoint" ) );

	FFTRepoKey key(gen, data, planContext, device);

	fftRepo_iterator pos = mapFFTs.find( key );
	if( pos == mapFFTs.end( ) )
		return	CLFFT_FILE_NOT_FOUND;

	switch (dir) {
	case CLFFT_FORWARD:
		kernel = pos->second.EntryPoint_fwd;
		break;
	case CLFFT_BACKWARD:
		kernel = pos->second.EntryPoint_back;
		break;
	default:
		assert (false);
		return CLFFT_INVALID_ARG_VALUE;
	}

	if (0 == kernel.size())
		return	CLFFT_FILE_NOT_FOUND;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::setclProgram( const clfftGenerators gen, const FFTKernelSignatureHeader * data, const cl_program& prog, const cl_device_id &device, const cl_context& planContext )
{
	scopedLock sLock( lockRepo, _T( "setclProgram" ) );

 	FFTRepoKey key(gen, data, planContext, device);

	fftRepo_iterator pos = mapFFTs.find( key );
	if( pos == mapFFTs.end( ) )
	{
		key.privatizeData(); // the key owns the data
		mapFFTs[ key ].clProgram = prog;
	}
	else {
		cl_program p = pos->second.clProgram;
		assert (NULL == p);
		if (NULL != p)
			clReleaseProgram (p);
		pos->second.clProgram = prog;
	}

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::getclProgram( const clfftGenerators gen, const FFTKernelSignatureHeader * data, cl_program& prog, const cl_device_id &device, const cl_context& planContext  )
{
	scopedLock sLock( lockRepo, _T( "getclProgram" ) );

	FFTRepoKey key(gen, data, planContext, device);

	fftRepo_iterator pos = mapFFTs.find( key );
	if( pos == mapFFTs.end( ) )
		return	CLFFT_INVALID_PROGRAM;
	prog = pos->second.clProgram;
	if (NULL == prog)
		return	CLFFT_INVALID_PROGRAM;

  cl_context progContext;
  clGetProgramInfo(prog, CL_PROGRAM_CONTEXT, sizeof(cl_context), &progContext, NULL);
  if (planContext!=progContext)
    return	CLFFT_INVALID_PROGRAM;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::setclKernel( cl_program prog, clfftDirection dir, const cl_kernel& kernel )
{
	scopedLock sLock( lockRepo, _T( "setclKernel" ) );

	fftKernels & Kernels = mapKernels[ prog ];

	cl_kernel * pk;
	lockRAII ** kernelLock;

	switch (dir) {
	case CLFFT_FORWARD:
		pk = & Kernels.kernel_fwd;
		kernelLock = & Kernels.kernel_fwd_lock;
		break;
	case CLFFT_BACKWARD:
		pk = & Kernels.kernel_back;
		kernelLock = & Kernels.kernel_back_lock;
		break;
	default:
		assert (false);
		return CLFFT_INVALID_ARG_VALUE;
	}

	assert (NULL == *pk);
	if (NULL != *pk)
		clReleaseKernel( *pk );

	*pk = kernel;

	if (NULL != *kernelLock)
		 delete kernelLock;

	*kernelLock = new lockRAII;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::getclKernel( cl_program prog, clfftDirection dir, cl_kernel& kernel, lockRAII*& kernelLock)
{
	scopedLock sLock( lockRepo, _T( "getclKernel" ) );

	Kernel_iterator pos = mapKernels.find( prog );
	if (pos == mapKernels.end( ) )
		return	CLFFT_INVALID_KERNEL;

	switch (dir) {
	case CLFFT_FORWARD:
		kernel = pos->second.kernel_fwd;
		kernelLock = pos->second.kernel_fwd_lock;
		break;
	case CLFFT_BACKWARD:
		kernel = pos->second.kernel_back;
		kernelLock = pos->second.kernel_back_lock;
		break;
	default:
		assert (false);
		return CLFFT_INVALID_ARG_VALUE;
	}

	if (NULL == kernel)
		return	CLFFT_INVALID_KERNEL;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::createPlan( clfftPlanHandle* plHandle, FFTPlan*& fftPlan )
{
	scopedLock sLock( lockRepo, _T( "insertPlan" ) );

	//	We keep track of this memory in our own collection class, to make sure it's freed in releaseResources
	//	The lifetime of a plan is tracked by the client and is freed when the client calls ::clfftDestroyPlan()
	fftPlan	= new FFTPlan;

	//	We allocate a new lock here, and expect it to be freed in ::clfftDestroyPlan();
	//	The lifetime of the lock is the same as the lifetime of the plan
	lockRAII* lockPlan	= new lockRAII;

	//	Add and remember the fftPlan in our map
	repoPlans[ planCount ] = std::make_pair( fftPlan, lockPlan );

	//	Assign the user handle the plan count (unique identifier), and bump the count for the next plan
	*plHandle	= planCount++;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::getPlan( clfftPlanHandle plHandle, FFTPlan*& fftPlan, lockRAII*& planLock )
{
	scopedLock sLock( lockRepo, _T( "getPlan" ) );

	//	First, check if we have already created a plan with this exact same FFTPlan
	repoPlansType::iterator iter	= repoPlans.find( plHandle );
	if( iter == repoPlans.end( ) )
		return	CLFFT_INVALID_PLAN;

	//	If plan is valid, return fill out the output pointers
	fftPlan		= iter->second.first;
	planLock	= iter->second.second;

	return	CLFFT_SUCCESS;
}

clfftStatus FFTRepo::deletePlan( clfftPlanHandle* plHandle )
{
	scopedLock sLock( lockRepo, _T( "deletePlan" ) );

	//	First, check if we have already created a plan with this exact same FFTPlan
	repoPlansType::iterator iter	= repoPlans.find( *plHandle );
	if( iter == repoPlans.end( ) )
		return	CLFFT_INVALID_PLAN;

	//	We lock the plan object while we are in the process of deleting it
	{
		scopedLock sLock( *iter->second.second, _T( "clfftDestroyPlan" ) );
		clReleaseContext( iter->second.first->context );

		//	Delete the FFTPlan
		delete iter->second.first;
	}

		//	Delete the lockRAII
	delete iter->second.second;

	//	Remove entry from our map object
	repoPlans.erase( iter );

	//	Clear the client's handle to signify that the plan is gone
	*plHandle = 0;

	return	CLFFT_SUCCESS;
}
<|endoftext|>


<commit_before>/*

    Copyright (C) 2017 Tadeusz Puźniakowski

    This file is part of mhttp.

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

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

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

	you can contact me via http://www.puzniakowski.pl

*/

#include "http_session.hpp"
#include "http_memorysessionstorage.hpp"

#include "http_request.hpp"
#include "http_response.hpp"

#include <iostream>
#include <list>

namespace tp {
namespace http {

std::string MemorySessionStorage::generateSessionId() {
	while ( true ) {
		int m = uniform_dist( e1 ) & 0x07fffffff;
		if ( sessions.count( std::to_string( m ) ) < 1 ) {
			return std::to_string( m );
		}
	}
}

Session &MemorySessionStorage::getSessionForRequest ( Request &req ) {
	std::lock_guard<std::mutex> guard( session_mutex );
	std::string sid = "";
	std::string cookiestring = req.header["cookie"];

	//std::cout << "getSessionForRequest cookie: " << cookiestring << " ; " << std::endl;

	std::regex pieces_regex( "sessionId=([0123456789][0123456789]*)" );
	std::smatch pieces_match;
	if ( std::regex_match ( cookiestring, pieces_match, pieces_regex ) ) {
		for ( size_t i = 0; i < pieces_match.size(); ++i ) {
			std::ssub_match sub_match = pieces_match[i];
			auto fsid = sub_match.str();
			if ( sessions.count( fsid ) > 0 ) {
				sid = fsid;
				break;
			}
		}
	}
	//std::cout << "getSessionForRequest cookie - sid: " << sid << " ; " << std::endl;

	//    std::cout  << cookiestring << std::endl;
	if ( sid == "" ) {
		sid = generateSessionId();
		if ((sessions.size() % sessionCleanupCycle) == 0) {
			std::list < std::string > sessionToDelete;
			for (auto &s : sessions) {
				if (s.second.getSecondsOfLife() > sessionTimeout) {
					sessionToDelete.push_back(s.first);
				}
			}
			for (auto &sidd : sessionToDelete) {
				sessions.erase(sidd);
			}
		}
		if ((maxSessions == -1) || ((int)sessions.size() > maxSessions)) {
			throw std::overflow_error("could not allocate another session");
		}
		sessions[sid].setId( sid );
	}
	return sessions[sid];
}

void MemorySessionStorage::storeSession ( Session session ) {
	std::lock_guard<std::mutex> guard( session_mutex );
	sessions[session.getId()] = session;
}

t_Response MemorySessionStorage::storeSessionForRequest ( Session session, t_Response &res ) {
	storeSession ( session );
	std::stringstream setcookie;
	setcookie << "sessionId" << "=" << session.getId();
	res.getHeader()["set-cookie"] = setcookie.str();
	//std::cout << "set-cookie header: " << res.getHeader()["set-cookie"] << std::endl;
	return res;
}

MemorySessionStorage::MemorySessionStorage(int sessionLifeTimeSeconds,int maxSessions_, int sessionCleanupCycle_)
		 : e1( r() ),
		 uniform_dist( 1001, 1 << ( sizeof( int ) * 8 - 2 ) ),
		 sessionTimeout(sessionLifeTimeSeconds),
		 maxSessions(maxSessions_),
		 sessionCleanupCycle(sessionCleanupCycle_) {
}

}
}
<commit_msg>bugfix in session handling - long info<commit_after>/*

    Copyright (C) 2017 Tadeusz Puźniakowski

    This file is part of mhttp.

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

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

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

	you can contact me via http://www.puzniakowski.pl

*/

#include "http_session.hpp"
#include "http_memorysessionstorage.hpp"

#include "http_request.hpp"
#include "http_response.hpp"

#include <iostream>
#include <list>

namespace tp {
namespace http {

std::string MemorySessionStorage::generateSessionId() {
	while ( true ) {
		int m = uniform_dist( e1 ) & 0x07fffffff;
		if ( sessions.count( std::to_string( m ) ) < 1 ) {
			return std::to_string( m );
		}
	}
}

Session &MemorySessionStorage::getSessionForRequest ( Request &req ) {
	std::lock_guard<std::mutex> guard( session_mutex );
	std::string sid = "";
	std::string cookiestring = req.header["cookie"];

	std::cout << "getSessionForRequest cookie: " << cookiestring << " ; " << std::endl;

	std::regex pieces_regex( "sessionId=([0123456789][0123456789]*)" );
	std::smatch pieces_match;
	if ( std::regex_match ( cookiestring, pieces_match, pieces_regex ) ) {
		for ( size_t i = 0; i < pieces_match.size(); ++i ) {
			std::ssub_match sub_match = pieces_match[i];
			auto fsid = sub_match.str();
			if ( sessions.count( fsid ) > 0 ) {
				sid = fsid;
				break;
			}
		}
	}
	std::cout << "getSessionForRequest cookie - sid: " << sid << " ; " << std::endl;

	//    std::cout  << cookiestring << std::endl;
	if ( sid == "" ) {
		sid = generateSessionId();
		if ((sessions.size() % sessionCleanupCycle) == 0) {
			std::list < std::string > sessionToDelete;
			for (auto &s : sessions) {
				if (s.second.getSecondsOfLife() > sessionTimeout) {
					sessionToDelete.push_back(s.first);
				}
			}
			for (auto &sidd : sessionToDelete) {
				sessions.erase(sidd);
			}
		}
		if ((maxSessions == -1) || ((int)sessions.size() > maxSessions)) {
			throw std::overflow_error("could not allocate another session");
		}
		sessions[sid].setId( sid );
	}
	return sessions[sid];
}

void MemorySessionStorage::storeSession ( Session session ) {
	std::lock_guard<std::mutex> guard( session_mutex );
	sessions[session.getId()] = session;
}

t_Response MemorySessionStorage::storeSessionForRequest ( Session session, t_Response &res ) {
	storeSession ( session );
	std::stringstream setcookie;
	setcookie << "sessionId" << "=" << session.getId();
	res.getHeader()["set-cookie"] = setcookie.str();
	//std::cout << "set-cookie header: " << res.getHeader()["set-cookie"] << std::endl;
	return res;
}

MemorySessionStorage::MemorySessionStorage(int sessionLifeTimeSeconds,int maxSessions_, int sessionCleanupCycle_)
		 : e1( r() ),
		 uniform_dist( 1001, 1 << ( sizeof( int ) * 8 - 2 ) ),
		 sessionTimeout(sessionLifeTimeSeconds),
		 maxSessions(maxSessions_),
		 sessionCleanupCycle(sessionCleanupCycle_) {
}

}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) [2017-2018] SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include "storage/Devices/BlkDeviceImpl.h"
#include "storage/Filesystems/ReiserfsImpl.h"
#include "storage/Utils/StorageDefines.h"
#include "storage/Utils/HumanString.h"
#include "storage/Utils/SystemCmd.h"
#include "storage/FreeInfo.h"
#include "storage/UsedFeatures.h"

namespace storage
{

    using namespace std;

    const char* DeviceTraits<Reiserfs>::classname = "Reiserfs";

    Reiserfs::Impl::Impl(const xmlNode* node)
	: BlkFilesystem::Impl(node)
    {
    }

    string
    Reiserfs::Impl::get_pretty_classname() const
    {
	// TRANSLATORS: name of object
	return _("Reiserfs").translated;
    }

    uint64_t
    Reiserfs::Impl::used_features() const
    {
	return UF_REISERFS | BlkFilesystem::Impl::used_features();
    }

    void
    Reiserfs::Impl::do_create()
    {
	const BlkDevice* blk_device = get_blk_device();

	string cmd_line = MKFSREISERFSBIN " -f -f " + get_mkfs_options() + " " +
	    quote(blk_device->get_name());

	wait_for_devices();

	SystemCmd cmd(cmd_line, SystemCmd::DoThrow);

	// uuid is included in mkfs output

	probe_uuid();
    }

    void
    Reiserfs::Impl::do_set_label() const
    {
	const BlkDevice* blk_device = get_blk_device();

	// TODO handle mounted

	string cmd_line = TUNEREISERFSBIN " -l " + quote(get_label()) + " " +
	    quote(blk_device->get_name());

	SystemCmd cmd(cmd_line, SystemCmd::DoThrow);
    }

    void
    Reiserfs::Impl::do_set_tune_options() const
    {
	const BlkDevice* blk_device = get_blk_device();

	string cmd_line = TUNEREISERFSBIN " " + get_tune_options() + " " + quote(blk_device->get_name());

	SystemCmd cmd(cmd_line, SystemCmd::DoThrow);
    }

    void
    Reiserfs::Impl::do_resize(const CommitData& commit_data, const Action::Resize* action) const
    {
	const Reiserfs* reiserfs_rhs = to_reiserfs(action->get_device(commit_data.actiongraph, RHS));

	const BlkDevice* blk_device_rhs = reiserfs_rhs->get_impl().get_blk_device();

	string cmd_line = REISERFSRESIZEBIN " -f";
	if (action->resize_mode == ResizeMode::SHRINK)
	    cmd_line = "echo y | " + cmd_line + " -s " +
		to_string(blk_device_rhs->get_size() / KiB) + "K";
	cmd_line += " " + quote(action->blk_device->get_name());

	wait_for_devices();

	SystemCmd cmd(cmd_line, SystemCmd::DoThrow);
    }

}
<commit_msg>- fixed message<commit_after>/*
 * Copyright (c) [2017-2020] SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include "storage/Devices/BlkDeviceImpl.h"
#include "storage/Filesystems/ReiserfsImpl.h"
#include "storage/Utils/StorageDefines.h"
#include "storage/Utils/HumanString.h"
#include "storage/Utils/SystemCmd.h"
#include "storage/FreeInfo.h"
#include "storage/UsedFeatures.h"

namespace storage
{

    using namespace std;

    const char* DeviceTraits<Reiserfs>::classname = "Reiserfs";

    Reiserfs::Impl::Impl(const xmlNode* node)
	: BlkFilesystem::Impl(node)
    {
    }

    string
    Reiserfs::Impl::get_pretty_classname() const
    {
	// TRANSLATORS: name of object
	return _("ReiserFS").translated;
    }

    uint64_t
    Reiserfs::Impl::used_features() const
    {
	return UF_REISERFS | BlkFilesystem::Impl::used_features();
    }

    void
    Reiserfs::Impl::do_create()
    {
	const BlkDevice* blk_device = get_blk_device();

	string cmd_line = MKFSREISERFSBIN " -f -f " + get_mkfs_options() + " " +
	    quote(blk_device->get_name());

	wait_for_devices();

	SystemCmd cmd(cmd_line, SystemCmd::DoThrow);

	// uuid is included in mkfs output

	probe_uuid();
    }

    void
    Reiserfs::Impl::do_set_label() const
    {
	const BlkDevice* blk_device = get_blk_device();

	// TODO handle mounted

	string cmd_line = TUNEREISERFSBIN " -l " + quote(get_label()) + " " +
	    quote(blk_device->get_name());

	SystemCmd cmd(cmd_line, SystemCmd::DoThrow);
    }

    void
    Reiserfs::Impl::do_set_tune_options() const
    {
	const BlkDevice* blk_device = get_blk_device();

	string cmd_line = TUNEREISERFSBIN " " + get_tune_options() + " " + quote(blk_device->get_name());

	SystemCmd cmd(cmd_line, SystemCmd::DoThrow);
    }

    void
    Reiserfs::Impl::do_resize(const CommitData& commit_data, const Action::Resize* action) const
    {
	const Reiserfs* reiserfs_rhs = to_reiserfs(action->get_device(commit_data.actiongraph, RHS));

	const BlkDevice* blk_device_rhs = reiserfs_rhs->get_impl().get_blk_device();

	string cmd_line = REISERFSRESIZEBIN " -f";
	if (action->resize_mode == ResizeMode::SHRINK)
	    cmd_line = "echo y | " + cmd_line + " -s " +
		to_string(blk_device_rhs->get_size() / KiB) + "K";
	cmd_line += " " + quote(action->blk_device->get_name());

	wait_for_devices();

	SystemCmd cmd(cmd_line, SystemCmd::DoThrow);
    }

}
<|endoftext|>