<commit_before>/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 * @endcopyright
 *
 * @file JNIUtil.cpp
 * @brief Implementation of the class JNIUtil
 */

#include "JNIUtil.h"
#include <locale.h>
#include <apr_strings.h>
#include <apr_tables.h>
#include <apr_general.h>
#include <apr_lib.h>

#include <svn_pools.h>
#include <svn_config.h>
//#include <ios>

#include "SVNClient.h"
#include "JNIMutex.h"
#include "JNICriticalSection.h"
#include "JNIThreadData.h"
#include "JNIStringHolder.h"

apr_pool_t *JNIUtil::g_pool = NULL;
std::list<SVNClient*> JNIUtil::g_finalizedObjects;
JNIMutex *JNIUtil::g_finalizedObjectsMutex = NULL;
JNIMutex *JNIUtil::g_logMutex = NULL;
bool JNIUtil::g_initException;
bool JNIUtil::g_inInit;
JNIEnv *JNIUtil::g_initEnv;
char JNIUtil::g_initFormatBuffer[formatBufferSize];
int JNIUtil::g_logLevel = JNIUtil::noLog;
std::ofstream JNIUtil::g_logStream;
Pool *JNIUtil::g_requestPool;

bool JNIUtil::JNIInit(JNIEnv *env)
{
	static bool run = false;
	if(run)
	{
		env->ExceptionClear();
		setEnv(env);
		JNICriticalSection cs(*g_finalizedObjectsMutex) ;
		if(isExceptionThrown())
		{
			return false;
		}

		for(std::list<SVNClient*>::iterator it = g_finalizedObjects.begin(); it != g_finalizedObjects.end(); it++)
		{
			delete *it;
		}
		g_finalizedObjects.clear();

		return true;
	}
	run = true;
	if(g_inInit)
	{
		return false;
	}
	g_inInit = true;
	g_initEnv = env;

	/* C programs default to the "C" locale by default.  But because svn
	 is supposed to be i18n-aware, it should inherit the default
	 locale of its environment.  */
	setlocale (LC_ALL, "");

	/* Initialize the APR subsystem, and register an atexit() function
	to Uninitialize that subsystem at program exit. */
	apr_status_t apr_err = apr_initialize ();
	if (apr_err)
	{
		fprintf (stderr, "error: apr_initialize\n");
		return false;
	}
	int err2 = atexit (apr_terminate);
	if (err2)
	{
		fprintf (stderr, "error: atexit returned %d\n", err2);
		return false;
	}

	/* Create our top-level pool. */
	g_pool = svn_pool_create (NULL);

	svn_error *err = svn_config_ensure (NULL, g_pool); // we use the default directory for config files
	if (err)
	{
		svn_pool_destroy (g_pool);
		handleSVNError(err);
		return false;
	}

	g_finalizedObjectsMutex = new JNIMutex(g_pool);
	if(isExceptionThrown())
	{
		return false;
	}

	g_logMutex = new JNIMutex(g_pool);
	if(isExceptionThrown())
	{
		return false;
	}

	if(!JNIThreadData::initThreadData())
	{
		return false;
	}

	setEnv(env);
	if(isExceptionThrown())
	{
		return false;
	}

	g_initEnv = NULL;
	g_inInit = false;
	return true;
}

apr_pool_t * JNIUtil::getPool()
{
	return g_pool;
}

void JNIUtil::throwError(const char *message)
{
	if(getLogLevel() >= errorLog)
	{
		JNICriticalSection cs(*g_logMutex);
		g_logStream << "Error thrown <" << message << ">" << std::endl;
	}
	JNIEnv *env = getEnv();
	jclass clazz = env->FindClass(JAVA_PACKAGE"/JNIError");
	if(isJavaExceptionThrown())
	{
		return;
	}
	env->ThrowNew(clazz, message);
	setExceptionThrown();
	env->DeleteLocalRef(clazz);
}

void JNIUtil::handleSVNError(svn_error *err)
{
	JNIEnv *env = getEnv();
	jclass clazz = env->FindClass(JAVA_PACKAGE"/ClientException");
	if(getLogLevel() >= exceptionLog)
	{
		JNICriticalSection cs(*g_logMutex);
		g_logStream << "Error SVN exception thrown message:<";
		g_logStream << err->message << "> file:<" << err->file << "> apr-err:<" << err->apr_err;
		g_logStream	<< ">" << std::endl;
	}
	if(isJavaExceptionThrown())
	{
		return;
	}

	std::string buffer;
	assembleErrorMessage(err, 0, APR_SUCCESS, buffer);
	jstring jmessage = makeJString(buffer.c_str());
	if(isJavaExceptionThrown())
	{
		return;
	}
	if(isJavaExceptionThrown())
	{
		return;
	}
	jstring jfile = makeJString(err->file);
	if(isJavaExceptionThrown())
	{
		return;
	}
	jmethodID mid = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;Ljava/lang/String;I)V");
	if(isJavaExceptionThrown())
	{
		return;
	}
	jobject error = env->NewObject(clazz, mid, jmessage, jfile, static_cast<jint>(err->apr_err));
	if(isJavaExceptionThrown())
	{
		return;
	}
	env->DeleteLocalRef(clazz);
	if(isJavaExceptionThrown())
	{
		return;
	}
	env->DeleteLocalRef(jmessage);
	if(isJavaExceptionThrown())
	{
		return;
	}
	env->DeleteLocalRef(jfile);
	if(isJavaExceptionThrown())
	{
		return;
	}
	env->Throw(static_cast<jthrowable>(error));
}

void JNIUtil::putFinalizedClient(SVNClient *cl)
{
	if(getLogLevel() >= errorLog)
	{
		JNICriticalSection cs(*g_logMutex);
		g_logStream << "a client object was not disposed" << std::endl;
	}
	JNICriticalSection cs(*g_finalizedObjectsMutex);
	if(isExceptionThrown())
	{
		return;
	}

	g_finalizedObjects.push_back(cl);

}

void JNIUtil::handleAPRError(int error, const char *op)
{
	char *buffer = getFormatBuffer();
	if(buffer == NULL)
	{
		return;
	}
    apr_snprintf(buffer, formatBufferSize, "an error occured in funcation %s with return value %d",
		op, error);

	throwError(buffer);
}

bool JNIUtil::isExceptionThrown()
{
	if(g_inInit)
	{
		return g_initException;
	}
	JNIThreadData *data = JNIThreadData::getThreadData();
	return data == NULL || data->m_exceptionThrown;
}

void JNIUtil::setEnv(JNIEnv *env)
{
	JNIThreadData *data = JNIThreadData::getThreadData();
	data->m_env = env;
	data->m_exceptionThrown = false;
}

JNIEnv * JNIUtil::getEnv()
{
	if(g_inInit)
	{
		return g_initEnv;
	}
	JNIThreadData *data = JNIThreadData::getThreadData();
	return data->m_env;
}

bool JNIUtil::isJavaExceptionThrown()
{
	JNIEnv *env = getEnv();
	if(env->ExceptionCheck())
	{
		jthrowable exp = env->ExceptionOccurred();
		env->ExceptionDescribe();
		env->Throw(exp);
		env->DeleteLocalRef(exp);
		return true;
	}
	return false;
}

jstring JNIUtil::makeJString(const char *txt)
{
	if(txt == NULL)
	{
		return NULL;
	}
	JNIEnv *env = getEnv();
	jstring js = env->NewStringUTF(txt);
	return js;
}

void JNIUtil::setExceptionThrown()
{
	if(g_inInit)
	{
		g_initException = true;
	}
	JNIThreadData *data = JNIThreadData::getThreadData();
	data->m_exceptionThrown = true;
}

void JNIUtil::initLogFile(int level, jstring path)
{
	JNICriticalSection cs(*g_logMutex);
	if(g_logLevel > noLog)
	{
		g_logStream.close();
	}
	g_logLevel = level;
	JNIStringHolder myPath(path);
	if(g_logLevel > noLog)
	{
		g_logStream.open(myPath, std::ios::app);
		//g_logStream.open(myPath, std::ios_base::app);
	}
}

char * JNIUtil::getFormatBuffer()
{
	if(g_inInit)
	{
		return g_initFormatBuffer;
	}
	JNIThreadData *data = JNIThreadData::getThreadData();
	if(data == NULL)
	{
		return g_initFormatBuffer;
	}
	return data->m_formatBuffer;
}

int JNIUtil::getLogLevel()
{
	return g_logLevel;
}

void JNIUtil::logMessage(const char *message)
{
	JNICriticalSection cs(*g_logMutex);
	g_logStream << message << std::endl;
}

jobject JNIUtil::createDate(apr_time_t time)
{
	jlong javatime = time /1000;
	JNIEnv *env = getEnv();
	jclass clazz = env->FindClass("java/util/Date");
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	static jmethodID mid = 0;
	if(mid == 0)
	{
		mid = env->GetMethodID(clazz, "<init>", "(J)V");
		if(isJavaExceptionThrown())
		{
			return NULL;
		}
	}
	jobject ret = env->NewObject(clazz, mid, javatime);
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	env->DeleteLocalRef(clazz);
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	return ret;
}

Pool * JNIUtil::getRequestPool()
{
	return g_requestPool;
}

void JNIUtil::setRequestPool(Pool *pool)
{
	g_requestPool = pool;
}

jbyteArray JNIUtil::makeJByteArray(const signed char *data, int length)
{
	if(data == NULL || length == 0)
	{
		return NULL;
	}
	JNIEnv *env = getEnv();
	jbyteArray ret = env->NewByteArray(length);
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	jbyte *retdata = env->GetByteArrayElements(ret, NULL);
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	memcpy(retdata, data, length);
	env->ReleaseByteArrayElements(ret, retdata, 0);
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	return ret;
}

