示例#1
0
uint64_t JoinPartition::writeByteStream(int which, ByteStream &bs)
{
	size_t &offset = (which == 0 ? nextSmallOffset : nextLargeOffset);
	fstream &fs = (which == 0 ? smallFile : largeFile);
	const char *filename = (which == 0 ? smallFilename.c_str() : largeFilename.c_str());

	fs.open(filename, ios::binary | ios::out | ios::app);
	int saveErrno = errno;
	if (!fs) {
		fs.close();
		ostringstream os;
		os << "Disk join could not open file (write access) " << filename << ": " << strerror(saveErrno) << endl;
		throw IDBExcept(os.str().c_str(), ERR_DBJ_FILE_IO_ERROR);
	}

	uint64_t ret = 0;
	size_t len = bs.length();
	idbassert(len != 0);

	fs.seekp(offset);

	if (!useCompression) {
		ret = len + 4;
		fs.write((char *) &len, sizeof(len));
		fs.write((char *) bs.buf(), len);
		saveErrno = errno;
		if (!fs) {
			fs.close();
			ostringstream os;
			os << "Disk join could not write file " << filename << ": " << strerror(saveErrno) << endl;
			throw IDBExcept(os.str().c_str(), ERR_DBJ_FILE_IO_ERROR);
		}
		totalBytesWritten += sizeof(len) + len;
	}
	else {
		uint64_t maxSize = compressor.maxCompressedSize(len);
		size_t actualSize;
		boost::scoped_array<uint8_t> compressed(new uint8_t[maxSize]);

		compressor.compress((char *) bs.buf(), len, (char *) compressed.get(), &actualSize);
		ret = actualSize + 4;
		fs.write((char *) &actualSize, sizeof(actualSize));
		fs.write((char *) compressed.get(), actualSize);
		saveErrno = errno;
		if (!fs) {
			fs.close();
			ostringstream os;
			os << "Disk join could not write file " << filename << ": " << strerror(saveErrno) << endl;
			throw IDBExcept(os.str().c_str(), ERR_DBJ_FILE_IO_ERROR);
		}
		totalBytesWritten += sizeof(actualSize) + actualSize;
	}
	bs.advance(len);

	offset = fs.tellp();
	fs.close();
	return ret;
}
示例#2
0
void InetStreamSocket::do_write(const ByteStream &msg, uint32_t whichMagic, Stats *stats) const
{
	uint32_t msglen = msg.length();
	uint32_t magic = whichMagic;
	uint32_t *realBuf;

	if (msglen == 0) return;

	/* buf.fCurOutPtr points to the data to send; ByteStream guarantees that there
	   are at least 8 bytes before that for the magic & length fields */
	realBuf = (uint32_t *)msg.buf();
	realBuf -= 2;
	realBuf[0] = magic;
	realBuf[1] = msglen;

	try {
		written(fSocketParms.sd(), (const uint8_t*)realBuf, msglen + sizeof(msglen) + sizeof(magic));
	}
	catch (std::exception& ex) {
		string errorMsg(ex.what());
		errorMsg += " -- write from " + toString();
		throw runtime_error(errorMsg);
	}
	if (stats)
		stats->dataSent(msglen + sizeof(msglen) + sizeof(magic));
}
示例#3
0
void InetStreamSocket::write_raw(const ByteStream& msg, Stats *stats) const
{
	uint32_t msglen = msg.length();

	if (msglen == 0) return;

	try {
		written(fSocketParms.sd(), msg.buf(), msglen);
	}
	catch (std::exception& ex) {
		string errorMsg(ex.what());
		errorMsg += " -- write_raw from " + toString();
		throw runtime_error(errorMsg);
	}
	if (stats)
		stats->dataSent(msglen);
}
void CompressedInetStreamSocket::write(const ByteStream& msg, Stats* stats)
{
    size_t outLen = 0;
    uint32_t len = msg.length();

    if (useCompression && (len > 512))
    {
        ByteStream smsg(alg.maxCompressedSize(len));

        alg.compress((char*) msg.buf(), len, (char*) smsg.getInputPtr(), &outLen);
        smsg.advanceInputPtr(outLen);

        if (outLen < len)
            do_write(smsg, COMPRESSED_BYTESTREAM_MAGIC, stats);
        else
            InetStreamSocket::write(msg, stats);
    }
    else
        InetStreamSocket::write(msg, stats);
}
示例#5
0
	void test14() {
		ByteStream bs;
		ifstream ifs("./Calpont.xml");
		ifs >> bs;
		string id(".");
		string value;
		{
			ConfigStream cs(bs, id);
			value = cs.getConfig("Message", "Name");
			CPPUNIT_ASSERT(value == "Message");
		}
		string bss(reinterpret_cast<const char*>(bs.buf()), bs.length());
		{
			ConfigStream cs(bss, id);
			value = cs.getConfig("Message", "Name");
			CPPUNIT_ASSERT(value == "Message");
		}
		{
			ConfigStream cs(bss.c_str(), id);
			value = cs.getConfig("Message", "Name");
			CPPUNIT_ASSERT(value == "Message");
		}
	}
