home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1990, 1991 Stanford University
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that (i) the above copyright notices and this permission notice appear in
- * all copies of the software and related documentation, and (ii) the name
- * Stanford may not be used in any advertising or publicity relating to
- * the software without the specific, prior written permission of
- * Stanford.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT
- * ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
- /* $Header: /Source/Media/drapeau/PortManager/RCS/PortList.c,v 1.72 92/10/07 18:26:03 drapeau Exp $ */
- /* $Log: PortList.c,v $
- * Revision 1.72 92/10/07 18:26:03 drapeau
- * Made a slight change to ScanPortListForDeadApps(). Before, the function
- * would remove at most one dead application from PM's internal app list
- * when the function was called, even if there were more than one dead app
- * at the time. The reason this was the case was due to the way that
- * PortManager checked to see if an application was running: PortManager used
- * to send a Ping message to the application. However, this would incur a wait
- * until the RPC timed out, the default time being 25 seconds. That means that
- * PortManager would not be available to respond to messages for 25 seconds per
- * dead application.
- * However, the new method for checking if an application is alive is to try and
- * create a new Sender; this function returns almost immediately, and so wastes
- * typically much less than a second. Because of this improvement, it is now
- * worthwhile to have the PortManager remove all dead applications at once when
- * possible. The new code does this.
- *
- * Revision 1.71 92/01/17 10:52:07 drapeau
- * Modified NewPortList(); incorrect malloc() call was only allocating
- * space for a pointer to a PortList, not for the PortList itself.
- *
- * Revision 1.7 91/11/25 11:39:38 drapeau
- * Plugged a memory leak in the PortListAddPortToList() function. The
- * function was allocating memory that was already allocated by the
- * caller.
- *
- * Revision 1.6 91/09/18 13:08:54 drapeau
- * Minor cosmetic changes to the code. Also, removed unused variables in the PortListPrint()
- * function.
- *
- * Revision 1.5 91/09/09 18:27:10 drapeau
- * Changed all diagnostic messages to go through the PrintDiagnostic() routine.
- *
- * Revision 1.4 91/09/03 17:02:05 drapeau
- * * Made cosmetic changes to conform to coding specifications.
- * * Modified ScanPortListForDeadApps() to improve performance: previously,
- * the function called both NewSender() and SenderPing(). The latter
- * message was sent to verify not only that the application was
- * running but that it was also listening for messages. Much testing
- * of the applications indicated that this extra test is not necessary;
- * it is enough to test if the network connection is still valid
- * (NewSender tests the validity of the network connection). If the
- * connection is valid, that means that the receiving application is
- * still using the network port and is listening for messages.
- * SenderPing() causes problems when the receiving application is in
- * a long wait, as when the vcrEdit applicaition is waiting for the VCR
- * to search (a process that can take several minutes). When the
- * receiving application is in such a wait, it cannot respond to the
- * SenderPing() message, and so the PortManager thinks the application
- * has stopped running. However, since the current timeout period for
- * the RPC message is 25 seconds, the PortManager is blocked until the
- * Ping returns failure. In short, the long search time of vcrEdit in
- * this case has caused the PortManager to be unavailable for 25 seconds.
- *
- * To fix this problem, the PortManager no longer sends the SenderPing()
- * message. The NewSender() message typically takes only a few
- * milliseconds to complete, thereby greatly improving the performance of
- * the PortManager.
- *
- * Revision 1.3 91/07/31 11:15:22 drapeau
- * Minor cosmetic changes made to conform to coding standards.
- *
- * Revision 1.2 91/06/17 18:14:04 drapeau
- * Added copyright notice.
- *
- * Revision 1.1 90/11/30 13:44:26 drapeau
- * Initial revision
- * */
-
- static char portListRcsid[] ="$Header: /Source/Media/drapeau/PortManager/RCS/PortList.c,v 1.72 92/10/07 18:26:03 drapeau Exp $";
-
- #include <stdio.h>
- #include <string.h>
- #include "PortList.h"
- #include <Receiver.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
-
- extern Receiver* portMgrReceiver;
- extern char diagMessage[];
- extern void PrintDiagnostic(char*);
-
- PortList* NewPortList()
- {
- PortList* newPortList;
-
- newPortList = (PortList*)malloc(sizeof(PortList));
- if (newPortList == (PortList*)NULL)
- return((PortList*)NULL);
- newPortList->port = NULL;
- newPortList->next = NULL;
- return(newPortList);
- } /* end function NewPortList */
-
-
-
- void DestroyPortList(PortList* portList)
- {
- PortList* tempHead;
- PortList* tempNext;
-
- if (portList == NULL) /* Was the PortList passed in empty? */
- {
- return; /* Yes, don't bother trying to free up the PortList */
- }
- else
- for (tempHead = portList; tempHead; tempHead = tempNext) /* Traverse the PortList, deleting one member at a time */
- {
- tempNext = tempHead->next; /* Point to the next element of the list */
- DestroyPort(tempHead->port); /* Free this element's Port structure */
- free(tempHead); /* Free this element */
- }
- return;
- } /* end function DestroyPortList */
-
-
-
- void PortListAddPortToList(PortList** portListPtr, Port* newPort)
- {
- PortList* tempPtr;
-
- if (*portListPtr == NULL) /* Has a PortList been created yet? */
- {
- *portListPtr = NewPortList(); /* Yes, get a new PortList and make it the 1st element...*/
- tempPtr = *portListPtr; /* ...of the PortList */
- }
- else /* No, a PortList already exists; find the end and... */
- { /* ...insert a new element there */
- for (tempPtr = *portListPtr; /* Traverse the PortList until the end is reached */
- tempPtr->next; tempPtr = tempPtr->next)
- ;
- tempPtr->next = NewPortList(); /* Create a new element and insert it at the end of the list */
- tempPtr = tempPtr->next;
- }
- tempPtr->port = newPort;
- return;
- } /* end function PortListAddPortToList*/
-
-
- void PortListRemovePortFromList(PortList** portListPtr,
- Port* portToRemove)
- {
- PortList* current;
- PortList* last;
- int found = 0;
-
- if (*portListPtr == NULL) /* Has a PortList been created yet? */
- return; /* No, don't try to remove anything from an empty list */
- current = *portListPtr; last = current; /* Point to the beginning of the PortList */
- while ((current) && (!found)) /* Search through the list until end reached or desired... */
- { /* ...element is found */
- if ((current->port->portNumber == portToRemove->portNumber) && /* Compare current Port in PortList to the Port to be... */
- (strcmp(current->port->appName, /* ...removed. Do they match on each attribute? */
- portToRemove->appName) == 0) &&
- (strcmp(current->port->hostName,
- portToRemove->hostName) == 0))
- { /* Yes, remove the current Port from the list */
- if (current == *portListPtr) /* Is the current Port the first in the list? */
- {
- *portListPtr = current->next; /* Yes, make the PortList point to the 2nd element now */
- }
- else /* No, re-route pointers: make the last element point... */
- { /* ...to the next element so the current element can be... */
- last->next = current->next; /* ...freed from the PortList */
- }
- DestroyPort(current->port);
- free(current); /* Free the current element from the PortList */
- found = 1; /* Set a flag indicating that the desired element was found */
- } /* end if (current... */
- else /* No, current element on the List was not the one desired */
- { /* Advance to the next element on the PortList and... */
- last = current; /* ...update temporary pointers */
- current = current->next;
- }
- } /* end while */
- return;
- } /* end PortListRemovePortFromList */
-
-
- void PortListPrint(PortList* portList)
- {
- PortList* current;
-
- if (portList == NULL)
- {
- sprintf(diagMessage, "\n\n\nNo applications are currently registered.\n");
- PrintDiagnostic(diagMessage);
- return;
- }
- sprintf(diagMessage, "\n\n\nList of currently open applications:\n");
- PrintDiagnostic(diagMessage);
- for (current = portList; current; current = current->next)
- {
- sprintf(diagMessage, "App Name: %s, Host Name: %s, Port Number: %d.\n",
- current->port->appName,
- current->port->hostName,
- current->port->portNumber);
- PrintDiagnostic(diagMessage);
- } /* end for...*/
- return;
- } /* end PortListPrint*/
-
-
-
- /********************************************************************
- * ScanPortListForDeadApps
- *
- * This function scans through a list of Ports, looking for applications that are no longer listening on their
- * Receiver's for whatever reason (probably because the app is no longer running). The function goes through the
- * list passed in as argument, and tries to check each item on the list. If each item on the list is still
- * listening for messages, then this function will scan the whole list. But, if one app on the list doesn't respond,
- * this function will remove its entry from the port list.
- * In addition, not too much time should be spent in this function, since it takes away from time this app should
- * be listening for messages. So, when appropriate, this function calculates the time it has been executing; when
- * it has been executing longer than a specified time ("maxTimePassed"), the function returns.
- */
-
- void ScanPortListForDeadApps(PortList** portListPtr) /* Takes one argument, a pointer to the head of a PortList */
- {
- PortList* thisPort;
- Sender* aSender;
- int result;
- int maxTimePassed = 1; /* Max number of seconds to be spent in this func. */
- struct timeval startTime, now; /* Used to calculate time has spent in this func. */
-
- if (*portListPtr == NULL) /* Is the Port List empty? */
- return; /* Yes, don't do anything; exit this function */
- result = gettimeofday(&now,(struct timezone*)NULL); /* Get current time */
- if (result) /* Was there a problem getting the time of day? */
- { /* Yes, print an error and exit the program */
- sprintf(diagMessage, "Could not get the time of day. Exiting.\n");
- PrintDiagnostic(diagMessage);
- exit(result);
- }
- startTime.tv_sec = now.tv_sec; /* Initialize time this function started */
- startTime.tv_usec = now.tv_usec;
- for (thisPort = *portListPtr; thisPort; thisPort = thisPort->next) /* Traverse the list of Ports, doing the following: */
- {
- aSender = NewSender(thisPort->port); /* Create a new Sender to communicate with this application */
- if (aSender == (Sender*)NULL) /* If the creation failed, assume the application is... */
- { /* ...gone. */
- PortListRemovePortFromList(portListPtr,thisPort->port); /* Remove this port from the list of active ports */
- }
- DestroySender(aSender); /* Destroy Sender used to test, since it's no longer needed */
- result = gettimeofday(&now,(struct timezone*)NULL); /* Get current time for later comparison with startTime */
- if (result) /* Was there a problem getting the time of day? */
- { /* Yes, print an error and exit the program */
- sprintf(diagMessage, "Could not get the time of day. Exiting.\n");
- PrintDiagnostic(diagMessage);
- exit(result);
- }
- if ((now.tv_sec - startTime.tv_sec) >= maxTimePassed) /* Has the maximum allowed time elapsed in this function? */
- return; /* Yes, leave this function without doing anymore checks */
- } /* end for (thisPort... */
- } /* end function ScanPortListForDeadApps */
-