void JNIUtil::assembleErrorMessage(svn_error *err, int depth, apr_status_t parent_apr_err, std::string &buffer)
{
    char errbuf[256];
//  char utfbuf[2048];
//  const char *err_string;

  /* Pretty-print the error */
  /* Note: we can also log errors here someday. */

  /* When we're recursing, don't repeat the top-level message if its
     the same as before. */
  if (depth == 0 || err->apr_err != parent_apr_err)
    {
      /* Is this a Subversion-specific error code? */
      if ((err->apr_err > APR_OS_START_USEERR)
          && (err->apr_err <= APR_OS_START_CANONERR))
          buffer.append(svn_strerror (err->apr_err, errbuf, sizeof (errbuf)));
      /* Otherwise, this must be an APR error code. */
      else
		  buffer.append(apr_strerror (err->apr_err, errbuf, sizeof (errbuf)));
      buffer.append("\n");
    }
  if (err->message)
	  buffer.append("svn: ").append(err->message).append("\n");

  if (err->child)
    assembleErrorMessage(err->child, depth + 1, err->apr_err, buffer);

}
<commit_msg>* JNIUtil.cpp (JNIUtil::handleSVNError(svn_error *err) 	handleSVNError will delete the parameter err to avoid leeks<commit_after>/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 * @endcopyright
 *
 * @file JNIUtil.cpp
 * @brief Implementation of the class JNIUtil
 */

#include "JNIUtil.h"
#include <locale.h>
#include <apr_strings.h>
#include <apr_tables.h>
#include <apr_general.h>
#include <apr_lib.h>

#include <svn_pools.h>
#include <svn_config.h>
//#include <ios>

#include "SVNClient.h"
#include "JNIMutex.h"
#include "JNICriticalSection.h"
#include "JNIThreadData.h"
#include "JNIStringHolder.h"

apr_pool_t *JNIUtil::g_pool = NULL;
std::list<SVNClient*> JNIUtil::g_finalizedObjects;
JNIMutex *JNIUtil::g_finalizedObjectsMutex = NULL;
JNIMutex *JNIUtil::g_logMutex = NULL;
bool JNIUtil::g_initException;
bool JNIUtil::g_inInit;
JNIEnv *JNIUtil::g_initEnv;
char JNIUtil::g_initFormatBuffer[formatBufferSize];
int JNIUtil::g_logLevel = JNIUtil::noLog;
std::ofstream JNIUtil::g_logStream;
Pool *JNIUtil::g_requestPool;

bool JNIUtil::JNIInit(JNIEnv *env)
{
	static bool run = false;
	if(run)
	{
		env->ExceptionClear();
		setEnv(env);
		JNICriticalSection cs(*g_finalizedObjectsMutex) ;
		if(isExceptionThrown())
		{
			return false;
		}

		for(std::list<SVNClient*>::iterator it = g_finalizedObjects.begin(); it != g_finalizedObjects.end(); it++)
		{
			delete *it;
		}
		g_finalizedObjects.clear();

		return true;
	}
	run = true;
	if(g_inInit)
	{
		return false;
	}
	g_inInit = true;
	g_initEnv = env;

	/* C programs default to the "C" locale by default.  But because svn
	 is supposed to be i18n-aware, it should inherit the default
	 locale of its environment.  */
	setlocale (LC_ALL, "");

	/* Initialize the APR subsystem, and register an atexit() function
	to Uninitialize that subsystem at program exit. */
	apr_status_t apr_err = apr_initialize ();
	if (apr_err)
	{
		fprintf (stderr, "error: apr_initialize\n");
		return false;
	}
	int err2 = atexit (apr_terminate);
	if (err2)
	{
		fprintf (stderr, "error: atexit returned %d\n", err2);
		return false;
	}

	/* Create our top-level pool. */
	g_pool = svn_pool_create (NULL);

	svn_error *err = svn_config_ensure (NULL, g_pool); // we use the default directory for config files
	if (err)
	{
		svn_pool_destroy (g_pool);
		handleSVNError(err);
		return false;
	}

	g_finalizedObjectsMutex = new JNIMutex(g_pool);
	if(isExceptionThrown())
	{
		return false;
	}

	g_logMutex = new JNIMutex(g_pool);
	if(isExceptionThrown())
	{
		return false;
	}

	if(!JNIThreadData::initThreadData())
	{
		return false;
	}

	setEnv(env);
	if(isExceptionThrown())
	{
		return false;
	}

	g_initEnv = NULL;
	g_inInit = false;
	return true;
}

apr_pool_t * JNIUtil::getPool()
{
	return g_pool;
}

void JNIUtil::throwError(const char *message)
{
	if(getLogLevel() >= errorLog)
	{
		JNICriticalSection cs(*g_logMutex);
		g_logStream << "Error thrown <" << message << ">" << std::endl;
	}
	JNIEnv *env = getEnv();
	jclass clazz = env->FindClass(JAVA_PACKAGE"/JNIError");
	if(isJavaExceptionThrown())
	{
		return;
	}
	env->ThrowNew(clazz, message);
	setExceptionThrown();
	env->DeleteLocalRef(clazz);
}

void JNIUtil::handleSVNError(svn_error *err)
{
	JNIEnv *env = getEnv();
	jclass clazz = env->FindClass(JAVA_PACKAGE"/ClientException");
	if(getLogLevel() >= exceptionLog)
	{
		JNICriticalSection cs(*g_logMutex);
		g_logStream << "Error SVN exception thrown message:<";
		g_logStream << err->message << "> file:<" << err->file << "> apr-err:<" << err->apr_err;
		g_logStream	<< ">" << std::endl;
	}
	if(isJavaExceptionThrown())
	{
		svn_error_clear(err);
		return;
	}

	std::string buffer;
	assembleErrorMessage(err, 0, APR_SUCCESS, buffer);
	jstring jmessage = makeJString(buffer.c_str());
	if(isJavaExceptionThrown())
	{
		svn_error_clear(err);
		return;
	}
	if(isJavaExceptionThrown())
	{
		svn_error_clear(err);
		return;
	}
	jstring jfile = makeJString(err->file);
	if(isJavaExceptionThrown())
	{
		svn_error_clear(err);
		return;
	}
	jmethodID mid = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;Ljava/lang/String;I)V");
	if(isJavaExceptionThrown())
	{
		svn_error_clear(err);
		return;
	}
	jobject error = env->NewObject(clazz, mid, jmessage, jfile, static_cast<jint>(err->apr_err));
	svn_error_clear(err);
	if(isJavaExceptionThrown())
	{
		return;
	}
	env->DeleteLocalRef(clazz);
	if(isJavaExceptionThrown())
	{
		return;
	}
	env->DeleteLocalRef(jmessage);
	if(isJavaExceptionThrown())
	{
		return;
	}
	env->DeleteLocalRef(jfile);
	if(isJavaExceptionThrown())
	{
		return;
	}
	env->Throw(static_cast<jthrowable>(error));
}

void JNIUtil::putFinalizedClient(SVNClient *cl)
{
	if(getLogLevel() >= errorLog)
	{
		JNICriticalSection cs(*g_logMutex);
		g_logStream << "a client object was not disposed" << std::endl;
	}
	JNICriticalSection cs(*g_finalizedObjectsMutex);
	if(isExceptionThrown())
	{
		return;
	}

	g_finalizedObjects.push_back(cl);

}

void JNIUtil::handleAPRError(int error, const char *op)
{
	char *buffer = getFormatBuffer();
	if(buffer == NULL)
	{
		return;
	}
    apr_snprintf(buffer, formatBufferSize, "an error occured in funcation %s with return value %d",
		op, error);

	throwError(buffer);
}

bool JNIUtil::isExceptionThrown()
{
	if(g_inInit)
	{
		return g_initException;
	}
	JNIThreadData *data = JNIThreadData::getThreadData();
	return data == NULL || data->m_exceptionThrown;
}

void JNIUtil::setEnv(JNIEnv *env)
{
	JNIThreadData *data = JNIThreadData::getThreadData();
	data->m_env = env;
	data->m_exceptionThrown = false;
}

JNIEnv * JNIUtil::getEnv()
{
	if(g_inInit)
	{
		return g_initEnv;
	}
	JNIThreadData *data = JNIThreadData::getThreadData();
	return data->m_env;
}

bool JNIUtil::isJavaExceptionThrown()
{
	JNIEnv *env = getEnv();
	if(env->ExceptionCheck())
	{
		jthrowable exp = env->ExceptionOccurred();
		env->ExceptionDescribe();
		env->Throw(exp);
		env->DeleteLocalRef(exp);
		return true;
	}
	return false;
}

jstring JNIUtil::makeJString(const char *txt)
{
	if(txt == NULL)
	{
		return NULL;
	}
	JNIEnv *env = getEnv();
	jstring js = env->NewStringUTF(txt);
	return js;
}

void JNIUtil::setExceptionThrown()
{
	if(g_inInit)
	{
		g_initException = true;
	}
	JNIThreadData *data = JNIThreadData::getThreadData();
	data->m_exceptionThrown = true;
}

void JNIUtil::initLogFile(int level, jstring path)
{
	JNICriticalSection cs(*g_logMutex);
	if(g_logLevel > noLog)
	{
		g_logStream.close();
	}
	g_logLevel = level;
	JNIStringHolder myPath(path);
	if(g_logLevel > noLog)
	{
		g_logStream.open(myPath, std::ios::app);
		//g_logStream.open(myPath, std::ios_base::app);
	}
}

char * JNIUtil::getFormatBuffer()
{
	if(g_inInit)
	{
		return g_initFormatBuffer;
	}
	JNIThreadData *data = JNIThreadData::getThreadData();
	if(data == NULL)
	{
		return g_initFormatBuffer;
	}
	return data->m_formatBuffer;
}

int JNIUtil::getLogLevel()
{
	return g_logLevel;
}

void JNIUtil::logMessage(const char *message)
{
	JNICriticalSection cs(*g_logMutex);
	g_logStream << message << std::endl;
}

jobject JNIUtil::createDate(apr_time_t time)
{
	jlong javatime = time /1000;
	JNIEnv *env = getEnv();
	jclass clazz = env->FindClass("java/util/Date");
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	static jmethodID mid = 0;
	if(mid == 0)
	{
		mid = env->GetMethodID(clazz, "<init>", "(J)V");
		if(isJavaExceptionThrown())
		{
			return NULL;
		}
	}
	jobject ret = env->NewObject(clazz, mid, javatime);
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	env->DeleteLocalRef(clazz);
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	return ret;
}

Pool * JNIUtil::getRequestPool()
{
	return g_requestPool;
}

void JNIUtil::setRequestPool(Pool *pool)
{
	g_requestPool = pool;
}

jbyteArray JNIUtil::makeJByteArray(const signed char *data, int length)
{
	if(data == NULL || length == 0)
	{
		return NULL;
	}
	JNIEnv *env = getEnv();
	jbyteArray ret = env->NewByteArray(length);
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	jbyte *retdata = env->GetByteArrayElements(ret, NULL);
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	memcpy(retdata, data, length);
	env->ReleaseByteArrayElements(ret, retdata, 0);
	if(isJavaExceptionThrown())
	{
		return NULL;
	}
	return ret;
}

void JNIUtil::assembleErrorMessage(svn_error *err, int depth, apr_status_t parent_apr_err, std::string &buffer)
{
    char errbuf[256];
//  char utfbuf[2048];
//  const char *err_string;

  /* Pretty-print the error */
  /* Note: we can also log errors here someday. */

  /* When we're recursing, don't repeat the top-level message if its
     the same as before. */
  if (depth == 0 || err->apr_err != parent_apr_err)
    {
      /* Is this a Subversion-specific error code? */
      if ((err->apr_err > APR_OS_START_USEERR)
          && (err->apr_err <= APR_OS_START_CANONERR))
          buffer.append(svn_strerror (err->apr_err, errbuf, sizeof (errbuf)));
      /* Otherwise, this must be an APR error code. */
      else
		  buffer.append(apr_strerror (err->apr_err, errbuf, sizeof (errbuf)));
      buffer.append("\n");
    }
  if (err->message)
	  buffer.append("svn: ").append(err->message).append("\n");

  if (err->child)
    assembleErrorMessage(err->child, depth + 1, err->apr_err, buffer);

}
<|endoftext|>


<commit_before><commit_msg>Constify some OUStrings<commit_after><|endoftext|>


<commit_before>TString names=("TTree_cuts");

TObjArray*  arrNames           = names.Tokenize(";");
const Int_t nDie               = arrNames->GetEntriesFast();
Int_t       selectedCentrality = -1; // not yet implemented
Int_t       selectedPID;
Bool_t      isPrefilterCutset;
Double_t    rejCutMee;
Double_t    rejCutTheta;
Double_t    rejCutPhiV;

//________________________________________________________________
// binning of 3D output histograms
// eta bins
const Double_t EtaMin   = -1.;
const Double_t EtaMax   =  1.;
const Int_t    nBinsEta = 40; //flexible to rebin
// phi bins
const Double_t PhiMin   = 0.;
const Double_t PhiMax   = 6.2832;
const Int_t    nBinsPhi = 60; //flexible to rebin

const Double_t PtBins[] = {0.0, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70,
						   0.75, 0.80, 0.85, 0.90, 1.00, 1.10, 1.15, 1.25, 1.35, 1.55, 1.80,
						   2.05, 2.30, 2.60, 2.90, 3.30, 3.60, 4.00, 5.00, 6.50, 8.00, 10.0};

// Bool_t bUseRelPResolution = kTRUE; //not used
Bool_t bUseEtaResolution      = kTRUE; // use eta or theta resolution?
Bool_t CalcEfficiencyRec      = kTRUE;
Bool_t CalcEfficiencyPoslabel = kFALSE;
Bool_t CalcResolution         = kTRUE;
Bool_t MakeResolutionSparse   = kFALSE;
Bool_t doPairing              = kTRUE;

