<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h>
#include "point.h"
#include "path.h"
#include "serialiser.h"
#include "udf_helpers.h"

extern "C" {

    MYSQL_UDF_CHAR_FUNC( spoint );
    MYSQL_UDF_REAL_FUNC( spoint_long );
    MYSQL_UDF_REAL_FUNC( spoint_lat );
    MYSQL_UDF_REAL_FUNC( spoint_x );
    MYSQL_UDF_REAL_FUNC( spoint_y );
    MYSQL_UDF_REAL_FUNC( spoint_z );
    MYSQL_UDF_INT_FUNC( spoint_equal );

}

//supporting spoint(long, lat) or spoint(geom_string) or spoint(SPath, i)
my_bool spoint_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
	buffer *outBuf = new buffer(1);

	//checking stuff to be correct
    if(args->arg_count == 2) {
        //check the first parameter, if it is a SPath or not
        if(args->arg_type[0] == STRING_RESULT) {
            buffer * buf = new buffer(1);

            MYSQL_UDF_CHK_SPHERETYPE( 0, buf, PROTECT({MYSQL_SPHERE_PATH}),
                                                " spoint(SPath, i) error decoding first parameter. Corrupted or not the correct type." );

            if(buf->isDynParams[0] == true) {
		    	outBuf->isDynParams[0] = true;
	        } else {
		    	outBuf->isDynParams[0] = false;
	            if(args->arg_type[1] == INT_RESULT) {
	                outBuf->memBufs[0] = spherepath_get_point((SPath *) buf->memBufs[0], *(long long*)args->args[1]);
	            } else {
	                MYSQL_UDF_CHKCONV_PARAM_TOREAL(1, "spoint(SPath, i) requires a numerical or integer parameter as i.");

	                if(args->args[1] == NULL) {
                		outBuf->isDynParams[0] = true;
	                } else {
		                outBuf->memBufs[0] = spherepath_point((SPath *) buf->memBufs[0], *(double*) args->args[1]);
				    	outBuf->argTypes[0] = MYSQL_SPHERE_POINT;
	                }
	            }
            }

        } else {
            //long/lat
            MYSQL_UDF_CHKCONV_PARAM_TOREAL(0, "spoint(long, lat) requires a numerical parameter as long.");
            MYSQL_UDF_CHKCONV_PARAM_TOREAL(1, "spoint(long, lat) requires a numerical parameter as lat.");

            if(args->args[0] == NULL || args->args[1] == NULL) {
        		outBuf->isDynParams[0] = true;
            } else {
		        outBuf->memBufs[0] = spherepoint_from_long_lat(*(double*)args->args[0], *(double*)args->args[1]);
		    	outBuf->argTypes[0] = MYSQL_SPHERE_POINT;
        		outBuf->isDynParams[0] = false;
            }
        }
    } else if (args->arg_count == 1) {
    	//string
        MYSQL_UDF_CHK_PARAM_CHAR(0, "spoint(coordinate_string) requires a string.");

        if(args->args[0] == NULL) {
    		outBuf->isDynParams[0] = true;
        } else {
			outBuf->memBufs[0] = spherepoint_in( (char*)args->args[0] );
			outBuf->argTypes[0] = MYSQL_SPHERE_POINT;
    		outBuf->isDynParams[0] = false;
        }
    } else {
		strcpy(message, "wrong number of arguments: spoint() requires one or two parameter");
		return 1;
    }

    if(outBuf->memBufs[0] == NULL && outBuf->isDynParams[0] == false) {
    	strcpy(message, "an error occurred while generating the spherical point");
    	return 1;
    }

    //no limits on number of decimals
    initid->decimals = 31;
    initid->maybe_null = 1;
    initid->max_length = 1024;
    initid->ptr = (char*)outBuf;

    return 0;
}

void spoint_deinit( UDF_INIT* initid ) {
	MYSQL_UDF_DEINIT_BUFFER();
}

char *spoint( UDF_INIT* initid, UDF_ARGS* args, char *result, unsigned long *length, char* is_null, char* error ) {
	buffer * memBuf = (buffer*)initid->ptr;

	if(memBuf->isDynParams[0] == true) {
		buffer *buf;
		if(memBuf->memBufs[0] != NULL) {
			free(memBuf->memBufs[0]);
			memBuf->memBufs[0] = NULL;
			if(memBuf->resBuf != NULL) {
				free(memBuf->resBuf);
			}
		}

	    if(args->arg_count == 2) {
	        //check the first parameter, if it is a SPath or not
	        if(args->arg_type[0] == STRING_RESULT) {
	            buffer * buf = new buffer(1);

	            //fool the macro
	            buf->isDynParams[0] = true;
	            MYSQL_UDF_DYNCHK_SPHERETYPE( 0, buf, PROTECT({MYSQL_SPHERE_PATH}) );

	            if(args->arg_type[1] == INT_RESULT) {
	                memBuf->memBufs[0] = spherepath_get_point((SPath *) buf->memBufs[0], *(long long*)args->args[1]);
	            } else {
	                MYSQL_UDF_DYNCHKCONV_PARAM_TOREAL(1);

	                memBuf->memBufs[0] = spherepath_point((SPath *) buf->memBufs[0], *(double*) args->args[1]);
			    	memBuf->argTypes[0] = MYSQL_SPHERE_POINT;
	            }
	        } else {
	            //long/lat
	            MYSQL_UDF_DYNCHKCONV_PARAM_TOREAL(0);
	            MYSQL_UDF_DYNCHKCONV_PARAM_TOREAL(1);

		        memBuf->memBufs[0] = spherepoint_from_long_lat(*(double*)args->args[0], *(double*)args->args[1]);
		    	memBuf->argTypes[0] = MYSQL_SPHERE_POINT;
	        }
	    } else if (args->arg_count == 1) {
	        MYSQL_UDF_DYNCHK_PARAM_CHAR(0);

			memBuf->memBufs[0] = spherepoint_in( (char*)args->args[0] );
			memBuf->argTypes[0] = MYSQL_SPHERE_POINT;
	    }

		if(memBuf->memBufs[0] == NULL) {
			*is_null = 1;
			return NULL;
		}
	}

	SPoint * point = (SPoint*)memBuf->memBufs[0];

	memBuf->resBuf = serialise(point);
	*length = getSerialisedLen(point);

	return memBuf->resBuf;
}