示例#6
0
void MasterDBRMNode::msgProcessor()
{
	struct ThreadParams *p;
	ByteStream msg;
	vector<ByteStream *> responses;
	vector<ByteStream *>::iterator it;
	int err;
	uint8_t cmd;
	StopWatch timer;
#ifdef BRM_VERBOSE
	cerr << "DBRM Controller: msgProcessor()" << endl;
#endif

	mutex2.lock();
	p = params;
	mutex2.unlock();
#ifndef __FreeBSD__
	mutex.unlock();
#endif
	while (!die) {
		try {
			msg = p->sock->read(&MSG_TIMEOUT);
		}
		catch (...) {
			THREAD_EXIT
			throw;
		}

		if (die) // || msg.length() == 0)
			break;
  		
 		else if (msg.length() == 0)
   			continue;

		/* Check for an command for the master */
		msg.peek(cmd);
#ifdef BRM_VERBOSE
		cerr << "DBRM Controller: recv'd message " << (int)cmd << " length " << msg.length() << endl;
#endif
		switch (cmd) {
			case HALT: doHalt(p->sock); continue;
			case RESUME: doResume(p->sock); continue;
			case RELOAD: 
				try { 
					doReload(p->sock);
				}
				catch (exception &e) {
					cerr << e.what() << endl;
				}
				continue;
			case SETREADONLY: doSetReadOnly(p->sock, true); continue;
			case SETREADWRITE: doSetReadOnly(p->sock, false); continue;
			case GETREADONLY: doGetReadOnly(p->sock); continue;
		}

		/* Process SessionManager calls */
		switch (cmd) {
			case VER_ID: doVerID(msg, p); continue;
			case SYSCAT_VER_ID: doSysCatVerID(msg, p); continue;
			case NEW_TXN_ID: doNewTxnID(msg, p); continue;
			case COMMITTED: doCommitted(msg, p); continue;
			case ROLLED_BACK: doRolledBack(msg, p); continue;
			case GET_TXN_ID: doGetTxnID(msg, p); continue;
			case SID_TID_MAP: doSIDTIDMap(msg, p); continue;
			case GET_UNIQUE_UINT32: doGetUniqueUint32(msg, p); continue;
			case GET_UNIQUE_UINT64: doGetUniqueUint64(msg, p); continue;
			case GET_SYSTEM_STATE: doGetSystemState(msg, p); continue;
			case SET_SYSTEM_STATE: doSetSystemState(msg, p); continue;
			case CLEAR_SYSTEM_STATE: doClearSystemState(msg, p); continue;
			case SM_RESET: doSessionManagerReset(msg, p); continue;
		}

		/* Process TableLock calls */
		switch (cmd) {
			case GET_TABLE_LOCK: doGetTableLock(msg, p); continue;
			case RELEASE_TABLE_LOCK: doReleaseTableLock(msg, p); continue;
			case CHANGE_TABLE_LOCK_STATE: doChangeTableLockState(msg, p); continue;
			case CHANGE_TABLE_LOCK_OWNER: doChangeTableLockOwner(msg, p); continue;
			case GET_ALL_TABLE_LOCKS: doGetAllTableLocks(msg, p); continue;
			case RELEASE_ALL_TABLE_LOCKS: doReleaseAllTableLocks(msg, p); continue;
			case GET_TABLE_LOCK_INFO: doGetTableLockInfo(msg, p); continue;
			case OWNER_CHECK: doOwnerCheck(msg, p); continue;
		}

		/* Process OIDManager calls */
		switch (cmd) {
			case ALLOC_OIDS: doAllocOIDs(msg, p); continue;
			case RETURN_OIDS: doReturnOIDs(msg, p); continue;
			case OIDM_SIZE: doOidmSize(msg, p); continue;

			case ALLOC_VBOID: doAllocVBOID(msg, p); continue;
			case GETDBROOTOFVBOID: doGetDBRootOfVBOID(msg, p); continue;
			case GETVBOIDTODBROOTMAP: doGetVBOIDToDBRootMap(msg, p); continue;
		}

		/* Process Autoincrement calls */
		switch (cmd) {
			case START_AI_SEQUENCE: doStartAISequence(msg, p); continue;
			case GET_AI_RANGE: doGetAIRange(msg, p); continue;
			case RESET_AI_SEQUENCE: doResetAISequence(msg, p); continue;
			case GET_AI_LOCK: doGetAILock(msg, p); continue;
			case RELEASE_AI_LOCK: doReleaseAILock(msg, p); continue;
			case DELETE_AI_SEQUENCE: doDeleteAISequence(msg, p); continue;
		}

retrycmd:
		uint32_t haltloops = 0;

		while (halting && ++haltloops < static_cast<uint32_t>(FIVE_MIN_TIMEOUT.tv_sec))
			sleep(1);

		slaveLock.lock();
		if (haltloops == FIVE_MIN_TIMEOUT.tv_sec) {
			ostringstream os;
			os << "A node is unresponsive for cmd = " << (uint32_t)cmd <<
				", no reconfigure in at least " << 
				FIVE_MIN_TIMEOUT.tv_sec << " seconds.  Setting read-only mode.";
			log(os.str());
			readOnly = true;
			halting = false;
		}	
	
		if (readOnly) {
			SEND_ALARM
			slaveLock.unlock();
			sendError(p->sock, ERR_READONLY);
			goto out;
		}

		/* TODO: Separate these out-of-band items into separate functions */

		/* Need to get the dbroot, convert to vbOID */
		if (cmd == BEGIN_VB_COPY) {
			try {
				boost::mutex::scoped_lock lk(oidsMutex);
				uint8_t *buf = msg.buf();

				// dbroot is currently after the cmd and transid
				uint16_t *dbRoot = (uint16_t *) &buf[1+4];

				// If that dbroot has no vboid, create one
				int16_t err;
				err = oids.getVBOIDOfDBRoot(*dbRoot);
				//cout << "dbRoot " << *dbRoot << " -> vbOID " << err << endl;
				if (err < 0) {
					err = oids.allocVBOID(*dbRoot);
				//	cout << "  - allocated oid " << err << endl;
				}
				*dbRoot = err;
			}
			catch (exception& ex) {
				ostringstream os;
				os << "DBRM Controller: Begin VBCopy failure. " << ex.what();
				log(os.str());
				sendError(p->sock, -1);
				goto out;
			}
		}

		/* Check for deadlock on beginVBCopy */
/*		if (cmd == BEGIN_VB_COPY) {
			ByteStream params(msg);
			VER_t txn;
			uint8_t tmp8;
			uint32_t tmp32;
			LBIDRange_v ranges;
			LBIDRange_v::iterator it;
			LBID_t end;

			params >> tmp8;   //throw away the cmd
			params >> tmp32;
			txn = tmp32;
			deserializeVector(params, ranges);
			for (it = ranges.begin(); it != ranges.end(); it++) {
				end = (*it).start + (*it).size - 1;
				err = rg->reserveRange((*it).start, end, txn, slaveLock);
				if (err != ERR_OK) {
					pthread_mutex_unlock(&slaveLock);
					sendError(p->sock, err);
					goto out;
				}
			}
		}
*/
		/* Release all blocks of lbids on vbRollback or vbCommit */
		if (cmd == VB_ROLLBACK1 || cmd == VB_ROLLBACK2 || cmd == VB_COMMIT) {
			ByteStream params(msg);
			VER_t txn;
			uint8_t tmp8;
			uint32_t tmp32;

			params >> tmp8;
			params >> tmp32;
			txn = tmp32;
			rg->releaseResources(txn);
		}

	/* XXXPAT: If beginVBCopy, vbRollback, or vbCommit fail for some reason,
	   the resource graph will be out of sync with the copylocks and/or vss.
	   There are 2 reasons they might fail:
			1) logical inconsistency between the resource graph and the 
			copylocks & vss
			2) "out of band" failures, like a network problem
	*/

		/* Need to atomically do the safety check and the clear. */
		if (cmd == BRM_CLEAR) {
			uint32_t txnCount = sm.getTxnCount();
			// do nothing if there's an active transaction
            if (txnCount != 0) {
				ByteStream *reply = new ByteStream();
				*reply << (uint8_t) ERR_FAILURE;
				responses.push_back(reply);
				goto no_confirm;
			}
		}

		try {
			distribute(&msg);
		}
		catch (...) {
			if (!halting) {
				SEND_ALARM
				undo();
				readOnly = true;
				slaveLock.unlock();
				ostringstream ostr;
				ostr << "DBRM Controller: Caught network error.  "
					"Sending command " << (uint32_t)cmd <<
					", length " << msg.length() << ".  Setting read-only mode.";
				log(ostr.str());
				sendError(p->sock, ERR_NETWORK);
				goto out;
			}
		}

#ifdef BRM_VERBOSE
		cerr << "DBRM Controller: distributed msg" << endl;
#endif

		bool readErrFlag; // ignore this flag in this case
		err = gatherResponses(cmd, msg.length(), &responses, readErrFlag);
		
#ifdef BRM_VERBOSE
		cerr << "DBRM Controller: got responses" << endl;
#endif

		CHECK_ERROR1(err)
		err = compareResponses(cmd, msg.length(), responses);
#ifdef BRM_VERBOSE
		cerr << "DBRM Controller: compared responses" << endl;
#endif

#ifdef BRM_DEBUG
		if ((cmd == BEGIN_VB_COPY || cmd == VB_ROLLBACK1 || cmd == VB_ROLLBACK2 ||
			cmd == VB_COMMIT) && err == -1)
			cerr << "DBRM Controller: inconsistency detected between the resource graph and the VSS or CopyLocks logic." << endl;
#endif

		// these command will have error message carried in the response
		if (!responses.empty() && (cmd == DELETE_PARTITION || cmd == MARK_PARTITION_FOR_DELETION || cmd == RESTORE_PARTITION) 
			 && err)
		{
			if (err != ERR_PARTITION_DISABLED && err != ERR_PARTITION_ENABLED && 
				  err != ERR_INVALID_OP_LAST_PARTITION && err != ERR_NOT_EXIST_PARTITION &&
				  err != ERR_NO_PARTITION_PERFORMED)
				undo();
			//goto no_confirm;
		}
		else 
		{ 
  		CHECK_ERROR1(err)
  	}

		// these cmds don't need the 2-phase commit
		if (cmd == FLUSH_INODE_CACHES || cmd == BRM_CLEAR || cmd == TAKE_SNAPSHOT)
			goto no_confirm;

#ifdef BRM_VERBOSE
		cerr << "DBRM Controller: sending confirmation" << endl;
#endif
		try {
			confirm();
		}
		catch (...) { 
			if (!halting) {
				SEND_ALARM
				ostringstream ostr;
				ostr << "DBRM Controller: Caught network error.  "
					"Confirming command " << (uint32_t)cmd <<
					", length " << msg.length() << ".  Setting read-only mode.";
				log(ostr.str());
				readOnly = true;
			}
		}

no_confirm:
		slaveLock.unlock();

		try {
			p->sock->write(*(responses.front()));
		}
		catch (...) {
			p->sock->close();
			log("DBRM Controller: Warning: could not send the reply to a command", logging::LOG_TYPE_WARNING);
		}

out:
		for (it = responses.begin(); it != responses.end(); it++)
			delete *it;
		responses.clear();
	}
示例#7
0
int main(int argc, char** argv)
{
    vflg = false;
    uint32_t tlvl = 0;
    bool dflg = false;
    int c;
    int32_t sid = -1;
    bool Bflg = false;

    opterr = 0;

    while ((c = getopt(argc, argv, "vt:ds:Bh")) != EOF)
        switch (c)
        {
        case 't':
            tlvl = static_cast<uint32_t>(strtoul(optarg, 0, 0));
            break;
        case 'v':
            vflg = true;
            break;
        case 'd':
            dflg = true;
            break;
        case 's':
            sid = static_cast<int32_t>(strtol(optarg, 0, 0));
            break;
        case 'B':
            Bflg = true;
            break;
        case 'h':
        case '?':
        default:
            usage();
            return (c == 'h' ? 0 : 1);
            break;
        }

    if (dflg)
        vflg = true;

    if ((argc - optind) < 1)
    {
        usage();
        return 1;
    }

    ifstream inputf;
    ByteStream bs;
    ByteStream dbs;
    ByteStream eoq;
    ByteStream tbs;
    ByteStream statsStream;
    ByteStream::quadbyte q = 0;
    eoq << q;
    uint32_t sessionid;
    time_t t;
    SJLP jl;
    DeliveredTableMap tm;
    DeliveredTableMap::iterator iter;
    DeliveredTableMap::iterator end;
    CalpontSelectExecutionPlan csep;
    struct timeval start_time;
    struct timeval end_time;

    MessageQueueClient* mqc = 0;

    if (!dflg)
        mqc = new MessageQueueClient("ExeMgr1");

    if (sid == -1)
    {
        time(&t);
        sessionid = static_cast<uint32_t>(t);
    }
    else
    {
        sessionid = static_cast<uint32_t>(sid);
    }
    sessionid &= 0x7fffffff;
    logging::ErrorCodes errorCodes;
    for ( ; optind < argc; optind++)
    {

        inputf.open(argv[optind]);

        if (!inputf.good())
        {
            cerr << "error opening plan stream " << argv[optind] << endl;
            return 1;
        }

        bs.reset();
        inputf >> bs;

        inputf.close();

        csep.unserialize(bs);

        csep.sessionID(sessionid);
        SessionManager sm;
        csep.verID(sm.verID());

        csep.traceFlags(0);
        ResourceManager rm;
        jl = JobListFactory::makeJobList(&csep, rm);
        csep.traceFlags(tlvl);

        if (vflg)
        {
            if (dflg)
                cout << endl << "Query:" << endl;
            else
            {
                cout << endl << "Session: " << sessionid <<
                     ", Sending Query";
                if (Bflg)
                    cout << " (" << argv[optind] << ')';
                cout << ':' << endl;
            }

            if (!Bflg)
                cout << csep.data() << endl << endl;
        }

        if (dflg)
            continue;

        try
        {
            dbs.reset();
            csep.serialize(dbs);

            gettimeofday(&start_time, 0);

            //try tuples first, but expect the worst...
            bool expectTuples = false;
            ByteStream tbs;
            ByteStream::quadbyte tqb = 4;
            tbs << tqb;
            mqc->write(tbs);

            //send the CSEP
            mqc->write(dbs);

            //read the response to the tuple request
            tbs = mqc->read();
            idbassert(tbs.length() == 4);
            tbs >> tqb;
            if (tqb == 4)
                expectTuples = true;

            if (!expectTuples)
                cout << "Using TableBand I/F" << endl;
            else
                cout << "Using tuple I/F" << endl;

            tm = jl->deliveredTables();

            iter = tm.begin();
            end = tm.end();

            OID toid;
            uint64_t rowTot;
            bool reported = false;
            bool needRGCtor = true;
            while (iter != end)
            {
                toid = iter->first;
                q = static_cast<ByteStream::quadbyte>(toid);
                tbs.reset();
                tbs << q;
                mqc->write(tbs);

                ByteStream tbbs;
                TableBand tb;
                RowGroup rg;
                rowTot = 0;
                uint16_t status = 0;
                TableBand::VBA::size_type rc;
                ofstream out;
                for (;;)
                {
                    tbbs = mqc->read();
#if 0
                    cout << tbbs.length() << endl;
                    out.open("bs1.dat");
                    idbassert(out.good());
                    out << tbbs;
                    out.close();
                    tbbs = mqc->read();
                    cout << tbbs.length() << endl;
                    out.open("bs2.dat");
                    idbassert(out.good());
                    out << tbbs;
                    out.close();
                    tbbs = mqc->read();
                    cout << tbbs.length() << endl;
                    out.open("bs3.dat");
                    idbassert(out.good());
                    out << tbbs;
                    out.close();
#endif
                    if(tbbs.length())
                    {
                        if (!expectTuples)
                            tb.unserialize(tbbs);
                        else
                        {
                            if (needRGCtor)
                            {
                                rg.deserialize(tbbs);
                                needRGCtor = false;
                                tbbs = mqc->read();
                            }
                            rg.setData((uint8_t*)tbbs.buf());
                        }
                    }
                    else
                    {   //@bug 1346
                        if (!status)
                            status = logging::makeJobListErr;
                        break;
                    }
                    if (!expectTuples)
                    {
                        rc = tb.getRowCount();
                        status = tb.getStatus();
                    }
                    else
                    {
                        rc = rg.getRowCount();
                        status = rg.getStatus();
                        if (rc == 0) status = 0;
                    }
                    if (rc == 0)
                        break;
                    rowTot += rc;
                }
                BatchPrimitive* step = dynamic_cast<BatchPrimitive*>( iter->second.get() );
                if (vflg && step)
                {
                    cout << "For table " << step->tableName();
                    if (!Bflg)
                        cout << " " << toid;
                    cout << ": read " << rowTot << " rows" << endl;
                }
                if (status && !reported)
                {
                    cout << "### Query failed: " << errorCodes.errorString(status) << "  Check crit.log\n";
                    reported = true;
                }
                if (!step && !reported)
                {
                    cout << "### Query failed: Did not return project BatchPrimitive. Check crit.log\n";
                    reported = true;
                }

                ++iter;
            }

            if (vflg)
            {
                gettimeofday(&end_time, 0);
                cout << "Query time: " << fixed << setprecision(1) << tm_diff(&start_time, &end_time) <<
                     " secs" << endl;

                //...Ask for query stats through special table id of 3
                const OID TABLE_ID_TO_GET_QUERY_STATS = 3;
                if (!Bflg)
                    cout << "Retrieving stats..." << endl;
                toid = TABLE_ID_TO_GET_QUERY_STATS;
                q = static_cast<ByteStream::quadbyte>(toid);
                statsStream.reset();
                statsStream << q;
                mqc->write(statsStream);

                ByteStream bs_statsString;
                bs_statsString = mqc->read();
                string statsString;
                bs_statsString >> statsString;

                string printStatsString;
                struct timeval startRunTime;
                parseStatsString (statsString, printStatsString, startRunTime);
                cout << printStatsString << "; QuerySetupTime-" <<
                     tm_diff(&start_time, &startRunTime) << "secs" << endl;
            }
            //...Close this query/session
            mqc->write(eoq);
            jl.reset();
        }
        catch(const exception& ex)
        {
            cout << "### SendPlan caught an exception: " << ex.what() << endl;
        }
    }
// 	jl.reset();
    CalpontSystemCatalog::removeCalpontSystemCatalog( sessionid );
    config::Config::deleteInstanceMap();

    delete mqc;

    return 0;
}
示例#8
0
int main (int	argc,	char   *argv[]	)
{
	g_sndbuf = 126976;
	g_sqns = 1000;

/* parse program arguments */
	const char* binary_name = strrchr (argv[0], '/');
	int c;
	while ((c = getopt (argc, argv, "b:m:t:s:n:p:r:f:k:g:w:q:lh")) != -1)
	{
		switch (c) {
		case 'b':	g_blocks = atoi(optarg); break;
		case 'm':	g_messages = atoi(optarg); break;
		case 't':	g_max_rte = atoi(optarg) * 400; break;

		case 'n':	g_network = optarg; break;
		case 's':	g_port = atoi (optarg); break;
		case 'p':	g_udp_encap_port = atoi (optarg); break;
		case 'r':	g_max_rte = atoi (optarg); break;

		case 'f':	g_fec = TRUE; break;
		case 'k':	g_k = atoi (optarg); break;
		case 'g':	g_n = atoi (optarg); break;
		case 'w':	g_sndbuf = atoi (optarg); break;
		case 'q':	g_sqns = atoi (optarg); break;

		case 'l':	g_multicast_loop = TRUE; break;

		case 'h':
		case '?': usage (binary_name);
		}
	}

	if (g_fec && ( !g_k || !g_n )) {
		puts ("Invalid Reed-Solomon parameters.");
		usage (binary_name);
	}

	log_init ();
	pgm_init ();

/* setup signal handlers */
	signal (SIGSEGV, on_sigsegv);
	signal (SIGHUP, SIG_IGN);

	ByteStream obs;
	ByteStream psbs;
	uint w = createData(obs, psbs);
	ByteStream::octbyte bytes_written = 0;
	time_t start_time = 0;
	if (!create_transport ())
	{
		start_time = time(0);
// Send total length for error check and to start timer on receive side
		gssize e = pgm_transport_send (g_transport, psbs.buf(), psbs.length(), 0);
		if (e < 0) 
			g_warning ("pgm_transport_send datasize failed.");
		for (uint i = 0; i < g_messages; ++i)
		{
			gsize e = pgm_transport_send (g_transport, obs.buf(), obs.length(), 0);
		        if (e < 0) 
				g_warning ("pgm_transport_send data failed.");

			bytes_written +=w;
		}
	}
	obs.reset();
//Send 0 length to indicate transmission finished.
	gssize e = pgm_transport_send (g_transport, &obs, 0, 0);
 	if (e < 0) 
		g_warning ("pgm_transport_send failed.");
	
	double elapsed_time = time(0) - start_time;

/* cleanup */
	if (g_transport) 
	{
		pgm_transport_destroy (g_transport, TRUE);
		g_transport = NULL;
	}

	std::cout << "pgmsend wrote " << bytes_written << " bytes with " << g_messages << " messages of " << w << " bytes in " << elapsed_time << " seconds ";
	if (elapsed_time)
		std::cout <<  bytes_written/elapsed_time/1024 << " Kbytes/second\n";
	else
		std::cout << std::endl;

	return 0;
}