// resolution binnings
Int_t    NbinsMom        = 2000;
Double_t MomMin          = 0.;
Double_t MomMax          = 10.;
Int_t    NbinsDeltaMom   = 1001;
Double_t DeltaMomMin     = -9.005;
Double_t DeltaMomMax     =  1.005;
Int_t    NbinsRelMom     =  1201;
Double_t RelMomMin       = -0.0005;
Double_t RelMomMax       =  1.2005;
Int_t    NbinsDeltaEta   = 1001;
Double_t DeltaEtaMin     = -0.5005;
Double_t DeltaEtaMax     =  0.5005;
Int_t    NbinsDeltaTheta = 1001;
Double_t DeltaThetaMin   = -0.5005;
Double_t DeltaThetaMax   =  0.5005;
Int_t    NbinsDeltaPhi   = 601;
Double_t DeltaPhiMin     = -0.3005;
Double_t DeltaPhiMax     =  0.3005;
Int_t    NbinsDeltaAngle = 401;
Double_t DeltaAngleMin   = -0.2005;
Double_t DeltaAngleMax   =  0.6005;

//Create mass bins
const Double_t MeeBins[] ={0.00, 0.025, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.12,
                            0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.95, 1.05, 1.25,
														1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 2.9, 3.0, 3.05, 3.1,
														3.3, 3.8, 5.00};
const Int_t nBinsMee  = sizeof(MeeBins)/sizeof(MeeBins[0])-1;

const Double_t PteeBins[] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,
                             1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9,
                             2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9,
                             3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5,
														 8.0, 8.5, 9.0, 9.5, 10.0};

const Int_t nBinsPtee = sizeof(PteeBins)/sizeof(PteeBins[0])-1;

// in increasing order
const TString sRuns("265309, 265334, 265335, 265338, 265339,
                     265342, 265343, 265344, 265377, 265378,
                     265381, 265383, 265384, 265385, 265387,
                     265388, 265419, 265420, 265421, 265422,
                     265424, 265427, 265435, 265499, 265500,
                     265501, 265521, 265525");

//
// ^^^^^^^^^^ [/end binning histograms] ^^^^^^^^^^

//________________________________________________________________
// specify if track tree shall be filled and written to file (only recommended for small checks!)
const Bool_t    writeTree = kFALSE;
// specify for which "cutInstance" the support histos should be filled!
const Int_t     supportedCutInstance = 0;
//
//________________________________________________________________
// settings which are identical for all configs that run together
// event cuts
const Bool_t    reqVertex = kTRUE;
const Double_t  vertexZcut = 10.;
//Set centrality in AddTask arguments
// MC cuts
const Double_t  EtaMinGEN = -1.;    // make sure to be within 3D histogram binning (EtaMin, EtaMax, PtBins[]).
const Double_t  EtaMaxGEN =  1.;
const Double_t  PtMinGEN  =  0.100; // 100 MeV as absolute lower limit for any setting.
const Double_t  PtMaxGEN  =  50.;

const Bool_t    CutInjectedSignals = kFALSE;
const UInt_t    NminEleInEventForRej = 2;
// ^^^^^^^^^^ [/end common settings] ^^^^^^^^^^

//________________________________________________________________
AliAnalysisCuts* SetupEventCuts()
{
	// event cuts are identical for all analysis 'cutInstance's that run together!
	AliDielectronEventCuts *eventCuts = new AliDielectronEventCuts("eventCuts","Vertex Track && |vtxZ|<10 && ncontrib>0");

  eventCuts->SetVertexType(AliDielectronEventCuts::kVtxSPD); // AOD
	eventCuts->SetRequireVertex();
	eventCuts->SetMinVtxContributors(1);
	eventCuts->SetVertexZ(-10.,10.);

	return eventCuts;
}

//________________________________________________________________
AliAnalysisFilter* SetupTrackCutsAndSettings(Int_t cutInstance, Bool_t hasITS = kTRUE)
{
	std::cout << "SetupTrackCutsAndSettings()" <<std::endl;
	AliAnalysisFilter *anaFilter = new AliAnalysisFilter("anaFilter","anaFilter"); // named constructor seems mandatory!
  selectedPID=-1;
  isPrefilterCutset=kFALSE;
  rejCutMee=-1;
  rejCutTheta=-1;
  rejCutPhiV=3.2; // relevant are values below pi, so initialization to 3.2 means disabling.
	// produce analysis filter by using functions in this config:
	anaFilter->AddCuts( SetupTrackCuts(cutInstance, hasITS) );
	anaFilter->AddCuts( SetupPIDcuts(cutInstance) );
	std::cout << "...cuts added!" <<std::endl;

	return anaFilter;
}

// prefilter cuts are not used at the moment
//________________________________________________________________
Int_t SetupPrefilterPairCuts(Int_t cutInstance)
{
  std::cout << "SetupPrefilterPairCuts()" <<std::endl;

  return 1;
}

//________________________________________________________________
AliAnalysisCuts* SetupTrackCuts(Int_t cutInstance, Bool_t hasITS = kTRUE)
{
  std::cout << "SetupTrackCuts()" <<std::endl;
  //AliAnalysisCuts* trackCuts=0x0;

	AliESDtrackCuts *fesdTrackCuts = new AliESDtrackCuts();

	//Cuts implemented in TreeMaker
	if(cutInstance == 0){
		//FilterBit 4 used to filter AODs
		//Set via GetStandardITSTPCTrackCuts 2011(kFALSE, 1)
		fesdTrackCuts->SetPtRange(0.2, 1e30);
    fesdTrackCuts->SetEtaRange(-0.8, 0.8);
		fesdTrackCuts->SetMinNCrossedRowsTPC(70);
		//fesdTrackCuts->SetMinRatioCrossedRowsOverFindableClustersTPC(0.8);
		fesdTrackCuts->SetMaxChi2PerClusterTPC(4);
		fesdTrackCuts->SetAcceptKinkDaughters(kFALSE);
		fesdTrackCuts->SetRequireSigmaToVertex(kFALSE);
		fesdTrackCuts->SetRequireTPCRefit(kTRUE);
		fesdTrackCuts->SetRequireITSRefit(kTRUE);
		fesdTrackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSPD,AliESDtrackCuts::kAny);
		fesdTrackCuts->SetRequireSigmaToVertex(kFALSE);
		fesdTrackCuts->SetMaxChi2PerClusterITS(36);

		//Manually set by fitler bit 4
		////Override setting in TrackCuts2011
		fesdTrackCuts->SetMaxDCAToVertexXY(2.4);
		fesdTrackCuts->SetMaxDCAToVertexZ(3.2);
		fesdTrackCuts->SetDCAToVertex2D(kTRUE);

		//Manually implemented track cuts in TreeMaker
		//General
		fesdTrackCuts->SetPtRange(0.2, 10);
		fesdTrackCuts->SetEtaRange(-0.8, 0.8);
		fesdTrackCuts->SetMaxDCAToVertexZ(3.0);
		fesdTrackCuts->SetMaxDCAToVertexXY(1.0);

		//TPC
		fesdTrackCuts->SetMinNClustersTPC(70);
		//fesdTrackCuts->SetMinNCrossedRowsTPC(60); FilterBit4 stronger cut
		fesdTrackCuts->SetMinRatioCrossedRowsOverFindableClustersTPC(0.3);
		//fesdTrackCuts->SetMaxChi2PerClusterTPC(4.5);
		fesdTrackCuts->SetMaxFractionSharedTPCClusters(0.4);

		//ITS
		if(hasITS){
			fesdTrackCuts->SetMinNClustersITS(4);
		}else{
			fesdTrackCuts->SetMinNClustersITS(2);
		}
	}

	return fesdTrackCuts;
}

//________________________________________________________________
AliAnalysisCuts* SetupPIDcuts(Int_t cutInstance)
{
	std::cout << "SetupPIDcuts()" <<std::endl;
	AliAnalysisCuts* pidCuts=0x0;

	AliDielectronPID *pid = new AliDielectronPID();

	//The only PID cut applied when creating Trees
	if(cutInstance == 0){
  	pid->AddCut(AliDielectronPID::kTPC, AliPID::kElectron, -4, 4, 0, 1e30, kFALSE, AliDielectronPID::kRequire, AliDielectronVarManager::kPt);
	}

	pidCuts = pid;
	return pidCuts;
}

<commit_msg>removed bug<commit_after>TString names=("TTree_cuts");

TObjArray*  arrNames           = names.Tokenize(";");
const Int_t nDie               = arrNames->GetEntriesFast();
Int_t       selectedCentrality = -1; // not yet implemented
Int_t       selectedPID;
Bool_t      isPrefilterCutset;
Double_t    rejCutMee;
Double_t    rejCutTheta;
Double_t    rejCutPhiV;

//________________________________________________________________
// binning of 3D output histograms
// eta bins
const Double_t EtaMin   = -1.;
const Double_t EtaMax   =  1.;
const Int_t    nBinsEta = 40; //flexible to rebin
// phi bins
const Double_t PhiMin   = 0.;
const Double_t PhiMax   = 6.2832;
const Int_t    nBinsPhi = 60; //flexible to rebin

const Double_t PtBins[] = {0.0, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70,
						   0.75, 0.80, 0.85, 0.90, 1.00, 1.10, 1.15, 1.25, 1.35, 1.55, 1.80,
						   2.05, 2.30, 2.60, 2.90, 3.30, 3.60, 4.00, 5.00, 6.50, 8.00, 10.0};

// Bool_t bUseRelPResolution = kTRUE; //not used
Bool_t bUseEtaResolution      = kTRUE; // use eta or theta resolution?
Bool_t CalcEfficiencyRec      = kTRUE;
Bool_t CalcEfficiencyPoslabel = kFALSE;
Bool_t CalcResolution         = kTRUE;
Bool_t MakeResolutionSparse   = kFALSE;
Bool_t doPairing              = kTRUE;

// resolution binnings
Int_t    NbinsMom        = 2000;
Double_t MomMin          = 0.;
Double_t MomMax          = 10.;
Int_t    NbinsDeltaMom   = 1001;
Double_t DeltaMomMin     = -9.005;
Double_t DeltaMomMax     =  1.005;
Int_t    NbinsRelMom     =  1201;
Double_t RelMomMin       = -0.0005;
Double_t RelMomMax       =  1.2005;
Int_t    NbinsDeltaEta   = 1001;
Double_t DeltaEtaMin     = -0.5005;
Double_t DeltaEtaMax     =  0.5005;
Int_t    NbinsDeltaTheta = 1001;
Double_t DeltaThetaMin   = -0.5005;
Double_t DeltaThetaMax   =  0.5005;
Int_t    NbinsDeltaPhi   = 601;
Double_t DeltaPhiMin     = -0.3005;
Double_t DeltaPhiMax     =  0.3005;
Int_t    NbinsDeltaAngle = 401;
Double_t DeltaAngleMin   = -0.2005;
Double_t DeltaAngleMax   =  0.6005;

//Create mass bins
const Double_t MeeBins[] ={0.00, 0.025, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.12,
                            0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.95, 1.05, 1.25,
														1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 2.9, 3.0, 3.05, 3.1,
														3.3, 3.8, 5.00};
const Int_t nBinsMee  = sizeof(MeeBins)/sizeof(MeeBins[0])-1;

const Double_t PteeBins[] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,
                             1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9,
                             2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9,
                             3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5,
														 8.0, 8.5, 9.0, 9.5, 10.0};

const Int_t nBinsPtee = sizeof(PteeBins)/sizeof(PteeBins[0])-1;