//spoint_long(SPoint)...
my_bool spoint_long_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_ONEPARAM_INIT( "spoint_long", PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_long_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

double spoint_long( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return spherepoint_long((SPoint*) memBuf->memBufs[0]);
}

//spoint_lat(SPoint)...
my_bool spoint_lat_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_ONEPARAM_INIT( "spoint_lat", PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_lat_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

double spoint_lat( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return spherepoint_lat((SPoint*) memBuf->memBufs[0]);
}

//spoint_x(SPoint)...
my_bool spoint_x_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_ONEPARAM_INIT( "spoint_x", PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_x_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

double spoint_x( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return spherepoint_x((SPoint*) memBuf->memBufs[0]);
}

//spoint_y(SPoint)...
my_bool spoint_y_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_ONEPARAM_INIT( "spoint_y", PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_y_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

double spoint_y( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return spherepoint_y((SPoint*) memBuf->memBufs[0]);
}

//spoint_z(SPoint)...
my_bool spoint_z_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_ONEPARAM_INIT( "spoint_z", PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_z_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

double spoint_z( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return spherepoint_z((SPoint*) memBuf->memBufs[0]);
}

//spoint_equal(SPoint)...
my_bool spoint_equal_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_TWOPARAM_INIT( "spoint_equal", PROTECT({MYSQL_SPHERE_POINT}), PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_equal_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

long long spoint_equal( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );
    MYSQL_UDF_DYNCHK_SPHERETYPE( 1, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return (long long)spherepoint_equal((SPoint *)memBuf->memBufs[0], (SPoint *)memBuf->memBufs[1]);
}
<commit_msg>small fixes<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h>
#include "point.h"
#include "path.h"
#include "serialiser.h"
#include "udf_helpers.h"

extern "C" {

    MYSQL_UDF_CHAR_FUNC( spoint );
    MYSQL_UDF_REAL_FUNC( spoint_long );
    MYSQL_UDF_REAL_FUNC( spoint_lat );
    MYSQL_UDF_REAL_FUNC( spoint_x );
    MYSQL_UDF_REAL_FUNC( spoint_y );
    MYSQL_UDF_REAL_FUNC( spoint_z );
    MYSQL_UDF_INT_FUNC( spoint_equal );

}

//supporting spoint(long, lat) or spoint(geom_string) or spoint(SPath, i)
my_bool spoint_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
	buffer *outBuf = new buffer(1);

	//checking stuff to be correct
    if(args->arg_count == 2) {
        //check the first parameter, if it is a SPath or not
        if(args->arg_type[0] == STRING_RESULT) {
            buffer * buf = new buffer(1);

            MYSQL_UDF_CHK_SPHERETYPE( 0, buf, PROTECT({MYSQL_SPHERE_PATH}),
                                                " spoint(SPath, i) error decoding first parameter. Corrupted or not the correct type." );

            if(buf->isDynParams[0] == true) {
		    	outBuf->isDynParams[0] = true;
	        } else {
		    	outBuf->isDynParams[0] = false;
	            if(args->arg_type[1] == INT_RESULT) {
	                outBuf->memBufs[0] = spherepath_get_point((SPath *) buf->memBufs[0], *(long long*)args->args[1]);
                    outBuf->argTypes[0] = MYSQL_SPHERE_POINT;
	            } else {
	                MYSQL_UDF_CHKCONV_PARAM_TOREAL(1, "spoint(SPath, i) requires a numerical or integer parameter as i.");

	                if(args->args[1] == NULL) {
                		outBuf->isDynParams[0] = true;
	                } else {
		                outBuf->memBufs[0] = spherepath_point((SPath *) buf->memBufs[0], *(double*) args->args[1]);
				    	outBuf->argTypes[0] = MYSQL_SPHERE_POINT;
	                }
	            }
            }

        } else {
            //long/lat
            MYSQL_UDF_CHKCONV_PARAM_TOREAL(0, "spoint(long, lat) requires a numerical parameter as long.");
            MYSQL_UDF_CHKCONV_PARAM_TOREAL(1, "spoint(long, lat) requires a numerical parameter as lat.");

            if(args->args[0] == NULL || args->args[1] == NULL) {
        		outBuf->isDynParams[0] = true;
            } else {
		        outBuf->memBufs[0] = spherepoint_from_long_lat(*(double*)args->args[0], *(double*)args->args[1]);
		    	outBuf->argTypes[0] = MYSQL_SPHERE_POINT;
        		outBuf->isDynParams[0] = false;
            }
        }
    } else if (args->arg_count == 1) {
    	//string
        MYSQL_UDF_CHK_PARAM_CHAR(0, "spoint(coordinate_string) requires a string.");

        if(args->args[0] == NULL) {
    		outBuf->isDynParams[0] = true;
        } else {
			outBuf->memBufs[0] = spherepoint_in( (char*)args->args[0] );
			outBuf->argTypes[0] = MYSQL_SPHERE_POINT;
    		outBuf->isDynParams[0] = false;
        }
    } else {
		strcpy(message, "wrong number of arguments: spoint() requires one or two parameter");
		return 1;
    }

    if(outBuf->memBufs[0] == NULL && outBuf->isDynParams[0] == false) {
    	strcpy(message, "an error occurred while generating the spherical point");
    	return 1;
    }

    //no limits on number of decimals
    initid->decimals = 31;
    initid->maybe_null = 1;
    initid->max_length = 1024;
    initid->ptr = (char*)outBuf;

    return 0;
}

void spoint_deinit( UDF_INIT* initid ) {
	MYSQL_UDF_DEINIT_BUFFER();
}

char *spoint( UDF_INIT* initid, UDF_ARGS* args, char *result, unsigned long *length, char* is_null, char* error ) {
	buffer * memBuf = (buffer*)initid->ptr;

	if(memBuf->isDynParams[0] == true) {
		buffer *buf;
		if(memBuf->memBufs[0] != NULL) {
			free(memBuf->memBufs[0]);
			memBuf->memBufs[0] = NULL;
			if(memBuf->resBuf != NULL) {
				free(memBuf->resBuf);
			}
		}

	    if(args->arg_count == 2) {
	        //check the first parameter, if it is a SPath or not
	        if(args->arg_type[0] == STRING_RESULT) {
	            buffer * buf = new buffer(1);

	            //fool the macro
	            buf->isDynParams[0] = true;
	            MYSQL_UDF_DYNCHK_SPHERETYPE( 0, buf, PROTECT({MYSQL_SPHERE_PATH}) );

	            if(args->arg_type[1] == INT_RESULT) {
	                memBuf->memBufs[0] = spherepath_get_point((SPath *) buf->memBufs[0], *(long long*)args->args[1]);
                    outBuf->argTypes[0] = MYSQL_SPHERE_POINT;
	            } else {
	                MYSQL_UDF_DYNCHKCONV_PARAM_TOREAL(1);

	                memBuf->memBufs[0] = spherepath_point((SPath *) buf->memBufs[0], *(double*) args->args[1]);
			    	memBuf->argTypes[0] = MYSQL_SPHERE_POINT;
	            }
	        } else {
	            //long/lat
	            MYSQL_UDF_DYNCHKCONV_PARAM_TOREAL(0);
	            MYSQL_UDF_DYNCHKCONV_PARAM_TOREAL(1);

		        memBuf->memBufs[0] = spherepoint_from_long_lat(*(double*)args->args[0], *(double*)args->args[1]);
		    	memBuf->argTypes[0] = MYSQL_SPHERE_POINT;
	        }
	    } else if (args->arg_count == 1) {
	        MYSQL_UDF_DYNCHK_PARAM_CHAR(0);

			memBuf->memBufs[0] = spherepoint_in( (char*)args->args[0] );
			memBuf->argTypes[0] = MYSQL_SPHERE_POINT;
	    }

		if(memBuf->memBufs[0] == NULL) {
			*is_null = 1;
			return NULL;
		}
	}

	SPoint * point = (SPoint*)memBuf->memBufs[0];

	memBuf->resBuf = serialise(point);
	*length = getSerialisedLen(point);

	return memBuf->resBuf;
}

//spoint_long(SPoint)...
my_bool spoint_long_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_ONEPARAM_INIT( "spoint_long", PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_long_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

double spoint_long( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return spherepoint_long((SPoint*) memBuf->memBufs[0]);
}

//spoint_lat(SPoint)...
my_bool spoint_lat_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_ONEPARAM_INIT( "spoint_lat", PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_lat_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

double spoint_lat( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return spherepoint_lat((SPoint*) memBuf->memBufs[0]);
}

//spoint_x(SPoint)...
my_bool spoint_x_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_ONEPARAM_INIT( "spoint_x", PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_x_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

double spoint_x( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return spherepoint_x((SPoint*) memBuf->memBufs[0]);
}

//spoint_y(SPoint)...
my_bool spoint_y_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_ONEPARAM_INIT( "spoint_y", PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_y_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

double spoint_y( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return spherepoint_y((SPoint*) memBuf->memBufs[0]);
}

//spoint_z(SPoint)...
my_bool spoint_z_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_ONEPARAM_INIT( "spoint_z", PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_z_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

double spoint_z( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return spherepoint_z((SPoint*) memBuf->memBufs[0]);
}

//spoint_equal(SPoint)...
my_bool spoint_equal_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) {
    MYSQL_UDF_SPHERE_TWOPARAM_INIT( "spoint_equal", PROTECT({MYSQL_SPHERE_POINT}), PROTECT({MYSQL_SPHERE_POINT}) );
}

void spoint_equal_deinit( UDF_INIT* initid ) {
    MYSQL_UDF_DEINIT_BUFFER();
}

long long spoint_equal( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error ) {
    buffer * memBuf = (buffer*)initid->ptr;

    MYSQL_UDF_DYNCHK_SPHERETYPE( 0, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );
    MYSQL_UDF_DYNCHK_SPHERETYPE( 1, memBuf, PROTECT({MYSQL_SPHERE_POINT}) );

    return (long long)spherepoint_equal((SPoint *)memBuf->memBufs[0], (SPoint *)memBuf->memBufs[1]);
}
<|endoftext|>


<commit_before>#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <dlfcn.h>
#include <signal.h>
#include <iostream>
#include <vector>
#include <string>
#include <map>

#include "config.h"

#include "hal.h"
#include "hal/hal_priv.h"

using namespace std;

#define SOCKET_PATH "/tmp/rtapi_fifo"

template<class T> T DLSYM(void *handle, const string &name) {
	return reinterpret_cast<T>(dlsym(handle, name.c_str()));
}

template<class T> T DLSYM(void *handle, const char *name) {
	return reinterpret_cast<T>(dlsym(handle, name));
}

static std::map<string, void*> modules;

extern "C" int schedule(void) { return sched_yield(); }

static int instance_count = 0;
static int force_exit = 0;

static int do_newinst_cmd(string type, string name, string arg) {
    void *module = modules["hal_lib"];
    if(!module) {
        cerr << "hal_lib not loaded\n";
        return -1;
    }

    hal_comp_t *(*find_comp_by_name)(char*) =
        DLSYM<hal_comp_t*(*)(char *)>(module, "halpr_find_comp_by_name");
    if(!find_comp_by_name) {
        cerr << "halpr_find_comp_by_name not found\n";
        return -1;
    }

    hal_comp_t *comp = find_comp_by_name((char*)type.c_str());
    if(!comp) {
        cerr << "Component not found\n";
        return -1;
    }

    return comp->make((char*)name.c_str(), (char*)arg.c_str());
}

static int do_comp_args(void *module, vector<string> args) {
    for(unsigned i=1; i < args.size(); i++) {
        string &s = args[i];
        unsigned idx = s.find('=');
        if(idx == string::npos) {
            cerr << "Cannot understand: " << s << endl;
            return -1;
        }
        string param_name(s, 0, idx);
        string param_value(s, idx+1);
        void *item=DLSYM<void*>(module, "rtapi_info_address_" + param_name);
        if(!item) {
            cerr << "Cannot understand: (NULL item) " << s << "\n";
            cerr << dlerror() << endl;
            return -1;
        }
        char **item_type=DLSYM<char**>(module, "rtapi_info_type_" + param_name);
        if(!item_type || !*item_type) {
            cerr << "Cannot understand: (NULL type) " << s << dlerror() << "\n";
            return -1;
        }
        string item_type_string = *item_type;

        if(item_type_string == "l") {
            **(long**)item = strtol(param_value.c_str(), NULL, 0);
        } else if(item_type_string == "i") {
            **(int**)item = strtol(param_value.c_str(), NULL, 0);
        } else {
            cerr << "Cannot understand: " << s << " (type)\n";
            return -1;
        }
    }
    return 0;
}

static int do_load_cmd(string name, vector<string> args) {
    void *w = modules[name];
    if(w == NULL) {
        char what[LINELEN+1];
        snprintf(what, LINELEN, "%s/%s.so", EMC2_RTLIB_DIR, name.c_str());
        void *module = modules[name] = dlopen(what, RTLD_GLOBAL | RTLD_LAZY);
        if(!module) {
            printf("%s: dlopen: %s\n", name.c_str(), dlerror());
            return -1;
        }
	/// XXX handle arguments
        int (*start)(void) = DLSYM<int(*)(void)>(module, "rtapi_app_main");
        if(!start) {
            printf("%s: dlsym: %s\n", name.c_str(), dlerror());
            return -1;
        }
        int result;

        result = do_comp_args(module, args);
        if(result < 0) { dlclose(module); return -1; }

        if ((result=start()) < 0) {
            printf("%s: rtapi_app_main: %d\n", name.c_str(), result);
	    return result;
        } else {
            instance_count ++;
	    return 0;
        }
    } else {
        printf("%s: already exists\n", name.c_str());
        return -1;
    }
}

static int do_unload_cmd(string name) {
    void *w = modules[name];
    if(w == NULL) {
        printf("%s: not loaded\n", name.c_str());
	return -1;
    } else {
        int (*stop)(void) = DLSYM<int(*)(void)>(w, "rtapi_app_exit");
	if(stop) stop();
	modules.erase(modules.find(name));
        dlclose(w);
        instance_count --;
    }
    return 0;
}

static int read_number(int fd) {
    int r = 0, neg=1;
    char ch;

    while(1) {
        int res = read(fd, &ch, 1);
        if(res != 1) return -1;
        if(ch == '-') neg = -1;
        else if(ch == ' ') return r * neg;
        else r = 10 * r + ch - '0';
    }
}

static string read_string(int fd) {
    int len = read_number(fd);
    char buf[len];
    read(fd, buf, len);
    return string(buf, len);
}

static vector<string> read_strings(int fd) {
    vector<string> result;
    int count = read_number(fd);
    for(int i=0; i<count; i++) {
        result.push_back(read_string(fd));
    }
    return result;
}

static void write_number(string &buf, int num) {
    char numbuf[10];
    sprintf(numbuf, "%d ", num);
    buf = buf + numbuf;
}

static void write_string(string &buf, string s) {
    write_number(buf, s.size());
    buf += s;
}

static void write_strings(int fd, vector<string> strings) {
    string buf;
    write_number(buf, strings.size());
    for(unsigned int i=0; i<strings.size(); i++) {
        write_string(buf, strings[i]);
    }
    write(fd, buf.data(), buf.size());
}

static void print_strings(vector<string> strings) {
    cout << "STRINGS:";
    for(unsigned int i=0; i<strings.size(); i++) {
        cout << " " << strings[i];
    }
    cout << "\n";
}

static int handle_command(vector<string> args) {
    if(args.size() == 1 && args[0] == "exit") {
        force_exit = 1;
        return 0;
    } else if(args.size() >= 2 && args[0] == "load") {
        string name = args[1];
        args.erase(args.begin());
        return do_load_cmd(name, args);
    } else if(args.size() == 2 && args[0] == "unload") {
        return do_unload_cmd(args[1]);
    } else if(args.size() == 3 && args[0] == "newinst") {
        return do_newinst_cmd(args[1], args[2], "");
    } else if(args.size() == 4 && args[0] == "newinst") {
        return do_newinst_cmd(args[1], args[2], args[3]);
    } else {
        cout << "Unrecognized command: ";
        print_strings(args);
        return -1;
    }
}

static int slave(int fd, vector<string> args) {
    write_strings(fd, args);
    int result = read_number(fd);
    return result;
}

static int master(int fd, vector<string> args) {
    dlopen(NULL, RTLD_GLOBAL);
    do_load_cmd("hal_lib", vector<string>()); instance_count = 0;
    if(args.size()) handle_command(args);
    do {
        struct sockaddr_un client_addr;
        memset(&client_addr, 0, sizeof(client_addr));
        socklen_t len = sizeof(client_addr);
        int fd1 = accept(fd, (sockaddr*)&client_addr, &len);
        if(fd1 < 0) {
            perror("accept");
        } else {
            int result = handle_command(read_strings(fd1));
            string buf;
            write_number(buf, result);
            write(fd1, buf.data(), buf.size());
            close(fd1);
        }
    } while(!force_exit && instance_count > 0);

    return 0;
}

int main(int argc, char **argv) {
    vector<string> args;
    for(int i=1; i<argc; i++) { args.push_back(string(argv[i])); }

become_master:
    int fd = socket(PF_UNIX, SOCK_STREAM, 0);
    if(fd == -1) { perror("socket"); exit(1); }

    struct sockaddr_un addr = { AF_UNIX, SOCKET_PATH };
    int result = bind(fd, (sockaddr*)&addr, sizeof(addr));

    if(result == 0) {
        int result = listen(fd, 10);
        if(result != 0) { perror("bind"); exit(1); }
        result = master(fd, args);
        unlink(SOCKET_PATH);
        return result;
    } else if( errno == EADDRINUSE) {
       for(int i=0; i < 3 ; i++) {
           result = connect(fd, (sockaddr*)&addr, sizeof(addr));
           if(result == 0) break;
           sleep(1);
       }
       if(result < 0 && errno == ECONNREFUSED) {
           unlink(SOCKET_PATH);
           fprintf(stdout, "Waited 3 seconds for master.  giving up.\n");
           close(fd);
           goto become_master;
       }
       if(result < 0) { perror("connect"); exit(1); }
       return slave(fd, args);
    } else {
        perror("bind"); exit(1);
    }
}
<commit_msg>some C++ compilers reject using reinterpret_cast to turn a data pointer into a function pointer.  The C-style cast is accepted, however.<commit_after>#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <dlfcn.h>
#include <signal.h>
#include <iostream>
#include <vector>
#include <string>
#include <map>

#include "config.h"

#include "hal.h"
#include "hal/hal_priv.h"

using namespace std;

#define SOCKET_PATH "/tmp/rtapi_fifo"

template<class T> T DLSYM(void *handle, const string &name) {
	return (T)(dlsym(handle, name.c_str()));
}

template<class T> T DLSYM(void *handle, const char *name) {
	return (T)(dlsym(handle, name));
}

static std::map<string, void*> modules;

extern "C" int schedule(void) { return sched_yield(); }

static int instance_count = 0;
static int force_exit = 0;

static int do_newinst_cmd(string type, string name, string arg) {
    void *module = modules["hal_lib"];
    if(!module) {
        cerr << "hal_lib not loaded\n";
        return -1;
    }

    hal_comp_t *(*find_comp_by_name)(char*) =
        DLSYM<hal_comp_t*(*)(char *)>(module, "halpr_find_comp_by_name");
    if(!find_comp_by_name) {
        cerr << "halpr_find_comp_by_name not found\n";
        return -1;
    }

    hal_comp_t *comp = find_comp_by_name((char*)type.c_str());
    if(!comp) {
        cerr << "Component not found\n";
        return -1;
    }

    return comp->make((char*)name.c_str(), (char*)arg.c_str());
}

static int do_comp_args(void *module, vector<string> args) {
    for(unsigned i=1; i < args.size(); i++) {
        string &s = args[i];
        unsigned idx = s.find('=');
        if(idx == string::npos) {
            cerr << "Cannot understand: " << s << endl;
            return -1;
        }
        string param_name(s, 0, idx);
        string param_value(s, idx+1);
        void *item=DLSYM<void*>(module, "rtapi_info_address_" + param_name);
        if(!item) {
            cerr << "Cannot understand: (NULL item) " << s << "\n";
            cerr << dlerror() << endl;
            return -1;
        }
        char **item_type=DLSYM<char**>(module, "rtapi_info_type_" + param_name);
        if(!item_type || !*item_type) {
            cerr << "Cannot understand: (NULL type) " << s << dlerror() << "\n";
            return -1;
        }
        string item_type_string = *item_type;

        if(item_type_string == "l") {
            **(long**)item = strtol(param_value.c_str(), NULL, 0);
        } else if(item_type_string == "i") {
            **(int**)item = strtol(param_value.c_str(), NULL, 0);
        } else {
            cerr << "Cannot understand: " << s << " (type)\n";
            return -1;
        }
    }
    return 0;
}

static int do_load_cmd(string name, vector<string> args) {
    void *w = modules[name];
    if(w == NULL) {
        char what[LINELEN+1];
        snprintf(what, LINELEN, "%s/%s.so", EMC2_RTLIB_DIR, name.c_str());
        void *module = modules[name] = dlopen(what, RTLD_GLOBAL | RTLD_LAZY);
        if(!module) {
            printf("%s: dlopen: %s\n", name.c_str(), dlerror());
            return -1;
        }
	/// XXX handle arguments
        int (*start)(void) = DLSYM<int(*)(void)>(module, "rtapi_app_main");
        if(!start) {
            printf("%s: dlsym: %s\n", name.c_str(), dlerror());
            return -1;
        }
        int result;

        result = do_comp_args(module, args);
        if(result < 0) { dlclose(module); return -1; }

        if ((result=start()) < 0) {
            printf("%s: rtapi_app_main: %d\n", name.c_str(), result);
	    return result;
        } else {
            instance_count ++;
	    return 0;
        }
    } else {
        printf("%s: already exists\n", name.c_str());
        return -1;
    }
}

static int do_unload_cmd(string name) {
    void *w = modules[name];
    if(w == NULL) {
        printf("%s: not loaded\n", name.c_str());
	return -1;
    } else {
        int (*stop)(void) = DLSYM<int(*)(void)>(w, "rtapi_app_exit");
	if(stop) stop();
	modules.erase(modules.find(name));
        dlclose(w);
        instance_count --;
    }
    return 0;
}

static int read_number(int fd) {
    int r = 0, neg=1;
    char ch;

    while(1) {
        int res = read(fd, &ch, 1);
        if(res != 1) return -1;
        if(ch == '-') neg = -1;
        else if(ch == ' ') return r * neg;
        else r = 10 * r + ch - '0';
    }
}

static string read_string(int fd) {
    int len = read_number(fd);
    char buf[len];
    read(fd, buf, len);
    return string(buf, len);
}

static vector<string> read_strings(int fd) {
    vector<string> result;
    int count = read_number(fd);
    for(int i=0; i<count; i++) {
        result.push_back(read_string(fd));
    }
    return result;
}

static void write_number(string &buf, int num) {
    char numbuf[10];
    sprintf(numbuf, "%d ", num);
    buf = buf + numbuf;
}

static void write_string(string &buf, string s) {
    write_number(buf, s.size());
    buf += s;
}

static void write_strings(int fd, vector<string> strings) {
    string buf;
    write_number(buf, strings.size());
    for(unsigned int i=0; i<strings.size(); i++) {
        write_string(buf, strings[i]);
    }
    write(fd, buf.data(), buf.size());
}

static void print_strings(vector<string> strings) {
    cout << "STRINGS:";
    for(unsigned int i=0; i<strings.size(); i++) {
        cout << " " << strings[i];
    }
    cout << "\n";
}

static int handle_command(vector<string> args) {
    if(args.size() == 1 && args[0] == "exit") {
        force_exit = 1;
        return 0;
    } else if(args.size() >= 2 && args[0] == "load") {
        string name = args[1];
        args.erase(args.begin());
        return do_load_cmd(name, args);
    } else if(args.size() == 2 && args[0] == "unload") {
        return do_unload_cmd(args[1]);
    } else if(args.size() == 3 && args[0] == "newinst") {
        return do_newinst_cmd(args[1], args[2], "");
    } else if(args.size() == 4 && args[0] == "newinst") {
        return do_newinst_cmd(args[1], args[2], args[3]);
    } else {
        cout << "Unrecognized command: ";
        print_strings(args);
        return -1;
    }
}

static int slave(int fd, vector<string> args) {
    write_strings(fd, args);
    int result = read_number(fd);
    return result;
}

static int master(int fd, vector<string> args) {
    dlopen(NULL, RTLD_GLOBAL);
    do_load_cmd("hal_lib", vector<string>()); instance_count = 0;
    if(args.size()) handle_command(args);
    do {
        struct sockaddr_un client_addr;
        memset(&client_addr, 0, sizeof(client_addr));
        socklen_t len = sizeof(client_addr);
        int fd1 = accept(fd, (sockaddr*)&client_addr, &len);
        if(fd1 < 0) {
            perror("accept");
        } else {
            int result = handle_command(read_strings(fd1));
            string buf;
            write_number(buf, result);
            write(fd1, buf.data(), buf.size());
            close(fd1);
        }
    } while(!force_exit && instance_count > 0);

    return 0;
}

int main(int argc, char **argv) {
    vector<string> args;
    for(int i=1; i<argc; i++) { args.push_back(string(argv[i])); }

become_master:
    int fd = socket(PF_UNIX, SOCK_STREAM, 0);
    if(fd == -1) { perror("socket"); exit(1); }

    struct sockaddr_un addr = { AF_UNIX, SOCKET_PATH };
    int result = bind(fd, (sockaddr*)&addr, sizeof(addr));

    if(result == 0) {
        int result = listen(fd, 10);
        if(result != 0) { perror("bind"); exit(1); }
        result = master(fd, args);
        unlink(SOCKET_PATH);
        return result;
    } else if( errno == EADDRINUSE) {
       for(int i=0; i < 3 ; i++) {
           result = connect(fd, (sockaddr*)&addr, sizeof(addr));
           if(result == 0) break;
           sleep(1);
       }
       if(result < 0 && errno == ECONNREFUSED) {
           unlink(SOCKET_PATH);
           fprintf(stdout, "Waited 3 seconds for master.  giving up.\n");
           close(fd);
           goto become_master;
       }
       if(result < 0) { perror("connect"); exit(1); }
       return slave(fd, args);
    } else {
        perror("bind"); exit(1);
    }
}
<|endoftext|>


<commit_before>/**
  *  @copyright Copyright (c) 2014, J-PET collaboration
  *  @file JPetManager.cp
  *  @author Wojciech Krzemien, wojciech.krzemien@if.uj.edu.pl
  */

#include "./JPetManager.h"
//#include "../JPetAnalysisModule/JPetAnalysisModule.h"
#include <cassert>

ClassImp(JPetManager);

JPetManager& JPetManager::GetManager()
{
  static JPetManager instance;
  return instance;
}

JPetManager::JPetManager(): TNamed("JPetMainManager", "JPetMainManager")
{

}

// adds the given analysis module to a list of registered task
// @todo check if the module is not already registered
void JPetManager::AddTask(JPetAnalysisModule* mod)
{
  assert(mod);
  fTasks.push_back(mod);
}

void JPetManager::Run()
{
  UnpackFile(); /// @todo some more clever way :P
  JPetWriter* currentWriter = 0;
  std::vector<JPetAnalysisModule*>::iterator taskIter;
  // pseudo-input container
  long long  kNevent = 0;
    for (taskIter = fTasks.begin(); taskIter != fTasks.end(); taskIter++) {
    (*taskIter)->CreateInputObjects(); /// readers
    (*taskIter)->CreateOutputObjects(); /// writers + histograms
    // tutaj pobierz liczbe zdarzen/obiektow z kontenera wejsciowego
    // (*taskIter)->GetInputModule() czy cos w tym stylu
    kNevent = (*taskIter)->GetEventNb();
    for (long long i = 0; i < kNevent; i++) {
      (*taskIter)->Exec();
    }
    (*taskIter)->Terminate();
  }
}

void JPetManager::ParseCmdLine(int argc, char** argv){
    fCmdParser.parse(argc, (const char **)argv);
    if (fCmdParser.paramIsSet()){
        fParamManager.readFile(fCmdParser.getParam().c_str());
    }
    if(fCmdParser.fileTypeIsSet()) {
      /// @todo fileType should be probably enum not string
      if (fCmdParser.getFileType()=="hld") {
        /// @todo other two parameters must be also set somewhere
        fUnpacker.setParams(fCmdParser.getFileName().c_str());
      }
    }
}

JPetManager::~JPetManager()
{
  std::vector<JPetAnalysisModule*>::iterator taskIter;
  for (taskIter = fTasks.begin(); taskIter != fTasks.end(); taskIter++) {
    (*taskIter)->Terminate();
    delete (*taskIter);
    *taskIter = 0;
  }
}
<commit_msg>Removed called to terminate for every task in the destructor of Manager according to #463<commit_after>/**
  *  @copyright Copyright (c) 2014, J-PET collaboration
  *  @file JPetManager.cp
  *  @author Wojciech Krzemien, wojciech.krzemien@if.uj.edu.pl
  */

#include "./JPetManager.h"
//#include "../JPetAnalysisModule/JPetAnalysisModule.h"
#include <cassert>

ClassImp(JPetManager);

JPetManager& JPetManager::GetManager()
{
  static JPetManager instance;
  return instance;
}

JPetManager::JPetManager(): TNamed("JPetMainManager", "JPetMainManager")
{

}

// adds the given analysis module to a list of registered task
// @todo check if the module is not already registered
void JPetManager::AddTask(JPetAnalysisModule* mod)
{
  assert(mod);
  fTasks.push_back(mod);
}

void JPetManager::Run()
{
  UnpackFile(); /// @todo some more clever way :P
  JPetWriter* currentWriter = 0;
  std::vector<JPetAnalysisModule*>::iterator taskIter;
  // pseudo-input container
  long long  kNevent = 0;
    for (taskIter = fTasks.begin(); taskIter != fTasks.end(); taskIter++) {
    (*taskIter)->CreateInputObjects(); /// readers
    (*taskIter)->CreateOutputObjects(); /// writers + histograms
    // tutaj pobierz liczbe zdarzen/obiektow z kontenera wejsciowego
    // (*taskIter)->GetInputModule() czy cos w tym stylu
    kNevent = (*taskIter)->GetEventNb();
    for (long long i = 0; i < kNevent; i++) {
      (*taskIter)->Exec();
    }
    (*taskIter)->Terminate();
  }
}

void JPetManager::ParseCmdLine(int argc, char** argv){
    fCmdParser.parse(argc, (const char **)argv);
    if (fCmdParser.paramIsSet()){
        fParamManager.readFile(fCmdParser.getParam().c_str());
    }
    if(fCmdParser.fileTypeIsSet()) {
      /// @todo fileType should be probably enum not string
      if (fCmdParser.getFileType()=="hld") {
        /// @todo other two parameters must be also set somewhere
        fUnpacker.setParams(fCmdParser.getFileName().c_str());
      }
    }
}

JPetManager::~JPetManager()
{
  std::vector<JPetAnalysisModule*>::iterator taskIter;
  for (taskIter = fTasks.begin(); taskIter != fTasks.end(); taskIter++) {
    delete (*taskIter);
    *taskIter = 0;
  }
}
<|endoftext|>


<commit_before>/**
  *  @copyright Copyright (c) 2014, J-PET collaboration
  *  @file JPetManager.cp
  *  @author Wojciech Krzemien, wojciech.krzemien@if.uj.edu.pl
  */

#include "./JPetManager.h"

#include <cassert>
#include <ctime>
#include <string>

#include "../../JPetLoggerInclude.h"
#include "../JPetScopeModule/JPetScopeModule.h"

//ClassImp(JPetManager);

JPetManager& JPetManager::GetManager()
{
  static JPetManager instance;
  return instance;
}

JPetManager::JPetManager(): TNamed("JPetMainManager", "JPetMainManager"), fIsProgressBarEnabled(false)
{

}

// adds the given analysis module to a list of registered task
// @todo check if the module is not already registered
void JPetManager::AddTask(JPetAnalysisModule* mod)
{
  assert(mod);
  fTasks.push_back(mod);
}

void JPetManager::Run()
{
  // write to log about starting
  INFO( "========== Starting processing tasks: " + GetTimeString() + " ==========" );

  if (fCmdParser.IsFileTypeSet()) {
    if (fCmdParser.getFileType() == "scope") {
      JPetScopeModule* module = new JPetScopeModule("JPetScopeModule", "Process Oscilloscope ASCII data into JPetLOR structures.");
      module->setFileName(getInputFileName().c_str());
      fTasks.push_front(module);
    } else if (fCmdParser.getFileType() == "hld"){
      UnpackFile();
    }
  }

  JPetWriter* currentWriter = 0;
  std::list<JPetAnalysisModule*>::iterator taskIter;
  // pseudo-input container
  long long  kNevent = 0;
  long long kFirstEvent = 0;
  long long kLastEvent = 0;
  for (taskIter = fTasks.begin(); taskIter != fTasks.end(); taskIter++) {
    (*taskIter)->createInputObjects( getInputFileName().c_str() ); /// readers
    (*taskIter)->createOutputObjects( getInputFileName().c_str() ); /// writers + histograms
    kNevent = (*taskIter)->getEventNb();
    kFirstEvent = 0;
    kLastEvent = kNevent-1;

    // handle the user-provided range of events to process,
    // but only for the first module to process
    if( taskIter==fTasks.begin() ){// only for first module
      if( fCmdParser.getLowerEventBound() != -1 &&
          fCmdParser.getHigherEventBound() != -1 &&
          fCmdParser.getHigherEventBound() < kNevent){ // only if user provided reasonable bounds
        kFirstEvent = fCmdParser.getLowerEventBound();
        kLastEvent = fCmdParser.getHigherEventBound();
        kNevent = kLastEvent - kFirstEvent + 1;
      }
    }

    for (long long i = kFirstEvent; i <= kLastEvent; i++) {
      if(fIsProgressBarEnabled)
      {
	std::cout << "Progressbar: " << setProgressBar(i, kNevent) << " %" << std::endl;
      }
      (*taskIter)->exec();
    }
    (*taskIter)->terminate();
  }

  INFO( "======== Finished processing all tasks: " + GetTimeString() + " ========\n" );
}

void JPetManager::ParseCmdLine(int argc, char** argv)
{
  fCmdParser.parse(argc, (const char**)argv);

  if (fCmdParser.isRunNumberSet()) { /// we should connect to the database
    fParamManager.getParametersFromDatabase(fCmdParser.getRunNumber()); /// @todo some error handling
  }
  if (fCmdParser.IsFileTypeSet()) {
    if (fCmdParser.getFileType() == "hld") {
      fUnpacker.setParams(fCmdParser.getFileName().c_str());
    }
  }
  if (fCmdParser.isProgressBarSet()) {
    fIsProgressBarEnabled = true;
  }
}

int JPetManager::getRunNumber() const
{
  if (fCmdParser.isRunNumberSet()) {
    return fCmdParser.getRunNumber();
  }
  return -1;
}

JPetManager::~JPetManager()
{
  std::list<JPetAnalysisModule*>::iterator taskIter;
  for (taskIter = fTasks.begin(); taskIter != fTasks.end(); taskIter++) {
    delete (*taskIter);
    *taskIter = 0;
  }
}

/**
 * @brief Get Input File name stripped off the extension and the suffixes like .tslot.* or .phys.*
 *
 * Example: if the file given on command line was ../file.phys.hit.root, this method will return ../file
 */
std::string JPetManager::getInputFileName() const
{
  std::string name = fCmdParser.getFileName().c_str();
  // strip suffixes of type .tslot.* and .phys.*
  int pos = name.find(".tslot");
  if ( pos == std::string::npos ) {
    pos = name.find(".phys");
  }
  if ( pos == std::string::npos ) {
    pos = name.find(".hld");
  }
  if ( pos == std::string::npos ) {
    pos = name.find(".root");
  }
  if ( pos != std::string::npos ) {
    name.erase( pos );
  }
  return name;
}

/**
 * @brief returns the time TString in the format dd.mm.yyyy HH:MM
 */
TString JPetManager::GetTimeString() const
{
  time_t _tm = time(NULL );
  struct tm* curtime = localtime ( &_tm );
  char buf[100];
  strftime( buf, 100, "%d.%m.%Y %R", curtime);

  return TString( buf );
}

float JPetManager::setProgressBar(int currentEventNumber, int numberOfEvents)
{
  return ( ((float)currentEventNumber) / numberOfEvents ) * 100;
}
<commit_msg>Improve progressbar.<commit_after>/**
  *  @copyright Copyright (c) 2014, J-PET collaboration
  *  @file JPetManager.cp
  *  @author Wojciech Krzemien, wojciech.krzemien@if.uj.edu.pl
  */

#include "./JPetManager.h"

#include <cassert>
#include <ctime>
#include <string>

#include "../../JPetLoggerInclude.h"
#include "../JPetScopeModule/JPetScopeModule.h"

//ClassImp(JPetManager);

JPetManager& JPetManager::GetManager()
{
  static JPetManager instance;
  return instance;
}

JPetManager::JPetManager(): TNamed("JPetMainManager", "JPetMainManager"), fIsProgressBarEnabled(false)
{

}

// adds the given analysis module to a list of registered task
// @todo check if the module is not already registered
void JPetManager::AddTask(JPetAnalysisModule* mod)
{
  assert(mod);
  fTasks.push_back(mod);
}

void JPetManager::Run()
{
  // write to log about starting
  INFO( "========== Starting processing tasks: " + GetTimeString() + " ==========" );

  if (fCmdParser.IsFileTypeSet()) {
    if (fCmdParser.getFileType() == "scope") {
      JPetScopeModule* module = new JPetScopeModule("JPetScopeModule", "Process Oscilloscope ASCII data into JPetLOR structures.");
      module->setFileName(getInputFileName().c_str());
      fTasks.push_front(module);
    } else if (fCmdParser.getFileType() == "hld"){
      UnpackFile();
    }
  }

  JPetWriter* currentWriter = 0;
  std::list<JPetAnalysisModule*>::iterator taskIter;
  // pseudo-input container
  long long  kNevent = 0;
  long long kFirstEvent = 0;
  long long kLastEvent = 0;
  for (taskIter = fTasks.begin(); taskIter != fTasks.end(); taskIter++) {
    (*taskIter)->createInputObjects( getInputFileName().c_str() ); /// readers
    (*taskIter)->createOutputObjects( getInputFileName().c_str() ); /// writers + histograms
    kNevent = (*taskIter)->getEventNb();
    kFirstEvent = 0;
    kLastEvent = kNevent-1;

    // handle the user-provided range of events to process,
    // but only for the first module to process
    if( taskIter==fTasks.begin() ){// only for first module
      if( fCmdParser.getLowerEventBound() != -1 &&
          fCmdParser.getHigherEventBound() != -1 &&
          fCmdParser.getHigherEventBound() < kNevent){ // only if user provided reasonable bounds
        kFirstEvent = fCmdParser.getLowerEventBound();
        kLastEvent = fCmdParser.getHigherEventBound();
        kNevent = kLastEvent - kFirstEvent + 1;
      }
    }

    for (long long i = kFirstEvent; i <= kLastEvent; i++) {
      if(fIsProgressBarEnabled)
      {
          printf("\r[%6.4f% %]", setProgressBar(i, kNevent));
      }
      (*taskIter)->exec();
    }
    (*taskIter)->terminate();
  }

  INFO( "======== Finished processing all tasks: " + GetTimeString() + " ========\n" );
}

void JPetManager::ParseCmdLine(int argc, char** argv)
{
  fCmdParser.parse(argc, (const char**)argv);

  if (fCmdParser.isRunNumberSet()) { /// we should connect to the database
    fParamManager.getParametersFromDatabase(fCmdParser.getRunNumber()); /// @todo some error handling
  }
  if (fCmdParser.IsFileTypeSet()) {
    if (fCmdParser.getFileType() == "hld") {
      fUnpacker.setParams(fCmdParser.getFileName().c_str());
    }
  }
  if (fCmdParser.isProgressBarSet()) {
    fIsProgressBarEnabled = true;
  }
}

int JPetManager::getRunNumber() const
{
  if (fCmdParser.isRunNumberSet()) {
    return fCmdParser.getRunNumber();
  }
  return -1;
}

JPetManager::~JPetManager()
{
  std::list<JPetAnalysisModule*>::iterator taskIter;
  for (taskIter = fTasks.begin(); taskIter != fTasks.end(); taskIter++) {
    delete (*taskIter);
    *taskIter = 0;
  }
}

/**
 * @brief Get Input File name stripped off the extension and the suffixes like .tslot.* or .phys.*
 *
 * Example: if the file given on command line was ../file.phys.hit.root, this method will return ../file
 */
std::string JPetManager::getInputFileName() const
{
  std::string name = fCmdParser.getFileName().c_str();
  // strip suffixes of type .tslot.* and .phys.*
  int pos = name.find(".tslot");
  if ( pos == std::string::npos ) {
    pos = name.find(".phys");
  }
  if ( pos == std::string::npos ) {
    pos = name.find(".hld");
  }
  if ( pos == std::string::npos ) {
    pos = name.find(".root");
  }
  if ( pos != std::string::npos ) {
    name.erase( pos );
  }
  return name;
}

/**
 * @brief returns the time TString in the format dd.mm.yyyy HH:MM
 */
TString JPetManager::GetTimeString() const
{
  time_t _tm = time(NULL );
  struct tm* curtime = localtime ( &_tm );
  char buf[100];
  strftime( buf, 100, "%d.%m.%Y %R", curtime);

  return TString( buf );
}

float JPetManager::setProgressBar(int currentEventNumber, int numberOfEvents)
{
  return ( ((float)currentEventNumber) / numberOfEvents ) * 100;
}
<|endoftext|>


<commit_before>/*
 * Queue_Test.cc
 *
 */

#include <iostream>
#include "queue.h"

using namespace std;
using namespace BOOOS;

class MyElement : public Queue::Element {
public:
    MyElement(string str) : _name(str) {}

    virtual ~MyElement() {}

    string & name() { return _name; }

private:
    string _name;
};

void print_queue(Queue & q) {
    cout << "Queue length: " << q.length() << endl;

    if(q.length()) {
        MyElement * elem = dynamic_cast<MyElement *>(q.head()->next());
        do {
            cout << elem->name() << endl;
            elem = dynamic_cast<MyElement *>(elem->next());
        } while (elem != q.head()->next());
    }

    cout << "==============================" << endl;
}

int main() {
    cout << "Welcome to BOOOS - Basic Object Oriented Operating System!" << endl;
    cout << "This program will test the class: Queue" << endl;

    Queue queue;

    MyElement * person1 = new MyElement("João");
    MyElement * person2 = new MyElement("Pedro");
    MyElement * person3 = new MyElement("Augusto");
    MyElement * person4 = new MyElement("Fábio");
    print_queue(queue);

    queue.insert(person1);
    print_queue(queue);
    queue.insert(person2);
    print_queue(queue);
    queue.insert(person3);
    print_queue(queue);
    queue.insert(person4);
    print_queue(queue);

    MyElement * removed_person = dynamic_cast<MyElement*>(queue.remove());
    delete removed_person; // Which element was removed?
    print_queue(queue);
    removed_person = dynamic_cast<MyElement*>(queue.remove());
    delete removed_person; // Which element was removed?
    print_queue(queue);
    removed_person = dynamic_cast<MyElement*>(queue.remove());
    delete removed_person; // Which element was removed?
    print_queue(queue);
    removed_person = dynamic_cast<MyElement*>(queue.remove());
    delete removed_person; // Which element was removed?
    print_queue(queue);

    return 0;
}
<commit_msg>delete print_queue statements<commit_after>/*
 * Queue_Test.cc
 *
 */

#include <iostream>
#include "queue.h"

using namespace std;
using namespace BOOOS;

class MyElement : public Queue::Element {
public:
    MyElement(string str) : _name(str) {}

    virtual ~MyElement() {}

    string & name() { return _name; }

private:
    string _name;
};

void print_queue(Queue & q) {
    cout << "Queue length: " << q.length() << endl;

    if(q.length()) {
        MyElement * elem = dynamic_cast<MyElement *>(q.head()->next());
        do {
            cout << elem->name() << endl;
            elem = dynamic_cast<MyElement *>(elem->next());
        } while (elem != q.head()->next());
    }

    cout << "==============================" << endl;
}

int main() {
    cout << "Welcome to BOOOS - Basic Object Oriented Operating System!" << endl;
    cout << "This program will test the class: Queue" << endl;

    Queue queue;

    MyElement * person1 = new MyElement("João");
    MyElement * person2 = new MyElement("Pedro");
    MyElement * person3 = new MyElement("Augusto");
    MyElement * person4 = new MyElement("Fábio");

    queue.insert(person1);
    queue.insert(person2);
    queue.insert(person3);
    queue.insert(person4);

    MyElement * removed_person = dynamic_cast<MyElement*>(queue.remove());
    delete removed_person; // Which element was removed?
    removed_person = dynamic_cast<MyElement*>(queue.remove());
    delete removed_person; // Which element was removed?
    removed_person = dynamic_cast<MyElement*>(queue.remove());
    delete removed_person; // Which element was removed?
    removed_person = dynamic_cast<MyElement*>(queue.remove());
    delete removed_person; // Which element was removed?

    return 0;
}
<|endoftext|>


<commit_before>#include <config.h>

#include "coarse_scale_operator.hh"

#include <dune/xt/common/exceptions.hh>
#include <dune/xt/common/configuration.hh>
#include <dune/xt/common/timings.hh>
#include <dune/stuff/grid/walker.hh>
#include <dune/gdt/operators/projections.hh>
#include <dune/gdt/operators/prolongations.hh>
#include <dune/gdt/spaces/constraints.hh>
#include <dune/gdt/functionals/l2.hh>
#include <dune/multiscale/msfem/localproblems/localproblemsolver.hh>
#include <dune/multiscale/msfem/localproblems/localsolutionmanager.hh>
#include <dune/multiscale/msfem/localproblems/localgridlist.hh>
#include <dune/multiscale/msfem/msfem_traits.hh>
#include <dune/multiscale/problems/base.hh>
#include <dune/multiscale/problems/selector.hh>
#include <dune/multiscale/common/df_io.hh>
#include <dune/multiscale/tools/misc.hh>
#include <dune/multiscale/msfem/coarse_rhs_functional.hh>
#include <dune/xt/common/parallel/partitioner.hh>
#include <dune/grid/utility/partitioning/seedlist.hh>
#include <sstream>

namespace Dune {
namespace Multiscale {

Stuff::LA::SparsityPatternDefault CoarseScaleOperator::pattern(const CoarseScaleOperator::RangeSpaceType& range_space,
                                                               const CoarseScaleOperator::SourceSpaceType& source_space,
                                                               const CoarseScaleOperator::GridViewType& grid_view) {
  return range_space.compute_volume_pattern(grid_view, source_space);
}

CoarseScaleOperator::CoarseScaleOperator(const DMP::ProblemContainer& problem,
                                         const CoarseScaleOperator::SourceSpaceType& source_space_in,
                                         LocalGridList& localGridList)
  : OperatorBaseType(global_matrix_, source_space_in)
  , AssemblerBaseType(source_space_in,
                      source_space_in.grid_view().grid().leafGridView<CommonTraits::InteriorPartition>())
  , global_matrix_(coarse_space().mapper().size(), coarse_space().mapper().size(),
                   EllipticOperatorType::pattern(coarse_space()))
  , local_operator_(problem.getDiffusion())
  , local_assembler_(local_operator_, localGridList)
  , msfem_rhs_(coarse_space(), "MsFEM right hand side")
  , dirichlet_projection_(coarse_space())
  , problem_(problem) {

  MS_LOG_INFO << "Assembling coarse system" << std::endl;
  Dune::XT::Common::ScopedTiming st("msfem.coarse.assemble");
  msfem_rhs_.vector() *= 0;
  const auto interior = coarse_space().grid_view().grid().leafGridView<CommonTraits::InteriorPartition>();
  typedef std::remove_const<decltype(interior)>::type InteriorType;
  Dune::XT::Common::IndexSetPartitioner<InteriorType> ip(interior.indexSet());
  SeedListPartitioning<typename InteriorType::Grid, 0> partitioning(interior, ip);
  CoarseRhsFunctional force_functional(problem_, msfem_rhs_.vector(), coarse_space(), localGridList, interior);

  const auto& dirichlet = problem_.getDirichletData();
  const auto& boundary_info = problem_.getModelData().boundaryInfo();
  const auto& neumann = problem_.getNeumannData();

  typedef CommonTraits::InteriorGridViewType InteriorView;
  GDT::Operators::DirichletProjectionLocalizable<InteriorView, Problem::DirichletDataBase,
                                                 CommonTraits::DiscreteFunctionType>
      dirichlet_projection_operator(interior, boundary_info, dirichlet, dirichlet_projection_);
  GDT::Functionals::L2Face<Problem::NeumannDataBase, CommonTraits::GdtVectorType, CommonTraits::SpaceType, InteriorView>
      neumann_functional(neumann, msfem_rhs_.vector(), coarse_space(), interior);

  this->add_codim0_assembler(local_assembler_, this->matrix());
  this->add(force_functional);

  this->add(neumann_functional,
            new DSG::ApplyOn::NeumannIntersections<CommonTraits::InteriorGridViewType>(boundary_info));
  this->add(dirichlet_projection_operator, new DSG::ApplyOn::BoundaryEntities<CommonTraits::InteriorGridViewType>());
  AssemblerBaseType::assemble(partitioning);
  // substract the operators action on the dirichlet values, since we assemble in H^1 but solve in H^1_0
  CommonTraits::GdtVectorType tmp(coarse_space().mapper().size());
  global_matrix_.mv(dirichlet_projection_.vector(), tmp);
  force_functional.vector() -= tmp;
  // apply the dirichlet zero constraints to restrict the system to H^1_0
  GDT::Spaces::DirichletConstraints<typename CommonTraits::GridViewType::Intersection> dirichlet_constraints(
      boundary_info, coarse_space().mapper().size(), true);
  this->add(dirichlet_constraints /*, new GDT::ApplyOn::BoundaryEntities< GridViewType >()*/);
  if (problem.config().get("threading.smp_constraints", false))
    AssemblerBaseType::assemble(partitioning);
  else
    AssemblerBaseType::assemble(false);
  dirichlet_constraints.apply(global_matrix_, force_functional.vector());
}

void CoarseScaleOperator::assemble() { DUNE_THROW(Dune::InvalidStateException, "nobody should be calling this"); }

void CoarseScaleOperator::apply_inverse(CoarseScaleOperator::CoarseDiscreteFunction& solution) {

  MS_LOG_INFO << "Assembling coarse system took "
              << std::lround(DXTC_TIMINGS.walltime("msfem.coarse.assemble") / 100.) / 10. << "s" << std::endl;
  Dune::XT::Common::ScopedTiming st("msfem.coarse.solve");

  BOOST_ASSERT_MSG(msfem_rhs_.dofs_valid(), "Coarse scale RHS DOFs need to be valid!");
  DXTC_TIMINGS.start("msfem.coarse.linearSolver");
  typedef typename BackendChooser<CoarseDiscreteFunctionSpace>::InverseOperatorType Inverse;
  const Inverse inverse(global_matrix_, msfem_rhs_.space().communicator());

  const auto type = problem_.config().get("msfem.coarse_solver", "bicgstab.ilut");
  auto options = Inverse::options(type);
  constexpr bool overwrite = true;
  options.set("preconditioner.anisotropy_dim", CommonTraits::world_dim, overwrite);
  options.set("preconditioner.isotropy_dim", CommonTraits::world_dim, overwrite);
  options.set("verbose", problem_.config().get("msfem.coarse_solver.verbose", 2), overwrite);
  options.set("max_iter", problem_.config().get("msfem.coarse_solver.max_iter", 300u), overwrite);
  options.set("preconditioner.verbose", "2", overwrite);
  options.set("smoother.verbose", "2", overwrite);
  options.set("post_check_solves_system", problem_.config().get("msfem.coarse_solver.check", false), overwrite);
  try {
    inverse.apply(msfem_rhs_.vector(), solution.vector(), options);
  }
  catch (Dune::Stuff::Exceptions::linear_solver_failed& f) {
    // prevents all ranks from outputting the same detailed error message
    MS_LOG_ERROR_0 << f.what();
    DUNE_THROW(InvalidStateException, "Coarse solve failed.");
  }

  if (!solution.dofs_valid())
    DUNE_THROW(InvalidStateException, "Degrees of freedom of coarse solution are not valid!");

  solution.vector() += dirichlet_projection_.vector();

  DXTC_TIMINGS.stop("msfem.coarse.linearSolver");
  MS_LOG_INFO << "Time to solve coarse MsFEM problem: " << DXTC_TIMINGS.walltime("msfem.coarse.linearSolver") << "ms."
              << std::endl;
}

const CoarseScaleOperator::SourceSpaceType& CoarseScaleOperator::coarse_space() const { return test_space(); }

} // namespace Multiscale {
} // namespace Dune {
<commit_msg>adds mpi barrier to fix coarse timing<commit_after>#include <config.h>

#include "coarse_scale_operator.hh"

#include <dune/xt/common/exceptions.hh>
#include <dune/xt/common/configuration.hh>
#include <dune/xt/common/timings.hh>
#include <dune/stuff/grid/walker.hh>
#include <dune/gdt/operators/projections.hh>
#include <dune/gdt/operators/prolongations.hh>
#include <dune/gdt/spaces/constraints.hh>
#include <dune/gdt/functionals/l2.hh>
#include <dune/multiscale/msfem/localproblems/localproblemsolver.hh>
#include <dune/multiscale/msfem/localproblems/localsolutionmanager.hh>
#include <dune/multiscale/msfem/localproblems/localgridlist.hh>
#include <dune/multiscale/msfem/msfem_traits.hh>
#include <dune/multiscale/problems/base.hh>
#include <dune/multiscale/problems/selector.hh>
#include <dune/multiscale/common/df_io.hh>
#include <dune/multiscale/tools/misc.hh>
#include <dune/multiscale/msfem/coarse_rhs_functional.hh>
#include <dune/xt/common/parallel/partitioner.hh>
#include <dune/grid/utility/partitioning/seedlist.hh>
#include <sstream>

namespace Dune {
namespace Multiscale {

Stuff::LA::SparsityPatternDefault CoarseScaleOperator::pattern(const CoarseScaleOperator::RangeSpaceType& range_space,
                                                               const CoarseScaleOperator::SourceSpaceType& source_space,
                                                               const CoarseScaleOperator::GridViewType& grid_view) {
  return range_space.compute_volume_pattern(grid_view, source_space);
}

CoarseScaleOperator::CoarseScaleOperator(const DMP::ProblemContainer& problem,
                                         const CoarseScaleOperator::SourceSpaceType& source_space_in,
                                         LocalGridList& localGridList)
  : OperatorBaseType(global_matrix_, source_space_in)
  , AssemblerBaseType(source_space_in,
                      source_space_in.grid_view().grid().leafGridView<CommonTraits::InteriorPartition>())
  , global_matrix_(coarse_space().mapper().size(), coarse_space().mapper().size(),
                   EllipticOperatorType::pattern(coarse_space()))
  , local_operator_(problem.getDiffusion())
  , local_assembler_(local_operator_, localGridList)
  , msfem_rhs_(coarse_space(), "MsFEM right hand side")
  , dirichlet_projection_(coarse_space())
  , problem_(problem) {

  MS_LOG_INFO << "Assembling coarse system" << std::endl;
  Dune::XT::Common::ScopedTiming st("msfem.coarse.assemble");
  msfem_rhs_.vector() *= 0;
  const auto interior = coarse_space().grid_view().grid().leafGridView<CommonTraits::InteriorPartition>();
  typedef std::remove_const<decltype(interior)>::type InteriorType;
  Dune::XT::Common::IndexSetPartitioner<InteriorType> ip(interior.indexSet());
  SeedListPartitioning<typename InteriorType::Grid, 0> partitioning(interior, ip);
  CoarseRhsFunctional force_functional(problem_, msfem_rhs_.vector(), coarse_space(), localGridList, interior);

  const auto& dirichlet = problem_.getDirichletData();
  const auto& boundary_info = problem_.getModelData().boundaryInfo();
  const auto& neumann = problem_.getNeumannData();

  typedef CommonTraits::InteriorGridViewType InteriorView;
  GDT::Operators::DirichletProjectionLocalizable<InteriorView, Problem::DirichletDataBase,
                                                 CommonTraits::DiscreteFunctionType>
      dirichlet_projection_operator(interior, boundary_info, dirichlet, dirichlet_projection_);
  GDT::Functionals::L2Face<Problem::NeumannDataBase, CommonTraits::GdtVectorType, CommonTraits::SpaceType, InteriorView>
      neumann_functional(neumann, msfem_rhs_.vector(), coarse_space(), interior);

  this->add_codim0_assembler(local_assembler_, this->matrix());
  this->add(force_functional);

  this->add(neumann_functional,
            new DSG::ApplyOn::NeumannIntersections<CommonTraits::InteriorGridViewType>(boundary_info));
  this->add(dirichlet_projection_operator, new DSG::ApplyOn::BoundaryEntities<CommonTraits::InteriorGridViewType>());
  AssemblerBaseType::assemble(partitioning);
  // substract the operators action on the dirichlet values, since we assemble in H^1 but solve in H^1_0
  CommonTraits::GdtVectorType tmp(coarse_space().mapper().size());
  global_matrix_.mv(dirichlet_projection_.vector(), tmp);
  force_functional.vector() -= tmp;
  // apply the dirichlet zero constraints to restrict the system to H^1_0
  GDT::Spaces::DirichletConstraints<typename CommonTraits::GridViewType::Intersection> dirichlet_constraints(
      boundary_info, coarse_space().mapper().size(), true);
  this->add(dirichlet_constraints /*, new GDT::ApplyOn::BoundaryEntities< GridViewType >()*/);
  if (problem.config().get("threading.smp_constraints", false))
    AssemblerBaseType::assemble(partitioning);
  else
    AssemblerBaseType::assemble(false);
  dirichlet_constraints.apply(global_matrix_, force_functional.vector());
}

void CoarseScaleOperator::assemble() { DUNE_THROW(Dune::InvalidStateException, "nobody should be calling this"); }

void CoarseScaleOperator::apply_inverse(CoarseScaleOperator::CoarseDiscreteFunction& solution) {
  //to synchronize timing:
  MPIHelper::getCollectiveCommunication().barrier();
  MS_LOG_INFO << "Assembling coarse system took "
              << std::lround(DXTC_TIMINGS.walltime("msfem.coarse.assemble") / 100.) / 10. << "s" << std::endl;
  Dune::XT::Common::ScopedTiming st("msfem.coarse.solve");

  BOOST_ASSERT_MSG(msfem_rhs_.dofs_valid(), "Coarse scale RHS DOFs need to be valid!");
  DXTC_TIMINGS.start("msfem.coarse.linearSolver");
  typedef typename BackendChooser<CoarseDiscreteFunctionSpace>::InverseOperatorType Inverse;
  const Inverse inverse(global_matrix_, msfem_rhs_.space().communicator());

  const auto type = problem_.config().get("msfem.coarse_solver", "bicgstab.ilut");
  auto options = Inverse::options(type);
  constexpr bool overwrite = true;
  options.set("preconditioner.anisotropy_dim", CommonTraits::world_dim, overwrite);
  options.set("preconditioner.isotropy_dim", CommonTraits::world_dim, overwrite);
  options.set("verbose", problem_.config().get("msfem.coarse_solver.verbose", 2), overwrite);
  options.set("max_iter", problem_.config().get("msfem.coarse_solver.max_iter", 300u), overwrite);
  options.set("preconditioner.verbose", "2", overwrite);
  options.set("smoother.verbose", "2", overwrite);
  options.set("post_check_solves_system", problem_.config().get("msfem.coarse_solver.check", false), overwrite);
  try {
    inverse.apply(msfem_rhs_.vector(), solution.vector(), options);
  }
  catch (Dune::Stuff::Exceptions::linear_solver_failed& f) {
    // prevents all ranks from outputting the same detailed error message
    MS_LOG_ERROR_0 << f.what();
    DUNE_THROW(InvalidStateException, "Coarse solve failed.");
  }

  if (!solution.dofs_valid())
    DUNE_THROW(InvalidStateException, "Degrees of freedom of coarse solution are not valid!");

  solution.vector() += dirichlet_projection_.vector();

  DXTC_TIMINGS.stop("msfem.coarse.linearSolver");
  MS_LOG_INFO << "Time to solve coarse MsFEM problem: " << DXTC_TIMINGS.walltime("msfem.coarse.linearSolver") << "ms."
              << std::endl;
}

const CoarseScaleOperator::SourceSpaceType& CoarseScaleOperator::coarse_space() const { return test_space(); }

} // namespace Multiscale {
} // namespace Dune {
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "FFMpegDecoder.h"

#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable:4251)
#endif
#include <Magick++.h>
#ifdef _WIN32
#pragma warning(pop)
#endif

#include "AsyncVideoDecoder.h"

#include "../graphics/Filterfliprgba.h"
#include "../graphics/Filterfliprgb.h"

#include "../base/TimeSource.h"
#include "../base/TestSuite.h"
#include "../base/Exception.h"
#include "../base/Profiler.h"
#include "../base/Directory.h"
#include "../base/DirEntry.h"

#include <stdio.h>
#include <string>
#include <sstream>

using namespace avg;
using namespace std;

// TODO:
//  - Seek forward & back (longer movies)
//  - Test getNumFrames
//  - Repeat for other File formats.
//  - Remove testfiles from python tests.
//  - Test YCbCr420p, YCbCr422

class DecoderTest: public Test {
    public:
        DecoderTest(bool bThreadedDecoder, bool bThreadedDemuxer)
          : Test(getDecoderName(bThreadedDecoder, bThreadedDemuxer), 2),
            m_bThreadedDecoder(bThreadedDecoder),
            m_bThreadedDemuxer(bThreadedDemuxer)
        {}

        void runTests()
        {
            basicFileTest("mpeg1-48x48.mpg", 30);
            basicFileTest("mjpeg-48x48.avi", 202);
            seekTest("mjpeg-48x48.avi");

            audioTest("22.050Hz_16bit_mono.wav");

            audioTest("44.1kHz_16bit_mono.wav");
            audioTest("44.1kHz_16bit_stereo.wav");
            audioTest("44.1kHz_24bit_mono.wav");
            audioTest("44.1kHz_24bit_stereo.wav");

            audioTest("48kHz_16bit_mono.wav");
            audioTest("48kHz_16bit_stereo.wav");
            audioTest("48kHz_24bit_mono.wav");
            audioTest("48kHz_24bit_stereo.wav");

            audioTest("44.1kHz_16bit_stereo.aif");
            audioTest("44.1kHz_mono.ogg");
            audioTest("44.1kHz_stereo.ogg");
            audioTest("44.1kHz_stereo.mp3");
        }

    private:
        void basicFileTest(const string& sFilename, int ExpectedNumFrames)
        {
            try {
                cerr << "    Testing " << sFilename << endl;

                VideoDecoderPtr pDecoder = createDecoder();
                pDecoder->open(getSrcDir()+"testfiles/"+sFilename, OGL_NONE,
                        m_bThreadedDemuxer);
                IntPoint FrameSize = pDecoder->getSize();
                TEST(FrameSize == IntPoint(48, 48));
                TEST(pDecoder->getPixelFormat() == B8G8R8X8);
                BitmapPtr pBmp(new Bitmap(FrameSize, B8G8R8X8));

                // Test first two frames.
                pDecoder->renderToBmp(pBmp, -1);
                compareImages(pBmp, sFilename+"_1");
                pDecoder->renderToBmp(pBmp, -1);
                compareImages(pBmp, sFilename+"_2");
                pDecoder->close();

                readWholeFile(sFilename, 1, ExpectedNumFrames);
                readWholeFile(sFilename, 0.5, ExpectedNumFrames);
                readWholeFile(sFilename, 2, ExpectedNumFrames/2);
            } catch (Magick::Exception & ex) {
                cerr << string(m_IndentLevel+6, ' ') << ex.what() << endl;
                throw;
            }
        }

        void seekTest(const string& sFilename)
        {
            cerr << "    Testing " << sFilename << " (seek)" << endl;

            VideoDecoderPtr pDecoder = createDecoder();
            pDecoder->open(getSrcDir()+"testfiles/"+sFilename, OGL_NONE,
                    m_bThreadedDemuxer);

            IntPoint FrameSize = pDecoder->getSize();
            BitmapPtr pBmp(new Bitmap(FrameSize, B8G8R8X8));

            // Seek forward
            pDecoder->seek((long long)(100*1000/pDecoder->getNominalFPS()));
            pDecoder->renderToBmp(pBmp, -1);
            compareImages(pBmp, sFilename+"_100");

            // Seek backward
            pDecoder->seek((long long)(53*1000/pDecoder->getNominalFPS()));
            pDecoder->renderToBmp(pBmp, -1);
            compareImages(pBmp, sFilename+"_53");

            // Seek to last frame
            pDecoder->seek((long long)(201*1000/pDecoder->getNominalFPS()));
            pDecoder->renderToBmp(pBmp, -1);
            compareImages(pBmp, sFilename+"_201");

            pDecoder->close();
        }

        void audioTest(const string& sFilename)
        {
            try {
                cerr << "    Testing " << sFilename << endl;

                VideoDecoderPtr pDecoder = createDecoder();
                pDecoder->setAudioFormat(2, 44100);
                pDecoder->open(getSrcDir()+"testfiles/"+sFilename, OGL_NONE,
                        m_bThreadedDemuxer);
                int TotalBytesDecoded = 0;
                while(!pDecoder->isEOF()) {
                    unsigned char AudioBuffer[1024];
                    int BytesDecoded = pDecoder->fillAudioFrame(AudioBuffer, 1024);
                    TotalBytesDecoded += BytesDecoded;
                }
                if (sFilename.find(".ogg") == string::npos) {
                    // Check if we've decoded the whole file.
                    // TODO: Find out what is broken with ogg files here.
                    int FramesDecoded = TotalBytesDecoded/4;
                    int FramesInDuration = pDecoder->getDuration()*44100/1000;
                    TEST (abs(FramesDecoded-FramesInDuration) < 45);
                }
            } catch (Magick::Exception & ex) {
                cerr << string(m_IndentLevel+6, ' ') << ex.what() << endl;
                throw;
            }
        }

        void readWholeFile(const string& sFilename,
                double SpeedFactor, int ExpectedNumFrames)
        {
            // Read whole file, test last image.
            VideoDecoderPtr pDecoder = createDecoder();
            pDecoder->open(getSrcDir()+"testfiles/"+sFilename, OGL_NONE,
                    m_bThreadedDemuxer);
            IntPoint FrameSize = pDecoder->getSize();
            BitmapPtr pBmp(new Bitmap(FrameSize, B8G8R8X8));
            double TimePerFrame = (1000.0/pDecoder->getFPS())*SpeedFactor;
            int NumFrames = 0;
            double CurTime = 0;

            while(!pDecoder->isEOF()) {
                FrameAvailableCode FrameAvailable =
                        pDecoder->renderToBmp(pBmp, (long long)CurTime);
                if (FrameAvailable == FA_NEW_FRAME) {
//                    stringstream ss;
//                    ss << "testfiles/result/" << sFilename << NumFrames << ".png";
//                    pBmp->save(ss.str());
                    NumFrames++;

                } else {
                    TimeSource::get()->msleep(0);
                }
                if (FrameAvailable == FA_NEW_FRAME || FrameAvailable == FA_USE_LAST_FRAME) {
                    CurTime += TimePerFrame;
                }
            }
//            cerr << "NumFrames: " << NumFrames << ", ExpectedNumFrames: " << ExpectedNumFrames << endl;
            TEST(NumFrames == ExpectedNumFrames);
            if (SpeedFactor == 1) {
                compareImages(pBmp, sFilename+"_end");
            }

            // Test loop.
            pDecoder->seek(0);
            pDecoder->renderToBmp(pBmp, -1);
            compareImages(pBmp, sFilename+"_loop");

            pDecoder->close();
        }

        VideoDecoderPtr createDecoder() {
            VideoDecoderPtr pDecoder;
            pDecoder = VideoDecoderPtr(new FFMpegDecoder());
            if (m_bThreadedDecoder) {
                pDecoder = VideoDecoderPtr(new AsyncVideoDecoder(pDecoder));
            }
            return pDecoder;
        }

        void compareImages(BitmapPtr pBmp, const string& sFilename)
        {
            BitmapPtr pBaselineBmp;
            try {
                pBaselineBmp = BitmapPtr(new Bitmap(
                        getSrcDir()+"testfiles/baseline/"+sFilename+".png"));
            } catch (Magick::Exception & ex) {
                TEST_FAILED("Error loading baseline image: " << ex.what());
                pBmp->save(getSrcDir()+"testfiles/result/"+sFilename+".png");
                return;
            }
            FilterFlipRGB().applyInPlace(pBaselineBmp);
#ifdef __BIG_ENDIAN__
            FilterFlipRGBA().applyInPlace(pBmp);
#endif
            int DiffPixels = pBaselineBmp->getNumDifferentPixels(*pBmp);
            if (DiffPixels > 0) {
                TEST_FAILED("Error: Decoded image differs from baseline '" <<
                        sFilename << "'. " << DiffPixels << " different pixels.");
                try {
                    pBmp->save(getSrcDir()+"testfiles/result/"+sFilename+".png");
                    BitmapPtr pOrigBmp(new Bitmap(getSrcDir()+"testfiles/baseline/"+sFilename+".png"));
                    pOrigBmp->save(getSrcDir()+"testfiles/result/"+sFilename+"_baseline.png");
                    Bitmap DiffBmp(*pBmp);
                    DiffBmp.subtract(&*pBaselineBmp);
                    DiffBmp.save(getSrcDir()+"testfiles/result/"+sFilename+"_diff.png");
                } catch (Magick::Exception & ex) {
                    TEST_FAILED("Error saving result image: " << ex.what());
                    return;
                }
            }
        }

        string getDecoderName(bool bThreadedDecoder, bool bThreadedDemuxer) {
            string sName = "DecoderTest(";
            if (bThreadedDecoder) {
                sName += "Threaded decoder, ";
            } else {
                sName += "Sync decoder, ";
            }
            if (bThreadedDemuxer) {
                return sName+string("Threaded demuxer)");
            } else {
                return sName+string("Sync demuxer)");
            }
        }

        bool m_bThreadedDecoder;
        bool m_bThreadedDemuxer;
};

class VideoTestSuite: public TestSuite {
public:
    VideoTestSuite()
        : TestSuite("VideoTestSuite")
    {
        addTest(TestPtr(new DecoderTest(false, false)));
        addTest(TestPtr(new DecoderTest(false, true)));
        addTest(TestPtr(new DecoderTest(true, false)));
        addTest(TestPtr(new DecoderTest(true, true)));
    }
};

void deleteOldResultImages()
{
    string sDirName("testfiles/result/");
    Directory Dir(sDirName);
    int err = Dir.open(true);
    if (err) {
        cerr << "Creating directory " << sDirName << " failed." << strerror(err) << endl;
    } else {
        cerr << "Deleting files in " << sDirName << endl;
        DirEntryPtr pEntry = Dir.getNextEntry();
        while (pEntry) {
            if (pEntry->getName()[0] != '.') {
                pEntry->remove();
            }
            pEntry = Dir.getNextEntry();
        }
    }
}

int main(int nargs, char** args)
{
    ThreadProfilerPtr pThreadProfiler = ThreadProfilerPtr(new ThreadProfiler("Main"));
    Profiler::get().registerThreadProfiler(pThreadProfiler);

    deleteOldResultImages();

    VideoTestSuite Suite;

    Suite.runTests();
    bool bOK = Suite.isOk();

    if (bOK) {
        return 0;
    } else {
        return 1;
    }
}

<commit_msg>Audio branch: Added Decoder::getCurTime() test.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "FFMpegDecoder.h"

#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable:4251)
#endif
#include <Magick++.h>
#ifdef _WIN32
#pragma warning(pop)
#endif

#include "AsyncVideoDecoder.h"

#include "../graphics/Filterfliprgba.h"
#include "../graphics/Filterfliprgb.h"

#include "../base/TimeSource.h"
#include "../base/TestSuite.h"
#include "../base/Exception.h"
#include "../base/Profiler.h"
#include "../base/Directory.h"
#include "../base/DirEntry.h"

#include <stdio.h>
#include <string>
#include <sstream>

using namespace avg;
using namespace std;

// TODO:
//  - Seek forward & back (longer movies)
//  - Test getNumFrames
//  - Repeat for other File formats.
//  - Remove testfiles from python tests.
//  - Test YCbCr420p, YCbCr422

class DecoderTest: public Test {
    public:
        DecoderTest(bool bThreadedDecoder, bool bThreadedDemuxer)
          : Test(getDecoderName(bThreadedDecoder, bThreadedDemuxer), 2),
            m_bThreadedDecoder(bThreadedDecoder),
            m_bThreadedDemuxer(bThreadedDemuxer)
        {}

        void runTests()
        {
            basicFileTest("mpeg1-48x48.mpg", 30);
            basicFileTest("mjpeg-48x48.avi", 202);
            seekTest("mjpeg-48x48.avi");

            audioTest("22.050Hz_16bit_mono.wav");

            audioTest("44.1kHz_16bit_mono.wav");
            audioTest("44.1kHz_16bit_stereo.wav");
            audioTest("44.1kHz_24bit_mono.wav");
            audioTest("44.1kHz_24bit_stereo.wav");

            audioTest("48kHz_16bit_mono.wav");
            audioTest("48kHz_16bit_stereo.wav");
            audioTest("48kHz_24bit_mono.wav");
            audioTest("48kHz_24bit_stereo.wav");

            audioTest("44.1kHz_16bit_stereo.aif");
            audioTest("44.1kHz_mono.ogg");
            audioTest("44.1kHz_stereo.ogg");
            audioTest("44.1kHz_stereo.mp3");
        }

    private:
        void basicFileTest(const string& sFilename, int ExpectedNumFrames)
        {
            try {
                cerr << "    Testing " << sFilename << endl;

                VideoDecoderPtr pDecoder = createDecoder();
                pDecoder->open(getSrcDir()+"testfiles/"+sFilename, OGL_NONE,
                        m_bThreadedDemuxer);
                IntPoint FrameSize = pDecoder->getSize();
                TEST(FrameSize == IntPoint(48, 48));
                TEST(pDecoder->getPixelFormat() == B8G8R8X8);
                BitmapPtr pBmp(new Bitmap(FrameSize, B8G8R8X8));

                // Test first two frames.
                pDecoder->renderToBmp(pBmp, -1);
                compareImages(pBmp, sFilename+"_1");
                pDecoder->renderToBmp(pBmp, -1);
                compareImages(pBmp, sFilename+"_2");
                pDecoder->close();

                readWholeFile(sFilename, 1, ExpectedNumFrames);
                readWholeFile(sFilename, 0.5, ExpectedNumFrames);
                readWholeFile(sFilename, 2, ExpectedNumFrames/2);
            } catch (Magick::Exception & ex) {
                cerr << string(m_IndentLevel+6, ' ') << ex.what() << endl;
                throw;
            }
        }

        void seekTest(const string& sFilename)
        {
            cerr << "    Testing " << sFilename << " (seek)" << endl;

            VideoDecoderPtr pDecoder = createDecoder();
            pDecoder->open(getSrcDir()+"testfiles/"+sFilename, OGL_NONE,
                    m_bThreadedDemuxer);

            IntPoint FrameSize = pDecoder->getSize();
            BitmapPtr pBmp(new Bitmap(FrameSize, B8G8R8X8));

            // Seek forward
            pDecoder->seek((long long)(100*1000/pDecoder->getNominalFPS()));
            pDecoder->renderToBmp(pBmp, -1);
            compareImages(pBmp, sFilename+"_100");

            // Seek backward
            pDecoder->seek((long long)(53*1000/pDecoder->getNominalFPS()));
            pDecoder->renderToBmp(pBmp, -1);
            compareImages(pBmp, sFilename+"_53");

            // Seek to last frame
            pDecoder->seek((long long)(201*1000/pDecoder->getNominalFPS()));
            pDecoder->renderToBmp(pBmp, -1);
            compareImages(pBmp, sFilename+"_201");

            pDecoder->close();
        }

        void audioTest(const string& sFilename)
        {
            // TODO:
            // - getCurTime()
            // - get/setSpeedFactor()
            // - get/setVolume()
            // - seek()
            try {
                cerr << "    Testing " << sFilename << endl;

                {
                    cerr << "      Reading complete file." << endl;
                    VideoDecoderPtr pDecoder = createDecoder();
                    pDecoder->setAudioFormat(2, 44100);
                    pDecoder->open(getSrcDir()+"testfiles/"+sFilename, OGL_NONE,
                            m_bThreadedDemuxer);
                    int TotalBytesDecoded = 0;
                    int NumWrongTimestamps = 0;
                    while(!pDecoder->isEOF()) {
                        unsigned char AudioBuffer[1024];
                        int BytesDecoded = pDecoder->fillAudioFrame(AudioBuffer, 1024);
                        TotalBytesDecoded += BytesDecoded;
                        int CurTime = int((TotalBytesDecoded/4)/44.1);
                        if (abs(CurTime-pDecoder->getCurTime() > 10)) {
                            NumWrongTimestamps++;
                        }
                        // TODO: Figure out why the timestamps go _backwards_ in mp3s
                        // sometimes.
//                        cerr << CurTime << "->" << pDecoder->getCurTime() << endl;
                    }
                    if (NumWrongTimestamps>0) {
                        TEST_FAILED(NumWrongTimestamps << " wrong timestamps.");
                    }
                    if (sFilename.find(".ogg") == string::npos) {
                        // Check if we've decoded the whole file.
                        // TODO: Find out what is broken with ogg files here.
                        int FramesDecoded = TotalBytesDecoded/4;
                        int FramesInDuration = pDecoder->getDuration()*44100/1000;
                        TEST (abs(FramesDecoded-FramesInDuration) < 45);
                    }
                }
/*
                {
                    cerr << "      Seek test." << endl;
                    VideoDecoderPtr pDecoder = createDecoder();
                    pDecoder->setAudioFormat(2, 44100);
                    pDecoder->open(getSrcDir()+"testfiles/"+sFilename, OGL_NONE,
                            m_bThreadedDemuxer);
                }
*/

            } catch (Magick::Exception & ex) {
                cerr << string(m_IndentLevel+6, ' ') << ex.what() << endl;
                throw;
            }
        }

        void readWholeFile(const string& sFilename,
                double SpeedFactor, int ExpectedNumFrames)
        {
            // Read whole file, test last image.
            VideoDecoderPtr pDecoder = createDecoder();
            pDecoder->open(getSrcDir()+"testfiles/"+sFilename, OGL_NONE,
                    m_bThreadedDemuxer);
            IntPoint FrameSize = pDecoder->getSize();
            BitmapPtr pBmp(new Bitmap(FrameSize, B8G8R8X8));
            double TimePerFrame = (1000.0/pDecoder->getFPS())*SpeedFactor;
            int NumFrames = 0;
            double CurTime = 0;

            while(!pDecoder->isEOF()) {
                FrameAvailableCode FrameAvailable =
                        pDecoder->renderToBmp(pBmp, (long long)CurTime);
                if (FrameAvailable == FA_NEW_FRAME) {
//                    stringstream ss;
//                    ss << "testfiles/result/" << sFilename << NumFrames << ".png";
//                    pBmp->save(ss.str());
                    NumFrames++;

                } else {
                    TimeSource::get()->msleep(0);
                }
                if (FrameAvailable == FA_NEW_FRAME || FrameAvailable == FA_USE_LAST_FRAME) {
                    CurTime += TimePerFrame;
                }
            }
//            cerr << "NumFrames: " << NumFrames << ", ExpectedNumFrames: " << ExpectedNumFrames << endl;
            TEST(NumFrames == ExpectedNumFrames);
            if (SpeedFactor == 1) {
                compareImages(pBmp, sFilename+"_end");
            }

            // Test loop.
            pDecoder->seek(0);
            pDecoder->renderToBmp(pBmp, -1);
            compareImages(pBmp, sFilename+"_loop");

            pDecoder->close();
        }

        VideoDecoderPtr createDecoder() {
            VideoDecoderPtr pDecoder;
            pDecoder = VideoDecoderPtr(new FFMpegDecoder());
            if (m_bThreadedDecoder) {
                pDecoder = VideoDecoderPtr(new AsyncVideoDecoder(pDecoder));
            }
            return pDecoder;
        }

        void compareImages(BitmapPtr pBmp, const string& sFilename)
        {
            BitmapPtr pBaselineBmp;
            try {
                pBaselineBmp = BitmapPtr(new Bitmap(
                        getSrcDir()+"testfiles/baseline/"+sFilename+".png"));
            } catch (Magick::Exception & ex) {
                TEST_FAILED("Error loading baseline image: " << ex.what());
                pBmp->save(getSrcDir()+"testfiles/result/"+sFilename+".png");
                return;
            }
            FilterFlipRGB().applyInPlace(pBaselineBmp);
#ifdef __BIG_ENDIAN__
            FilterFlipRGBA().applyInPlace(pBmp);
#endif
            int DiffPixels = pBaselineBmp->getNumDifferentPixels(*pBmp);
            if (DiffPixels > 0) {
                TEST_FAILED("Error: Decoded image differs from baseline '" <<
                        sFilename << "'. " << DiffPixels << " different pixels.");
                try {
                    pBmp->save(getSrcDir()+"testfiles/result/"+sFilename+".png");
                    BitmapPtr pOrigBmp(new Bitmap(getSrcDir()+"testfiles/baseline/"+sFilename+".png"));
                    pOrigBmp->save(getSrcDir()+"testfiles/result/"+sFilename+"_baseline.png");
                    Bitmap DiffBmp(*pBmp);
                    DiffBmp.subtract(&*pBaselineBmp);
                    DiffBmp.save(getSrcDir()+"testfiles/result/"+sFilename+"_diff.png");
                } catch (Magick::Exception & ex) {
                    TEST_FAILED("Error saving result image: " << ex.what());
                    return;
                }
            }
        }

        string getDecoderName(bool bThreadedDecoder, bool bThreadedDemuxer) {
            string sName = "DecoderTest(";
            if (bThreadedDecoder) {
                sName += "Threaded decoder, ";
            } else {
                sName += "Sync decoder, ";
            }
            if (bThreadedDemuxer) {
                return sName+string("Threaded demuxer)");
            } else {
                return sName+string("Sync demuxer)");
            }
        }

        bool m_bThreadedDecoder;
        bool m_bThreadedDemuxer;
};

class VideoTestSuite: public TestSuite {
public:
    VideoTestSuite()
        : TestSuite("VideoTestSuite")
    {
        addTest(TestPtr(new DecoderTest(false, false)));
        addTest(TestPtr(new DecoderTest(false, true)));
        addTest(TestPtr(new DecoderTest(true, false)));
        addTest(TestPtr(new DecoderTest(true, true)));
    }
};

void deleteOldResultImages()
{
    string sDirName("testfiles/result/");
    Directory Dir(sDirName);
    int err = Dir.open(true);
    if (err) {
        cerr << "Creating directory " << sDirName << " failed." << strerror(err) << endl;
    } else {
        cerr << "Deleting files in " << sDirName << endl;
        DirEntryPtr pEntry = Dir.getNextEntry();
        while (pEntry) {
            if (pEntry->getName()[0] != '.') {
                pEntry->remove();
            }
            pEntry = Dir.getNextEntry();
        }
    }
}

int main(int nargs, char** args)
{
    ThreadProfilerPtr pThreadProfiler = ThreadProfilerPtr(new ThreadProfiler("Main"));
    Profiler::get().registerThreadProfiler(pThreadProfiler);

    deleteOldResultImages();

    VideoTestSuite Suite;

    Suite.runTests();
    bool bOK = Suite.isOk();

    if (bOK) {
        return 0;
    } else {
        return 1;
    }
}

<|endoftext|>


<commit_before>/*
 @ 0xCCCCCCCC
*/

#include "blocking_queue.h"

int main()
{
    // Add test code
    BlockingQueue<int> bq;
    bq.Enqueue(1);
    bq.Dequeue();
    return 0;
}<commit_msg>BlockingQueue: add test code.<commit_after>/*
 @ 0xCCCCCCCC
*/

#include <cstdlib>
#include <future>
#include <iostream>

#include "blocking_queue.h"

const int kSleepTime = 1000;

template<typename T>
void Produce(BlockingQueue<T>& queue)
{
    while (true) {
        auto item = rand() % 1000;
        std::cout << "produced item " << item << std::endl;
        queue.Enqueue(item);
        std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 500));
    }
}

template<typename T>
void Consume(BlockingQueue<T>& queue)
{
    while (true) {
        auto item = queue.Dequeue();
        std::cout << "consume item " << item << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 1000));
    }
}

int main()
{
    srand(time(nullptr));
    BlockingQueue<int> bq;

    std::async(std::launch::async, Produce<int>, std::ref(bq));
    std::async(std::launch::async, Consume<int>, std::ref(bq));
    std::async(std::launch::async, Consume<int>, std::ref(bq));

    return 0;
}<|endoftext|>