void prepareBuffer()
    {
        _block = getBlockManager().createBlock();

        if(_tableInfo._identifier == "EMPLOYEES") {
            _block->addValue(csvsqldb::Variant(4711));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(1970, csvsqldb::Date::September, 23)));
            _block->addValue(csvsqldb::Variant("Lars"));
            _block->addValue(csvsqldb::Variant("Fürstenberg"));
            _block->addValue(csvsqldb::Variant("M"));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(2012, csvsqldb::Date::February, 1)));
            _block->nextRow();
            _block->addValue(csvsqldb::Variant(815));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(1969, csvsqldb::Date::May, 17)));
            _block->addValue(csvsqldb::Variant("Mark"));
            _block->addValue(csvsqldb::Variant("Fürstenberg"));
            _block->addValue(csvsqldb::Variant("M"));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(2003, csvsqldb::Date::April, 15)));
            _block->nextRow();
            _block->addValue(csvsqldb::Variant(9227));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(1963, csvsqldb::Date::March, 6)));
            _block->addValue(csvsqldb::Variant("Angelica"));
            _block->addValue(csvsqldb::Variant("Tello de Fürstenberg"));
            _block->addValue(csvsqldb::Variant("F"));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(2003, csvsqldb::Date::June, 15)));
            _block->nextRow();
        } else if(_tableInfo._identifier == "SALARIES") {
            _block->addValue(csvsqldb::Variant(4711));
            _block->addValue(csvsqldb::Variant(12000.0));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(2012, csvsqldb::Date::February, 1)));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(2015, csvsqldb::Date::February, 1)));
            _block->nextRow();
            _block->addValue(csvsqldb::Variant(9227));
            _block->addValue(csvsqldb::Variant(450.0));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(2003, csvsqldb::Date::June, 15)));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(2015, csvsqldb::Date::February, 1)));
            _block->nextRow();
            _block->addValue(csvsqldb::Variant(815));
            _block->addValue(csvsqldb::Variant(6000.0));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(2003, csvsqldb::Date::April, 15)));
            _block->addValue(csvsqldb::Variant(csvsqldb::Date(2015, csvsqldb::Date::February, 1)));
            _block->nextRow();
        }
        _block->endBlocks();

        _iterator = std::make_shared<csvsqldb::BlockIterator>(_types, *this, getBlockManager());
    }
	Source::~Source(void)
	{
		/*
		 * Log that someone is deleting me.
		 */
		Logger* l = getBlockManager()->getLogger();
		l->log(Logger::LEVEL_CRIT,
			"%s: waiting for QUIT SEMAPHORE to be unlocked...", getName());

		/*
		 * Wait on the semaphore which signals that
		 * the block can quit.
		 */
		_quitSem.wait();

		/*
		 * Log that delete is ok.
		 */
		l->log(Logger::LEVEL_CRIT, "%s: bye bye", getName());
	}
	void Sink::run(void)
	{
		int32 ret = 0, is_msg = 0, handler_ret = 0;
		int32 data_ready = 0;

		Logger* sl = getBlockManager()->getLogger();
		cmessage cm;

		while (!_quit) {
			//if (_started) {
			//	// get a message from control pin non blocking
			//	ret = getControlPin()->tryRecvMessage(&cm);
			//	if (ret == SUCCESS) is_msg = 1;
			//} else {
			// get a message from control pin blocking
			ret = getControlPin()->recvMessage(&cm);
			if (ret == SUCCESS)
				is_msg = 1;
			//}

			if (is_msg) {
				// detect terminate event
				if (cm.code == Block::EVENT_TERMINATE) {
					_started = false; _quit = true;
					sl->log(Logger::LEVEL_NOTICE,
							"%s: terminate request received", getName());

					// set status
					setStatus(STATUS_TERMINATING);

					// jump to while()
					//continue;
				} else {
					// check message codes and set status
					switch (cm.code) {
					case EVENT_PAUSE:
						setStatus(STATUS_PAUSED);
						_started = false;
						sl->log(Logger::LEVEL_NOTICE,
								"%s: pause request received", getName());
						break;
					case EVENT_RESET:
						setStatus(STATUS_RESETTING);
						_started = false;
						sl->log(Logger::LEVEL_NOTICE,
								"%s: reset request received", getName());
						break;
					case EVENT_START:
						setStatus(STATUS_STARTED);
						_started = true;
						sl->log(Logger::LEVEL_NOTICE,
								"%s: start request received", getName());
						break;
					case EVENT_STOP:
						setStatus(STATUS_STOPPED);
						_started = false;
						sl->log(Logger::LEVEL_NOTICE,
								"%s: stop request received", getName());
						break;
					case EVENT_BUFFERIZE:
						setStatus(STATUS_BUFFERIZING);
						_started = true;
						sl->log(Logger::LEVEL_NOTICE,
								"%s: bufferize request received", getName());
						break;
					case EVENT_SEEK:
						setStatus(STATUS_SEEKING);
						setSeekInfo(&cm.seek);
						sl->log(Logger::LEVEL_NOTICE,
								"%s: seek request received (strange)",
								getName());
						break;
					case EVENT_TELL:
						setStatus(STATUS_TELLING);
						sl->log(Logger::LEVEL_NOTICE,
								"%s: tell request received (strange)",
								getName());
						break;
					case EVENT_SKIP:
						setStatus(STATUS_SKIPPING);
						_started = true;	setSeekInfo(&cm.seek);
						sl->log(Logger::LEVEL_NOTICE,
								"%s: skip request received", getName());
						break;
					case EVENT_QUIT:
						setStatus(STATUS_QUITTING);
						_started = false; _quit = true;
						sl->log(Logger::LEVEL_NOTICE,
								"%s: quit request received", getName());
						break;
					case EVENT_TIMEOUT:
						sl->log(Logger::LEVEL_NOTICE,
								"%s: timeout request received", getName());
						break;
					case EVENT_DATA_READY:
						setStatus(STATUS_STARTED);
						_started = true; data_ready = 1;
						sl->log(Logger::LEVEL_NOTICE,
								"%s: data_ready request received", getName());
						break;
					case EVENT_COMMAND:
						sl->log(Logger::LEVEL_NOTICE,
								"%s: command request received", getName());
						break;
					default:
						if (cm.code >= EVENT_MAX_ID)
							sl->log(Logger::LEVEL_CRIT,
									"%s: invalid message code (%d)",
									getName(), cm.code);
						else
							sl->log(Logger::LEVEL_CRIT,
									"%s: user message %d received", getName(),
									cm.code);
					}

					// execute event handler for this message code
					handler_ret = executeEventHandler(cm.code);
					if (handler_ret == Block::HANDLER_UNDEFINED) {
						sl->log(Logger::LEVEL_NOTICE,
								"%s: undefined handler %d", getName(), cm.code);
					} else if (handler_ret == BlockHandler::HFAILURE) {
						_started = false; setStatus(STATUS_READY);
						sl->log(Logger::LEVEL_ERROR, "%s: handler %d failed",
								getName(), cm.code);
					}

					/*
					 * This block checks for StatusListeners availability. If
					 * any status listener has been registered, this block sends
					 * status messages to it.
					 */
					if (cm.status_listener) {
						// DEBUG
						//UOSUTIL_DOUT((stderr, "Untested code: status listener\n"));

						smessage sm;
						memset(&sm, 0, sizeof(smessage));

						sm.code = cm.code;
						sm.serial = cm.serial;
						sm.status = getStatus();
						sm.eh_return = handler_ret;
						snprintf(sm.error, SM_MESSAGE_SZ, "%s",
							getErrorString());

						ret = cm.status_listener->notifyStatusMessage(&sm);
						if (ret == FAILURE) {
							sl->log(Logger::LEVEL_WARN,
									"%s: cannot notify status to registered listener",
									getName());
						}

						// DEBUG
						//UOSUTIL_DOUT((stderr, "Untested code: status listener end\n"));
					}

					// set status to ready if compatible
					if (cm.code != EVENT_START &&
						cm.code != EVENT_STOP &&
						cm.code != EVENT_PAUSE &&
						cm.code != EVENT_DATA_READY &&
						cm.code != EVENT_COMMAND)
						setStatus(STATUS_READY);

					// wait for next message
					is_msg = 0;
				}
			}

			if (_started && data_ready) {
				// do sink main action: consume data if ready
				handler_ret = executeActionHandler(ACTION_DATA_CONSUME);
				if (handler_ret == Block::HANDLER_UNDEFINED) {
					_started = false; setStatus(STATUS_READY);
					sl->log(Logger::LEVEL_CRIT,
							"%s: undefined action handler", getName());
				} else if (handler_ret == BlockHandler::HSUCCESS) {
					// DO NOTHING HERE (useless log)
				} else if (handler_ret == BlockHandler::HFAILURE) {
					   	_started = false; setStatus(STATUS_READY);
					sl->log(Logger::LEVEL_ERROR,
					   		"%s: action handler returned FAILURE", getName());
				} else if (handler_ret == BlockHandler::HCRITICAL) {
					   	_started = false; setStatus(STATUS_READY);
					sl->log(Logger::LEVEL_EMERG,
					   		"%s: action handler returned CRITICAL FAILURE",
					   		getName());
				} else {
					sl->log(Logger::LEVEL_CRIT,
					   		"%s: action handler returned undefined value",
					   		getName());
				}

				// reset data_ready flag
				data_ready = 0;
			}
		}


		// release the quit semaphore
		sl-> log(Logger::LEVEL_CRIT,
				"%s: Releasing QUIT SEMAPHORE (so quitting)", getName());

		_quitSem. post();

		// log termination before block destruction
		sl-> log(Logger::LEVEL_CRIT,
				"%s: Asking BlockManager for termination", getName());

		/*
		 * Notify the block manager that this block is quitting.
		 * Messages must be sent with normal priority since the
		 * block manager have to complete all pending activities.
		 */
		cmessage bmm;

		memset(&bmm, 0, sizeof(bmm));
		bmm. code = BlockManager::BM_MESSAGE_BLOCKQUIT;
		bmm. from = this;

		getControlPin()-> sendMessage(&bmm);
	}