// in increasing order
const TString sRuns("265309, 265334, 265335, 265338, 265339,
                     265342, 265343, 265344, 265377, 265378,
                     265381, 265383, 265384, 265385, 265387,
                     265388, 265419, 265420, 265421, 265422,
                     265424, 265427, 265435, 265499, 265500,
                     265501, 265521, 265525");

//
// ^^^^^^^^^^ [/end binning histograms] ^^^^^^^^^^

//________________________________________________________________
// specify if track tree shall be filled and written to file (only recommended for small checks!)
const Bool_t    writeTree = kFALSE;
// specify for which "cutInstance" the support histos should be filled!
const Int_t     supportedCutInstance = 0;
//
//________________________________________________________________
// settings which are identical for all configs that run together
// event cuts
const Bool_t    reqVertex = kTRUE;
const Double_t  vertexZcut = 10.;
//Set centrality in AddTask arguments
// MC cuts
const Double_t  EtaMinGEN = -1.;    // make sure to be within 3D histogram binning (EtaMin, EtaMax, PtBins[]).
const Double_t  EtaMaxGEN =  1.;
const Double_t  PtMinGEN  =  0.100; // 100 MeV as absolute lower limit for any setting.
const Double_t  PtMaxGEN  =  50.;

const Bool_t    CutInjectedSignals = kFALSE;
const UInt_t    NminEleInEventForRej = 2;
// ^^^^^^^^^^ [/end common settings] ^^^^^^^^^^

//________________________________________________________________
AliAnalysisCuts* SetupEventCuts()
{
	// event cuts are identical for all analysis 'cutInstance's that run together!
	AliDielectronEventCuts *eventCuts = new AliDielectronEventCuts("eventCuts","Vertex Track && |vtxZ|<10 && ncontrib>0");

  eventCuts->SetVertexType(AliDielectronEventCuts::kVtxSPD); // AOD
	eventCuts->SetRequireVertex();
	eventCuts->SetMinVtxContributors(1);
	eventCuts->SetVertexZ(-10.,10.);

	return eventCuts;
}

//________________________________________________________________
AliAnalysisFilter* SetupTrackCutsAndSettings(Int_t cutInstance, Bool_t hasITS = kTRUE)
{
	std::cout << "SetupTrackCutsAndSettings()" <<std::endl;
	AliAnalysisFilter *anaFilter = new AliAnalysisFilter("anaFilter","anaFilter"); // named constructor seems mandatory!
  selectedPID=-1;
  isPrefilterCutset=kFALSE;
  rejCutMee=-1;
  rejCutTheta=-1;
  rejCutPhiV=3.2; // relevant are values below pi, so initialization to 3.2 means disabling.
	// produce analysis filter by using functions in this config:
	anaFilter->AddCuts( SetupTrackCuts(cutInstance, hasITS) );
	anaFilter->AddCuts( SetupPIDcuts(cutInstance) );
	std::cout << "...cuts added!" <<std::endl;

	return anaFilter;
}

// prefilter cuts are not used at the moment
//________________________________________________________________
Int_t SetupPrefilterPairCuts(Int_t cutInstance)
{
  std::cout << "SetupPrefilterPairCuts()" <<std::endl;

  return 1;
}

//________________________________________________________________
AliAnalysisCuts* SetupTrackCuts(Int_t cutInstance, Bool_t hasITS = kTRUE)
{
  std::cout << "SetupTrackCuts()" <<std::endl;
  //AliAnalysisCuts* trackCuts=0x0;

	AliESDtrackCuts *fesdTrackCuts = new AliESDtrackCuts();

	//Cuts implemented in TreeMaker
	if(cutInstance == 0){
		//FilterBit 4 used to filter AODs
		//Set via GetStandardITSTPCTrackCuts 2011(kFALSE, 1)
		fesdTrackCuts->SetMinNCrossedRowsTPC(70);
		//fesdTrackCuts->SetMinRatioCrossedRowsOverFindableClustersTPC(0.8);
		fesdTrackCuts->SetMaxChi2PerClusterTPC(4);
		fesdTrackCuts->SetAcceptKinkDaughters(kFALSE);
		fesdTrackCuts->SetRequireSigmaToVertex(kFALSE);
		fesdTrackCuts->SetRequireTPCRefit(kTRUE);
		fesdTrackCuts->SetRequireITSRefit(kTRUE);
		fesdTrackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSPD,AliESDtrackCuts::kAny);
		fesdTrackCuts->SetRequireSigmaToVertex(kFALSE);
		fesdTrackCuts->SetMaxChi2PerClusterITS(36);

		//Manually set by fitler bit 4
		////Override setting in TrackCuts2011
		fesdTrackCuts->SetMaxDCAToVertexXY(2.4);
		fesdTrackCuts->SetMaxDCAToVertexZ(3.2);
		fesdTrackCuts->SetDCAToVertex2D(kTRUE);

		//Manually implemented track cuts in TreeMaker
		//General
		fesdTrackCuts->SetPtRange(0.2, 10);
		fesdTrackCuts->SetEtaRange(-0.8, 0.8);
		fesdTrackCuts->SetMaxDCAToVertexZ(3.0);
		fesdTrackCuts->SetMaxDCAToVertexXY(1.0);

		//TPC
		fesdTrackCuts->SetMinNClustersTPC(70);
		//fesdTrackCuts->SetMinNCrossedRowsTPC(60); FilterBit4 stronger cut
		fesdTrackCuts->SetMinRatioCrossedRowsOverFindableClustersTPC(0.3);
		//fesdTrackCuts->SetMaxChi2PerClusterTPC(4.5);
		fesdTrackCuts->SetMaxFractionSharedTPCClusters(0.4);

		//ITS
		if(hasITS){
			fesdTrackCuts->SetMinNClustersITS(4);
		}else{
			fesdTrackCuts->SetMinNClustersITS(2);
		}
	}

	return fesdTrackCuts;
}

//________________________________________________________________
AliAnalysisCuts* SetupPIDcuts(Int_t cutInstance)
{
	std::cout << "SetupPIDcuts()" <<std::endl;
	AliAnalysisCuts* pidCuts=0x0;

	AliDielectronPID *pid = new AliDielectronPID();

	//The only PID cut applied when creating Trees
	if(cutInstance == 0){
  	pid->AddCut(AliDielectronPID::kTPC, AliPID::kElectron, -4, 4, 0, 1e30, kFALSE, AliDielectronPID::kRequire, AliDielectronVarManager::kPt);
	}

	pidCuts = pid;
	return pidCuts;
}

<|endoftext|>


<commit_before>/** @file

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include <cstring>
#include <deque>
#include "P_SSLConfig.h"
#include "SSLSessionCache.h"

#define SSLSESSIONCACHE_STRINGIFY0(x) #x
#define SSLSESSIONCACHE_STRINGIFY(x) SSLSESSIONCACHE_STRINGIFY0(x)
#define SSLSESSIONCACHE_LINENO SSLSESSIONCACHE_STRINGIFY(__LINE__)

#ifdef DEBUG
#define PRINT_BUCKET(x) this->print(x " at " __FILE__ ":" SSLSESSIONCACHE_LINENO);
#else
#define PRINT_BUCKET(x)
#endif

using ts::detail::RBNode;

/* Session Cache */
SSLSessionCache::SSLSessionCache()
  : session_bucket(NULL) {
  Debug("ssl.session_cache", "Created new ssl session cache %p with %ld buckets each with size max size %ld", this, SSLConfigParams::session_cache_number_buckets, SSLConfigParams::session_cache_max_bucket_size);

  session_bucket = new SSLSessionBucket[SSLConfigParams::session_cache_number_buckets];
}

SSLSessionCache::~SSLSessionCache() {
  delete []session_bucket;
}

bool SSLSessionCache::getSession(const SSLSessionID &sid, SSL_SESSION **sess) const {
  uint64_t hash = sid.hash();
  uint64_t target_bucket = hash % SSLConfigParams::session_cache_number_buckets;
  SSLSessionBucket *bucket = &session_bucket[target_bucket];
  bool ret = false;

  if (is_debug_tag_set("ssl.session_cache")) {
     char buf[sid.len * 2 + 1];
     sid.toString(buf, sizeof(buf));
     Debug("ssl.session_cache.get", "SessionCache looking in bucket %" PRId64 " (%p) for session '%s' (hash: %" PRIX64 ").", target_bucket, bucket, buf, hash);
   }

  ret = bucket->getSession(sid, sess);

  if (ret)
    SSL_INCREMENT_DYN_STAT(ssl_session_cache_hit);
  else
    SSL_INCREMENT_DYN_STAT(ssl_session_cache_miss);

  return ret;
}

void SSLSessionCache::removeSession(const SSLSessionID &sid) {
  uint64_t hash = sid.hash();
  uint64_t target_bucket = hash % SSLConfigParams::session_cache_number_buckets;
  SSLSessionBucket *bucket = &session_bucket[target_bucket];

  if (is_debug_tag_set("ssl.session_cache")) {
     char buf[sid.len * 2 + 1];
     sid.toString(buf, sizeof(buf));
     Debug("ssl.session_cache.remove", "SessionCache using bucket %" PRId64 " (%p): Removing session '%s' (hash: %" PRIX64 ").", target_bucket, bucket, buf, hash);
   }

  SSL_INCREMENT_DYN_STAT(ssl_session_cache_eviction);
  bucket->removeSession(sid);
}

void SSLSessionCache::insertSession(const SSLSessionID &sid, SSL_SESSION *sess) {
  uint64_t hash = sid.hash();
  uint64_t target_bucket = hash % SSLConfigParams::session_cache_number_buckets;
  SSLSessionBucket *bucket = &session_bucket[target_bucket];

  if (is_debug_tag_set("ssl.session_cache")) {
     char buf[sid.len * 2 + 1];
     sid.toString(buf, sizeof(buf));
     Debug("ssl.session_cache.insert", "SessionCache using bucket %" PRId64 " (%p): Inserting session '%s' (hash: %" PRIX64 ").", target_bucket, bucket, buf, hash);
   }

  bucket->insertSession(sid, sess);
}

void SSLSessionBucket::insertSession(const SSLSessionID &id, SSL_SESSION *sess) {
  size_t len = i2d_SSL_SESSION(sess, NULL); // make sure we're not going to need more than SSL_MAX_SESSION_SIZE bytes
  /* do not cache a session that's too big. */
  if (len > (size_t) SSL_MAX_SESSION_SIZE) {
      Debug("ssl.session_cache", "Unable to save SSL session because size of %zd exceeds the max of %d", len, SSL_MAX_SESSION_SIZE);
      return;
  }

  if (is_debug_tag_set("ssl.session_cache")) {
    char buf[id.len * 2 + 1];
    id.toString(buf, sizeof(buf));
    Debug("ssl.session_cache", "Inserting session '%s' to bucket %p.", buf, this);
  }

  Ptr<IOBufferData> buf;
  buf = new_IOBufferData(buffer_size_to_index(len, MAX_BUFFER_SIZE_INDEX), MEMALIGNED);
  ink_release_assert(static_cast<size_t>(buf->block_size()) >= len);
  unsigned char *loc = reinterpret_cast<unsigned char *>(buf->data());
  i2d_SSL_SESSION(sess, &loc);

  SSLSession *ssl_session = new SSLSession(id, buf, len);

  MUTEX_TRY_LOCK(lock, mutex, this_ethread());
  if (!lock.is_locked()) {
    SSL_INCREMENT_DYN_STAT(ssl_session_cache_lock_contention);
    if (SSLConfigParams::session_cache_skip_on_lock_contention)
      return;

    lock.acquire(this_ethread());
  }

  PRINT_BUCKET("insertSession before")
  if (queue.size >= static_cast<int>(SSLConfigParams::session_cache_max_bucket_size)) {
      removeOldestSession();
  }

  /* do the actual insert */
  queue.enqueue(ssl_session);

  PRINT_BUCKET("insertSession after")
}

