⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mover.c

📁 网络数据管理协议的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
	}			if ((flags = fcntl(session->mover.sock,					   F_SETFL, flags|O_NDELAY|O_NONBLOCK)) < 0)	{		Error(LOG_ERR, "moverAcceptConnection: fcntl(F_SETFL) error: %s.\n",			  strerror(errno));		ndmpdMoverError(session, NDMP_MOVER_HALT_INTERNAL_ERROR);		return;	}	if (session->mover.mode == NDMP_MOVER_MODE_READ)	{		if (ndmpdAddFileHandler(session, (void*)session,								session->mover.sock,								NDMPD_SELECT_MODE_READ,								HC_MOVER,								moverDataRead) < 0)		{			ndmpdMoverError(session, NDMP_MOVER_HALT_INTERNAL_ERROR);			return;		}	}		Debug(DBG_CAT_MOVER|DBG_FOC_FLOW,		  "moverAcceptConnection: Received connection from %s\n",		  inet_ntoa(from.sin_addr));	session->mover.state = NDMP_MOVER_STATE_ACTIVE;}/* * moverDataRead *   Reads backup data from the data connection and writes the *   received data to the tape device. * * Parameters: *   cookie  (input) - session pointer. *   fd      (input) - file descriptor. *   mode    (input) - select mode. * * Returns: *   void. */static voidmoverDataRead(void*		cookie,			  int		fd,			  u_long	mode __attribute__ ((unused))){	NdmpdSession*	session = (NdmpdSession*)cookie;	int				n;		Debug(DBG_CAT_MOVER|DBG_FOC_FLOW,		  "moverDataRead.\n");	n = read(fd,			 &session->mover.buf[session->mover.wIndex],			 session->mover.recordSize - session->mover.wIndex);	/*	 * Since this function is only called when select believes data	 * is available to be read, a return of zero indicates the	 * connection has been closed.	 */	if (n <= 0)	{		u_long	index;				if (n < 0 && errno == EWOULDBLOCK)			return;					/* Save the index since moverTapeFlush resets it. */		index = session->mover.wIndex;		/* Flush any buffered data to tape. */		if (moverTapeFlush(session) >= 0)		{			session->mover.dataWritten += index;			session->mover.recordNum++;		}				if (n == 0)			ndmpdMoverError(session, NDMP_MOVER_HALT_CONNECT_CLOSED);		else			ndmpdMoverError(session, NDMP_MOVER_HALT_INTERNAL_ERROR);		return;	}	session->mover.wIndex += n;	if (session->mover.wIndex == session->mover.recordSize)	{		n = moverTapeWrite(session, session->mover.buf,					  session->mover.recordSize);		if (n <= 0)		{			ndmpdMoverError(session, (n == 0 ? NDMP_MOVER_HALT_ABORTED									  : NDMP_MOVER_HALT_INTERNAL_ERROR));			return;		}				session->mover.wIndex = 0;		session->mover.dataWritten += n;		session->mover.recordNum++;	}}/* * moverDataWrite *   Reads backup data from the tape device and writes the *   data to the data connection. *   This function is called by ndmpdSelect when the data connection *   is ready for more data to be written. * * Parameters: *   cookie  (input) - session pointer. *   fd      (input) - file descriptor. *   mode    (input) - select mode. * * Returns: *   void. */static voidmoverDataWrite(void*		cookie,			   int			fd,			   u_long		mode __attribute__ ((unused))){	NdmpdSession*	session = (NdmpdSession*)cookie;	int				n;	u_long			len;		Debug(DBG_CAT_MOVER|DBG_FOC_FLOW,		  "moverDataWrite: rIndex:%u wIndex:%u bytesLeftToRead:%llu.\n",		  session->mover.rIndex, session->mover.wIndex,		  session->mover.bytesLeftToRead);	/*	 * Read more data into the tape buffer if the buffer is empty.	 */	if (session->mover.wIndex == 0)	{		/*		 * If the end of the mover window has been reached,		 * then notify the client that a seek is needed.		 * Remove the file handler to prevent this function from		 * being called. The handler will be reinstalled in		 * ndmpdMoverContinue.		 */		if (session->mover.position >=			session->mover.windowOffset + session->mover.windowLength)		{			ndmp_notify_mover_paused_request	pauseRequest;			session->mover.state        = NDMP_MOVER_STATE_PAUSED;			session->mover.pauseReason  = NDMP_MOVER_PAUSE_SEEK;			pauseRequest.reason         = NDMP_MOVER_PAUSE_SEEK;			pauseRequest.seek_position  = longLongToQuad(session->mover.position);			(void)ndmpdRemoveFileHandler(session, fd);			if (ndmpSendRequest(session->connection, NDMP_NOTIFY_MOVER_PAUSED,								NDMP_NO_ERR, (void *)&pauseRequest, 0) < 0)			{				Error(LOG_ERR,					  "moverDataWrite: error sending notify_mover_paused request.\n");				ndmpdMoverError(session, NDMP_MOVER_HALT_INTERNAL_ERROR);			}			return;		}		n = moverTapeRead(session, session->mover.buf);		Debug(DBG_CAT_MOVER|DBG_FOC_DETAIL,			  "moverDataWrite: read %u bytes from tape.\n", n);		if (n <= 0)		{			ndmpdMoverError(session, (n == 0 ? NDMP_MOVER_HALT_ABORTED									  : NDMP_MOVER_HALT_INTERNAL_ERROR));			return;		}				/*		 * Discard data if the current data stream position is		 * prior to the seek position. This is necessary if a seek		 * request set the seek pointer to a position that is not a		 * record boundary. The seek request handler can only position		 * to the start of a record.		 */		if (session->mover.position < session->mover.seekPosition)		{			session->mover.rIndex = session->mover.seekPosition -				session->mover.position;			session->mover.position = session->mover.seekPosition;		}				session->mover.wIndex = n;	}		/*	 * The limit on the total amount of data to be sent can be	 * dictated by either the end of the mover window or the end of the	 * seek window. 	 * First determine which window applies and then determine if the	 * send length needs to be less than a full record to avoid	 * exceeding the window.	 */	if (session->mover.position + session->mover.bytesLeftToRead >		session->mover.windowOffset + session->mover.windowLength)		len = session->mover.windowOffset + session->mover.windowLength -			session->mover.position;	else		len = session->mover.bytesLeftToRead;	/*	 * Now limit the length to the amount of data in the buffer.	 */	if (len > session->mover.wIndex - session->mover.rIndex)		len = session->mover.wIndex - session->mover.rIndex;		/*	 * Write the data to the data connection.	 */	n = write(session->mover.sock,			  &session->mover.buf[session->mover.rIndex],			  len);	if (n < 0)	{		if (errno == EWOULDBLOCK)			return;					ndmpdMoverError(session, NDMP_MOVER_HALT_CONNECT_CLOSED);		return;	}		Debug(DBG_CAT_MOVER|DBG_FOC_DETAIL,		  "moverDataWrite: wrote %u of %u bytes to data connection; position:%llu rIndex:%lu.\n",		  n, len, session->mover.position, session->mover.rIndex);	session->mover.rIndex          += n;	session->mover.position        += n;	session->mover.bytesLeftToRead -= n;	/*	 * If all data in the buffer has been written,	 * zero the buffer indices. The next call to this function	 * will read more data from the tape device into the buffer.	 */	if (session->mover.rIndex == session->mover.wIndex)	{		session->mover.rIndex = 0;		session->mover.wIndex = 0;	}	/*	 * If the read limit has been reached,	 * then remove the file handler to prevent this	 * function from getting called. The next mover_read request	 * will reinstall the handler.	 */	if (session->mover.bytesLeftToRead == 0)		(void)ndmpdRemoveFileHandler(session, fd);}/* * moverTapeWrite *   Writes a data record to tape. Detects and handles EOT conditions. * * Parameters: *   session (input) - session pointer. *   data    (input) - data to be written. *   length  (input) - length of data to be written. * * Returns: *    0 - operation aborted by client. *   -1 - error. *   otherwise - number of bytes written. */static intmoverTapeWrite(NdmpdSession*	session,			   char*			data,			   ssize_t			length){	ssize_t		n;	int			err;		Debug(DBG_CAT_MOVER|DBG_FOC_FLOW,		  "moverTapeWrite: length:%u\n", length);	for (;;)	{		if (session->tape.recordCount == DEBUG_TAPE_SIZE)			n = 0;		else		{			n = write(session->tape.fd, data, length);			if (n < 0)			{				Error(LOG_ERR,					  "moverTapeWrite: tape write error: %s.\n",					  strerror(errno));				return(-1);			}		}				if (n == 0)		{			/*			 * End of media reached.			 * Notify client and wait for the client to			 * either abort the operation or continue the			 * operation after changing the tape.			 */			ndmpdApiLog((void*)session, NDMP_LOG_NORMAL, 0,						"End of tape reached. Load next tape.\n");						err = moverChangeTape(session);						/* Operation aborted or connection terminated? */			if (err < 0)				return(-1);			/* Retry the write to the new tape. */			continue;		}		session->tape.recordCount++;		return(n);	}}/* * tapeFLush *   Writes all remaining buffered data to tape. A partial record is *   padded out to a full record with zeros. * * Parameters: *   session (input) - session pointer. *   data    (input) - data to be written. *   length  (input) - length of data to be written. * * Returns: *   -1 - error. *   otherwise - number of bytes written. */static intmoverTapeFlush(NdmpdSession*	session){	int	n;		Debug(DBG_CAT_MOVER|DBG_FOC_FLOW,		  "moverTapeFlush.\n");	if (session->mover.wIndex == 0)		return(0);	memset((void*)&session->mover.buf[session->mover.wIndex],		   0, session->mover.recordSize - session->mover.wIndex);	n = moverTapeWrite(session,				  session->mover.buf,				  session->mover.recordSize);	if (n < 0)	{		Error(LOG_ERR,			  "moverTapeFlush: write error: %s.\n",			  strerror(errno));		return(-1);	}		session->mover.wIndex = 0;	return(0);}/* * moverTapeRead *   Reads a data record from tape. Detects and handles EOT conditions. * * Parameters: *   session (input) - session pointer. *   data    (input) - location to read data to. * * Returns: *    0 - operation aborted. *   -1 - tape read error. *   otherwise - number of bytes read. */static intmoverTapeRead(NdmpdSession*	session,		 char*				data){	ssize_t		n;	int			err;		for (;;)	{		if (session->tape.recordCount == DEBUG_TAPE_SIZE)			n = 0;		else		{			n = read(session->tape.fd, data, session->mover.recordSize);			if (n < 0)			{				Error(LOG_ERR,					  "moverTapeRead: tape read error: %s.\n",					  strerror(errno));				return(-1);			}		}				if (n == 0)		{			/*			 * End of media reached.			 * Notify client and wait for the client to			 * either abort the data operation or continue the			 * operation after changing the tape.			 */			ndmpdApiLog((void*)session, NDMP_LOG_NORMAL, 0,						"End of tape reached. Load next tape.\n");						err = moverChangeTape(session);						/* Operation aborted or connection terminated? */			if (err < 0)				return(0);			/* Retry the read from the new tape. */			continue;		}		session->mover.recordNum++;		session->tape.recordCount++;		return(n);	}}/* * moverChangeTape *   Send an ndmp_notify_mover_paused request to the *   NDMP client to inform the client that a tape volume change is required. *   Process messages until the data/mover operation is either aborted *   or continued. * * Parameters: *   clientData (input) - session pointer. * * Returns: *   0 - operation has been continued. *  -1 - operation has been aborted. */static intmoverChangeTape(NdmpdSession*		session){	ndmp_notify_mover_paused_request	request;	session->mover.state = NDMP_MOVER_STATE_PAUSED;		if (session->mover.mode == NDMP_MOVER_MODE_READ)		session->mover.pauseReason = NDMP_MOVER_PAUSE_EOM;	else		session->mover.pauseReason = NDMP_MOVER_PAUSE_EOF;		request.reason = session->mover.pauseReason;	request.seek_position  = longLongToQuad(0LL);	if (ndmpSendRequest(session->connection, NDMP_NOTIFY_MOVER_PAUSED,						NDMP_NO_ERR, (void *)&request, 0) < 0)	{		Error(LOG_ERR,			  "moverChangeTape: error sending notify_mover_paused_request.\n");		return(-1);	}	/*	 * Process messages until the state is changed by	 * an abort, continue, or close request .	 */	for (;;)	{		if (ndmpdSelect(session, TRUE, HC_CLIENT) < 0)			return(-1);		if (session->eof == TRUE)			return(-1);				switch (session->mover.state)		{			case NDMP_MOVER_STATE_ACTIVE:				session->tape.recordCount = 0;				return(0);							case NDMP_MOVER_STATE_PAUSED:				continue;								default:				return(-1);		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -