void RedistributeWorkerThread::handleDataCont(SBS& sbs, size_t& size)
{
	size_t ack = 0;

	try
	{
		size_t bytesRcvd = 0;
		*sbs >> bytesRcvd;

		if (bytesRcvd != sbs->length())
		{
			ostringstream oss;
			oss << "Incorrect data length: " << sbs->length() << ", expecting " << bytesRcvd;
			fErrorMsg = oss.str();
			fErrorCode = RED_EC_BS_TOO_SHORT;
			logMessage(fErrorMsg, __LINE__);
			throw runtime_error(fErrorMsg);
		}

		errno = 0;
		size_t n = fwrite(sbs->buf(), 1, bytesRcvd, fNewFilePtr);
		if (n != bytesRcvd)
		{
			int e = errno;
			ostringstream oss;
			oss << "Fail to write file: " << strerror(e) << " (" << e << ")";
			fErrorMsg = oss.str();
			fErrorCode = RED_EC_FWRITE_FAIL;
			logMessage(fErrorMsg, __LINE__);
			throw runtime_error(fErrorMsg);
		}

		ack = bytesRcvd;
		size += ack;
	}
	catch (const std::exception&)
	{
		// NACK
		size = -1;
	}
	catch (...)
	{
		// NACK
		ack = -1;
	}

	// ack received data
	sbs.reset();
	fMsgHeader.messageId = RED_DATA_ACK;
	fBs.restart();
	fBs << (ByteStream::byte) WriteEngine::WE_SVR_REDISTRIBUTE;  // dummy, keep for now.
	fBs.append((const ByteStream::byte*) &fMsgHeader, sizeof(fMsgHeader));
	fBs << ack;
	fIOSocket.write(fBs);
}
bool RedistributeWorkerThread::checkDataTransferAck(SBS& sbs, size_t size)
{
	if (sbs->length() == 0)
	{
		ostringstream oss;
		oss << "Zero byte read, Network error.";
		fErrorMsg = oss.str();
		logMessage(fErrorMsg, __LINE__);
		fErrorCode = RED_EC_NETWORK_FAIL;
	}
	else if (sbs->length() < (sizeof(RedistributeMsgHeader) + 1))
	{
		ostringstream oss;
		oss << "Short message, length=" << sbs->length();
		fErrorMsg = oss.str();
		logMessage(fErrorMsg, __LINE__);
		fErrorCode = RED_EC_WKR_MSG_SHORT;
	}
	else
	{
		// Need check header info
		ByteStream::byte wesMsgId;
		*sbs >> wesMsgId;
		//const RedistributeMsgHeader* h = (const RedistributeMsgHeader*) sbs->buf();
		sbs->advance(sizeof(RedistributeMsgHeader));
		size_t ack;
		*sbs >> ack;

		if (ack != size)
		{
			ostringstream oss;
			oss << "Acked size does not match request: " << ack << "/" << size;
			fErrorMsg = oss.str();
			logMessage(fErrorMsg, __LINE__);
			fErrorCode = RED_EC_SIZE_NACK;
		}
	}

	sbs.reset();

	return (fErrorCode == RED_EC_OK);
}
void RedistributeWorkerThread::handleDataStart(SBS& sbs, size_t& size)
{
	char fileName[WriteEngine::FILE_NAME_SIZE];

	try
	{
		// extract the control data for the segment file
		RedistributeDataControl dc;
		if (sbs->length() >= sizeof(RedistributeDataControl))
		{
			memcpy(&dc, sbs->buf(), sizeof(RedistributeDataControl));
			sbs->advance(sizeof(RedistributeDataControl));
			size = dc.size;
		}
		else
		{
			ostringstream oss;
			oss << "Short message, length=" << sbs->length();
			fErrorMsg = oss.str();
			fErrorCode = RED_EC_WKR_MSG_SHORT;
			logMessage(fErrorMsg, __LINE__);
			throw runtime_error(fErrorMsg);
		}

		// create and open the file for writing.
		WriteEngine::FileOp fileOp;  // just to get filename, not for file operations
		int rc = fileOp.oid2FileName(dc.oid, fileName, true, dc.dbroot, dc.partition, dc.segment);
		if (rc == WriteEngine::NO_ERROR)
		{
			ostringstream oss;
			oss << "=>redistributing: " << fileName << ", oid=" << dc.oid << ", db=" << dc.dbroot
				<< ", part=" << dc.partition << ", seg=" << dc.segment << " from db="
				<< fMsgHeader.destination;  // fMsgHeader has swapped source and destination.
			logMessage(oss.str(), __LINE__);
		}
		else
		{
			fErrorCode = RED_EC_OID_TO_FILENAME;
			ostringstream oss;
			oss << "Failed to get file name: oid=" << dc.oid << ", dbroot=" << dc.dbroot
				<< ", partition=" << dc.partition << ", segment=" << dc.segment;
			fErrorMsg = oss.str();
			logMessage(fErrorMsg, __LINE__);
			throw runtime_error(fErrorMsg);
		}

		if (fNewFilePtr != NULL)
			closeFile(fNewFilePtr);

		errno = 0;
		fNewFilePtr = fopen(fileName, "wb");
		if (fNewFilePtr != NULL)
		{
			ostringstream oss;
			oss << "open " << fileName << ", oid=" << dc.oid << ", dbroot="
				<< dc.dbroot << ", partition=" << dc.partition << ", segment=" << dc.segment
				<< ". " << fNewFilePtr;
			logMessage(oss.str(), __LINE__);
		}
		else
		{
			int e = errno;
			fErrorCode = RED_EC_OPEN_FILE_FAIL;
			ostringstream oss;
			oss << "Failed to open " << fileName << ", oid=" << dc.oid << ", dbroot="
				<< dc.dbroot << ", partition=" << dc.partition << ", segment=" << dc.segment
				<< ". " << strerror(e) << " (" << e << ")";
			fErrorMsg = oss.str();
			logMessage(fErrorMsg, __LINE__);
			throw runtime_error(fErrorMsg);
		}

		// set output buffering
		errno = 0;
		if (setvbuf(fNewFilePtr, fWriteBuffer.get(), _IOFBF, CHUNK_SIZE))
		{
			int e = errno;
			ostringstream oss;
			oss << "Failed to set i/o buffer: " << strerror(e) << " (" << e << ")";
			fErrorMsg = oss.str();
			logMessage(fErrorMsg, __LINE__);

			// not throwing an exception now.
		}

		// add to set for remove after abort
		addToDirSet(fileName, false);

		// do a fseek will show the right size, but will not actually allocate the continuous block.
		// do write 4k block till file size.
		char buf[PRE_ALLOC_SIZE] = {1};
		size_t nmemb = size / PRE_ALLOC_SIZE;
		while (nmemb-- > 0)
		{
			errno = 0;
			size_t n = fwrite(buf, PRE_ALLOC_SIZE, 1, fNewFilePtr);
			if (n != 1)
			{
				int e = errno;
				ostringstream oss;
				oss << "Fail to preallocate file: " << strerror(e) << " (" << e << ")";
				fErrorMsg = oss.str();
				fErrorCode = RED_EC_FWRITE_FAIL;
				logMessage(fErrorMsg, __LINE__);
				throw runtime_error(fErrorMsg);
			}
		}

		// move back to beging to write real data
		fflush(fNewFilePtr);
		rewind(fNewFilePtr);
	}
	catch (const std::exception& ex)
	{
		// NACK
		size = -1;
		logMessage(ex.what(), __LINE__);
	}
	catch (...)
	{
		// NACK
		size = -1;
	}

	// ack file size
	fMsgHeader.messageId = RED_DATA_ACK;
	fBs.restart();
	fBs << (ByteStream::byte) WriteEngine::WE_SVR_REDISTRIBUTE;  // dummy, keep for now.
	fBs.append((const ByteStream::byte*) &fMsgHeader, sizeof(fMsgHeader));
	fBs << size;
	fIOSocket.write(fBs);

	// reset to count the data received
	size = 0;
	sbs.reset();
}
예제 #4
0
void WEClients::Listen ( boost::shared_ptr<MessageQueueClient> client, uint32_t connIndex)
{
	SBS sbs;

	try {
		while ( Busy() )
		{
			//TODO: This call blocks so setting Busy() in another thread doesn't work here...
			sbs = client->read();
			if ( sbs->length() != 0 )
			{
				//cout << "adding data to connIndex " << endl;
				addDataToOutput(sbs, connIndex);
			}
			else // got zero bytes on read, nothing more will come
			{
				if (closingConnection > 0)
				{
					return;
				}
				cerr << "WEC got 0 byte message for object " << this << endl;
				goto Error;
			}
		}
		return;
	} catch (std::exception& e)
	{
		cerr << "WEC Caught EXCEPTION: " << e.what() << endl;
		goto Error;
	}
	catch (...)
	{
		cerr << "WEC Caught UNKNOWN EXCEPT" << endl;
		goto Error;
	}
Error:
	// error condition! push 0 length bs to messagequeuemap and
	// eventually let jobstep error out.
	mutex::scoped_lock lk(fMlock);

	MessageQueueMap::iterator map_tok;
	sbs.reset(new ByteStream(0));

	for (map_tok = fSessionMessages.begin(); map_tok != fSessionMessages.end(); ++map_tok)
	{
		map_tok->second->queue.clear();
		(void)atomicops::atomicInc(&map_tok->second->unackedWork[0]);
		map_tok->second->queue.push(sbs);
	}
	lk.unlock();

	// reset the pmconnection map
	{
		mutex::scoped_lock onErrLock(fOnErrMutex);
		string moduleName = client->moduleName();
		ClientList::iterator itor = fPmConnections.begin();
		while (itor != fPmConnections.end())
		{
			if (moduleName == (itor->second)->moduleName())
			{
				(fPmConnections[itor->first]).reset();
				pmCount--;
				ostringstream oss;
				//oss << "WECLIENT: connection to is reset and this = " << this << " and pmcount is decremented.";
				//writeToLog(__FILE__, __LINE__, oss.str() , LOG_TYPE_DEBUG);
			}
				
			itor++;
		}
		// send alarm
		SNMPManager alarmMgr;
//		string alarmItem = sin_addr2String(client->serv_addr().sin_addr);
		string alarmItem = client->addr2String();
		alarmItem.append(" WriteEngineServer");
		alarmMgr.sendAlarmReport(alarmItem.c_str(), oam::CONN_FAILURE, SET);
	}
	return;
}