bool SSLSessionBucket::getSession(const SSLSessionID &id,
                                  SSL_SESSION **sess) {
  char buf[id.len * 2 + 1];
  buf[0] = '\0'; // just to be safe.
  if (is_debug_tag_set("ssl.session_cache")) {
   id.toString(buf, sizeof(buf));
  }

  Debug("ssl.session_cache", "Looking for session with id '%s' in bucket %p", buf, this);

  MUTEX_TRY_LOCK(lock, mutex, this_ethread());
  if (!lock.is_locked()) {
   SSL_INCREMENT_DYN_STAT(ssl_session_cache_lock_contention);
   if (SSLConfigParams::session_cache_skip_on_lock_contention)
     return false;

   lock.acquire(this_ethread());
  }

  PRINT_BUCKET("getSession")

  // We work backwards because that's the most likely place we'll find our session...
  SSLSession *node = queue.tail;
  while (node) {
    if (node->session_id == id)
    {
       const unsigned char *loc = reinterpret_cast<const unsigned char *>(node->asn1_data->data());
       *sess = d2i_SSL_SESSION(NULL, &loc, node->len_asn1_data);

       return true;
    }
    node = node->link.prev;
  }

  Debug("ssl.session_cache", "Session with id '%s' not found in bucket %p.", buf, this);
  return false;
}

void inline SSLSessionBucket::print(const char *ref_str) const {
  /* NOTE: This method assumes you're already holding the bucket lock */
  if (!is_debug_tag_set("ssl.session_cache.bucket")) {
     return;
  }

  fprintf(stderr, "-------------- BUCKET %p (%s) ----------------\n", this, ref_str);
  fprintf(stderr, "Current Size: %d, Max Size: %zd\n", queue.size, SSLConfigParams::session_cache_max_bucket_size);
  fprintf(stderr, "Queue: \n");

  SSLSession *node = queue.head;
  while(node) {
    char s_buf[2 * node->session_id.len + 1];
    node->session_id.toString(s_buf, sizeof(s_buf));
    fprintf(stderr, "  %s\n", s_buf);
    node = node->link.next;
  }
}

void inline SSLSessionBucket::removeOldestSession() {
  PRINT_BUCKET("removeOldestSession before")
  while (queue.head && queue.size >= static_cast<int>(SSLConfigParams::session_cache_max_bucket_size)) {
    SSLSession *old_head = queue.pop();
    if (is_debug_tag_set("ssl.session_cache")) {
      char buf[old_head->session_id.len * 2 + 1];
      old_head->session_id.toString(buf, sizeof(buf));
      Debug("ssl.session_cache", "Removing session '%s' from bucket %p because the bucket has size %d and max %zd", buf, this, (queue.size + 1), SSLConfigParams::session_cache_max_bucket_size);
    }
    delete old_head;
  }
  PRINT_BUCKET("removeOldestSession after")
}

void SSLSessionBucket::removeSession(const SSLSessionID &id) {
  MUTEX_LOCK(lock, mutex, this_ethread()); // We can't bail on contention here because this session MUST be removed.
  SSLSession *node = queue.head;
  while (node) {
    if (node->session_id == id)
    {
      queue.remove(node);
      delete node;
      return;
    }
  }
}

/* Session Bucket */
SSLSessionBucket::SSLSessionBucket()
 : mutex(new ProxyMutex())
{
  mutex->init("session_bucket");
}

SSLSessionBucket::~SSLSessionBucket() {

}

<commit_msg>TS-3156: use a proxy allocated mutex<commit_after>/** @file

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include <cstring>
#include <deque>
#include "P_SSLConfig.h"
#include "SSLSessionCache.h"

#define SSLSESSIONCACHE_STRINGIFY0(x) #x
#define SSLSESSIONCACHE_STRINGIFY(x) SSLSESSIONCACHE_STRINGIFY0(x)
#define SSLSESSIONCACHE_LINENO SSLSESSIONCACHE_STRINGIFY(__LINE__)

#ifdef DEBUG
#define PRINT_BUCKET(x) this->print(x " at " __FILE__ ":" SSLSESSIONCACHE_LINENO);
#else
#define PRINT_BUCKET(x)
#endif

using ts::detail::RBNode;

/* Session Cache */
SSLSessionCache::SSLSessionCache()
  : session_bucket(NULL) {
  Debug("ssl.session_cache", "Created new ssl session cache %p with %ld buckets each with size max size %ld", this, SSLConfigParams::session_cache_number_buckets, SSLConfigParams::session_cache_max_bucket_size);

  session_bucket = new SSLSessionBucket[SSLConfigParams::session_cache_number_buckets];
}

SSLSessionCache::~SSLSessionCache() {
  delete []session_bucket;
}

bool SSLSessionCache::getSession(const SSLSessionID &sid, SSL_SESSION **sess) const {
  uint64_t hash = sid.hash();
  uint64_t target_bucket = hash % SSLConfigParams::session_cache_number_buckets;
  SSLSessionBucket *bucket = &session_bucket[target_bucket];
  bool ret = false;

  if (is_debug_tag_set("ssl.session_cache")) {
     char buf[sid.len * 2 + 1];
     sid.toString(buf, sizeof(buf));
     Debug("ssl.session_cache.get", "SessionCache looking in bucket %" PRId64 " (%p) for session '%s' (hash: %" PRIX64 ").", target_bucket, bucket, buf, hash);
   }

  ret = bucket->getSession(sid, sess);

  if (ret)
    SSL_INCREMENT_DYN_STAT(ssl_session_cache_hit);
  else
    SSL_INCREMENT_DYN_STAT(ssl_session_cache_miss);

  return ret;
}

void SSLSessionCache::removeSession(const SSLSessionID &sid) {
  uint64_t hash = sid.hash();
  uint64_t target_bucket = hash % SSLConfigParams::session_cache_number_buckets;
  SSLSessionBucket *bucket = &session_bucket[target_bucket];

  if (is_debug_tag_set("ssl.session_cache")) {
     char buf[sid.len * 2 + 1];
     sid.toString(buf, sizeof(buf));
     Debug("ssl.session_cache.remove", "SessionCache using bucket %" PRId64 " (%p): Removing session '%s' (hash: %" PRIX64 ").", target_bucket, bucket, buf, hash);
   }

  SSL_INCREMENT_DYN_STAT(ssl_session_cache_eviction);
  bucket->removeSession(sid);
}

void SSLSessionCache::insertSession(const SSLSessionID &sid, SSL_SESSION *sess) {
  uint64_t hash = sid.hash();
  uint64_t target_bucket = hash % SSLConfigParams::session_cache_number_buckets;
  SSLSessionBucket *bucket = &session_bucket[target_bucket];

  if (is_debug_tag_set("ssl.session_cache")) {
     char buf[sid.len * 2 + 1];
     sid.toString(buf, sizeof(buf));
     Debug("ssl.session_cache.insert", "SessionCache using bucket %" PRId64 " (%p): Inserting session '%s' (hash: %" PRIX64 ").", target_bucket, bucket, buf, hash);
   }

  bucket->insertSession(sid, sess);
}

void SSLSessionBucket::insertSession(const SSLSessionID &id, SSL_SESSION *sess) {
  size_t len = i2d_SSL_SESSION(sess, NULL); // make sure we're not going to need more than SSL_MAX_SESSION_SIZE bytes
  /* do not cache a session that's too big. */
  if (len > (size_t) SSL_MAX_SESSION_SIZE) {
      Debug("ssl.session_cache", "Unable to save SSL session because size of %zd exceeds the max of %d", len, SSL_MAX_SESSION_SIZE);
      return;
  }

  if (is_debug_tag_set("ssl.session_cache")) {
    char buf[id.len * 2 + 1];
    id.toString(buf, sizeof(buf));
    Debug("ssl.session_cache", "Inserting session '%s' to bucket %p.", buf, this);
  }

  Ptr<IOBufferData> buf;
  buf = new_IOBufferData(buffer_size_to_index(len, MAX_BUFFER_SIZE_INDEX), MEMALIGNED);
  ink_release_assert(static_cast<size_t>(buf->block_size()) >= len);
  unsigned char *loc = reinterpret_cast<unsigned char *>(buf->data());
  i2d_SSL_SESSION(sess, &loc);

  SSLSession *ssl_session = new SSLSession(id, buf, len);

  MUTEX_TRY_LOCK(lock, mutex, this_ethread());
  if (!lock.is_locked()) {
    SSL_INCREMENT_DYN_STAT(ssl_session_cache_lock_contention);
    if (SSLConfigParams::session_cache_skip_on_lock_contention)
      return;

    lock.acquire(this_ethread());
  }

  PRINT_BUCKET("insertSession before")
  if (queue.size >= static_cast<int>(SSLConfigParams::session_cache_max_bucket_size)) {
      removeOldestSession();
  }

  /* do the actual insert */
  queue.enqueue(ssl_session);

  PRINT_BUCKET("insertSession after")
}

bool SSLSessionBucket::getSession(const SSLSessionID &id,
                                  SSL_SESSION **sess) {
  char buf[id.len * 2 + 1];
  buf[0] = '\0'; // just to be safe.
  if (is_debug_tag_set("ssl.session_cache")) {
   id.toString(buf, sizeof(buf));
  }

  Debug("ssl.session_cache", "Looking for session with id '%s' in bucket %p", buf, this);

  MUTEX_TRY_LOCK(lock, mutex, this_ethread());
  if (!lock.is_locked()) {
   SSL_INCREMENT_DYN_STAT(ssl_session_cache_lock_contention);
   if (SSLConfigParams::session_cache_skip_on_lock_contention)
     return false;

   lock.acquire(this_ethread());
  }

  PRINT_BUCKET("getSession")

  // We work backwards because that's the most likely place we'll find our session...
  SSLSession *node = queue.tail;
  while (node) {
    if (node->session_id == id)
    {
       const unsigned char *loc = reinterpret_cast<const unsigned char *>(node->asn1_data->data());
       *sess = d2i_SSL_SESSION(NULL, &loc, node->len_asn1_data);

       return true;
    }
    node = node->link.prev;
  }

  Debug("ssl.session_cache", "Session with id '%s' not found in bucket %p.", buf, this);
  return false;
}

void inline SSLSessionBucket::print(const char *ref_str) const {
  /* NOTE: This method assumes you're already holding the bucket lock */
  if (!is_debug_tag_set("ssl.session_cache.bucket")) {
     return;
  }

  fprintf(stderr, "-------------- BUCKET %p (%s) ----------------\n", this, ref_str);
  fprintf(stderr, "Current Size: %d, Max Size: %zd\n", queue.size, SSLConfigParams::session_cache_max_bucket_size);
  fprintf(stderr, "Queue: \n");

  SSLSession *node = queue.head;
  while(node) {
    char s_buf[2 * node->session_id.len + 1];
    node->session_id.toString(s_buf, sizeof(s_buf));
    fprintf(stderr, "  %s\n", s_buf);
    node = node->link.next;
  }
}

void inline SSLSessionBucket::removeOldestSession() {
  PRINT_BUCKET("removeOldestSession before")
  while (queue.head && queue.size >= static_cast<int>(SSLConfigParams::session_cache_max_bucket_size)) {
    SSLSession *old_head = queue.pop();
    if (is_debug_tag_set("ssl.session_cache")) {
      char buf[old_head->session_id.len * 2 + 1];
      old_head->session_id.toString(buf, sizeof(buf));
      Debug("ssl.session_cache", "Removing session '%s' from bucket %p because the bucket has size %d and max %zd", buf, this, (queue.size + 1), SSLConfigParams::session_cache_max_bucket_size);
    }
    delete old_head;
  }
  PRINT_BUCKET("removeOldestSession after")
}

