(FILECREATED "12-May-86 22:06:35" {ROSEBOWL}<FEUERMAN>LISP>NCCLIENT.;22 32309  

      changes to:  (VARS NCCLIENTCOMS)
		   (RECORDS NSADDRESS)
		   (FNS NCSERVER.LOCALLISTNOTEFILES NCSERVER.LOCALCREATENOTEFILE 
			NCSERVER.LOCALDELETENOTEFILE NCSERVER.LOCALSUBSCRIBETONOTEFILE 
			NCSERVER.LOCALCANCELNOTEFILESUBSCRIPTION NCSERVER.LOCALLISTUIDS 
			NCSERVER.LOCALLISTCLIENTS NCSERVER.LOCALCREATECARD NCSERVER.LOCALDELETECARD 
			NCSERVER.LOCALGETCARDPART NCSERVER.LOCALOBTAINWRITELOCK 
			NCSERVER.LOCALPUTCARDPART NCSERVER.LOCALRELEASEWRITELOCK 
			NCSERVER.LOCALCANCELCARDPARTSUBSCRIPTION NCCLIENT.LOCALLISTNOTEFILES 
			NCCLIENT.LOCALCREATENOTEFILE NCCLIENT.LOCALDELETENOTEFILE 
			NCCLIENT.LOCALSUBSCRIBETONOTEFILE NCCLIENT.LOCALCANCELNOTEFILESUBSCRIPTION 
			NCCLIENT.LOCALLISTUIDS NCCLIENT.LOCALLISTCLIENTS NCCLIENT.LOCALCREATECARD 
			NCCLIENT.LOCALDELETECARD NCCLIENT.LOCALGETCARDPART 
			NCCLIENT.LOCALOBTAINWRITELOCK NCCLIENT.LOCALPUTCARDPART 
			NCCLIENT.LOCALRELEASEWRITELOCK NCCLIENT.LOCALCANCELCARDPARTSUBSCRIPTION)

      previous date: " 8-May-86 13:54:17" {ROSEBOWL}<FEUERMAN>LISP>NCCLIENT.;21)


(PRETTYCOMPRINT NCCLIENTCOMS)

