home *** CD-ROM | disk | FTP | other *** search
- /*
- * $RCSfile: callServer.c,v $
- * $Revision: 1.2 $
- * $Date: 1996/05/04 23:51:44 $
- */
- /**********************************************************************
- * EXODUS Database Toolkit Software
- * Copyright (c) 1991 Computer Sciences Department, University of
- * Wisconsin -- Madison
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
- * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
- * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * The EXODUS Project Group requests users of this software to return
- * any improvements or extensions that they make to:
- *
- * EXODUS Project Group
- * c/o David J. DeWitt and Michael J. Carey
- * Computer Sciences Department
- * University of Wisconsin -- Madison
- * Madison, WI 53706
- *
- * or exodus@cs.wisc.edu
- *
- * In addition, the EXODUS Project Group requests that users grant the
- * Computer Sciences Department rights to redistribute these changes.
- **********************************************************************/
-
-
- #include "sysdefs.h"
- #include "ess.h"
- #include "checking.h"
- #include "trace.h"
- #include "error.h"
- #include "list.h"
- #include "tid.h"
- #include "io.h"
- #include "lock.h"
- #include "object.h"
- #include "msgdefs.h"
- #include "trans.h"
- #include "bf.h"
- #include "lsn.h"
- #include "loginfo.h"
- #include "serverinfo.h"
- #include "bitvec.h"
- #include "link.h"
- #include "msg_funcs.h"
- #include "trans_funcs.h"
- #include "msg_globals.h"
- #include "trans_globals.h"
- #include "sm_globals.h"
- #include "util_funcs.h"
- #include "trans_globals.h"
-
-
- int
- callServerMulti (
- SERVERINFO *serverInfo,
- IOVECENT *_iovec,
- int veclen
- )
- {
- MESSAGE *message;
- TID tidOfMessage;
- int messageType;
- int bytesSent;
- int bytesToSend = 0;
-
- SM_ASSERT(LEVEL_1, veclen > 0);
- SM_ASSERT(LEVEL_1, _iovec != NULL);
- SM_ASSERT(LEVEL_1, _iovec[0].iov_len == sizeof(MESSAGE));
-
- message = (MESSAGE *) _iovec[0].iov_base;
-
- SM_ASSERT(LEVEL_1, message != NULL);
-
- tidOfMessage = message->header.params.in.tid;
- messageType = message->header.type;
-
- TRPRINT(TR_MSG, TR_LEVEL_1, ("Msg %d(tid=%d)-->%s,%s ",
- messageType, tidOfMessage,
- serverInfo->hostName, serverInfo->name));
-
- if ( !(serverInfo->flags & SERV_CONNECTED) ) {
- SM_ERROR(TYPE_USER, esmSERVERDIED);
- return(esmFAILURE);
- }
-
- /*
- * put the magic (version) number in the message
- * see if a repsonse is expected or not
- */
- message->header.version = MESSAGE_VERSION;
-
- /*
- * Keep trying to send the message is the write is interrupted
- */
- while (TRUE) {
-
- /*
- * See if there is extra data (i.e. a page) to send with the message
- */
- #ifdef DEBUG
- if (veclen > 0) {
- int i;
-
- for(i=0; i<veclen; i++) {
- SM_ASSERT(LEVEL_1, _iovec[i].iov_len != 0);
- SM_ASSERT(LEVEL_1, _iovec[i].iov_base != NULL);
- }
- SM_ASSERT(LEVEL_1, _iovec != NULL);
- } else {
- SM_ASSERT(LEVEL_1, _iovec == NULL);
- }
- #endif DEBUG
- SM_ASSERT(LEVEL_1, _iovec[0].iov_len == sizeof(MESSAGE));
-
- {
- int i;
- for(bytesToSend = 0, i=0; i<veclen; i++) {
- bytesToSend += _iovec[i].iov_len;
- }
- }
-
- #if !(defined(linux))
- if (veclen > 1 ) {
- bytesSent = writev(serverInfo->socket, _iovec, veclen);
- } else {
- /* ever so slightly cheaper */
- bytesSent =
- write(serverInfo->socket, (char *) message, sizeof(MESSAGE));
- }
- #else
- /*
- We can't seem to consistently send large chunks of data to a socket
- using the writev() function. So, at the cost of efficiency, we'll
- send each buffer separately. We'll also check to see if only a partial
- write occurred, then send the remainder.
- */
- if (veclen > 1 ) {
- char *msg_base;
- int i, nSent, nSend, nThisTime;
- bytesSent = 0;
- for(i=0; i<veclen; i++) {
- nSend = _iovec[i].iov_len;
- nSent = 0;
- msg_base = (char *)_iovec[i].iov_base;
-
- while(nSend){
- nThisTime = write(serverInfo->socket,
- msg_base, nSend);
- TRPRINT(TR_MSG, TR_LEVEL_2,
- ("Buffer %d: sent %d of %d bytes",
- i, nThisTime, nSend));
- nSent += nThisTime;
- msg_base += nThisTime;
- nSend -= nThisTime;
- }
- bytesSent += nSent;
- }
- } else {
- char *msg_base;
- int nSend, nThisTime;
- bytesSent = 0;
- nSend = sizeof(MESSAGE);
- msg_base = (char *)message;
- while(nSend){
- nThisTime = write(serverInfo->socket,
- msg_base, nSend);
- TRPRINT(TR_MSG, TR_LEVEL_2,
- ("Write: sent %d of %d bytes",
- nThisTime, nSend));
- bytesSent += nThisTime;
- msg_base += nThisTime;
- nSend -= nThisTime;
- }
- }
- #endif !linux
-
- /*
- * See if the call was interrupted
- */
- if ((bytesSent < 0) && (errno == EINTR)) {
- SM_ERROR(TYPE_LOG, errno);
- continue; /* try again */
- }
- break; /* finished or error */
- }
-
- /*
- * If the write failed, abort the transaction
- */
- if (bytesSent < 0) {
-
- SM_ERROR(TYPE_SYS, errno);
-
- switch(errno) {
- case ENETDOWN:
- case ENETUNREACH:
- case ENETRESET:
- case ECONNABORTED:
- case ECONNRESET:
- case EPIPE:
-
- (void) detectedDisconnect(serverInfo);
- break;
-
- case EINTR:
- SM_ERROR(TYPE_CRASH, esmINTERNAL);
- break;
-
- default:
-
- CLIENT_ABORT_TID( getLocalTid() );
- break;
- }
-
- return(esmFAILURE);
-
- } else if (bytesSent != bytesToSend) {
-
- if (TransRec.clientTransState == T_ACTIVE) {
- TransRec.clientTransState = T_ABORT;
- }
- SM_ERROR(TYPE_SYS, errno);
- SM_ERROR(TYPE_FATAL, esmINTERNAL);
- return(esmFAILURE);
- }
-
- TRPRINT(TR_MSG, TR_LEVEL_2, ("sent %d bytes successfully", bytesSent));
-
- MsgStats.sent[messageType]++;
- incPages(bytesSent, SENT, TRUE);
-
- /*
- * see if we do not need to read the reply
- */
- if (message->header.replyRequested == FALSE) {
- MsgStats.no_reply_requested[messageType]++;
- return(esmNOERROR);
- }
-
- /*
- * Read the reply (message). There may be data apppended
- * to the message structure. They are read by the caller of this func.
- */
- if (msg_Receive(serverInfo, message, (int)sizeof(MESSAGE)) < 0) {
- return(esmFAILURE);
- }
- #ifdef DEBUG
- if(messageType != message->header.type) {
- fprintf(stderr, "got reply for msg type %d; expected %d\n",
- message->header.type, messageType);
- SM_ERROR(TYPE_FATAL, esmINTERNAL);
- }
- #endif DEBUG
-
- TRPRINT(TR_MSG, TR_LEVEL_1, ("got reply for msg type %d",
- message->header.type));
-
- if (message->header.params.out.errno != esmNOERROR) {
- SM_ERROR(TYPE_USER, (int) message->header.params.out.errno);
- return(esmFAILURE);
-
- } else {
- return(esmNOERROR);
- }
- }
-
- int
- callServer (
- SERVERINFO *serverInfo,
- MESSAGE *message,
- char *data,
- int dataLength
- )
- {
- IOVECTOR IoVector;
- int i = 1;
-
- IoVector[0].iov_base = (char *) message;
- IoVector[0].iov_len = sizeof(MESSAGE);
-
- if(dataLength > 0) {
- IoVector[1].iov_base = data;
- IoVector[1].iov_len = dataLength;
- i++;
- }
-
- return callServerMulti(serverInfo, &(IoVector[0]), i);
- }
-
-