void SSLSessionBucket::removeSession(const SSLSessionID &id) {
  MUTEX_LOCK(lock, mutex, this_ethread()); // We can't bail on contention here because this session MUST be removed.
  SSLSession *node = queue.head;
  while (node) {
    if (node->session_id == id)
    {
      queue.remove(node);
      delete node;
      return;
    }
  }
}

/* Session Bucket */
SSLSessionBucket::SSLSessionBucket() : mutex(new_ProxyMutex())
{
}

SSLSessionBucket::~SSLSessionBucket()
{
}

<|endoftext|>


<commit_before>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This test is POSIX only.

#include <unistd.h>
#include <stdio.h>

#include "base/basictypes.h"
#include "chrome/common/file_descriptor_set_posix.h"
#include "testing/gtest/include/gtest/gtest.h"

// The FileDescriptorSet will try and close some of the descriptor numbers
// which we given it. This is the base descriptor value. It's great enough such
// that no real descriptor will accidently be closed.
static const int kFDBase = 50000;

TEST(FileDescriptorSet, BasicAdd) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_EQ(set->size(), 0u);
  ASSERT_TRUE(set->empty());
  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_EQ(set->size(), 1u);
  ASSERT_TRUE(!set->empty());

  // Empties the set and stops a warning about deleting a set with unconsumed
  // descriptors
  set->CommitAll();
}

TEST(FileDescriptorSet, BasicAddAndClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_EQ(set->size(), 0u);
  ASSERT_TRUE(set->empty());
  ASSERT_TRUE(set->AddAndAutoClose(kFDBase));
  ASSERT_EQ(set->size(), 1u);
  ASSERT_TRUE(!set->empty());

  set->CommitAll();
}

TEST(FileDescriptorSet, MaxSize) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  for (unsigned i = 0;
       i < FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE; ++i) {
    ASSERT_TRUE(set->Add(kFDBase + 1 + i));
  }

  ASSERT_TRUE(!set->Add(kFDBase));

  set->CommitAll();
}

TEST(FileDescriptorSet, SetDescriptors) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->empty());
  set->SetDescriptors(NULL, 0);
  ASSERT_TRUE(set->empty());

  static const int fds[] = {kFDBase};
  set->SetDescriptors(fds, 1);
  ASSERT_TRUE(!set->empty());
  ASSERT_EQ(set->size(), 1u);

  set->CommitAll();
}

TEST(FileDescriptorSet, GetDescriptors) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  set->GetDescriptors(NULL);
  ASSERT_TRUE(set->Add(kFDBase));

  int fds[1];
  fds[0] = 0;
  set->GetDescriptors(fds);
  ASSERT_EQ(fds[0], kFDBase);
  set->CommitAll();
  ASSERT_TRUE(set->empty());
}

TEST(FileDescriptorSet, WalkInOrder) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);

  set->CommitAll();
}

TEST(FileDescriptorSet, WalkWrongOrder) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(2), -1);

  set->CommitAll();
}

TEST(FileDescriptorSet, WalkCycle) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);

  set->CommitAll();
}

TEST(FileDescriptorSet, DontClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  const int fd = open("/dev/null", O_RDONLY);
  ASSERT_TRUE(set->Add(fd));
  set->CommitAll();

  const int duped = dup(fd);
  ASSERT_GE(duped, 0);
  close(duped);
  close(fd);
}

TEST(FileDescriptorSet, DoClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  const int fd = open("/dev/null", O_RDONLY);
  ASSERT_TRUE(set->AddAndAutoClose(fd));
  set->CommitAll();

  const int duped = dup(fd);
  ASSERT_EQ(duped, -1);
  close(fd);
}
<commit_msg>Mac: build fix<commit_after>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This test is POSIX only.

#include <unistd.h>
#include <fcntl.h>

#include "base/basictypes.h"
#include "chrome/common/file_descriptor_set_posix.h"
#include "testing/gtest/include/gtest/gtest.h"

// The FileDescriptorSet will try and close some of the descriptor numbers
// which we given it. This is the base descriptor value. It's great enough such
// that no real descriptor will accidently be closed.
static const int kFDBase = 50000;

TEST(FileDescriptorSet, BasicAdd) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_EQ(set->size(), 0u);
  ASSERT_TRUE(set->empty());
  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_EQ(set->size(), 1u);
  ASSERT_TRUE(!set->empty());

  // Empties the set and stops a warning about deleting a set with unconsumed
  // descriptors
  set->CommitAll();
}

TEST(FileDescriptorSet, BasicAddAndClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_EQ(set->size(), 0u);
  ASSERT_TRUE(set->empty());
  ASSERT_TRUE(set->AddAndAutoClose(kFDBase));
  ASSERT_EQ(set->size(), 1u);
  ASSERT_TRUE(!set->empty());

  set->CommitAll();
}

TEST(FileDescriptorSet, MaxSize) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  for (unsigned i = 0;
       i < FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE; ++i) {
    ASSERT_TRUE(set->Add(kFDBase + 1 + i));
  }

  ASSERT_TRUE(!set->Add(kFDBase));

  set->CommitAll();
}

TEST(FileDescriptorSet, SetDescriptors) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->empty());
  set->SetDescriptors(NULL, 0);
  ASSERT_TRUE(set->empty());

  static const int fds[] = {kFDBase};
  set->SetDescriptors(fds, 1);
  ASSERT_TRUE(!set->empty());
  ASSERT_EQ(set->size(), 1u);

  set->CommitAll();
}

TEST(FileDescriptorSet, GetDescriptors) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  set->GetDescriptors(NULL);
  ASSERT_TRUE(set->Add(kFDBase));

  int fds[1];
  fds[0] = 0;
  set->GetDescriptors(fds);
  ASSERT_EQ(fds[0], kFDBase);
  set->CommitAll();
  ASSERT_TRUE(set->empty());
}

TEST(FileDescriptorSet, WalkInOrder) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);

  set->CommitAll();
}

TEST(FileDescriptorSet, WalkWrongOrder) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(2), -1);

  set->CommitAll();
}

TEST(FileDescriptorSet, WalkCycle) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);

  set->CommitAll();
}

TEST(FileDescriptorSet, DontClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  const int fd = open("/dev/null", O_RDONLY);
  ASSERT_TRUE(set->Add(fd));
  set->CommitAll();

  const int duped = dup(fd);
  ASSERT_GE(duped, 0);
  close(duped);
  close(fd);
}

TEST(FileDescriptorSet, DoClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  const int fd = open("/dev/null", O_RDONLY);
  ASSERT_TRUE(set->AddAndAutoClose(fd));
  set->CommitAll();

  const int duped = dup(fd);
  ASSERT_EQ(duped, -1);
  close(fd);
}
<|endoftext|>


<commit_before>#pragma once

#define NUM_THREAD_BLOCKS 2500
#define NUM_THREADS 640000

#include <Interface/Manager/ComputeShaderManager.hpp>
#include <Internal/Light/LightInfoImpl.hpp>
#include <DirectXMath.h>
#include <d3d11.h>
#include <vector>
namespace DoremiEngine
{
    namespace Graphic
    {
        struct LightInfo;
        struct GraphicModuleContext;
        struct Plane
        {
            DirectX::XMFLOAT3 normal; // plane normal
            float distance; // distance to origin
        };
        struct FrustumInfo
        {
            Plane plane[4];
        };

        struct LightIndexListBuffer
        {
            // std::vector<unsigned int> lightIndexList;
            unsigned int LightIndexList[NUM_THREAD_BLOCKS * 200];
        };

        struct LightGridInfo
        {
            unsigned int offset;
            unsigned int value;
        };

        struct LightGridBuffer
        {
            LightGridInfo lightGridInfo[NUM_THREAD_BLOCKS];
        };

        struct LightCounterBuffer
        {
            float counter;
        };

        struct FrustumArray
        {
            FrustumInfo frustum[NUM_THREAD_BLOCKS];
        };

        enum BufferType
        {
            FRUSTUM,
            O_LIGHTCOUNTER,
            T_LIGHTCOUNTER,
            O_LIGHTINDEXLIST,
            T_LIGHTINDEXLIST,
            O_LIGHTGRID,
            T_LIGHTGRID,

            NUM_BUFFERS
        };

        class ComputeShaderManagerImpl : public ComputeShaderManager
        {
        public:
            ComputeShaderManagerImpl(const GraphicModuleContext& p_graphicContext);
            ~ComputeShaderManagerImpl();
            void CreateComputeShaders() override;
            // Set UAV for compute shaders. Index specifies which struct to send
            void SetUAV(BufferType index) override;
            void SetSRV();
            ID3D11UnorderedAccessView* GetUAV(int i) override;
            void DispatchFrustum() override;
            void DispatchCulling() override;
            void CopyCullingData() override;
            void CopyData(BufferType index);

        private:
            const GraphicModuleContext& m_graphicContext;
            ID3D11DeviceContext* m_deviceContext;
            FrustumArray* m_frustumArray;
            LightCounterBuffer* m_oLightCounter;
            LightCounterBuffer* m_tLightCounter;
            LightIndexListBuffer* m_oLightIndexList;
            LightIndexListBuffer* m_tLightIndexList;
            LightGridBuffer* m_oLightGrid;
            LightGridBuffer* m_tLightGrid;
            ID3D11UnorderedAccessView* m_uav[NUM_BUFFERS];
            ID3D11ShaderResourceView* m_srv[NUM_BUFFERS];
            ID3D11Buffer* m_buffer[NUM_BUFFERS];
            ID3D11Buffer* m_bufferResult[NUM_BUFFERS];
            ComputeShader* m_frustumShader;
            ComputeShader* m_cullingShader;
        };
    }
}
<commit_msg>Fixed forward declaration for incorrect type<commit_after>#pragma once

#define NUM_THREAD_BLOCKS 2500
#define NUM_THREADS 640000

#include <Interface/Manager/ComputeShaderManager.hpp>
#include <Internal/Light/LightInfoImpl.hpp>
#include <DirectXMath.h>
#include <d3d11.h>
#include <vector>
namespace DoremiEngine
{
    namespace Graphic
    {
        class LightInfo;
        struct GraphicModuleContext;
        struct Plane
        {
            DirectX::XMFLOAT3 normal; // plane normal
            float distance; // distance to origin
        };
        struct FrustumInfo
        {
            Plane plane[4];
        };

        struct LightIndexListBuffer
        {
            // std::vector<unsigned int> lightIndexList;
            unsigned int LightIndexList[NUM_THREAD_BLOCKS * 200];
        };

        struct LightGridInfo
        {
            unsigned int offset;
            unsigned int value;
        };

        struct LightGridBuffer
        {
            LightGridInfo lightGridInfo[NUM_THREAD_BLOCKS];
        };

        struct LightCounterBuffer
        {
            float counter;
        };

        struct FrustumArray
        {
            FrustumInfo frustum[NUM_THREAD_BLOCKS];
        };

        enum BufferType
        {
            FRUSTUM,
            O_LIGHTCOUNTER,
            T_LIGHTCOUNTER,
            O_LIGHTINDEXLIST,
            T_LIGHTINDEXLIST,
            O_LIGHTGRID,
            T_LIGHTGRID,

            NUM_BUFFERS
        };

        class ComputeShaderManagerImpl : public ComputeShaderManager
        {
        public:
            ComputeShaderManagerImpl(const GraphicModuleContext& p_graphicContext);
            ~ComputeShaderManagerImpl();
            void CreateComputeShaders() override;
            // Set UAV for compute shaders. Index specifies which struct to send
            void SetUAV(BufferType index) override;
            void SetSRV();
            ID3D11UnorderedAccessView* GetUAV(int i) override;
            void DispatchFrustum() override;
            void DispatchCulling() override;
            void CopyCullingData() override;
            void CopyData(BufferType index);