(RPAQQ NCCLIENTCOMS ((FNS NCCLIENT.FILELOADEDP)
	(FILES (SOURCE)
	       NCCLIENTLISTENER)
	(* Only need the Server CALLER Courier program if the LISTENER isn't already loaded.)
	(P (OR (NCCLIENT.FILELOADEDP (QUOTE NCSERVERLISTENER))
	       (FILESLOAD (SOURCE)
			  NCSERVERCALLER)))
	(* * Functions to call the Courier procedures directly.)
	(FNS NCCLIENT.LISTNOTEFILES NCCLIENT.CREATENOTEFILE NCCLIENT.DELETENOTEFILE 
	     NCCLIENT.SUBSCRIBETONOTEFILE NCCLIENT.CANCELNOTEFILESUBSCRIPTION NCCLIENT.LISTUIDS 
	     NCCLIENT.LISTCLIENTS NCCLIENT.CREATECARD NCCLIENT.DELETECARD NCCLIENT.GETCARDPART 
	     NCCLIENT.OBTAINWRITELOCK NCCLIENT.PUTCARDPART NCCLIENT.RELEASEWRITELOCK 
	     NCCLIENT.CANCELCARDPARTSUBSCRIPTION)
	(* * Functions for calling server routines when the server machine is the same as the client 
	   machine.)
	(FNS NCCLIENT.LOCALLISTNOTEFILES NCCLIENT.LOCALCREATENOTEFILE NCCLIENT.LOCALDELETENOTEFILE 
	     NCCLIENT.LOCALSUBSCRIBETONOTEFILE NCCLIENT.LOCALCANCELNOTEFILESUBSCRIPTION 
	     NCCLIENT.LOCALLISTUIDS NCCLIENT.LOCALLISTCLIENTS NCCLIENT.LOCALCREATECARD 
	     NCCLIENT.LOCALDELETECARD NCCLIENT.LOCALGETCARDPART NCCLIENT.LOCALOBTAINWRITELOCK 
	     NCCLIENT.LOCALPUTCARDPART NCCLIENT.LOCALRELEASEWRITELOCK 
	     NCCLIENT.LOCALCANCELCARDPARTSUBSCRIPTION)
	(* * The GetCardPart and PutCardPart functions to be called with the BEFORE or AFTER litatom.)
	(FNS NCCLIENT.REMOTEGETFN NCCLIENT.REMOTEPUTFN)
	(* * These functions are the ones which field the calls to the Courier Server about 
	   notifications of changes to the NoteFile.)
	(FNS NCCLIENT.CARDCREATED NCCLIENT.CARDDELETED NCCLIENT.CARDPARTCHANGED 
	     NCCLIENT.WRITELOCKRELEASED NCCLIENT.WRITELOCKOBTAINED)
	(* * The local handlers of Client notifications. These are called by the Server notifier if 
	   the NoteFile happens to reside on the same machine.)
	(FNS NCCLIENT.LOCALCARDCREATED NCCLIENT.LOCALCARDDELETED NCCLIENT.LOCALCARDPARTCHANGED 
	     NCCLIENT.LOCALWRITELOCKOBTAINED NCCLIENT.LOCALWRITELOCKRELEASED)
	(* * The notification queue stuff.)
	(FNS NCCLIENT.PROCESSCHANGE NCCLIENT.START.CLIENTLISTENER \NCCLIENT.PROCESS)
	(* * Miscellaneous functions.)
	(FNS NCCLIENT.GETCOURIERSTREAM NCCLIENT.COURIERSTREAMFROMHOST NCCLIENT.COURIERSTREAMFROMUID 
	     NCCLIENT.GETNOTEFILEHOST NCCLIENT.GETNSADDRESS NCCLIENT.PARTCHANGEDNOTIFICATION 
	     NCCLIENT.REMOVEHOST)
	(FILES NCNOTEFILEPROP QUEUE)
	(GLOBALVARS NCCLIENT.SERVERSTREAMS NCCLIENT.CHANGEQUEUE)
	(INITVARS (NCCLIENT.SERVERSTREAMS NIL)
		  (NCCLIENT.CHANGEQUEUE (QUEUE.CREATE)))
	(DECLARE: DONTCOPY (RECORDS NSADDRESS))
	(P (COURIER.START.SERVER)
	   (NCCLIENT.START.CLIENTLISTENER))))
(DEFINEQ

(NCCLIENT.FILELOADEDP
  [LAMBDA (FILENAME)                                         (* Feuerman " 2-May-86 10:43")
    (GETPROP FILENAME (QUOTE FILEDATES])
)
(FILESLOAD (SOURCE)
	   NCCLIENTLISTENER)



(* Only need the Server CALLER Courier program if the LISTENER isn't already loaded.)

(OR (NCCLIENT.FILELOADEDP (QUOTE NCSERVERLISTENER))
    (FILESLOAD (SOURCE)
	       NCSERVERCALLER))
(* * Functions to call the Courier procedures directly.)

(DEFINEQ

(NCCLIENT.LISTNOTEFILES
  [LAMBDA (NOTEFILEPATTERN)                                  (* Feuerman " 8-May-86 13:02")
    (for F in [COURIER.EXPEDITED.CALL (NCCLIENT.GETNSADDRESS (FILENAMEFIELD NOTEFILEPATTERN
										      (QUOTE HOST)))
					    0
					    (QUOTE NoteCardsServer)
					    (QUOTE ListNoteFiles)
					    (MKSTRING (PROG ((UNPACKEDPATTERN (UNPACKFILENAME
										    NOTEFILEPATTERN)))
							        (LISTPUT UNPACKEDPATTERN
									   (QUOTE HOST)
									   NIL)
							        (OR (LISTGET UNPACKEDPATTERN
										 (QUOTE NAME))
								      (LISTPUT UNPACKEDPATTERN
										 (QUOTE NAME)
										 (QUOTE *)))
							        (RETURN (PACKFILENAME 
										  UNPACKEDPATTERN]
       collect (PACK* (QUOTE {)
			  (NSNAME.TO.STRING (CH.LOOKUP.OBJECT (FILENAMEFIELD NOTEFILEPATTERN
										   (QUOTE HOST)))
					      T)
			  (QUOTE })
			  F])

(NCCLIENT.CREATENOTEFILE
  [LAMBDA (NOTEFILENAME)                                     (* Feuerman "31-Mar-86 16:17")

          (* * Called by the client to create a NoteFile on a NoteCards Server.)


    (PACK* (QUOTE {)
	     (NSNAME.TO.STRING (CH.LOOKUP.OBJECT (FILENAMEFIELD NOTEFILENAME (QUOTE HOST)))
				 T)
	     (QUOTE })
	     (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM (FILENAMEFIELD NOTEFILENAME (QUOTE
									     HOST)))
			     (QUOTE NoteCardsServer)
			     (QUOTE CreateNoteFile)
			     (MKSTRING (NCCLIENT.REMOVEHOST NOTEFILENAME])

(NCCLIENT.DELETENOTEFILE
  [LAMBDA (NOTEFILENAME)                                     (* Feuerman "31-Mar-86 16:17")

          (* * Deletes the file on the remote NoteCards Server.)


    (PACK* (QUOTE {)
	     (NSNAME.TO.STRING (CH.LOOKUP.OBJECT (FILENAMEFIELD NOTEFILENAME (QUOTE HOST)))
				 T)
	     (QUOTE })
	     (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM (FILENAMEFIELD NOTEFILENAME (QUOTE
									     HOST)))
			     (QUOTE NoteCardsServer)
			     (QUOTE DeleteNoteFile)
			     (MKSTRING (NCCLIENT.REMOVEHOST NOTEFILENAME])

(NCCLIENT.SUBSCRIBETONOTEFILE
  [LAMBDA (FILENAMEorUID)                                    (* Feuerman " 2-May-86 08:56")

          (* * Returns a list of 4 UIDs: The Notefile UID, the Table of Contents Card UID, the Orphans UID, and the To Be 
	  Filed UID. Opens the NoteFile at the Server end if necessary.)


    (PROG [(NOTEFILENAME (COND
			     ((type? UID FILENAMEorUID)
			       (ffetch (NoteFile FullFileName) of (NC.NoteFileFromNoteFileUID
									FILENAMEorUID)))
			     (T FILENAMEorUID]
	    (RETURN (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM (FILENAMEFIELD NOTEFILENAME
										    (QUOTE HOST)))
				      (QUOTE NoteCardsServer)
				      (QUOTE SubscribeToNoteFile)
				      (LIST (QUOTE FILENAME)
					      (MKSTRING (NCCLIENT.REMOVEHOST NOTEFILENAME)))
				      \MY.NSADDRESS])

(NCCLIENT.CANCELNOTEFILESUBSCRIPTION
  [LAMBDA (UIDorFILENAME)                                    (* Feuerman " 2-May-86 08:41")

          (* * Tells the Server that this client is no longer interested in the NoteFile specified by UIDorFILENAME.)


    (PROG [(REALFILENAME (COND
			     ((type? UID UIDorFILENAME)
			       (ffetch (NoteFile FullFileName) of (NC.NoteFileFromNoteFileUID
									UIDorFILENAME)))
			     (T UIDorFILENAME]
	    (RETURN (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM (FILENAMEFIELD REALFILENAME
										    (QUOTE HOST)))
				      (QUOTE NoteCardsServer)
				      (QUOTE CancelNoteFileSubscription)
				      (LIST (QUOTE FILENAME)
					      (MKSTRING (NCCLIENT.REMOVEHOST REALFILENAME)))
				      \MY.NSADDRESS])

(NCCLIENT.LISTUIDS
  [LAMBDA (NOTEFILEUID)                                      (* Feuerman " 2-May-86 09:53")

          (* * Returns a list of all card UIDs for the NoteFile specified by NOTEFILEUID. These are all of the UIDs that are 
	  keys in the hash array on the server side.)


    (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM NOTEFILEUID)
		    (QUOTE NoteCardsServer)
		    (QUOTE ListUIDs)
		    NOTEFILEUID])

(NCCLIENT.LISTCLIENTS
  [LAMBDA (NOTEFILEUID)                                      (* Feuerman " 2-May-86 10:14")

          (* * Returns a list of clients currently subscribed to the NoteFile specified by NOTEFILEUID.)


    (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM NOTEFILEUID)
		    (QUOTE NoteCardsServer)
		    (QUOTE ListClients)
		    NOTEFILEUID])

(NCCLIENT.CREATECARD
  [LAMBDA (NOTEFILEUID)                                      (* Feuerman " 2-May-86 13:19")

          (* * Sends off the message to the Server 
	  "I'm creating a new card.  Reserve me a spot in the NoteFile and give me the UID.")


    (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM NOTEFILEUID)
		    (QUOTE NoteCardsServer)
		    (QUOTE CreateCard)
		    NOTEFILEUID \MY.NSADDRESS])

(NCCLIENT.DELETECARD
  [LAMBDA (NOTEFILEUID NOTECARDUID)                          (* Feuerman " 6-May-86 16:17")

          (* * Tries to delete the card referred to by NOTECARDUID. Will fail miserably if not all of the writelocks are 
	  owned for the card. By miserably, we mean that a break window will come up.)


    (DECLARE (GLOBALVARS \MY.NSADDRESS))
    (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM NOTEFILEUID)
		    (QUOTE NoteCardsServer)
		    (QUOTE DeleteCard)
		    NOTEFILEUID NOTECARDUID \MY.NSADDRESS])

(NCCLIENT.GETCARDPART
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 5-May-86 10:28")

          (* * This is the actual construction of the Courier call.)


    (DECLARE (GLOBALVARS \MY.NSADDRESS))
    (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM NOTEFILEUID)
		    (QUOTE NoteCardsServer)
		    (QUOTE GetCardPart)
		    NOTEFILEUID NOTECARDUID CARDPART \MY.NSADDRESS NIL])

(NCCLIENT.OBTAINWRITELOCK
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 2-May-86 15:05")

          (* * Obtains the write-lock for the CARDPART of the indicated NoteCard. Returns T if successful, NIL otherwise.)


    (DECLARE (GLOBALVARS \MY.NSADDRESS))
    (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM NOTEFILEUID)
		    (QUOTE NoteCardsServer)
		    (QUOTE ObtainWriteLock)
		    NOTEFILEUID NOTECARDUID CARDPART \MY.NSADDRESS])

(NCCLIENT.PUTCARDPART
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART SOURCESTREAM)    (* Feuerman " 6-May-86 08:48")

          (* * Constructs the actual courier call to the putcardpart service. Returns the Bulk data stream that the caller 
	  should copy the data onto. The caller should then finish off by closing the bulk data stream using CLOSE.BULK.DATA 
	  I think.)


    (DECLARE (GLOBALVARS \MY.NSADDRESS))
    (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM NOTEFILEUID)
		    (QUOTE NoteCardsServer)
		    (QUOTE PutCardPart)
		    NOTEFILEUID NOTECARDUID CARDPART (FUNCTION [LAMBDA (BULK.SOURCE.STREAM)
			(COPYBYTES SOURCESTREAM BULK.SOURCE.STREAM])
		    \MY.NSADDRESS])

(NCCLIENT.RELEASEWRITELOCK
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 5-May-86 07:55")

          (* * Instructs the server that this client is ready to give up the write lock for the given CARDPART.
	  Function simply returns T if the Client had the write lock and it was successfully released, NIL otherwise.)


    (DECLARE (GLOBALVARS \MY.NSADDRESS))
    (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM NOTEFILEUID)
		    (QUOTE NoteCardsServer)
		    (QUOTE ReleaseWriteLock)
		    NOTEFILEUID NOTECARDUID CARDPART \MY.NSADDRESS])

(NCCLIENT.CANCELCARDPARTSUBSCRIPTION
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 5-May-86 08:11")

          (* * Asks to be removed from the subscribers list for a particular card part.)


    (DECLARE (GLOBALVARS \MY.NSADDRESS))
    (COURIER.CALL (NCCLIENT.GETCOURIERSTREAM NOTEFILEUID)
		    (QUOTE NoteCardsServer)
		    (QUOTE CancelCardPartSubscription)
		    NOTEFILEUID NOTECARDUID CARDPART \MY.NSADDRESS])
)
(* * Functions for calling server routines when the server machine is the same as the client 
machine.)

(DEFINEQ

(NCCLIENT.LOCALLISTNOTEFILES
  [LAMBDA (PATTERN)                                          (* Feuerman " 8-May-86 13:10")

          (* * Simply calls the regular list notefiles function.)


    (for File in (NCSERVER.LISTNOTEFILES (NCSERVER.REMOVEHOST PATTERN))
       collect (PACK* (QUOTE {DSK})
			  File])

(NCCLIENT.LOCALCREATENOTEFILE
  [LAMBDA (NOTEFILENAME)                                     (* Feuerman " 8-May-86 12:55")

          (* * Called by the local client for creating new notefiles.)


    (PROG [(CREATEDNOTEFILENAME (NCSERVER.CREATENOTEFILE (NCSERVER.REMOVEHOST NOTEFILENAME]
	    (RETURN (AND CREATEDNOTEFILENAME (PACK* (QUOTE {DSK})
							  CREATEDNOTEFILENAME])

(NCCLIENT.LOCALDELETENOTEFILE
  [LAMBDA (NOTEFILENAME)                                     (* Feuerman " 7-May-86 08:22")

          (* * Simply calls the delete notefile routine.)


    (PROG [(DELFILERESULT (NCSERVER.DELETENOTEFILE (NCSERVER.REMOVEHOST NOTEFILENAME]
	    (RETURN (AND DELFILERESULT (PACK* (QUOTE {DSK})
						    DELFILERESULT])

(NCCLIENT.LOCALSUBSCRIBETONOTEFILE
  [LAMBDA (FILENAMEorUID)                                    (* Feuerman " 7-May-86 13:54")

          (* * Opens a subscription to the notefile in the name of (QUOTE SELF.))


    (NCSERVER.SUBSCRIBETONOTEFILE (COND
				      ((type? UID FILENAMEorUID)
					(LIST (QUOTE NOTEFILEUID)
						FILENAMEorUID))
				      (T (LIST (QUOTE FILENAME)
						 FILENAMEorUID)))
				    (QUOTE SELF])

(NCCLIENT.LOCALCANCELNOTEFILESUBSCRIPTION
  [LAMBDA (NOTEFILEorUID)                                    (* Feuerman " 7-May-86 08:49")

          (* * Removes SELF from the subscription list of the notefile.)


    (NCSERVER.CANCELNOTEFILESUBSCRIPTION (COND
					     ((type? NoteFile NOTEFILEorUID)
					       NOTEFILEorUID)
					     ((type? UID NOTEFILEorUID)
					       (NC.NoteFileFromNoteFileUID NOTEFILEorUID))
					     ((LITATOM NOTEFILEorUID)
					       (NC.NoteFileFromFileName NOTEFILEorUID))
					     (T (SHOULDNT 
				    "Need either a NoteFile, UID, or Filename for NOTEFILEorUID ")))
					   (QUOTE SELF])

(NCCLIENT.LOCALLISTUIDS
  [LAMBDA (NOTEFILEUID)                                      (* Feuerman " 7-May-86 08:53")

          (* * Simply calls the regular list uids function.)


    (NCSERVER.LISTUIDS NOTEFILEUID])

(NCCLIENT.LOCALLISTCLIENTS
  [LAMBDA (NOTEFILEUID)                                      (* Feuerman " 7-May-86 09:00")

          (* * Simply calls the regular listclients function.)


    (NCSERVER.LISTCLIENTS NOTEFILEUID])

(NCCLIENT.LOCALCREATECARD
  [LAMBDA (NOTEFILEUID)                                      (* Feuerman " 7-May-86 09:04")

          (* * Reserves a spot in the NoteFile in the name of (QUOTE SELF.))


    (NCSERVER.CREATECARD NOTEFILEUID (QUOTE SELF])

(NCCLIENT.LOCALDELETECARD
  [LAMBDA (NOTEFILEUID NOTECARDUID)                          (* Feuerman " 7-May-86 09:12")

          (* * Simply deletes the card in the name of SELF.)


    (NCSERVER.DELETECARD NOTEFILEUID NOTECARDUID (QUOTE SELF])

(NCCLIENT.LOCALGETCARDPART
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART BUCKETSTREAM)    (* Feuerman " 7-May-86 09:25")

          (* * The BUCKETSTREAM is probably the Stream field of the NoteFile to fill with the data for the card part in 
	  question.)


    (NCSERVER.GETCARDPART NOTEFILEUID NOTECARDUID CARDPART (QUOTE SELF)
			    BUCKETSTREAM])

(NCCLIENT.LOCALOBTAINWRITELOCK
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 7-May-86 09:34")
    (NCSERVER.OBTAINWRITELOCK NOTEFILEUID NOTECARDUID CARDPART (QUOTE SELF])

(NCCLIENT.LOCALPUTCARDPART
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART BUCKETSTREAM)    (* Feuerman " 8-May-86 13:50")

          (* * BUCKETSTREAM is the stream containing the information that the PUTCARDPART function will dump into the 
	  NoteFile.)



          (* * MAJOR NOTE: The file pointer for BUCKETSTREAM must be set up correctly; this function will NOT set the file 
	  pointer to the beginning.)


    (COND
      ((NCSERVER.PUTCARDPART NOTEFILEUID NOTECARDUID CARDPART BUCKETSTREAM (QUOTE SELF))
	T)
      (T (SHOULDNT "Client probably needs to obtain a writelock on the card part."])

(NCCLIENT.LOCALRELEASEWRITELOCK
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 7-May-86 10:14")
    (NCSERVER.RELEASEWRITELOCK NOTEFILEUID NOTECARDUID CARDPART (QUOTE SELF])

(NCCLIENT.LOCALCANCELCARDPARTSUBSCRIPTION
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 7-May-86 10:17")
    (NCSERVER.CANCELCARDPARTSUBSCRIPTION NOTEFILEUID NOTECARDUID CARDPART (QUOTE SELF])
)
(* * The GetCardPart and PutCardPart functions to be called with the BEFORE or AFTER litatom.)

(DEFINEQ

(NCCLIENT.REMOTEGETFN
  [LAMBDA (NOTEFILE NOTECARD CARDPART BEFORE.AFTER)          (* Feuerman " 5-May-86 10:29")

          (* * The Get function for the remote Server device case. NOTEFILE and NOTECARD are both actual objects, NOT the 
	  UID! In the BEFORE case, we get the bucket of bits from the Server and stuff it into the Stream slot of the 
	  NoteFile. In the AFTER case, nothing is done.)


    (AND (EQ BEFORE.AFTER (QUOTE BEFORE))
	   (PROG ([CORESTREAM (replace (NoteFile Stream) of NOTEFILE
				   with (OPENSTREAM (QUOTE {NODIRCORE})
							(QUOTE BOTH]
		    (BULKDATASTREAM (NCCLIENT.GETCARDPART (ffetch (NoteFile UID) of NOTEFILE)
							    (ffetch (Card UID) of NOTECARD)
							    CARDPART)))

          (* * Because we passed NIL in as the BULK.DATA.SINK argument to GetCardPart, COURIER.CALL returns in this case as 
	  its value a stream that contains the bulk data. When that bulk data stream is closed, the result specified in the 
	  Courier RETURNS clause is actually returned as the value of that CLOSEF. In this particular case, that will be 
	  NIL.)

                                                             (* Transfer the data off of the Bulk data stream, and 
							     into the local one that we'll be returning.)
	           (COPYBYTES BULKDATASTREAM CORESTREAM)
	           (CLOSEF BULKDATASTREAM)
	           (SETFILEPTR CORESTREAM 0)
	           (RETURN CORESTREAM])

(NCCLIENT.REMOTEPUTFN
  [LAMBDA (NOTEFILE NOTECARD CARDPART BEFORE.AFTER)          (* Feuerman " 6-May-86 08:48")

          (* * This is the Put Function which in the BEFORE case sets up the local core stream for the caller to put stuff 
	  into, and in the after case transfers that data onto the bulk data source.)


    (SELECTQ BEFORE.AFTER
	       [BEFORE (replace (NoteFile Stream) of NOTEFILE with (OPENSTREAM (QUOTE
											 {NODIRCORE})
										       (QUOTE
											 BOTH]
	       [AFTER (PROG ((LOCALSTREAM (ffetch (NoteFile Stream) of NOTEFILE)))
			      (SETFILEPTR LOCALSTREAM 0)
			      (RETURN (NCCLIENT.PUTCARDPART (ffetch (NoteFile UID)
								   of NOTEFILE)
								(ffetch (Card UID) of NOTECARD)
								CARDPART LOCALSTREAM]
	       (SHOULDNT "BEFORE.AFTER argument should be one of 'BEFORE or 'AFTER"])
)
(* * These functions are the ones which field the calls to the Courier Server about 
notifications of changes to the NoteFile.)

(DEFINEQ

(NCCLIENT.CARDCREATED
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID)
                                                             (* Feuerman " 8-May-86 10:58")

          (* * Fields the CARDCREATED notifications. Should return confirmation that the message was received.)


    (PROMPTPRINT (CONCAT "Card with UID " NOTECARDUID " has been created for NoteFile with UID " 
			     NOTEFILEUID))
    (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE (QUOTE (T])

(NCCLIENT.CARDDELETED
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID)
                                                             (* Feuerman " 8-May-86 11:00")

          (* * Fields the CARDDELETED notifications.)


    (PROMPTPRINT (CONCAT "NoteCard with UID " NOTECARDUID 
			     " has been deleted from NoteFile with UID "
			     NOTEFILEUID))
    (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE (QUOTE (T])

(NCCLIENT.CARDPARTCHANGED
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID CARDPART)
                                                             (* Feuerman " 8-May-86 11:06")

          (* * Fields the cardpartchanged notifications. Needs to enqueue the notification to be dealt with later.
	  But acknowledge the nofication right away.)


    (QUEUE.ENQUEUE NCCLIENT.CHANGEQUEUE (LIST NOTEFILEUID NOTECARDUID CARDPART))
    (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE (QUOTE (T])

(NCCLIENT.WRITELOCKRELEASED
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID CARDPART)
                                                             (* Feuerman " 8-May-86 11:03")

          (* * Fields the notifications about the writelock for a cardpart having been released.)


    (PROMPTPRINT (CONCAT "Writelock released for CardPart " CARDPART " of NoteCard with UID " 
			     NOTECARDUID " of NoteFile with UID " NOTEFILEUID))
    (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE (QUOTE (T])

(NCCLIENT.WRITELOCKOBTAINED
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID CARDPART)
                                                             (* Feuerman " 8-May-86 11:01")

          (* * Fields the notifications that a writelock has be obtained.)


    (PROMPTPRINT (CONCAT "Writelock just obtained for CardPart " CARDPART " of NoteCard " 
			     NOTECARDUID " in NoteFile " NOTEFILEUID))
    (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE (QUOTE (T])
)
(* * The local handlers of Client notifications. These are called by the Server notifier if 
the NoteFile happens to reside on the same machine.)

(DEFINEQ

(NCCLIENT.LOCALCARDCREATED
  [LAMBDA (NOTEFILEUID NOTECARDUID)                          (* Feuerman " 8-May-86 08:37")

          (* * Notifies SELF that a card was created.)


    (PROMPTPRINT (CONCAT "New card created for NoteFile " (ffetch (NoteFile FullFileName)
								 of (NC.NoteFileFromNoteFileUID
									NOTEFILEUID))
			     ":  " NOTECARDUID])

(NCCLIENT.LOCALCARDDELETED
  [LAMBDA (NOTEFILEUID NOTECARDUID)                          (* Feuerman " 8-May-86 08:40")

          (* * Notifies SELF that a card was deleted.)


    (PROMPTPRINT (CONCAT "Card deleted for NoteFile " (ffetch (NoteFile FullFileName)
							     of (NC.NoteFileFromNoteFileUID
								    NOTEFILEUID))
			     ":  " NOTECARDUID])

(NCCLIENT.LOCALCARDPARTCHANGED
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 8-May-86 12:46")

          (* * Notifies SELF that CARDPART has just changed.)


    (QUEUE.ENQUEUE NCCLIENT.CHANGEQUEUE (LIST NOTEFILEUID NOTECARDUID CARDPART))
    T])

(NCCLIENT.LOCALWRITELOCKOBTAINED
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 8-May-86 08:45")

          (* * Notifies SELF that the writelock for the cardpart has been obtained.)


    (PROMPTPRINT (CONCAT "Writelock has just been obtained for card part " CARDPART 
			     " of NoteCard "
			     NOTECARDUID " in NoteFile " (ffetch (NoteFile FullFileName)
							    of (NC.NoteFileFromNoteFileUID 
										      NOTEFILEUID])

(NCCLIENT.LOCALWRITELOCKRELEASED
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 8-May-86 08:52")

          (* * Notifies SELF that the writelock for the cardpart has been released.)


    (PROMPTPRINT (CONCAT "Writelock has just been released for card part " CARDPART 
			     " of NoteCard "
			     NOTECARDUID " in NoteFile " (ffetch (NoteFile FullFileName)
							    of (NC.NoteFileFromNoteFileUID 
										      NOTEFILEUID])
)
(* * The notification queue stuff.)

(DEFINEQ

(NCCLIENT.PROCESSCHANGE
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 8-May-86 12:38")

          (* * This function handles the change message.)


    (PROMPTPRINT (CONCAT "CardPart " CARDPART " has changed for NoteCard with UID " NOTECARDUID 
			     " in NoteFile with UID "
			     NOTEFILEUID])

(NCCLIENT.START.CLIENTLISTENER
  [LAMBDA NIL                                                (* Feuerman " 8-May-86 12:38")

          (* * Starts the client process which spends its entire time checking the change queue for change notifications.)


    (ADD.PROCESS (LIST (QUOTE \NCCLIENT.PROCESS)
			   (KWOTE NCCLIENT.CHANGEQUEUE)
			   (KWOTE (FUNCTION NCCLIENT.PROCESSCHANGE)))
		   (QUOTE NAME)
		   (QUOTE NoteCardsClient)
		   (QUOTE RESTARTABLE)
		   T])

(\NCCLIENT.PROCESS
  [LAMBDA (QUEUE FN)                                         (* Feuerman " 8-May-86 12:35")
    (while T
       do (BLOCK)
	    (COND
	      ((CAR QUEUE)
		(APPLY FN (QUEUE.DEQUEUE QUEUE])
)
(* * Miscellaneous functions.)

(DEFINEQ

(NCCLIENT.GETCOURIERSTREAM
  [LAMBDA (HOSTorUID)                                        (* Feuerman " 2-May-86 08:30")

          (* * Given a HOSTorUID, finds the Courier Stream associated with it. This function merely hands off the argument to
	  the correct function for dealing with that type of arg.)


    (COND
      ((type? UID HOSTorUID)
	(NCCLIENT.COURIERSTREAMFROMUID HOSTorUID))
      (T (NCCLIENT.COURIERSTREAMFROMHOST HOSTorUID])

(NCCLIENT.COURIERSTREAMFROMHOST
  [LAMBDA (HOST)                                             (* Feuerman " 2-May-86 08:35")

          (* * This function returns the Courier Stream for Courier calls to HOST If a stream has already been opened for 
	  HOST, it will be saved on the GLOBALVAR propertylist NCCLIENT.SERVERSTREAMS. Otherwise, a new stream is opened and 
	  stored on that variable.)


    (PROG ([REALHOST (U-CASE (MKATOM (NSNAME.TO.STRING (CH.LOOKUP.OBJECT HOST)
							       T]
	     STREAM)
	    (RETURN (COND
			((NULL NCCLIENT.SERVERSTREAMS)
			  [SETQ NCCLIENT.SERVERSTREAMS (LIST REALHOST (COURIER.OPEN
								   (NCCLIENT.GETNSADDRESS REALHOST]
			  (LISTGET NCCLIENT.SERVERSTREAMS REALHOST))
			((AND (SETQ STREAM (LISTGET NCCLIENT.SERVERSTREAMS REALHOST))
				(OPENP STREAM)
				(SPPOUTPUTSTREAM STREAM))
			  STREAM)
			(T (LISTPUT NCCLIENT.SERVERSTREAMS REALHOST (COURIER.OPEN (
									    NCCLIENT.GETNSADDRESS
											REALHOST])

(NCCLIENT.COURIERSTREAMFROMUID
  [LAMBDA (UID)                                              (* Feuerman " 2-May-86 09:57")

          (* * If UID is found in the NC.NoteFilesHashArray, then it is the UID for a NoteFile. The Courier Stream can then 
	  be gotten off of the NoteFile's UserProps or by computing it from the host of the full file name.)


    (PROG ((NoteFile (NC.NoteFileFromNoteFileUID UID))
	     STREAM)
	    (RETURN (COND
			[NoteFile (COND
				    ((AND (SETQ STREAM (NCNOTEFILEPROP.NoteFileGetProp
						NoteFile
						(QUOTE COURIERSTREAM)))
					    (SPPOUTPUTSTREAM STREAM))
				      STREAM)
				    (T (NCNOTEFILEPROP.NoteFilePutProp
					 NoteFile
					 (QUOTE COURIERSTREAM)
					 (NCCLIENT.COURIERSTREAMFROMHOST
					   (FILENAMEFIELD (ffetch (NoteFile FullFileName)
							       of NoteFile)
							    (QUOTE HOST]
			(T (ERROR 
	     "Don't know how to find Courier Stream given a UID not in the NC.NoteFilesHashArray"])

(NCCLIENT.GETNOTEFILEHOST
  [LAMBDA (NOTEFILEUID)                                      (* Feuerman "21-Mar-86 15:04")

          (* * Figures out which host the NoteFile associated with NOTEFILEUID is living on.)



          (* * Someday we'll do this right, as soon as we have a client running in 1.3. For now, just assume the host is 
	  GNUDNIK:VISTA.)


    (QUOTE GNUDNIK:VISTA])

(NCCLIENT.GETNSADDRESS
  [LAMBDA (HOST)                                             (* Feuerman "19-Mar-86 14:18")

          (* * This function simply looks up HOST as a name in the CLEARINGHOUSE and returns the NS address, with only one 
	  change: It makes sure that the SOCKET field of the NS address is 0.0 This has proved to be the source of a lot of 
	  "Host not responding" messages in the middle of COURIER.OPENs.)


    (create NSADDRESS reusing (LOOKUP.NS.SERVER HOST)
				  NSSOCKET ← 0])

(NCCLIENT.PARTCHANGEDNOTIFICATION
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID CARDPART)
                                                             (* Feuerman "20-Mar-86 07:55")

          (* * The Client's function which actually responds to the part changed notification sent out by the 
	  NOTECARDSERVER.)


    (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServiceNotImplemented)
		     (LIST "PartChangedNotification"])

(NCCLIENT.REMOVEHOST
  [LAMBDA (FILENAME)                                         (* Feuerman "20-Mar-86 08:28")

          (* * Simple strips the host name out of FILENAME. Useful for exchanging file names between client and server, 
	  because the server will want to refer to the host as {DSK}, but the client will want to call it {GNUDNIK:VISTA} or 
	  whatever the host is called.)


    (PROG ((UNPACKEDFILENAME (UNPACKFILENAME FILENAME)))
	    (LISTPUT UNPACKEDFILENAME (QUOTE HOST)
		       NIL)
	    (RETURN (PACKFILENAME UNPACKEDFILENAME])
)
(FILESLOAD NCNOTEFILEPROP QUEUE)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS NCCLIENT.SERVERSTREAMS NCCLIENT.CHANGEQUEUE)
)

(RPAQ? NCCLIENT.SERVERSTREAMS NIL)

(RPAQ? NCCLIENT.CHANGEQUEUE (QUEUE.CREATE))
(DECLARE: DONTCOPY 
[DECLARE: EVAL@COMPILE 

(DATATYPE NSADDRESS ((NSNET FIXP)
		       (NSHNM0 WORD)
		       (NSHNM1 WORD)
		       (NSHNM2 WORD)
		       (NSSOCKET WORD))
		      (ACCESSFNS (NSHOSTNUMBER (LOADNSHOSTNUMBER (LOCF (fetch NSHNM0
									    of DATUM)))
						 (STORENSHOSTNUMBER (LOCF (fetch NSHNM0
									     of DATUM))
								    NEWVALUE)))
		      (BLOCKRECORD NSADDRESS ((NSNETHI WORD)
				      (NSNETLO WORD))))
]
(/DECLAREDATATYPE (QUOTE NSADDRESS)
		  (QUOTE (FIXP WORD WORD WORD WORD))
		  [QUOTE ((NSADDRESS 0 FIXP)
			  (NSADDRESS 2 (BITS . 15))
			  (NSADDRESS 3 (BITS . 15))
			  (NSADDRESS 4 (BITS . 15))
			  (NSADDRESS 5 (BITS . 15]
		  (QUOTE 6))
)
(COURIER.START.SERVER)
(NCCLIENT.START.CLIENTLISTENER)
(DECLARE: DONTCOPY
  (FILEMAP (NIL (3801 3983 (NCCLIENT.FILELOADEDP 3811 . 3981)) (4284 12828 (NCCLIENT.LISTNOTEFILES 4294
 . 5297) (NCCLIENT.CREATENOTEFILE 5299 . 5922) (NCCLIENT.DELETENOTEFILE 5924 . 6531) (
NCCLIENT.SUBSCRIBETONOTEFILE 6533 . 7421) (NCCLIENT.CANCELNOTEFILESUBSCRIPTION 7423 . 8250) (
NCCLIENT.LISTUIDS 8252 . 8701) (NCCLIENT.LISTCLIENTS 8703 . 9086) (NCCLIENT.CREATECARD 9088 . 9521) (
NCCLIENT.DELETECARD 9523 . 10080) (NCCLIENT.GETCARDPART 10082 . 10517) (NCCLIENT.OBTAINWRITELOCK 10519
 . 11012) (NCCLIENT.PUTCARDPART 11014 . 11741) (NCCLIENT.RELEASEWRITELOCK 11743 . 12343) (
NCCLIENT.CANCELCARDPARTSUBSCRIPTION 12345 . 12826)) (12939 17956 (NCCLIENT.LOCALLISTNOTEFILES 12949 . 
13298) (NCCLIENT.LOCALCREATENOTEFILE 13300 . 13717) (NCCLIENT.LOCALDELETENOTEFILE 13719 . 14106) (
NCCLIENT.LOCALSUBSCRIBETONOTEFILE 14108 . 14575) (NCCLIENT.LOCALCANCELNOTEFILESUBSCRIPTION 14577 . 
15250) (NCCLIENT.LOCALLISTUIDS 15252 . 15484) (NCCLIENT.LOCALLISTCLIENTS 15486 . 15726) (
NCCLIENT.LOCALCREATECARD 15728 . 15996) (NCCLIENT.LOCALDELETECARD 15998 . 16262) (
NCCLIENT.LOCALGETCARDPART 16264 . 16638) (NCCLIENT.LOCALOBTAINWRITELOCK 16640 . 16855) (
NCCLIENT.LOCALPUTCARDPART 16857 . 17496) (NCCLIENT.LOCALRELEASEWRITELOCK 17498 . 17715) (
NCCLIENT.LOCALCANCELCARDPARTSUBSCRIPTION 17717 . 17954)) (18058 20532 (NCCLIENT.REMOTEGETFN 18068 . 
19602) (NCCLIENT.REMOTEPUTFN 19604 . 20530)) (20667 23244 (NCCLIENT.CARDCREATED 20677 . 21185) (
NCCLIENT.CARDDELETED 21187 . 21650) (NCCLIENT.CARDPARTCHANGED 21652 . 22188) (
NCCLIENT.WRITELOCKRELEASED 22190 . 22733) (NCCLIENT.WRITELOCKOBTAINED 22735 . 23242)) (23397 25481 (
NCCLIENT.LOCALCARDCREATED 23407 . 23796) (NCCLIENT.LOCALCARDDELETED 23798 . 24189) (
NCCLIENT.LOCALCARDPARTCHANGED 24191 . 24487) (NCCLIENT.LOCALWRITELOCKOBTAINED 24489 . 24983) (
NCCLIENT.LOCALWRITELOCKRELEASED 24985 . 25479)) (25524 26641 (NCCLIENT.PROCESSCHANGE 25534 . 25882) (
NCCLIENT.START.CLIENTLISTENER 25884 . 26394) (\NCCLIENT.PROCESS 26396 . 26639)) (26679 31300 (
NCCLIENT.GETCOURIERSTREAM 26689 . 27164) (NCCLIENT.COURIERSTREAMFROMHOST 27166 . 28236) (
NCCLIENT.COURIERSTREAMFROMUID 28238 . 29279) (NCCLIENT.GETNOTEFILEHOST 29281 . 29690) (
NCCLIENT.GETNSADDRESS 29692 . 30225) (NCCLIENT.PARTCHANGEDNOTIFICATION 30227 . 30703) (
NCCLIENT.REMOVEHOST 30705 . 31298)))))
STOP