Exemple #1
0
static void
ldo_putref(ScarabSession * session, int reference, ScarabDatum * obj)
{
	LDO_Session    *s;
	ScarabDatum    *ref;

	s = (LDO_Session *) session->encoder;
	ref = scarab_new_integer(reference);

	scarab_dict_put(s->refs, ref, obj);
	scarab_free_datum(ref);
	scarab_free_datum(obj);
}
Datum VariableRegistry::generateCodecDatum() {
	
	ScarabDatum *codec = NULL;
    shared_ptr<Variable> var;
	
	
	boost::mutex::scoped_lock s_lock(lock);

    int dictSize = master_variable_list.size();
	
	codec = scarab_dict_new(dictSize, &scarab_dict_times2);
	
	
    for(int i = 0; i < dictSize; i++) {
        var = master_variable_list[i];
		
		if(var == NULL) { 
            continue; 
        }
        
		int codec_code = var->getCodecCode();
		
		if(codec_code == RESERVED_CODEC_CODE) {
			continue;
		}
        
		VariableProperties *props = var->getProperties();
		
        if(props == NULL){ 
            continue; 
        }
        
        Datum serialized_var(props->operator Datum());
		
        if(serialized_var.isUndefined()) {
            mdebug("local parameter null value at param (%d)", i);
        }
		ScarabDatum *codec_key = scarab_new_integer(codec_code);
        scarab_dict_put(codec, codec_key, serialized_var.getScarabDatum());
		scarab_free_datum(codec_key);
    }
	
	
    Datum returnCodec(codec);
	scarab_free_datum(codec);
    return returnCodec;  
}
EventWrapper DataFileIndexer::EventsIterator::getNextEvent() {
    EventWrapper event;
    
    while (current_event_block < matching_event_blocks.size()) {
        if ((current_relative_event == dfi.events_per_block) || (current_datum == NULL)) {
            // Advance to the next block
            scarab_seek(dfi.session, matching_event_blocks[current_event_block]->blockOffset(), SEEK_SET);
            current_relative_event = 0;
        }
        
        // Read through the event block
		while (event.empty() && (current_relative_event < dfi.events_per_block) && (current_datum = scarab_read(dfi.session)))
        {
            if (!DataFileUtilities::isScarabEvent(current_datum)) {
                // Skip invalid events
                scarab_free_datum(current_datum);
                continue;
            }
            
			MWTime event_time = DataFileUtilities::getScarabEventTime(current_datum);
			
            // Check the time criterion
            if (event_time >= lower_bound && event_time <= upper_bound) {
				unsigned int event_code = DataFileUtilities::getScarabEventCode(current_datum);
				
                // Check if the event code matches
                if (event_codes_to_match.empty() ||
                    (event_codes_to_match.find(event_code) != event_codes_to_match.end()))
                {
                    event = EventWrapper(current_datum);
                }
			}
			
			scarab_free_datum(current_datum);
			current_relative_event++;
		}
        
        if ((current_relative_event == dfi.events_per_block) || (current_datum == NULL))
            current_event_block++;
        
        if (!event.empty())
            return event;
    }
    
    return event;
}
Exemple #4
0
static ScarabDatum *
ldo_read_dict(ScarabSession * session)
{
	int             len;
	ScarabDatum    *dict;

	len = ldo_readber(session);
	dict = scarab_dict_new(len, scarab_dict_times2);

	for (; len > 0; len--)
	{
		ScarabDatum *key  = ldo_read(session);
		ScarabDatum *value = ldo_read(session);
		scarab_dict_put(dict,
						key,
						value);
		scarab_free_datum(key);
		scarab_free_datum(value);
	}
	return dict;
}
Exemple #5
0
static ScarabDatum *
ldo_getref(ScarabSession * session, int reference)
{
	LDO_Session    *s;
	ScarabDatum    *ref;
	ScarabDatum    *obj;

	s = (LDO_Session *) session->encoder;
	ref = scarab_new_integer(reference);
	obj = scarab_dict_get(s->refs, ref);

	scarab_free_datum(ref);

	return obj;
}
Exemple #6
0
static ScarabDatum *
ldo_read_list(ScarabSession * session)
{
	int             i;
	int             len;
	ScarabDatum    *list;
	ScarabDatum	   *list_element;

	len = ldo_readber(session);
	list = scarab_list_new(len);

	for (i = 0; i < len; i++)
	{
		list_element = ldo_read(session);
		scarab_list_put(list, i, list_element);
		scarab_free_datum(list_element);
	}
	return list;
}
Exemple #7
0
std::vector<ScarabDatumWrapper> DataFileIndexer::events(const std::vector<unsigned int> &event_codes_to_match,
														const MonkeyWorksTime lower_bound, 
														const MonkeyWorksTime upper_bound) const {
	std::vector<ScarabDatumWrapper> return_vector;



	std::vector<boost::shared_ptr<EventBlock> > event_blocks_with_time = root->children(event_codes_to_match, lower_bound, upper_bound);
	if (event_blocks_with_time.size() == 0) {
		std::cerr << "Error in indexing - no blocks found to search for codecs.  Short file?  Bug: fix" << std::endl;	
	}
	
	//std::cout << "EventBlock size" << event_blocks_with_time.size();
	for(std::vector<boost::shared_ptr<EventBlock> >::const_iterator i = event_blocks_with_time.begin();
		i != event_blocks_with_time.end();
		++i) {
		long int block_offset = (*i)->blockOffset();
		scarab_seek(session, block_offset, SEEK_SET);
		
		ScarabDatum *current_datum = NULL;
		unsigned int current_relative_event = 0;
		
		while((current_datum = scarab_read(session)) && current_relative_event < events_per_block) {
			MonkeyWorksTime event_time = DataFileUtilities::getScarabEventTime(current_datum);
			if(event_time >= lower_bound && event_time <= upper_bound) {
				unsigned int event_code = DataFileUtilities::getScarabEventCode(current_datum);
				for(std::vector<unsigned int>::const_iterator j = event_codes_to_match.begin();
					j != event_codes_to_match.end();
					++j) {
					if(event_code == *j) {
						return_vector.push_back(ScarabDatumWrapper(current_datum));	
					}
				}
			}
			
			scarab_free_datum(current_datum);
			current_relative_event++; //std::cout << "cur rel" << current_relative_event;
		}			
	}
	
	return return_vector;	
}
void DataFileIndexer::buildIndex(unsigned int _events_per_block, unsigned int multiplication_factor_per_level) {
    number_of_events = 0;
    events_per_block = _events_per_block;
    root.reset();
	
	{
		std::vector<boost::shared_ptr<EventBlock> > event_blocks;
		{
			std::set<unsigned int> event_codes_in_block;
			MWTime max_time = MIN_MWORKS_TIME();
			MWTime min_time = MAX_MWORKS_TIME();
			long int previous_datum_location = scarab_tell(session);
			
			ScarabDatum *datum = NULL;
			while(datum = scarab_read(session)) {
                if (!DataFileUtilities::isScarabEvent(datum)) {
                    // Ignore invalid events
                    scarab_free_datum(datum);
                    continue;
                }
                
				event_codes_in_block.insert(DataFileUtilities::getScarabEventCode(datum));
				
				MWTime event_time = DataFileUtilities::getScarabEventTime(datum);
				max_time = std::max(max_time, event_time);
				min_time = std::min(min_time, event_time);
				
				number_of_events++;
				if(number_of_events % events_per_block == 0) {
					boost::shared_ptr<EventBlock> new_event_block = boost::shared_ptr<EventBlock>(new EventBlock(previous_datum_location, min_time, max_time, event_codes_in_block));
					event_blocks.push_back(new_event_block);
					
					event_codes_in_block.clear();
					max_time = MIN_MWORKS_TIME();
					min_time = MAX_MWORKS_TIME();
					previous_datum_location = scarab_tell(session);
				}			
				scarab_free_datum(datum);
			}
			
			// add in the remainder blocks
			boost::shared_ptr<EventBlock> new_event_block = boost::shared_ptr<EventBlock>(new EventBlock(previous_datum_location, min_time, max_time, event_codes_in_block));
			event_blocks.push_back(new_event_block);
		}
		
		
		{
			// build the tree
			int events_per_node = events_per_block;
			int number_of_levels = 1;
			while(events_per_node < number_of_events) {
				number_of_levels++;
				events_per_node *= multiplication_factor_per_level;
			}
			
			std::vector <boost::shared_ptr<EventBlock> > blocks_at_next_level = event_blocks;
			for(int i = 1; i < number_of_levels; ++i) {
				std::vector <boost::shared_ptr<EventBlock> > blocks_at_current_level;
				
				std::vector<boost::shared_ptr<EventBlock> >::const_iterator j = blocks_at_next_level.begin();
				while(j != blocks_at_next_level.end()) {
					std::vector <boost::shared_ptr<EventBlock> > children;					
					for(int k = 0; k < multiplication_factor_per_level && j != blocks_at_next_level.end(); ++k) {
						children.push_back(*j);
						++j;
					}
					boost::shared_ptr<EventBlock> new_block = boost::shared_ptr<EventBlock>(new EventBlock(children));
					blocks_at_current_level.push_back(new_block);
				}
				
				blocks_at_next_level = blocks_at_current_level;
			}
			
			if(blocks_at_next_level.size() != 1) {
				//badness
				throw DataFileIndexerError("Something went wrong ... please abort and try again");
			}
            
            // DDC added a patch to fix failure to index small numbers of events
            // force a mandatory level below root
            boost::shared_ptr<EventBlock> subroot = blocks_at_next_level.at(0);
            std::vector< boost::shared_ptr<EventBlock> > root_children;
            root_children.push_back(subroot);
			root = boost::shared_ptr<EventBlock>(new EventBlock(root_children));
        }
	}
}
int ScarabWriteConnection::service() {
	boost::mutex::scoped_lock lock(connectLock);

	static int n_written = 0;
	
	shared_ptr <Clock> clock = Clock::instance();
	static MWTime start_time = clock->getCurrentTimeUS();
//    static int functionCount = 0;
//    mdebug("entering write service");
//    struct timespec time_to_sleep;
//    time_to_sleep.tv_sec = 0;
//    time_to_sleep.tv_nsec = 200000000; //200 ms
//    while(1) {
//        mdebug("start write while loop");
//        if(servicing) {
//            // we are already servicing this connection.
//            mdebug("Already Servicing Writing");
//            M_ISUNLOCK;
//            continue;
//            //1return 1;
//        }
        servicing = true;
    
    //    mdebug("Started servicing write function count = %d", functionCount);
//        functionCount++;
        if(getScarabError(pipe)) {
            mwarning(M_NETWORK_MESSAGE_DOMAIN, "Session Failure on ID %ld", cid);
            servicing = false;
            if(sibling) {
                sibling->setInterrupt(true);
            }
            term = true;
            
            return -1;
        }

        // if we have been requested to get interrupted
        // if we are interrupted while processing events there will be a
        // slight delay while out task is re-scheduled
        if(interrupt) {
            mwarning(M_NETWORK_MESSAGE_DOMAIN,
					"Write Service Routine Interrupted on id %ld", cid);
            if(sibling) {
                sibling->setInterrupt(true);
            }
            ScarabDatum * termEvent;
            // puts a control event of type termination into a scarab package
            // and sends the package
            termEvent = scarab_list_new(SCARAB_EVENT_N_TOPLEVEL_ELEMENTS);
			
			ScarabDatum *termCode = scarab_new_integer(RESERVED_TERMINATION_CODE);
            scarab_list_put(termEvent, SCARAB_EVENT_CODEC_CODE_INDEX, termCode);
			scarab_free_datum(termCode);
			
			shared_ptr <Clock> clock = Clock::instance();
			ScarabDatum *time = scarab_new_integer(clock->getCurrentTimeUS());
            scarab_list_put(termEvent, SCARAB_EVENT_TIME_INDEX, time);
			scarab_free_datum(time);

            if(scarab_write(pipe, termEvent) == 0) {
                // success
                mdebug("Wrote termination message from id %ld", cid);
                servicing = false;
                term = true; // mark the connection for termination
                scarab_free_datum(termEvent);
				return 0;
            } else {
                mwarning(M_NETWORK_MESSAGE_DOMAIN,
					"Failed to Write Termination Sequence on socket %ld", cid);
                // even though there was an error we are going to 
                // terminate
                term = true; // mark the connection for termination
                scarab_free_datum(termEvent);
				return -1;
            }
			
			scarab_free_datum(termEvent);
        }
    
        // while we have events to process but havent been requested for
        // interruption.
        
		while(buffer_reader->nextEventExists() && !interrupt) {
            
            //MWTime event_time = newevent->getTime();
            //mEventType type = newevent->getEventType();
            //mVariable *var = newevent->getParam();
            ScarabDatum * scarab_event;
        			
			#define USE_EXPLICIT_BUFFERING	1
			#define BUFFER_HIGH_WATER_MARK	1
			#define MAX_EVENTS_TO_BUFFER	10000
			
			if(USE_EXPLICIT_BUFFERING && buffer_reader->hasAtLeastNEvents(BUFFER_HIGH_WATER_MARK)) {
			
				scarab_force_buffering(pipe, 1);
				
				// fill up the macro event
				int numEventsBuffered = 0;
				bool buffering = true;
				do {
					
					shared_ptr<Event> newevent = buffer_reader->getNextEvent();
					if(newevent == NULL) {
						// don't send anything if an event was NULL.
						servicing = false;
						scarab_free_datum(scarab_event);
						return 1;
					}
					
					scarab_event = newevent->toScarabDatum();

					// stop buffering when you run out of events, or you hit the max events
					if(!(buffering = buffer_reader->nextEventExists() && numEventsBuffered<MAX_EVENTS_TO_BUFFER)) {
						scarab_force_buffering(pipe, 0);
					}
					
					if(scarab_write(pipe, scarab_event) == 0) {
						n_written++;
					} else {
						merror(M_SYSTEM_MESSAGE_DOMAIN, "scarab buffered write error");
						servicing = false;
						return -1;
					}
					
					scarab_free_datum(scarab_event);
					++numEventsBuffered;
				} while(buffering);
				
			
			} else {
				
				// Single event write
				shared_ptr<Event> newevent = buffer_reader->getNextEvent();
				if(newevent == NULL) {
					// don't send anything if an event was NULL.
					servicing = false;
					return 1;
				}
				
				scarab_event = newevent->toScarabDatum();
								
				if(scarab_write(pipe, scarab_event) == 0) {
					n_written++;
				} else {
					merror(M_SYSTEM_MESSAGE_DOMAIN, "scarab write error");
					servicing = false;
					return -1;
				}
				
				scarab_free_datum(scarab_event);
				
			}
			
			// Some reporting
			#define  N  1000
			static int last_nwritten = 0;
			if(n_written - last_nwritten >= N){
				last_nwritten = n_written;
				
				MWTime now = clock->getCurrentTimeUS();
				
				/*fprintf(stderr, "last: %lld, now: %lld\n",
							start_time,
							now
							); */
//				fprintf(stderr, "%g events / sec (%d event in %lld usec)\n",
//							(double)N / howlong,
//							N, now - start_time
//							);
//				fprintf(stderr, "Number of items unserviced: %d\n",
//						buffer_reader->getNItemsUnserviced());
//				fflush(stderr);
				start_time = now;
			}
        } 


        servicing = false;

        return 1;
//    }
}
Exemple #10
0
void scarab_free_datum(ScarabDatum *d){
	
	int i;
	
	if(d == NULL) return;
	
	// Unnecessary checking?  Actually accounts for 16% of the time in this
	// call, and this call is made frequently...
	//if(d->mutex != NULL){
	pthread_mutex_lock(d->mutex); // lock just THIS mutex
	//} else {
		//???
	//}
	//scarab_lock_datum(d);

	// One fewer reference to this object
	d->ref_count--;
	
	// If the thing is no longer referenced, kill it
	if((d->ref_count) == 0){
	
		switch (d->type) 
		{
			case SCARAB_DICT: 
				// free sub-data
				for(i = 0; i < d->data.dict->tablesize; i++){
					scarab_free_datum(d->data.dict->keys[i]);
					scarab_free_datum(d->data.dict->values[i]);
				}
				
				// Free the parts
				scarab_mem_free(d->data.dict->keys);
				scarab_mem_free(d->data.dict->values);
				
				scarab_mem_free(d->data.dict);
					
				break;
			case SCARAB_LIST:
				// free sub-data
				for(i = 0; i < d->data.list->size; i++){
					scarab_free_datum(d->data.list->values[i]);
				}

				// free parts
				scarab_mem_free(d->data.list->values);
				scarab_mem_free(d->data.list);

				break;
			case SCARAB_FLOAT_OPAQUE:
			case SCARAB_OPAQUE:
				
				// free opaque data
				if(d->data.opaque.data != NULL){
					scarab_mem_free(d->data.opaque.data );
				}
				break;
			default:
				
				break;
		}
		
		//scarab_unlock_datum(d);
		//scarab_destroy_lock(d);
		
		// Take the lock out of the ScarabDatum, we want to hang onto it
		// until we're done
		pthread_mutex_t *lock = d->mutex;
		scarab_mem_free(d);
		
		// now, release the lock and destroy it
		pthread_mutex_unlock(lock);
		pthread_mutex_destroy(lock);
		free(lock);
		
		return;
	}	
	
// Unnecessary checking?
//	if(d->mutex != NULL){
		pthread_mutex_unlock(d->mutex);
//	} else {
		//???
//	}
	//scarab_unlock_datum(d);
	
		
}
void VariableRegistry::updateFromCodecDatum(const Datum &codec) {
	mprintf(M_SYSTEM_MESSAGE_DOMAIN,
			"Received new codec, updating variable registry.");
	
    if(!codec.isDictionary()) {
        merror(M_SYSTEM_MESSAGE_DOMAIN,
			   "Invalid codec received.  Registry is unchanged.");
		return;
	}
 	
	boost::mutex::scoped_lock s_lock(lock);
	
	master_variable_list.clear();
	
	// add the placeholders
	//addPlaceholders();
	
	
	//////////////////////////////////////////////////////////////////
	// now add what's in the codec 
	
	ScarabDatum *datum = codec.getScarabDatum();
	
	ScarabDatum ** keys = datum->data.dict->keys;
	int size = datum->data.dict->tablesize;
	
	
	
	int maxCodecCode = -1;
	// find the maximum codec value
	for(int i = 0; i < size; ++i) {
		if(keys[i]) {
			long long code = keys[i]->data.integer;
			maxCodecCode = (maxCodecCode < code) ? code : maxCodecCode;
		}
	}
		
	// add each variable in order to the registry
	for(int i = N_RESERVED_CODEC_CODES; i<=maxCodecCode; ++i) {
		ScarabDatum *key = scarab_new_integer(i);
		ScarabDatum *serializedVariable = scarab_dict_get(datum, key);
		scarab_free_datum(key);
		
		if(!serializedVariable) {
            shared_ptr<EmptyVariable> empty_var(new EmptyVariable);
            master_variable_list.push_back(empty_var);
            continue;
        } else {
			if(serializedVariable->type != SCARAB_DICT) {
				// these must be  placeholder datums in the package
				// that we should ignore.
				mwarning(M_SYSTEM_MESSAGE_DOMAIN,
						 "Bad variable received from network stream");
				
                shared_ptr<EmptyVariable> empty_var(new EmptyVariable);
                master_variable_list.push_back(empty_var);
                continue;
			}
						
			VariableProperties *props = 
				new VariableProperties(serializedVariable);
			
			if(props == NULL){
				mwarning(M_SYSTEM_MESSAGE_DOMAIN,
						 "Bad variable received from network stream");
				
                shared_ptr<EmptyVariable> empty_var(new EmptyVariable);
                master_variable_list.push_back(empty_var);
                continue;
			}
			
			shared_ptr<Variable> newvar(new GlobalVariable(props));
			newvar->setCodecCode(i); //necessary? .. Yup
			
			master_variable_list.push_back(newvar);
            
            std::string tag = newvar->getVariableName();
            if(!tag.empty()){
                master_variable_dictionary[tag] = newvar;
            }
		}
	}
}
Exemple #12
0
void scarab_free_datum(ScarabDatum *d){
	
	int i;
	
	if(d == NULL) return;
	
#ifdef THREAD_SAFE_SCARAB_DATUM
	pthread_mutex_lock(d->mutex);
#endif

	// One fewer reference to this object
	d->ref_count--;
	
	// If the thing is no longer referenced, kill it
	if((d->ref_count) == 0){
	
		switch (d->type) 
		{
			case SCARAB_DICT: 
				// free sub-data
				for(i = 0; i < d->data.dict->tablesize; i++){
					scarab_free_datum(d->data.dict->keys[i]);
					scarab_free_datum(d->data.dict->values[i]);
				}
				
				// Free the parts
				scarab_mem_free(d->data.dict->keys);
				scarab_mem_free(d->data.dict->values);
				
				scarab_mem_free(d->data.dict);
					
				break;
			case SCARAB_LIST:
				// free sub-data
				for(i = 0; i < d->data.list->size; i++){
					scarab_free_datum(d->data.list->values[i]);
				}

				// free parts
				scarab_mem_free(d->data.list->values);
				scarab_mem_free(d->data.list);

				break;
			case SCARAB_OPAQUE:
				
				// free opaque data
				if(d->data.opaque.data != NULL){
					scarab_mem_free(d->data.opaque.data );
				}
				break;
			default:
				
				break;
		}
		
#ifdef THREAD_SAFE_SCARAB_DATUM
		// Take the lock out of the ScarabDatum, we want to hang onto it
		// until we're done
		pthread_mutex_t *lock = d->mutex;
#endif
        
		scarab_mem_free(d);
		
#ifdef THREAD_SAFE_SCARAB_DATUM
		// now, release the lock and destroy it
		pthread_mutex_unlock(lock);
		pthread_mutex_destroy(lock);
		scarab_mem_free(lock);
#endif
		
		return;
	}	
	
#ifdef THREAD_SAFE_SCARAB_DATUM
	pthread_mutex_unlock(d->mutex);
#endif
}
Exemple #13
0
DataFileIndexer::DataFileIndexer(const boost::filesystem::path &data_file, 
								 const unsigned int _events_per_block,
								 const unsigned int multiplication_factor_per_level,
								 const int number_of_indexing_threads) : events_per_block(_events_per_block) {
	uri = "ldobinary:file://" + data_file.string();
	
	// I hate myself for this
	char *uri_temp = new char[uri.length() + 1];
	strncpy(uri_temp, uri.c_str(), uri.length() + 1);
	session = scarab_session_connect(uri_temp);
	delete [] uri_temp;

	
	{
		std::vector<boost::shared_ptr<EventBlock> > event_blocks;
		{
			number_of_events = 0;
			
			std::vector<unsigned int> event_codes_in_block;
			MonkeyWorksTime max_time = MIN_MONKEY_WORKS_TIME();
			MonkeyWorksTime min_time = MAX_MONKEY_WORKS_TIME();
			long int previous_datum_location = scarab_tell(session);
			
			ScarabDatum *datum = NULL;
			while(datum = scarab_read(session)) {
				event_codes_in_block.push_back(DataFileUtilities::getScarabEventCode(datum));
				
				const MonkeyWorksTime event_time = DataFileUtilities::getScarabEventTime(datum);
				max_time = max_time > event_time ? max_time : event_time;
				min_time = min_time < event_time ? min_time : event_time;
				
				number_of_events++; 
				//std::cout << number_of_events << " ";
				
				if(number_of_events % events_per_block == 0) { 
					std::sort(event_codes_in_block.begin(), event_codes_in_block.end());
					event_codes_in_block.erase(std::unique(event_codes_in_block.begin(), 
														   event_codes_in_block.end()), 
											   event_codes_in_block.end());
					std::cout << "indexing block " << event_blocks.size() << " .. time : " << min_time << "LL - " << max_time << "LL" << std::endl;

					//				cerr << "new event block : num events : " << event_codes_in_block.size() << endl;
					boost::shared_ptr<EventBlock> new_event_block = boost::shared_ptr<EventBlock>(new EventBlock(previous_datum_location, min_time, max_time, event_codes_in_block));
					event_blocks.push_back(new_event_block);
					
					event_codes_in_block.clear();
					max_time = MIN_MONKEY_WORKS_TIME();
					min_time = MAX_MONKEY_WORKS_TIME();
					previous_datum_location = scarab_tell(session);
				}			
				scarab_free_datum(datum);
			}
			
			// add in the remainder blocks
			boost::shared_ptr<EventBlock> new_event_block = boost::shared_ptr<EventBlock>(new EventBlock(previous_datum_location, min_time, max_time, event_codes_in_block));
			event_blocks.push_back(new_event_block);
			//std::cout << "size " << event_blocks.size();
			
		}
		
		
		{
			// build the tree
			int events_per_node = events_per_block;
			int number_of_levels = 1;
			while(events_per_node < number_of_events) {
				number_of_levels++;
				events_per_node *= multiplication_factor_per_level;
			}
			
			std::vector <boost::shared_ptr<EventBlock> > blocks_at_next_level = event_blocks;
			for(int i = 1; i < number_of_levels; ++i) {
				std::vector <boost::shared_ptr<EventBlock> > blocks_at_current_level;
				
				std::vector<boost::shared_ptr<EventBlock> >::const_iterator j = blocks_at_next_level.begin();
				while(j != blocks_at_next_level.end()) {
					std::vector <boost::shared_ptr<EventBlock> > children;					
					for(int k = 0; k < multiplication_factor_per_level && j != blocks_at_next_level.end(); ++k) {
						children.push_back(*j);
						++j;
					}
					boost::shared_ptr<EventBlock> new_block = boost::shared_ptr<EventBlock>(new EventBlock(children));
					blocks_at_current_level.push_back(new_block);
				}
				
				blocks_at_next_level = blocks_at_current_level;
			}
			
			if(blocks_at_next_level.size() != 1) {
				//badness
				std::cerr << "something went wrong...please abort and try again" << std::endl;
				throw new std::exception;
			}
			root = blocks_at_next_level.at(0);
		}
	}
}
ScarabDatumWrapper::~ScarabDatumWrapper() {
	scarab_free_datum(datum);
}