        private:
            const GraphicModuleContext& m_graphicContext;
            ID3D11DeviceContext* m_deviceContext;
            FrustumArray* m_frustumArray;
            LightCounterBuffer* m_oLightCounter;
            LightCounterBuffer* m_tLightCounter;
            LightIndexListBuffer* m_oLightIndexList;
            LightIndexListBuffer* m_tLightIndexList;
            LightGridBuffer* m_oLightGrid;
            LightGridBuffer* m_tLightGrid;
            ID3D11UnorderedAccessView* m_uav[NUM_BUFFERS];
            ID3D11ShaderResourceView* m_srv[NUM_BUFFERS];
            ID3D11Buffer* m_buffer[NUM_BUFFERS];
            ID3D11Buffer* m_bufferResult[NUM_BUFFERS];
            ComputeShader* m_frustumShader;
            ComputeShader* m_cullingShader;
        };
    }
}
<|endoftext|>


<commit_before>/**
 * @file regularized_svd_test.cpp
 * @author Siddharth Agrawal
 *
 * Test the RegularizedSVDFunction class.
 */
#include <mlpack/core.hpp>
#include <mlpack/methods/regularized_svd/regularized_svd.hpp>

#include <boost/test/unit_test.hpp>
#include "old_boost_test_definitions.hpp"

using namespace mlpack::svd;

BOOST_AUTO_TEST_SUITE(RegularizedSVDTest);

BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionRandomEvaluate)
{
  // Define useful constants.
  const size_t numUsers = 100;
  const size_t numItems = 100;
  const size_t numRatings = 1000;
  const size_t maxRating = 5;
  const size_t rank = 10;
  const size_t numTrials = 50;

  // Make a random rating dataset.
  arma::mat data = arma::randu(3, numRatings);
  data.row(0) = floor(data.row(0) * numUsers);
  data.row(1) = floor(data.row(1) * numItems);
  data.row(2) = floor(data.row(2) * maxRating + 0.5);

  // Make a RegularizedSVDFunction with zero regularization.
  RegularizedSVDFunction rSVDFunc(data, rank, 0);

  for(size_t i = 0; i < numTrials; i++)
  {
    arma::mat parameters = arma::randu(rank, numUsers + numItems);

    // Calculate cost by summing up cost of each example.
    double cost = 0;
    for(size_t j = 0; j < numRatings; j++)
    {
      const size_t user = data(0, j);
      const size_t item = data(1, j) + numUsers;

      const double rating = data(2, j);
      double ratingError = rating - arma::dot(parameters.col(user),
                                              parameters.col(item));
      double ratingErrorSquared = ratingError * ratingError;

      cost += ratingErrorSquared;
    }

    // Compare calculated cost and value obtained using Evaluate().
    BOOST_REQUIRE_CLOSE(cost, rSVDFunc.Evaluate(parameters), 1e-5);
  }
}

BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionRegularizationEvaluate)
{
  // Define useful constants.
  const size_t numUsers = 100;
  const size_t numItems = 100;
  const size_t numRatings = 1000;
  const size_t maxRating = 5;
  const size_t rank = 10;
  const size_t numTrials = 50;

  // Make a random rating dataset.
  arma::mat data = arma::randu(3, numRatings);
  data.row(0) = floor(data.row(0) * numUsers);
  data.row(1) = floor(data.row(1) * numItems);
  data.row(2) = floor(data.row(2) * maxRating + 0.5);

  // Make three RegularizedSVDFunction objects with different amounts of
  // regularization.
  RegularizedSVDFunction rSVDFuncNoReg(data, rank, 0);
  RegularizedSVDFunction rSVDFuncSmallReg(data, rank, 0.5);
  RegularizedSVDFunction rSVDFuncBigReg(data, rank, 20);

  for(size_t i = 0; i < numTrials; i++)
  {
    arma::mat parameters = arma::randu(rank, numUsers + numItems);

    // Calculate the regularization contributions of parameters corresponding to
    // each rating and sum them up.
    double smallRegTerm = 0;
    double bigRegTerm = 0;
    for(size_t j = 0; j < numRatings; j++)
    {
      const size_t user = data(0, j);
      const size_t item = data(1, j) + numUsers;

      double userVecNorm = arma::norm(parameters.col(user), 2);
      double itemVecNorm = arma::norm(parameters.col(item), 2);
      smallRegTerm += 0.5 * (userVecNorm * userVecNorm +
                             itemVecNorm * itemVecNorm);
      bigRegTerm += 20 * (userVecNorm * userVecNorm +
                          itemVecNorm * itemVecNorm);
    }

    // Cost with regularization should be close to the sum of cost without
    // regularization and the regularization terms.
    BOOST_REQUIRE_CLOSE(rSVDFuncNoReg.Evaluate(parameters) + smallRegTerm,
        rSVDFuncSmallReg.Evaluate(parameters), 1e-5);
    BOOST_REQUIRE_CLOSE(rSVDFuncNoReg.Evaluate(parameters) + bigRegTerm,
        rSVDFuncBigReg.Evaluate(parameters), 1e-5);
  }
}

BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionGradient)
{
  // Define useful constants.
  const size_t numUsers = 50;
  const size_t numItems = 50;
  const size_t numRatings = 100;
  const size_t maxRating = 5;
  const size_t rank = 10;

  // Make a random rating dataset.
  arma::mat data = arma::randu(3, numRatings);
  data.row(0) = floor(data.row(0) * numUsers);
  data.row(1) = floor(data.row(1) * numItems);
  data.row(2) = floor(data.row(2) * maxRating + 0.5);

  arma::mat parameters = arma::randu(rank, numUsers + numItems);

  // Make two RegularizedSVDFunction objects, one with regularization and one
  // without.
  RegularizedSVDFunction rSVDFunc1(data, rank, 0);
  RegularizedSVDFunction rSVDFunc2(data, rank, 0.5);

  // Calculate gradients for both the objects.
  arma::mat gradient1, gradient2;
  rSVDFunc1.Gradient(parameters, gradient1);
  rSVDFunc2.Gradient(parameters, gradient2);

  // Perturbation constant.
  const double epsilon = 0.0001;
  double costPlus1, costMinus1, numGradient1;
  double costPlus2, costMinus2, numGradient2;

  for(size_t i = 0; i < rank; i++)
  {
    for(size_t j = 0; j < numUsers + numItems; j++)
    {
      // Perturb parameter with a positive constant and get costs.
      parameters(i, j) += epsilon;
      costPlus1 = rSVDFunc1.Evaluate(parameters);
      costPlus2 = rSVDFunc2.Evaluate(parameters);

      // Perturb parameter with a negative constant and get costs.
      parameters(i, j) -= 2 * epsilon;
      costMinus1 = rSVDFunc1.Evaluate(parameters);
      costMinus2 = rSVDFunc2.Evaluate(parameters);

      // Compute numerical gradients using the costs calculated above.
      numGradient1 = (costPlus1 - costMinus1) / (2 * epsilon);
      numGradient2 = (costPlus2 - costMinus2) / (2 * epsilon);

      // Restore the parameter value.
      parameters(i, j) += epsilon;

      // Compare numerical and backpropagation gradient values.
      BOOST_REQUIRE_CLOSE(numGradient1, gradient1(i, j), 1e-2);
      BOOST_REQUIRE_CLOSE(numGradient2, gradient2(i, j), 1e-2);
    }
  }
}

BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionOptimize)
{
  // Define useful constants.
  const size_t numUsers = 50;
  const size_t numItems = 50;
  const size_t numRatings = 100;
  const size_t iterations = 10;
  const size_t rank = 10;
  const double alpha = 0.01;
  const double lambda = 0.01;

  // Initiate random parameters.
  arma::mat parameters = arma::randu(rank, numUsers + numItems);

  // Make a random rating dataset.
  arma::mat data = arma::randu(3, numRatings);
  data.row(0) = floor(data.row(0) * numUsers);
  data.row(1) = floor(data.row(1) * numItems);

  // Make rating entries based on the parameters.
  for(size_t i = 0; i < numRatings; i++)
  {
    data(2, i) = arma::dot(parameters.col(data(0, i)),
                           parameters.col(numUsers + data(1, i)));
  }

  // Make the Reg SVD function and the optimizer.
  RegularizedSVDFunction rSVDFunc(data, rank, lambda);
  mlpack::optimization::SGD<RegularizedSVDFunction> optimizer(rSVDFunc,
      alpha, iterations * numRatings);

  // Obtain optimized parameters after training.
  arma::mat optParameters = arma::randu(rank, numUsers + numItems);
  optimizer.Optimize(optParameters);

  // Get predicted ratings from optimized parameters.
  arma::mat predictedData(1, numRatings);
  for(size_t i = 0; i < numRatings; i++)
  {
    predictedData(0, i) = arma::dot(optParameters.col(data(0, i)),
                                    optParameters.col(numUsers + data(1, i)));
  }

  // Calculate relative error.
  double relativeError = arma::norm(data.row(2) - predictedData, "frob") /
                         arma::norm(data, "frob");

  // Relative error should be small.
  BOOST_REQUIRE_SMALL(relativeError, 1e-2);
}

BOOST_AUTO_TEST_SUITE_END();
<commit_msg>For each random dataset, ensure that the size of the implied user/item matrix is numUsers by numItems by manually setting the last element.  Some formatting and const-correctness fixes.  Also, increase the number of iterations for the optimization test since it didn't seem to be converging (hopefully the specific number of 10 passes over the data was not chosen for a particular reason).<commit_after>/**
 * @file regularized_svd_test.cpp
 * @author Siddharth Agrawal
 *
 * Test the RegularizedSVDFunction class.
 */
#include <mlpack/core.hpp>
#include <mlpack/methods/regularized_svd/regularized_svd.hpp>

#include <boost/test/unit_test.hpp>
#include "old_boost_test_definitions.hpp"

using namespace mlpack;
using namespace mlpack::svd;

BOOST_AUTO_TEST_SUITE(RegularizedSVDTest);

BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionRandomEvaluate)
{
  // Define useful constants.
  const size_t numUsers = 100;
  const size_t numItems = 100;
  const size_t numRatings = 1000;
  const size_t maxRating = 5;
  const size_t rank = 10;
  const size_t numTrials = 50;

  // Make a random rating dataset.
  arma::mat data = arma::randu(3, numRatings);
  data.row(0) = floor(data.row(0) * numUsers);
  data.row(1) = floor(data.row(1) * numItems);
  data.row(2) = floor(data.row(2) * maxRating + 0.5);

  // Manually set last row to maximum user and maximum item.
  data(0, numRatings - 1) = numUsers - 1;
  data(1, numRatings - 1) = numItems - 1;

  // Make a RegularizedSVDFunction with zero regularization.
  RegularizedSVDFunction rSVDFunc(data, rank, 0);

  for (size_t i = 0; i < numTrials; i++)
  {
    arma::mat parameters = arma::randu(rank, numUsers + numItems);

    // Calculate cost by summing up cost of each example.
    double cost = 0;
    for (size_t j = 0; j < numRatings; j++)
    {
      const size_t user = data(0, j);
      const size_t item = data(1, j) + numUsers;

      const double rating = data(2, j);
      const double ratingError = rating - arma::dot(parameters.col(user),
                                                    parameters.col(item));
      const double ratingErrorSquared = ratingError * ratingError;

      cost += ratingErrorSquared;
    }

    // Compare calculated cost and value obtained using Evaluate().
    BOOST_REQUIRE_CLOSE(cost, rSVDFunc.Evaluate(parameters), 1e-5);
  }
}

BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionRegularizationEvaluate)
{
  // Define useful constants.
  const size_t numUsers = 100;
  const size_t numItems = 100;
  const size_t numRatings = 1000;
  const size_t maxRating = 5;
  const size_t rank = 10;
  const size_t numTrials = 50;

  // Make a random rating dataset.
  arma::mat data = arma::randu(3, numRatings);
  data.row(0) = floor(data.row(0) * numUsers);
  data.row(1) = floor(data.row(1) * numItems);
  data.row(2) = floor(data.row(2) * maxRating + 0.5);

  // Manually set last row to maximum user and maximum item.
  data(0, numRatings - 1) = numUsers - 1;
  data(1, numRatings - 1) = numItems - 1;

  // Make three RegularizedSVDFunction objects with different amounts of
  // regularization.
  RegularizedSVDFunction rSVDFuncNoReg(data, rank, 0);
  RegularizedSVDFunction rSVDFuncSmallReg(data, rank, 0.5);
  RegularizedSVDFunction rSVDFuncBigReg(data, rank, 20);

  for (size_t i = 0; i < numTrials; i++)
  {
    arma::mat parameters = arma::randu(rank, numUsers + numItems);

    // Calculate the regularization contributions of parameters corresponding to
    // each rating and sum them up.
    double smallRegTerm = 0;
    double bigRegTerm = 0;
    for (size_t j = 0; j < numRatings; j++)
    {
      const size_t user = data(0, j);
      const size_t item = data(1, j) + numUsers;

      const double userVecNorm = arma::norm(parameters.col(user), 2);
      const double itemVecNorm = arma::norm(parameters.col(item), 2);
      smallRegTerm += 0.5 * (userVecNorm * userVecNorm +
                             itemVecNorm * itemVecNorm);
      bigRegTerm += 20 * (userVecNorm * userVecNorm +
                          itemVecNorm * itemVecNorm);
    }

    // Cost with regularization should be close to the sum of cost without
    // regularization and the regularization terms.
    BOOST_REQUIRE_CLOSE(rSVDFuncNoReg.Evaluate(parameters) + smallRegTerm,
        rSVDFuncSmallReg.Evaluate(parameters), 1e-5);
    BOOST_REQUIRE_CLOSE(rSVDFuncNoReg.Evaluate(parameters) + bigRegTerm,
        rSVDFuncBigReg.Evaluate(parameters), 1e-5);
  }
}

BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionGradient)
{
  // Define useful constants.
  const size_t numUsers = 50;
  const size_t numItems = 50;
  const size_t numRatings = 100;
  const size_t maxRating = 5;
  const size_t rank = 10;

  // Make a random rating dataset.
  arma::mat data = arma::randu(3, numRatings);
  data.row(0) = floor(data.row(0) * numUsers);
  data.row(1) = floor(data.row(1) * numItems);
  data.row(2) = floor(data.row(2) * maxRating + 0.5);

  // Manually set last row to maximum user and maximum item.
  data(0, numRatings - 1) = numUsers - 1;
  data(1, numRatings - 1) = numItems - 1;

  arma::mat parameters = arma::randu(rank, numUsers + numItems);

  // Make two RegularizedSVDFunction objects, one with regularization and one
  // without.
  RegularizedSVDFunction rSVDFunc1(data, rank, 0);
  RegularizedSVDFunction rSVDFunc2(data, rank, 0.5);

  // Calculate gradients for both the objects.
  arma::mat gradient1, gradient2;
  rSVDFunc1.Gradient(parameters, gradient1);
  rSVDFunc2.Gradient(parameters, gradient2);

  // Perturbation constant.
  const double epsilon = 0.0001;
  double costPlus1, costMinus1, numGradient1;
  double costPlus2, costMinus2, numGradient2;

  for (size_t i = 0; i < rank; i++)
  {
    for (size_t j = 0; j < numUsers + numItems; j++)
    {
      // Perturb parameter with a positive constant and get costs.
      parameters(i, j) += epsilon;
      costPlus1 = rSVDFunc1.Evaluate(parameters);
      costPlus2 = rSVDFunc2.Evaluate(parameters);

      // Perturb parameter with a negative constant and get costs.
      parameters(i, j) -= 2 * epsilon;
      costMinus1 = rSVDFunc1.Evaluate(parameters);
      costMinus2 = rSVDFunc2.Evaluate(parameters);

      // Compute numerical gradients using the costs calculated above.
      numGradient1 = (costPlus1 - costMinus1) / (2 * epsilon);
      numGradient2 = (costPlus2 - costMinus2) / (2 * epsilon);

      // Restore the parameter value.
      parameters(i, j) += epsilon;

      // Compare numerical and backpropagation gradient values.
      BOOST_REQUIRE_CLOSE(numGradient1, gradient1(i, j), 1e-2);
      BOOST_REQUIRE_CLOSE(numGradient2, gradient2(i, j), 1e-2);
    }
  }
}

BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionOptimize)
{
  // Define useful constants.
  const size_t numUsers = 50;
  const size_t numItems = 50;
  const size_t numRatings = 100;
  const size_t iterations = 30;
  const size_t rank = 10;
  const double alpha = 0.01;
  const double lambda = 0.01;

  // Initiate random parameters.
  arma::mat parameters = arma::randu(rank, numUsers + numItems);

  // Make a random rating dataset.
  arma::mat data = arma::randu(3, numRatings);
  data.row(0) = floor(data.row(0) * numUsers);
  data.row(1) = floor(data.row(1) * numItems);

  // Manually set last row to maximum user and maximum item.
  data(0, numRatings - 1) = numUsers - 1;
  data(1, numRatings - 1) = numItems - 1;

  // Make rating entries based on the parameters.
  for (size_t i = 0; i < numRatings; i++)
  {
    data(2, i) = arma::dot(parameters.col(data(0, i)),
                           parameters.col(numUsers + data(1, i)));
  }

  // Make the Reg SVD function and the optimizer.
  RegularizedSVDFunction rSVDFunc(data, rank, lambda);
  mlpack::optimization::SGD<RegularizedSVDFunction> optimizer(rSVDFunc,
      alpha, iterations * numRatings);

  // Obtain optimized parameters after training.
  arma::mat optParameters = arma::randu(rank, numUsers + numItems);
  optimizer.Optimize(optParameters);

  // Get predicted ratings from optimized parameters.
  arma::mat predictedData(1, numRatings);
  for (size_t i = 0; i < numRatings; i++)
  {
    predictedData(0, i) = arma::dot(optParameters.col(data(0, i)),
                                    optParameters.col(numUsers + data(1, i)));
  }

  // Calculate relative error.
  const double relativeError = arma::norm(data.row(2) - predictedData, "frob") /
                               arma::norm(data, "frob");

  // Relative error should be small.
  BOOST_REQUIRE_SMALL(relativeError, 1e-2);
}

BOOST_AUTO_TEST_SUITE_END();
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "catch.hpp"

#include "dll/rbm.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

TEST_CASE( "rbm/mnist_1", "rbm::simple" ) {
    dll::rbm_desc<
        28 * 28, 100,
        dll::batch_size<25>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_2", "rbm::momentum" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::momentum
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_3", "rbm::pcd_trainer" ) {
    dll::rbm_desc<
        28 * 28, 100,
        dll::batch_size<25>,
        dll::momentum,
        dll::trainer<dll::pcd1_trainer_t>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-1);
}

TEST_CASE( "rbm/mnist_4", "rbm::decay_l1" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::weight_decay<dll::decay_type::L1>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_5", "rbm::decay_l2" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::weight_decay<dll::decay_type::L2>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_6", "rbm::sparsity" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::sparsity
    >::rbm_t rbm;

    //0.01 (default) is way too low for 100 hidden units
    rbm.sparsity_target = 0.1;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_7", "rbm::gaussian" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::visible<dll::unit_type::GAUSSIAN>
    >::rbm_t rbm;

    rbm.learning_rate *= 10;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::normalize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 200);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_8", "rbm::softmax" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::hidden<dll::unit_type::SOFTMAX>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    //This test is kind of fake since softmax unit are not really made for
    //reconstruction. It is here to ensure that softmax units are working.

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_9", "rbm::nrlu" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::hidden<dll::unit_type::RELU>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 200);

    REQUIRE(error < 1e-1);
}

TEST_CASE( "rbm/mnist_10", "rbm::nrlu1" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::hidden<dll::unit_type::RELU1>
    >::rbm_t rbm;

    rbm.learning_rate *= 2.0;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 200);

    REQUIRE(error < 1e-1);
}

TEST_CASE( "rbm/mnist_11", "rbm::nrlu6" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::hidden<dll::unit_type::RELU6>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 200);

    REQUIRE(error < 1e-1);
}

TEST_CASE( "rbm/mnist_12", "rbm::init_weights" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::init_weights
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 200);

    REQUIRE(error < 1e-3);
}

TEST_CASE( "rbm/mnist_13", "rbm::exp" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::hidden<dll::unit_type::EXP>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    //This test is kind of fake since exp unit are not really made for
    //reconstruction. It is here to ensure that exp units are working.
    //exponential units are not even made for training

    REQUIRE(std::isnan(error));
}<commit_msg>Clean<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "catch.hpp"

#include "dll/rbm.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

TEST_CASE( "rbm/mnist_1", "rbm::simple" ) {
    dll::rbm_desc<
        28 * 28, 100,
        dll::batch_size<25>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_2", "rbm::momentum" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::momentum
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_3", "rbm::pcd_trainer" ) {
    dll::rbm_desc<
        28 * 28, 100,
        dll::batch_size<25>,
        dll::momentum,
        dll::trainer<dll::pcd1_trainer_t>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-1);
}

TEST_CASE( "rbm/mnist_4", "rbm::decay_l1" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::weight_decay<dll::decay_type::L1>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_5", "rbm::decay_l2" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::weight_decay<dll::decay_type::L2>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_6", "rbm::sparsity" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::sparsity
    >::rbm_t rbm;

    //0.01 (default) is way too low for 100 hidden units
    rbm.sparsity_target = 0.1;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_7", "rbm::gaussian" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::visible<dll::unit_type::GAUSSIAN>
    >::rbm_t rbm;

    rbm.learning_rate *= 10;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::normalize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 200);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_8", "rbm::softmax" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::hidden<dll::unit_type::SOFTMAX>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    REQUIRE(error < 1e-2);
}

TEST_CASE( "rbm/mnist_9", "rbm::relu" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::hidden<dll::unit_type::RELU>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 200);

    REQUIRE(error < 1e-1);
}

TEST_CASE( "rbm/mnist_10", "rbm::relu1" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::hidden<dll::unit_type::RELU1>
    >::rbm_t rbm;

    rbm.learning_rate *= 2.0;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 200);

    REQUIRE(error < 1e-1);
}

TEST_CASE( "rbm/mnist_11", "rbm::relu6" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::hidden<dll::unit_type::RELU6>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 200);

    REQUIRE(error < 1e-1);
}

TEST_CASE( "rbm/mnist_12", "rbm::init_weights" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::init_weights
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 200);

    REQUIRE(error < 1e-3);
}

TEST_CASE( "rbm/mnist_13", "rbm::exp" ) {
    dll::rbm_desc<
        28 * 28, 100,
       dll::batch_size<25>,
       dll::hidden<dll::unit_type::EXP>
    >::rbm_t rbm;

    auto dataset = mnist::read_dataset<std::vector, std::vector, double>();

    REQUIRE(!dataset.training_images.empty());
    dataset.training_images.resize(100);

    mnist::binarize_dataset(dataset);

    auto error = rbm.train(dataset.training_images, 100);

    //This test is kind of fake since exp unit are not really made for
    //reconstruction. It is here to ensure that exp units are working.
    //exponential units are not even made for training

    REQUIRE(std::isnan(error));
}<|endoftext|>