# ChangeLog.txt -- The NIED project change log
# Created on November 7, 2001

Phone book

	Omar Rood	952-937-4876
	Brad Thoen	952-937-4244
	Rod Larsen	952-937-4650
	Hugh Sparks	952-937-4539
	Jim Rosenow	952-937-4374
	Terry Nelson	952-937-xxxx
	Tom Miller	952-937-4071

Office IP Numbers

	We have 16 Assigned numbers in subnet 13:

	hostIPSVX	:= '148.150.13.30'
	hostIPSVY	:= '148.150.13.35'
	hostIPSVZ	:= '148.150.13.37'
	hostIPTBL	:= '148.150.13.32'
	hostIPDOC	:= '148.150.13.39'
	hostIPDLG	:= '148.150.13.41'
	hostIPCON	:= '148.150.13.32'

	dspIPSVX	:= '148.150.13.31'
	dspIPSVY	:= '148.150.13.36'
	dspIPSVZ	:= '148.150.13.38'
	dspIPTBL	:= '148.150.13.42'
	dspIPDOC	:= '148.150.13.43'
	dspIPDLG	:= '148.150.13.52'

	Laptops:

	NIED-HUGH	:= '148.150.13.47'
	NIED-BRAD	:= '148.150.13.50'
	NIED-TERRY	:= '148.150.13.99'
	
	Currently unused:

	148.150.13.32

	The above IP address definitions and all Coops and
	Scramnet node definitions are in Network.txt.

TCP/IP Setup at MTS NIED Lab

	Subnet mask:		255.255.255.0
	Default gateway:	148.150.13.2
	Preferred DNS server:	148.150.110.11
	Alternate DNS server:	148.150.135.11
	General:		Client for Microsoft Networks
				File and Printer Sharing
				Internet Protocol (TCP/IP)
	Advanced TCP/IP Settings:
		DNS:	Append these DNS suffixes:  mts.com
			Register this connections addresses in DNS
		WINS:	148.150.130.11
			148.150.110.11
			Enable LMHOSTS lookup
			Enable NetBIOS over TCP/IP


2001-xx-xx Brad Thoen
	
	Created the NiedSVProj applications.

2001-11-05 Monday HVS

	Rewire the control room and shuffle the furniture.
	Add IP numbers to the 141 subnet so each host, target
	and Laptop can have a unique IP.

	Jim Rosenow installs new VxWorks PROM on the X machine
	so it allows boot parameter changes. Install VC++ on
	the Y host.

	Apply all knows Windows 2000 updates to the Y Host.
	This will be the master for now.

2001-11-06 Tuesday HVS

	Apply all known Windows 2000 updates to the X host.

	Setup and test the configuration used when the
	targets were in Brads office. (It works...)

	Tear down the LAN and replace the 3COM 100 mb hub
	with a 10 mb hub. We will need a dual hub or I will
	have to get a new PCMCIA card.

	/bin/startX.vxc
	/bin/startY.vxc
		Change the names of the VxWorks startup scripts to
		reflect the names of the controllers:
	
	/gui/constants.alt
		Change the network IP numbers to reflect lab setup.

2001-11-07 Wednesday HVS

	Map network drives to share the NiedSVProj folder
	on the master host: NIED-HOST-Y. All hosts use
	drive M: to access this folder. This makes it possible
	to work on the code from any machine on the LAN.
	Even the master host uses the network drive letter to
	access the local directory.

	Prep to DeGauss Brad's project organization.

	Change the boot PROMS on all the PPC machines to
	fetch their images from the master host.

	***************
	BRAD:
	Because each application is built by including a file named
	after the host such as aadefineX.alt etc., why have all the
	weird arrays and IF statements in the other build files?
	All the machines can use the same constants right in the
	aadefineN.alt files. All the conditional code in the other
	files can be removed?

	Why do we need the "otherID" in the main aadefine.alt?
	Why not move the ip numbers out of constants.alt?
	The Node routing setup should be done from the table
	controller, not by the individual hosts.

	Proposal: MySystem.alt
		Remove all the non-local remotePort configuration stuff.
		This should be done by the table controller.

	In order to proceed without a table controller, a 'master' debug
	script file is needed that configures the nodes and remotePorts.
	This script can be run by any of the hosts.
	*******************

	startX.bat
	startY.bat
	startZ.bat
		These scripts build the Alltalk gui for the three applications.

	Workspace.bat
		Script to launch VC++
		The VC++ project is rebuilt to hide all glark files.

	Documents\VisualCSetup.txt
		Describes how to setup the VC++ workspace from scratch.

	AppGui/constantsX.alt
	AppGui/constantsY.alt
	AppGui/constantsZ.alt
	AppGui/aadefineX.alt
	AppGui/aadefineY.alt
	AppGui/aadefineZ.alt
		Removed the "constantsXYZ" files and merged their
		contents into aadefineX, aadefineY, aadefineZ.alt

	************ Brad has merged his dsp changes into this project.

	Back this thing up as:

	*****************************************
	*	NiedSVProj-2001-11-07		*
	*****************************************

2001-11-08 Thursday HVS

	We want to remove all references to "other" nodes.
	This will be handled by the master controller after
	the valve controller starts.

	Currently, the app contains the concept of "machineID"
	and "otherID". These are indicies into arrays that 
	contain the hostNode, dspNode, dspName, dspIP.

	These can become simple constants in the aadefineX,Y,Z files.

	The master controller must setup the clients by adding config paths
	to the remotePorts and Nodes.


	aadefine.alt
		Remove machineID, otherID and associated arrays.
		Configure only the local node: Node.is[hostNode]

	constants.alt
		Remove the arrays.
		Make global definitions for nodes,names, IP, etc.

	aadefineX.alt
	aadefineY.alt
	aadefineZ.alt
		Define the local parameters by refering to the global
		values in constants:

		scramNode
		hostNode
		supNode
		dspNode
		dspName
		dspIP

	virtualMachine.alt
		Replace the machineID with scramNode where the
		Scramnet monitor is created.

	MySystem.alt
		Modify the remotePort configuration code to only deal
		with the local machine.
		Remove the arrays hostNodes, supNodes, dspNodes, dspIPs, dspNames.
		Old code:
			remotePort
				.open[	drvrFileName,
					hostNodes.get[machineID],
					supNodes.get[machineID]]		
				.config[dspNodes.get[machineID],
					dspNames.get[machineID],
					dspIPs.get[machineID]]
				.config[dspNodes.get[otherID],
					dspNames.get[otherID],
					dspIPs.get[otherID]]
				.create[dspNames.get[machineID],
					dspNodes.get[machineID]]
		New code:
			remotePort
				.open[drvrFileName, hostNode, supNode]		
				.config[dspNode, dspName, dspIP]
				.create[dspName, dspNode]
	
	TODO: The master controller must add routes to Node and .config
	the remotePorts so they can see each other. The old code that
	did this when we had only X & Y:

	(From aadefine.alt)
		Node.route[hostNodes.get[otherID], hostIPs.get[otherID]]

	(From MySystem.alt)
		remotePort.config
		[	dspNodes.get[otherID],
			dspNames.get[otherID],
			dspIPs.get[otherID]
		]

	******************

	Dealing with application building and startup.
	I want the .dll stuff out of the way, but it has to be in
	the same directory as the .exe, so I put them all in the
	bin directory. The bin directory is a candidate for being
	the "distribution" directory that we give customers who
	don't get the source code.

	Bin\aaBuildX.bat
	Bin\aaBuildY.bat
	Bin\aaBuildZ.bat
		Build scripts that create and update the applications in bin.

	AppGui\aaMakeX.alt
	AppGui\aaMakeY.alt
	AppGui\aaMakeZ.alt
		These are the Alltalk scripts that actually write the 
		image into the application exe files.

	The configuration files are now in a sub directory of bin.
	Maybe this isn't really necessary now that the bin directory is
	such a mess anyway...

	aadefine.alt
		Add configDirectory and configSubDirectory

	MySystem.alt
		Use onfigDirectory & configSubDirectory
		Note that the code to build these paths at run time
		is now exactly the same as the code from aadefine.alt.

	MySystem.alt
		Add metod for #quitBuild to get us out of the DOS build
		script.
		Add a variable "reallyStarted". This is used to ignore
		the #quitBuild message when we are a running application
		and also to let us exit quietly when we aren't really
		running a machine.

	aaBuildX
	aaBuildY
	aaBuildZ
		These are special DOS LOCAL shortcuts to build the application
		exe files in the bin directory. They DO NOT contain network
		information.

	aaStartX
	aaStartY
	aaStartZ
		These are special DOS LOCAL shortcuts to start the applications
		in the bin directory. They DO NOT contain network information.

	*********************************
	*	IMPORTANT NOTE		*
	*********************************
	
	The aaBuild and aaStart scripts depend on the mapping of network
	drive M. If you want to work on a private copy of the applications,
	you can put the NiedSVProj directory anywhere on your machine. You
	must then map a network drive M to this directory.

	This method allows quick switch between projects as well as letting
	you keep projects sources on different machines.

	MapDrive.bat
		This is a script that will map the network drive M to point
		to the NiedSVProj on Nied-Host-Y. By putting a copy of this
		file into each of your projects, you can move them anywhere
		and they will build and run correctly. All you have to is
		edit this file when you move the project. To switch between
		projects you are working on concurrently, simply go into the
		project and run the MapDrive script.

	Back this thing up as:

	*****************************************
	*	NiedSVProj-2001-11-08		*
	*****************************************

2001-11-12 Monday HVS

	Move the aaBuildX,Y,Z.bat scripts to AppCon.
	This keeps all the non-binary stuff out of bin.
	Bin will become part of the deliverable application directory.

2001-12-18 Tuesday HVS

	New subnet assigned to NIED room. See table at top off this file
	for new IP Numbers.
	
	gui/constants.alt
		Update IP numbers for each host and dsp.

	Set new IP Numbers on the dsp eproms.

	Note: During the development process, the vxWorks and coops.o
	object files are kept on nied-host-y. All the valve controllers
	share the NiedSVProj directory on nied-host-y as well. By convention,
	all hosts map the project directory to network drive M.
	When we test the installation, copies of the application will go to
	each host so the valve controllers will operate independently.

	autoexec.bat
		Now contains the script from define.bat.

	define.bat (Definitions for vx works command line tools)
		Moved into the documents directory.
		Update comment about autoexec.bat.

2001-12-19 Wednesday HVS
	
	AppGui/aadefine.alt:

	ResultArrays.alt
	RemoteThing.alt
	Link.alt
	Uplink.alt
	Node.alt
		Added/updated

	The new nodes work and interprocessor connections are automatic!
	
	TODO: When the X application quits, the Y application freezes up even
	though Nodes are shutdown. Could it be the ScramNET?

2001-12-20 Thursday HVS

	When either of two valve controllers stop, the other crashes at
	the DSP level. This happens only if the Scramnet was active, so
	something is blowing up in the Scramnet driver.

February 8, 2001

	Add #setDelay to Node.class to set the delay for all
	existing and future nodes.

	Altlink.c
	When closing a node, wait before flushing and resetting
	the socket interface.

December 18, 2001 HVS
	
	Major revision:
	
	Node has been broken up and the use of metaclasses for
	state information has been eliminated:

	Uplink.alt
		Handle incomming messages
	Downlink.alt
		Handle outgoing messages
	RemoteThing.alt
		Proxy for all non-local entities
	Node
		Creates Uplinks & Downlinks on demand.
		Handle errors.
		Forwarding agent for RemoteThings associated
		with this nodeNumber.

	RemoteThing can also map nodes to the old Coops
	remotePort, so we can interoperate with different
	kinds of remote object with different protocols.

	TODO: Handle node.close better.

Jan-March 2002 HVS

	Japanese xlation (See project log)

April-May HVS
	Installing new NIED operating systems.
	Two trips to Tardec in Detroit
	Two weeks at NADS.

May 15, 2002 HVS

	Add protocol to Node, Uplink and Downlink to
	keep the connection alive and notify the local
	program when the connection state changes.

June 04, 2002 HVS

	Renamed the routing configuration methods and added new
	ones to support a default route. The code for reroute
	(which is now called simply "route") has been revised
	so it does not require the know route to be connected.

	See the revised AAReadme.txt for details.

June 05, 2002 HVS

	Node.alt
	Downlink.alt
		Assorted minor bugs associated with waiting for a
		connection.

	RemotePort.alt
		Somehow the changes to support 2 upward message
		parameters from Coops got lost. This is required
		to support InpConnector and OutConnector.

February 13, 2002 Wednesday HVS

	Revise the Makefile to assume we are running on drive M:
	To do a make in a DOS window, switch to "M:" and run make.

October 14, 2002 (Monday) HVS

	Update Node.c to use sockReadable from Alltalk.
	Backup last Brad rev of niedProj: This is the sentinal version.

	niedProj-02-10-14

	TODO:
	Add mtShort to Nodes.
	Use a dictionary to map the selector names. (Faster)

	Rework:
	Coops->Coops

	Alltalk can pass the type string which is known by self
	reflexion. Coops can only pass a type string by asking.
	Now, we use this as a check when possible, but the older
	coops classes have type string elements that need to be
	updated en masse.


	TODO:
	Change Link.c/linkForward to use varargs.

	TODO:
	Replace the winSocket with mswSocket.c

	Avoiding the type loop: another strategy:
	When a node acts as a relay, it does not have
	the type string required to decode the message
	unless the sender has provided this information.
	We want only one version of Node.c, so the 
	Downlink must always ask the receiver for the
	types. This is done in the old coops by simply
	sending a message with a known type string.
	The same technique will work for Node:
	TODO: Make the _type generic bypass the forward
	substitution of the requested type string.
	HOW:
	Currently, executeGeneric calls the local _type.
	Instead, it should call linkType. This procedure
	will ask the target link for the type string if
	the receiver is non-local.

October 15, 2002 (Tuesday) HVS

	Move the linkTypes cache to Node.c
	This is necessary to handle the special forwarding
	of type requests. Node only requests the type
	string if none was provided.

	The linkForward problem could be complex.
	Maybe it would be better to try this in two steps:
	1) Get AccProj going again with the old links and
	the new generic. Then put in the node?

	When the supervisor does a forwarding transaction,
	the Node will first send the message locally.
	The message contains the type string, so executeMessage
	is called from Node with this string. The message will
	be forwarded to Downlink, which will need to ask the 
	DSP for the type string again.

	****************************

	MySystem.alt
		Disable the linking process so it can be debugged.


October 16, 2002 (Wednesday) HVS

	Should the Uplink be told the node number of the host node?
	Otherwise, upward messages have to go out though a symmetric
	node connection...

	For now:
->	Node.c
	Comment out linkDefine for the host node.
	Remove the fork loop from main.
	Remove the host node number read operation from Node.new.

	Link.alt
	Add the class field to the message object so it will not
	be a special case in Node.c

	Node.c uses a pile while Node.alt uses a pool of buffers.
	The pile requires special alignments to function...

	MySystem.alt
	Modify to make a temporary nodal connection.

	TODO:
	RemotePort.alt
	Back this up and make a new stub that uses the node.
	The key function of RemotePort is to ping the simulation
	and fit into the exisiting remoteModel lookup code.

October 17, 2002 (Thursday) HVS

	Node.c
	Add protocol for the old mtGetMessage. This lets
	Brad's apps start without errors.
	
	Converted Machine.dll -> Simulation.exe
	It works!

October 21, 2002 (Monday) HVS

	Made Simulation.exe be a win32 app instead of console.
	Add a "real" timer event to drive the simulation.
	This eliminates some of the artificial clock tuning.
	
October 22, 2002 (Tuesday) HVS

	Fix fork.c again.
	Should mtPing and mtGetMessage be combined?
	Or should mtGetMessage be eliminated?
	
October 23, 2002 (Wednesday) HVS

	Trying to combine ping and upward message protocol...
	Ideas:

	1) Every message reply should return the pending upward
	message count.

	2) The host will only ping the connection when no other
	messages have been sent for some specified time interval.

	3) A symmetric timer is used in Node.c to decide when
	the host has gone away. If no message arrives on time,
	a specified receiver is notified.

	So is ping still needed?
		
	When no other message is pending, the host will send
	an mtGetMessage. If a message is pending, it is returned
	at once. The pending message count in the reply is also
	updated so the Node.alt can pull up all the pending messages
	at once.

	TODO: 
	Test the latest Downlink.c on the PPC.
	Test the latest Downlink.c on a parallel simulation.

	Node.c
	Add protocol for routing and pre-connecting.
	Add monitor loop as a WM_TIMER driven event.
	Is a userCycle still necessary?

	Fork can be eliminated if we specify a connection
	as asynchronous. When a Node sends a message over
	an asynchronous connection, no reply is expected or
	sent. 

	Asynchronous connections work in Node.alt the same way.
	The asynchronous attribute is a property of all connections
	aimed at a given node number. If both types of connection
	are needed for a given host, use mulitple node numbers.

	******************

	Handling a larger node space.
	Currently: To make a local object remote:
	Subtract off the heap base.
	"Or" it with 0x1 and the node number shifted to the high order hexel.

	Proposed:
	We force all allocations from the heap to be long-word aligned.
	This means that the address of an object always has the low
	order two bits clear.
	We can shift the heap offset one more bit to the right and still
	have a free bit to or with 0x1.
	Now we have 5 bits in the upper bits of the object.
	Still not enough?
	Also, it makes the node number hard to read when debugging.

	We can gain even more space for node numbers by going to a 
	ROT imlementation of the object space.

	Most Coops applications have less that 10k objects.
	If we make the ROT big enough for 32000 objects, it will
	only take up 128k bytes. This is a disposable amount of 
	memory in all of our systems.

	To make this work well, Alltalk would have to use a ROT
	as well. How can this work out to be an advantage?
	The biggest advantage is that we don't have to relocate
	the contents of any heap allocation to restore the heap.
	We should eliminate garbage collection as well.

	An alltalk app need about 128k objects.
	To support this, the rot would contain 512k bytes. This is
	nothing. But would we gain a lot?

	How many bits are needed for 128k objects?
	
	Bits	nObject	ROTSize
	17	128k	512k
 	18	256K	1024k

	If we could live with 65k objects, we could use 16 bits even.
	This would give us a node space of 65k nodes. Not bad at all!
	But we can't.
	NADS, for example, has 72k Alltalk objects. Tardec has 65k objects.
	AccProj has 51k objects.
	
	28	bits	16 nodes
	27	bits	32 nodes
	26	bits	64 nodes
	25 	bits	128 nodes
	24	bits	256 nodes

	So we need the top 8 bits for the node number.
	This works out well because we use exactly 2 hexels
	instead of of 1.

	We need to clear 8 bits.
	To do this only by shifting,
	objects would have to allocated with the lower 8 bits clear.
	The minimum object size would be
	0x10 - 0x00 = 256 bytes. In alltalk, this would be 256/8 =
	32 instance variables in an allocated object. A little bit
	too big to waste.
	
	Currently, when we subtract the heap base, we are getting
	offsets that need no more than 6 hexels = 24 bits.

	The largest offset we could have would be: 16 megs.

	So the Alltalk heap would have to be limited to 16 megabytes.
	This is probably reasonable for the time being.
	Nads used a 6 meg heap or 23 bits of offset.

	It would appear that we can use 2 hexels right now without
	using a ROT!

	We can gain more room by shifting the offset right by one bit.

	So the largest alltalk heap offset would be 32 megs and
	we don't need a ROT.

	Is there any reason to consider a rot?
	
	Bad:
	It would probably slow down Alltalk a little bit...
	It uses some extra memory.
	
	Good:
	Very fast heap save & restore.
	Heap logic is greatly simplified.
	Context->self would be an integer.
	Context->ivars would be a pre-computed pointer.
	Or we could make the method do this with some
	kind of BEGIN macro:

		ivars = pointer(context->self)

	It would be possible to have re-allocated buffers like Smalltalk.
	Some kinds of List would be a lot smaller.
	Very large node spaces would be possible.
	
	Alternatives:
	Currently, Alltalk object references are 2 long words.
	With a ROT we could reduce this to 1 long words:
	5 hexels for the rot index.
	0XFFFFF 1 million distinct objects.
	3 hexels for the class rot index. (4k classes)
	Is this a good balance?

	But what about scalars?
	If we take away 2 bits from the object index, we 
	have room for 256k objects. The two bits are used
	to identify scalars:
	
	00	A rot index
	01	An integer
	11	A float.
	This would mean that floats get packed into 30 bits,
	which is Not a Good Thing (tm)

	Ok. Let's go the other way:
	Keep the object references 2 long words.
	We identify scalars by the rot index of their class.
	We combine the next long word with the 5 hexels in the
	rot index field. This gives us 13 hexels for a big
	scalar. If we waste one, we get 12 hexels... No good.

	Ok. Let's try using 3 long words:
	The first word has the class and object rot index.
	The next two are reserved for scalars.
	We identify scalars by their rot index.
	We have 64 bit integers.
	Double precision floats.
	Single precision complex numbers.
	We can have rational numbers as well if we like...

	****************************

	A puzzle:
	When Alltalk sends a message to coops using nodes,
	the message contains the typeString for the parameters
	but the return type is unknown. Node.alt puts in an "O"
	as a catch-all. The receiver has to modify the return
	type based on the typestring found for the local object
	(If it is local...)

	If the receiver is local, we can ask for the type string.
	This type string could be compared to the alltalk type string...
	The return type must be taken from the local type however
	because Alltalk doesn't know.

	What about a forwarding message?
	In this case, the type string has to be requested from the
	remote system anyway because we can't tear down the C stack
	to send the message without this information. The cache
	will save us some time because the Downlink will return
	the type immediately.

	What happens if the uplink part of Node always sends the
	#type message to a prosective receiver?

	The method for #type in class Object has to be handled in a
	special way. This is a side effect of the way execute.c works.
	We have to avoid recursive calls to _type, so execute.c can
	only work on local objects. 

	When execute.c needs a type string, it has to ask link.c.
	Link will look at the object's node. If it is local, the
	local version of _type is used to get the type string.

	If the object is non-local, link will forward the query
	to the Downlink with a special entry point for _type.

	=> link.c should become RemoteObject.c ?
	This would be more consistant with the Alltalk use of the class.

	It is not imperative, but it would be nice if the 'core' of
	COOPS didn't depend on the remote-object-link-node mechanism.

	With this in mind, it would be nice if execute could obtain
	the type of local or remote objects with the same syntax.

	This can be done if the type string for _type is special case
	in execute.

	When execute sees the selector #type, it doesn't ask for a type
	string. It simply supplies a type string.

	This works much better and cleans up the code in Node.c.

	=> DON'T FORGET to update the message reply size for upward
	messages!

	=> DON'T FORGET to re-enable automatic download in MySystem.start2.

	Object.c
	generic.dat
		Add the selector #typeString and rename the method in Object.
		This was done because people use #type for other methods and
		we can't have execute treat it in a special way for those
		cases.

	=> Redo the array passing in Node.c to match the code used for mtString.

October 24, 2002 (Thursday) HVS

	The Alltalk side hangs when closing after the new shell was installed.
	Change #typeString to __type to match the way __close was done.

	I tried many ways to exechange time between Alltalk and the
	simulation:

	Using a non-blocking test for the input socket:
	1) WM_TIMER events (slow)
	2) Waitable timer with private thread. (Very slow)
	3) Free running (Very slow)

	Using no event loop and a block read on the socket works best
	so far.

	=> It appears that an extra parameter is being sent with
	each array. One slot for the size and one slot is zero.
	This is an artifact of the old method that put the heap
	index in this slot. With sockets, we don't need this, so
	it should be removed. DONE BUT NOT TESTED!

	Automatically starting the Alltalk application and letting
	it launch the simulation causes hang-ups. Using 

November 5, 2002 (Tuesday) HVS

	The Downlink cannot use unstack message as it is currently 
	formulated because the caller of a procedure who passes a
	string parameter doesn't normally supply the string length.
	
	Ideas: It would be possible to read strings one char at a time.
	This has no great cost if the socket is already being buffered
	in the program.

	If this is done, the only remaining task is removing the network
	ordering code and modifying the sockXXXX to use the Alltalk version!

	With so much removed from Downlink, it might be nice to combine it
	with Node?

	Maybe it would be best of all to take out Uplink as was done in Alltalk.
	So Node is very small and takes care of creating Uplinks and Downlinks
	on demand.

	The separate files work out better for making free pools and supporting
	the metaclass protocol as well.

	I tried to remove Uplink, but the protocol in Node relies on knowing
	the fields. By adding parameters to #init, we can avoid this and 
	separate the classes.


	Downlink.c
		Remove the index field from mtShort.
		Add support for mtLong until Brad gets his thing together.

November 6, 2002 (Wednesday) HVS

	Got rid of the sockH2N & N2H functions.
	TODO:
		Revise Node.alt to NOT send the message class.
	TODO:
		Contack Cobra guy about WinXP weirdness.
	->Test the ftp server!!!!

	TODO:
		When multiple connections are active in Node.c,
		we cannot do a blocking read on any one socket.
		Instead, a select must be used to respond to
		any socket that becomes readable. Failing this,
		we need to block on a timer loop in the system.
	
	*****************************************
	*	"shove" in mswSocket did not	*
	*	return the correct count!	*
	*****************************************

	The asynch form of the socket package used in Alltalk does
	not work correctly with coops. This may be the XP weirdness...

November 7, 2002 (Thursday) HVS

	It works! (Sort of.)
	Here's the poop:
	With a blocking read in Node.c, the program runs very fast.
	Probably as fast as shared memory.
	With non-blocking reads and polling in Node.c, the program
	slows to a crawl. I believe Windows punishes compute-bound
	processes by time slicing them very unfavorably.
	
	I also tried a WM_TIMER polling loop. This helps alot, but
	it is still slow compared to the blocking read. Using a
	WM_TIMER in a real application would seriously limit
	performance.

	We can't really do blocking reads, so we need a portable
	means to sleep on a select(...) call. This has to work
	on both Windows and VxWorks.

	TODO:
	1) Work out the sleep on select().
	2) Once a socket is readable, it may block in the middle of 
	a message. We need to time this out correctly and not block
	the Alltalk application. On the Coops side, we need to run
	down the connection and dispose of the Uplink.


	IDEAS:
	The polling loop for instances of Uplink will build a select
	a do a blocking wait for something to read. If nothing arrives
	during that time, the userCycle is allowed to continue.
	This should have an effect like using WM_TIMER, but it will
	release the moment a message or connection request arrives.

	To deal with connection requests in the same select structure,
	we reserve the first entry for the Node itself.
	
	TODO: Need to revise Alltalk mswSocket to match coops.
	Change: It is better for both read and accept to block.
	The caller can determine how to wait/poll using sockReadable.

	TODO: Need a uniform error logger for mswSocket.
	TODO: Need to make sure the WSAGetError is correct in connect.

	I tried using a global select built into mswSocket.
	When sockets are connected or accepted, a new entry is
	place in a global fd_set. The application can call 
	sockWait(timeout) to wait for any readable activity.
	If the socket times out, we don't bother to poll.

	Update: No timeout is needed for the coops simulation.
	It is sufficient to block on any/all sockets and then
	poll for the one that needs attention. This could be
	done more efficiently by saveing the fd_set that results
	from the blocking select. In any case, it is very fast
	now and we don't waste much time.


	TODO: Update readArrays & writeArrays for the Uplink.
	TODO: Update readArrays & writeArrays for the Downlink.

	*********************************************************
	*	Tell Dean about error in UpSockPPC:		*
	*	messageToStack "to" case doesn't set type	*
	*********************************************************

November 11, 2002 (Monday) HVS

	Uplink.c
		Returning strings had an off-by-one.

	It is NOT a good idea for upward messages to be initiated
	on the same socket as the Downlink-Uplink pair. We need
	to flush the socket buffers if an error occurs due to
	a timeout. This could not succeed if the Uplink tried
	to send back an unexpected message. By keeping the
	Downlink in control, we know that whatever's left
	is junk.


	A new Alltalk, 2.972 was created to fix a bug in the
	methods for #multiplex in all the array classes: It
	did not correctly handle cases where the source array
	was a subclass of one of the built-in array types.

	*********************************************************
	*	Summary of changes to Brad's code:		*
	*********************************************************

	1) Remove references to remotePort and replace with Node equivalents.
	2) Modify method associated with attaching to the vm in MySystem.
	3) Remove all the casting of arrays to integers in the models.
	4) Change all arrays that are for results to one of the ResultArrays.
	5) Get rid of "L" type strings.

	Most things work.
	TODO: Still have to resolve upward messages.
	TODO: Should a framing protocol be used to correct errors due
	to broken socktes?
	TODO: Add the real exception handler so Alltalk cannot crash
	even when processor exceptions occur. This was done for b600
	to deal with obscure socket problems. It probably should be
	done here as well.
	TODO: Update Alltalk to use Alltalk3-style exception handling.

	Dealing with upward messages:
	Why:
	1) We can't handle messages from coops in a general way because
	Alltalk doesn't supply type string.
	2) Upward messages must be asynchronous. This is handled by
	polling so the Downlink doesn't encounter an unexpected upward
	messages.
	3) We have to ping from the host anyway, so we might as well
	know about the upward messages anyway.

	- Add a field to the normal reply to reflect how many upward
	messages are available.
	- The Downlink.alt tests this field and handles the upward
	messages immediately after every message.
	- Downlink will not ping unless no other messages have been
	sent in a defined interval. Sending a message takes the place
	of the ping.
	- When uploading using GetMessage, the reply is a full-sized
	message. This has to be a special case in Downlink.alt.


	Downlink.alt
		#readReply Sets a variable in the Downlink to reflect then
		number of pending upward messages?
		No. I used #ping to do this instead.

November 12, 2002 (Tuesday) HVS

	Dealing with explicit selectors.
	When Downlink.alt finds a selector parameters, it substitutes
	the name of the selector and passes it as a string parameter
	of type "T". The Uplink.c recognizes "T" parameters and substitutes
	the local selector number.

	Sequence.c
	Closure.c
		Change the "L" types to "I"
	Recorder.c
	Clock.c
	Closure.c
	EuroWatch.c
	Ufg.c
	Task.c
	StringClosure.c
	Sys.c
		Use "T" for the selector in #connect.
	
	TODO: Now that all the "T"s are in place,
	we can switch the selector representation.
	This makes it possible for coops nodes to communicate
	that don't share the same generic map.

	Status: Changing Selectors to type T with strings in the
	global rep broke the application.
	I may have missed one...
	That was it. AccProj seems to work...

	Data acquistion starts but doesn't clock...
	This is because upward messages have the wrong selector numbers.
	(After the "T" type change...)


November 13, 2002 (Wednesday) HVS
	
	Upward messages cannot be read all at once because the
	process will be interrupted by more downward messages.
	The protocol must allow an exchange of messages for
	each message sent.

	Ideas:
	1) Make mtGetMessage return the pending count with each message.
		This is o.k., but we don't want to get caught in a 
		loop where the number changes while we're processing.
	2) Add a message to get the count first.
		This was done when the #ping message existed.
		It works well, but it involves an extra message.
	3) Use the exisiting mechanism, but queue all the upward messages.
		This would work and it would be fast, but it involves a lot
		of machinery.

	Idea 1 seems best. We can just ignore the pending count after the first message.
	Where to put the count?
	If GetMessage returns a result of type mtMessage, we process the message.
	If GetMessage returns NIL, we exit the loop.
	It is easier to return one message at a time...

	Brad uses the same arrays for both copyTo and copyFrom operations.
	All these classes must be revised to cast for results.
	array.become[RealResult] etc.


	Casting to RealResult:

		Ahc2
		Ahc
		Apc
		Rls
		Aic	
		Maic
		Ppc
		ScopeDaq (SmallResult)


	copyFrom puzzles:
		GenServo 
		Vector
		Lms, dLms
		Tfe, dTfe
		Fir

November 14, 2002 (Thursday) HVS

	The sockRead in mswSocket for coops was set up for synchronous reads.
	I found it blocked on recv.
	The Alltalk version returns zero in this condition. 
	The Link.alt reader uses a timeout loop to read the socket.
	This is probably how the Coops version should work as well.


	Idea:
	Use a pair of sockets for each connection.
	The first is the normal Downlink/Uplink channel.
	The second is used to reset the Uplink.
	When an error occurs, on the Downlink size, it
	flushes the input buffer and sends a reset to the
	on the error socket. The Uplink will monitor the
	error socket whenever it does a sync read. If
	it gets the error, it flushes the socket and returns
	to the top-level loop.

	The bug:
	With all other operations turned off,
	sending a an array over and over eventually
	causes a bogus socket count to appear on the Downlink.alt
	socket. 

	It appears right after sending an array on the same socket.
	It looks a though some of the array "spills over".

	An experiment: I checked that the total number of bytes
	read and written by both sides agree. They do. This means
	that the problem is only conceptual.

November 16, 2002 (Saturday) HVS

	Is the Socket protocol at fault?
	The same number of bytes go in and out on both sides, so
	the problem probably at a higher level.
	The effect of having "extra" bytes after sending a message
	and reading a reply suggests that the reply reader didn't
	finish reading all the bytes.

	Ther error occurs when sending bytes DOWN to the Uplink.c,
	The only bytes expected on the return path are a short reply
	message. Yet we see a 'big' array of characters as though
	something large was being sent up as an upward message.
	This would occur if an array was seen by the Uplink.c as
	a result instead of an incomming value.

	Experiment:
	Determine if a bogus array is being sent up.
	Breakpoint the "from" case in the array processing code.
	Result:
	The break point is never hit, but the error still occurs.
	Conclusion:
	It is not a bogus upward array.

	Experiment:
	Does it have something to do with polling for upward messages?
	Breakpoint the mtGetMessage and disable all events on the host side.
	Result:
	mtGetMessage is never processed.
	Conclusion:
	It has nothing to do with upward replies.

	The number of messages that have to be sent before the error
	occurs seems to be random.

	When sending 4k buffers, the error message always finds exactly
	1932 bytes left in the buffer.

	Experiment:
	If we cause the error using some other size of array, does the
	resulting error byte count change? Is it always the same value
	(but some other number?)
	Result:
	I reduced the size of the buffer from 4096 to 4094 (2047 shorts).
	The result was still 1932 bytes when the error occured.
	Then I tried using 1011 shorts (2022 bytes).
	This time, the error was 924 bytes extra. This value was consistant
	even though it takes a random number of trials to break the socket.

		2022 924 difference is 1098
		4096 1932 difference is 2164


November 18, 2002 (Monday) HVS

	I'm adding a sentinel to the message heading.
	By checking the sentinel on the sending and
	receiving side, I can find out when we become
	desynchronized.

	The sentinel detects a bad message being sent down from Alltalk.
	
	Next, I will use an IntegerArray with numbered elements to detect
	the point of desynchronization.

	The result: 
	In Uplink.c, readMessage is getting the middle of the integer array,
	right at the 512 boundary. This is an Integer array, so this is at
	the 2048 byte mark.
	
	Next:
	In the "test8" procedure, try to detect the complete array by 
	checking the elements. Then clear the array to make sure we
	don't see an artifact from the previous trial.
	
	If Uplink.c did not read the entire array from the last message,
	the left over bytes would account for the problem.

	Alternatively, if the Downlink.alt did not send the whole array
	on the previous message, we would get hung up trying to read
	the next test8 message.

	-> The best idea is that Uplink.c failed to read the whole message,
	leaving bytes in the buffer.


	This was indeed the case.
	The code for sockRead in mswSocket could exit early.
	This is an old bug that is also in Alltalk.
	It was never noticed before because the higher level code
	worked around the problem.

	Idea:
	The sentinel word should be left in the message protocol and
	the ipChecksum should be added.

	readMessage should skip bytes until a valid header is obtained.
	This will make the code survive most host crashes/errors.

	TODO:
	Socket errors cannot be reported through the uplink,
	so do something else...

	TODO:
	Timeouts must be enabled for the socket reader.

	TODO:
	Add the sentinel to Uplink.alt and Downlink.c

	TODO:
	All the terminal & connection stuff from NiedProj should be compared
	to AccProjNewlink and updated to work with shares.
	Most of the niedProj code is correct.

	Link.alt
	NotifyDelay is now 10 instead of 500. This was done because it now
	takes the place of the polling loop in RemotePort.

	TODO: Make Simulation.exe go to the bin directory.

	The name "Simulation.exe" should probably be derived from the project name.
	A global kill on that name should be done when the application starts
	to make sure previous incarnations don't survive.

	Review copyFrom puzzles:

		GenServo
		Vector
		Lms, dLms
		Tfe, dTfe
		Fir

	These seem to be ok. They don't use the method for #copyFrom even though
	it is implemented in the coops classes.

November 19, 2002 (Tuesday) HVS

	Update to Brad's latest version of AccProj.
	Several bugs in AccProj were uncovered by the new links.
	De-Gauss the coops foundation modules so they work with either
	Schema 8-tabs or Brad 4-tabs.

	TODO: Update Downlink.c
	TODO: Update the Terminal classes.
	TODO: Add "P" types to the host. (For Scramnet host cards.)


November 20, 2002 (Wednesday) HVS

	Add the share-enabled versions of the dataflow classes from niedProj:

	Terminal
	IntTerminal
	FloatTerminal
	InpConnector
	OutConnector
	Share

November 21, 2002 (Thursday) HVS

	Port.h - removed.
	Consolodate non-instance procedures in Uplink so they
	can move to Link.c when Downlink is finished and factored.

	TODO: Add sentinel to Uplink.alt
	TODO: Add sentinel to AltLink.c
	TODO: Update mswSocket for AltLink.c


November 25, 2002 (Monday) HVS

	Downlink.c
	The original only needs the signature, but timeouts
	are no longer correct:

	- Assemble the message & verify all parameters.
	- Write the arrays.
	- Read the reply including a possible string.
	- Localize the result.
	- Read the arrays.
	- Return the result.

	AltLink.c should share with Downlink.c
	The only difference is the origin of the type string.

	Downlink.c
	Add mtBoolean.
	Rewrite case for mtSelector.

November 26, 2002 (Tuesday) HVS

	All of Brad's simulation works on the host with
	the new nodes, updated alltalk, & coops!

NOvember 27, 2002 (Wednesday) HVS

	Ready to try the dsp.
	Update all vx classes to new protocol.
	Recompile everything done so far for vxWorks.

November 28, 2002 (Thursday) HVS

	Many problems compiling for vxWorks.
	GCC makes us honest men.

December 2, 2002 (Monday) HVS

	Update vxSocket.c to sync with the new mswSocket.
	TODO: Rework stub for vxWorks test.
	Still getting socket errors from Alltalk.

December 3, 2002 (Tuesday) HVS

	In the lab: Rework the Makefile. Move Tornado.
	Test Downlink again by adding sentinel to
	Uplink.alt.
	
	TODO: Merge altLink.c and Downlink.c to use common modules.

	ARRG! Alltalk gave a bogus socket error. GetLastError was
	not used correctly in the socket class. (Fixed)

December 4, 2002 (Wednesday) HVS

	Node.c
	Message.c
	Link.c
		Merged/condensed into Node.c:
		Messages don't need to be objects.

	method.c
		Removed. 
		Methods are not objects in coops and the structure
		was only used in Class.c
	
	Downlink.c
		Fixed polling for upward messages.
		Add support for returning selectors.

	TODO:
		Add shared pointers for the connectors?
		Currently, niedProj uses an ad-hoc method 
		to deal with references to shared memory.

	Idea:
	Dealing with pointers:
	Every pointer is associated with a share.
	Every share has a share number which works just like
	the Coops node number. A given coops node can have one
	or more shares. When a pointer arrives, we check to see
	if the share number matches on of the local shares.
	If it does, we as the share to localize the pointer.
	A global pointer consists of a share number in the top
	2 hexes and a long word offset in the lower part of the
	word. The lsb is set to 1 so we know the value is not
	a local pointer.

	When we pass a pointer out of coops, it is globalized:
	We try to find out which share it lives in and then
	remove the base address, make it odd and 'or' in the
	node bits. 

	All the active shares in a coops node are kept on a list.
	The share structures has the base address and top address
	in the share:

	typedef struct shareVars
	{	struct shareVars *next ;
		unsigned int shareNumber ;
		unsigned int avail ;
		unsigned int size ;
		char *first ;
		char *last ;
		char *free ;
	} shares ;

	End Idea

	Uplink.alt
	Add sentinel to buffer for error returns.

	TODO: Should Uplink.alt also return upward messages?
	This is not so simple because the alternative of
	creating a Downlink automatically might be better
	for Alltalk-Alltalk communication.

December 5, 2002 (Thursday) HVS

	Try for explict creation of the Downlink on the DSP:
	The coops part of the simulation runs on the DSP!

December 9, 2002 (Monday) HVS

	Backoff and repeat tests on the host with simulation.
	Changes from last week were not tested enough...
	Fix Downlink so the stack stays synchronized.
	Brad's sim works on the host now. (Again.)

December 10, 2002 (Tuesday) HVS
	
	Alltalk is not catching socket errors that occur when
	a Downlink is automatically created...

	Downlink on the DSP does not work at all as of the last
	round of fixes.

	Move back to office.
	Install VME box under my desk.
	Update build procedures and code to run simulation on the
	old dsp.

December 11, 2002 (Wednesday) HVS

	Compile and run on the 2604.
	It loads without error but crashes in the Supervisor.dll.
	(Now Supervisor.exe)

	Downlink is failing in down-going floating point array
	transfers...

December 12, 2002 (Thursday) HVS

	Fixed Downlink arrays.
	Supervisor runs through vm create up to Tfe!

December 16, 2002 (Monday)

	
December 18, 2002 (Wednesday) HVS

	Fix Alltalk catch-throw problem.
	Rebuild coops.o for the PPC.
	Test new Downlink on host (ok)
	Test new Downlink on dsp (not ok...)

	Deal with Tardec.

December 19, 2002 (Thursday before XMas)


	Downlink.c
		Rewrote the stack scanner so it is not necessary to
		va_start the stack more than once.
		I borrowed the unstackMessage procedure from execute.c
		This introduces the "args" array as an intermediate
		representation. This would not be necessary if we
		kept the local array address in the message.

	TODO:
		The Downlink and fork should probably be hidden in Node.
		User cycle will then contain only "doit(node)".
		Downlinks will be created on demand as in Alltalk.

January 6, 2003 (Monday) HVS

	Autocreation of the Downlink breaks VxWorks somehow...
	This is not on the critical path, so I abandoned this feature.

January 7, 2003 (Tuesday) HVS

	Tried new cross development tools (DevCPP)
	Something wrong in vxSocket.c?
	Doesn't compile with newer GNU tools.
	DevCPP builds Alltalk for windows but doesn't work at all
	under Linux. It might cross-devel and allow network debugging
	on the PPC... Later.


January 8, 2003 (Wednesday) HVS

	Almost all of AccProj works on the dsp!
	The hangup is corruption due to creating a dPsd...

January 9, 2003 (Thursday) HVS

	TODO:	Remove "jvars" and "kvars": The Studio bug still occurs.

	dPsd.c
	dRls.c
		Disable supervisor messages. 
		The problem is somewhere in this path...
	DONE:	Undo these changes!
	
	Now _read in class Rls is broken.
	It does a copyFrom the dsp...
	The supervisor fails asking for the typeString for copyFrom...
	FIXED: There was a flaw in Downlink.c that caused the typeString
	in the method for transmit to be corrupted. This is subtle: I
	fixed this once before and then removed the fix! The problem
	is that the resturned string from a remote message is stored
	in a static variable. You can't use this value after another
	message has been sent.

January 13, 2003 (Monday) HVS

	Creating Aic fails...
	But that is the newRate(self->supervisor) problem in dAic.

	So tackle that next...

	-> newRate(supervisor) is not being forked...

	<Backup>
	Idea:
	Change the sim project to run as node 1.
	Then connect the supervisor to the sim just like it would
	have connected to the dsp.

	The message newRate worked in the integrated simulation.
	Update messages do work between the supervisor.exe and
	alltalk. So the problem is with the queue? Maybe overflow?

	Fixed: Uplink got a transmit (upward) for typeString. This
	was handled correctly by execute in the simulation. But
	it is a special case when we have an Uplink because the
	typeString is already known. The fix is in the method for
	#transmit in Uplink.c: It simply returns "OII" for the
	type request. The message will go to the list inside 
	Uplink as usual.

January 14, 2003 (Tuesday) HVS

	ALMOST everything works BUT:

	For instances of Iir in Alltalk we have:

	r.class.name -> "Iir"
	r.remote._class.name -> "Iir"
	r.remote.remote._class.name -> "dIir"

	r.remote.remote.task._class.name -> "Task"

	r.remote.task._class.name -> "Uplink"  ARRG!

	1) Bug 1: The supervisor is sending the message #task to self->dsp.
	The self->dsp is on node 1.
	When the #transmit message is executed, we end up in the Uplink,
	which returns "self" as the value of transmit. The wrong Link is
	being chosen for node 1. Somehow, the link table is not right.
	The Downlink for node 1 should have been set when the downlink
	is created. That needs to be checked next.


	The Downlink to the dsp is created after the Node.
	No Uplinks exist until a connection request arrives from Alltalk.
	When the first uplink is created, it set all entries in the link
	table to itself to take care of the default route upward.

	The first Uplink should only take over the unused link table entries.
	TODO: Maybe the default route should be set explicitly?


January 15, 2003 (Wednesday) HVS

	TODO: Fix race condition on link startup in configsim.c
	TODO: Add a simulation clock that runs on the DSP.
	TODO: Fix white space problem in debugger.
	TODO: Test the "P" Scramnet address mapping with Nodes.
	TODO: The MySystem.attach method must do the node.host mapping for the dsp.
	TODO: When connected to the DSP, the Alltalk application does not quit normally.

	Socket library:
		
	winSocket.c
		Change readable and writable methods to use a wait timeout.
		TODO: This should be done in Alltalk as well. It is more robust
		than polling.
	
	Mts493Duc.c
		The self->mode was not set before it was used to index an
		array. FIXED.

	TODO: Pass this on to the clan.

	Still can't shut down the DSP: We send the mtClose message and close
	the host. The DSP locks up. Even the serial port can't talk to the
	terminal emulator.

January 16 - February 28 HVS

	Working on real-time simulation for Windows.
	This lets a real clock run on the Windows simulation.
	The change log for this project is in ACCProjNewLink

	TODO: 
	VxClock.c
	WinClock.c
		They must enable a clock-local interrupt enable/disable.
	Scheduler.c
		Must use the clock lock/unlock NOT asmEnable asmDisable.


March 03, 2003 (Monday) HVS

	Clock.c
		This is now generic.
	winClock.c
		Procedures used by Clock.c under Windows.
		Supports preemptive clock tics even when simulating.
	vxClock.c
		Procedures used by Clock.c under VxWorks.

	Ideas to make simulations work on slow and fast hosts:
	1) Adaptive clock rate.
		On slow machines, we slow down the real clock rate.
		The reported clock rate stays the same so filter
		calculations work out.
	2) Adaptive clock ratio.
		The clock can tic more than once per real tic.
		This lets simulations go faster than real time.
	3) Hybrid:
		Measure the processor use each tic.
		If we are using too much, slow down the real tics.
		If we are using too little, speed up the real tics.

	It would be nice to get rid of the "clock ratio" and just adapt
	the real tic rate.

	First try: Move the metrics into Clock.c.
	Evaluate the metric on each tic and adjust 1) The clock rate
	until we are one tic too slow. Then 2) Adjust the clock ratio
	until we are just 1 tic too fast.

	Experiment: Add a selector to adjust the ratio and see if this
	algorithm works (by hand) on the slow Nied host.

March 04, 2003 (Tuesday) HVS

	No adaption is needed for most simulations.
	Instead, the process is made real-time class.
	The thread for the clock is given high, but not highest
	priority. This seems to work well on both very slow and
	very fast machines. The drawback is that we don't go faster
	than real-time.

March 5, 2003 (Wednesday) HVS

	Dealing with the debugger:

	1) When acc.exe starts, it looks for a command line parameter.
	If this parameter is present, it does NOT launch simulation.exe.
	It assumes that it is already running in the dubugger. 
	
	2) The comamnd line parameters for simulation.exe and supervisor.exe
	are passed as parameters to a special method in sys instead.

	3) Each Brad project has a class defined in vm.c called "Vm".
	This class has no instances.
	Instead, the userOpen code puts the class itself into the dictionary.
	Alltalk looks up this class and sends it the "create" message with
	application-dependant parameters.

	4) When Simulation.exe starts with a command line parameter, it
	uses this parameter to launch the named GUI program.


	5) A command line parameter is passed by the VC debugger to 
	the GUI program. This parameter is used to tell the GUI not to
	launch the coops application.

	6) The debugger must be configured to pass the node number and
	GUI app name to the coops program.

	Link.alt
		Modfied to increase delay on close.
	MySystem.alt
		#stop Modified to wait for the sockets to close before exit.
	winShell.alt
		Pass the node number to userOpen instead of argc, argv.
		Now the supervisor, simulation, and powerpc get their node
		numbers the same way.
	Uplink.alt
		Idea: When the last instance closes, terminate the application.

March 6, 2003 (Thursday) HVS

	Link.alt
		Add a message type for remote shutdown (mtShutdown)
	Node.alt
		Add a method to shutdown a remote node.
		Modify method for #connected to deal with unconnected nodes.
	Downlink.alt
		Add a method to perform #shutdown on target node.
	Uplink.alt
		Add protocol and method to perform shutdown.
	Uplink.c
		Add protocol and method to perform shutdown.
		Make socket errors from any host shutdown the program.
		Is this a good idea?
	MySystem.alt
		Add node.shutdown[supNode] before quiting.
	winShell.alt
		Add protocol to shutdown the supervisor or simulation.
	winSocket.c
		Add extra error code handlingn for thread-level errors.
	

	Dealing with zombie processes and related socket errors:

	"Connection reset by peer" errors are processed when the 
	simulation.exe or supervisor.exe finds that the Alltalk GUI
	has died.

	The Node on the coops side will continue to operate, but the
	associated Uplink should be closed.

	TODO: How to distinguish socket errors from normal "allowed"
	coops errors?

	Both Uplink.c and Downlink.c need to handle socket errors in
	a special way because after a socket error, the normal error
	path back to the upstream Downlink is closed.

	IDEA1: Add a new entry point to except.c for errorSocket(...).
	This function will display the error locally (printf on VxWorks,
	dialog box on windows.) and then call a user-defined procedure.
	This procedure, by default, will close the node and exit the
	application.

	On VxWorks, all errors should probably get the printf treatment.


March 10 (Monday) HVS

	NADS day.

March 11 (Tuesday) HVS

	NADS day.

March 17-19 (Monday-Wednesday) HVS

	Update all of Nied to use this version of Nodes.
	Merge changes to AccProj with newer Brad changes to Nied.
	Routine debugging of type strings etc.

	Outline of new startup process:

	CoopsCom\network.alt:

	- Defines all the variables but DOES NOT assign values

	node
	supNode
	dspNode
	dspIP
	scramNode
	hostNode


	CoopsCom\MySystem.alt:

	METHOD attach
		Assigns values to:

		supNode
		dspNode
		dspIP
		scramNode
		hostNode

	
	METHOD connect 
		Creates the node and then does: (indirectly)
		self.configureNode
		self.attachModels

	METHOD configureNode OF EachSubclass
		Builds the routing table.
		Subclasses append behavior as needed.
		
	END METHOD

	
	METHOD attachModels
		Create vm on the supervisor, passing
		the supNode, dspNod, dspIP, dspName & scramNode.
		Attach all the models.
		Download all the parameters.

March 20 (Thursday) HVS

	Get Nied simulation working...
	TBD: X, Y, Z & Table controller.
	Switched to the PPC.

March 25 (Tuesday) HVS

	ServoValve Z working on PPC
	Tardec intervention

March 26 (Wednesday) HVS

	ServoValve X, Y working on PPC
	
March 27 (Thursday) HVS

	Table controller & DOC updated and working.
	
March 31 (Monday) HVS

	Debugging Grand Connector.  It doesn't work...
	Data logger needs a Brad update...		
	
April 1 (Tuesday) HVS

	Testing setup:
	On host 2: Table controller and SVZ.
	They start and run ok.

	On host 3: The grand connector.
	Stalls on normal startup during the interconnection
	process.
	
	An error dialog appears on SVZ host:

	I put in a break at the MainP.notify to catch the
	software before it does the connection.
	
	The MainP.notify message for both SVZ and the TBL
	set up the shares correctly.

	The method for connectSVZtoTBL:

	self.connectSVCtoTBL[vmSVZ, scramNodeSVC, z1, z14, az1, az5]

	Has actual parameters:

	self.connectSVCtoTBL[vmSVZ, 3, 11, 24, 11, 15]

	This part works: outConn.connect[inpConn] works!
		
	Sometime while doing the actuator feedback connection,
	The SVZ program on host 2 reports this error in a dialog box:

	SVZ GUI(2) Reports: "Node 3: (Terminal.connect) Reference error 2"

	Node 3 is the table controller host.
	SVZ host is node 2.

	The type 2 reference error occurs when an input terminal
	other than the target of a connection is referenced before
	the connection is completed. Someone 'pinged' the table controller
	with a message that asked for an input terminal before the forked
	connection completion message could be processed.

	The Table Controller host program is polling terminals on the
	TBL DSP. This is a no-no because of the "Terminal lastLocation" issue.

	Several fixes for this program have been proposed.

	The method for Terminal.connect gets an output terminal and
	an input terminal. The problem is to find the object ivar location
	where the input terminal is stored.

	To make sure, I will repeat the test with the polling loop off
	in the TBL main panel.

	That was not the problem: The TBL host only polls output terminals.

	The issue seems to be with the message #attach that completes
	the InpConnector-to-target input connector connecton.

	This has to propagate via 2-parameter upward messages.
	The message should get resolved in the supervisor application,
	so we can debug there.

    	It appears that #attach is not getting through with the
	right parameters.

	Strategy: printf the #attach parameterts at each stage.

April 3, 2003 (Wednesday) HVS

	Step back: Create a debugging applicaion. It takes too long
	to bring up Nied for each round of debugging.


	aaTest.alt - Subset of Grand Connector for debugging.

	outConnSVZ.connect[inpConnTBL] ! Seems to work
	outConnTBL.connect[inpConnSVZ] ! Locks up up everything

	When the TBL dsp runs the method for OutConnector.connect, it
	forks a message to SVZ's InpConnector to complete the connection.
	This will go up to to the TBL supervisor, which will have no
	route to get to SVZ, so the message goes up to the the TBL host.
	The TBL host will try to send the connect method to SVZ which
	locks up. Why?

	Is the TBL making a connection to Z on demand?

	It would appear that dsp Z is able to fork a message to the dsp TBL correctly.
	What route will this message take?
	supZ will get the message to dspTBL and send in to hostZ. hostZ will try to 
	send a message to dspTBL...

	Experiment:
	Try giving the hosts directly links to the dsps rather than going
	through the supervisors.
	Try giving the supervisors direct links to all the dsps and hosts.


	Result:

	outConnSVZ.connect[inpConnTBL]
		hostZ reports an upward message.
		The message is: inpConnTBL .connect[outConnSVZ, outConnSVZ] 
		The first parameter is correct for sure.
		The second parameter is wrong!!!
		It is supposed to be a share index (global share value).
		FIXED: It was a bug in hex2.

	outConnTBL.connect[inpConnSVZ]

		Seems to work...

	Now for a real connection:

		adConverter.out.connect[inpDFbk.inp[10]]

		adConverter.out = 0xD0061EFD

		inpDFbk.inp[10] = 0xE004CD45

		Reported by hostZ:

		Upward message:

		0xE004C0F1 .attach[0, E0051859]

		The 0xE004C0F1 is inpConnTBL, which is correct.
		The pin number is zero, which is probably right.
		But the target terminal is wrong...


	Let's rebuild and let it fly...

	After connectSVZtoTBL...

	hostTBL reports nothing. (And is still running)

	
	hostZ (node D) reports an error:

	Upward message:
		
		0xE004C0F1 .connect[0xD00FEEAD, 0x10000005]

	Upward message:
		
		0xE004C0F1 .attach[0, 0xE0051859]

	This exactly correct!!!
	It is equivalent to:

		inpConnTBL.attach[0, inpDFbk.inp[10]]

	An error followed with traceback:

		(Terminal.connect) Reference error 2.

	It appears that the target terminal for the attach is
	incorrect. (It is on the right processor though...)

	A whole queue of Terminal errors occur, with a correct
	attach messages reported for each: the pin numbers increment
	as expected.

	Can this error be repeated without harm?

	The connection succeeded!
	Can other connections be done?
	Yes, they are working when done one at a time...
	The pin numbers in attach are incrementing by 3. Why is that?

	The reason for the whole bug is the fact that an upward
	message occurs to complete the connection. This returns
	control to the grand connector before the connection is 
	actually performed. It hauls off and send the next connection,
	which causes a terminal reference error.

	The fix is to make the connection synchronous by appropriate routing.

	Idea:
	In configsup, break up dspOpen so we can do it several times.
	Let each dsp create Downlinks to the target DSP where it will	
	complete connections.
	Get rid of "fork" in OutConnector: Just do the connection
	right then and there.
	
	configdsp:
		Will need a list of Downlinks.

	configsup:
		Will need only one Downlink.

	
	How did it work before?

	We had multiple downlinks on the supervisor.
	userCycle had to be done with exactly this order:
	
		1) Get a message (#connect)
		2) Execute the message (which will to to downlink)
		3) Poll the Downlinks for upward messages. (There will be an attach)
		4) Downlink will execute the attach at once because there is a 
		   dedicated downlink to the target.

	A quick fix for the existing system:
	Make the supervisor create multiple Downlinks as well.
	The Grand connector will ask each active supervisor node to create
	a downlink to every dsp. This will make the current configuration run
	like the old one. The key is to get the transaction to be synchronous
	from the Grand Connectors point of view.

	Other ways?

	The best way is to make connections synchronous and have the necessary link.
	Fan out could fail because we would queue up a bunch of target input terminals
	for connections, but earlier connections will invalidate the reference to the
	input terminals. (Some might become OutputTerminals.)

	Give each machine a routing table.
	Make Downlinks on demand.
	This will make things work if we keep a LAN topology.

	Get rid of Downlink creation on both the supervisor and the DSP.


April 4, 2003 (Thursday) HVS

	After breaking Downlink & Node, I restored yesterdays backup.

	Results of the successful part of the experiment:
	Adding Downlinks between the DSP's GREATLY speeds up the configuration
	process. Setting this up by hand would be a big mess though.
 
	I attempted to make Node create/dispose of Downlinks automatically
	and broke Node.c to a point where I restored the backup.

	Outline:

	Downlink.c
		Add pool for free and active links. (Just like Uplink.)

	Node.c
		When Node forwards a message, it checks the routing table.
		If no link exists, it creates one using the IP map.
		The logic is exactly the same as Node.alt

	configsup/configdsp.c
		Code in the routing table setup.
		There is no harm in letting each processor know about the table.

	Idea:
		Put the node/IP map on the primary server.
		Let the DSP's fetch it using the inline nfs or rlogin file
		xfer.
		Node.alt can work the same way so there is only one Network
		file in the whole project. That's a Good Thing.(tm)

	Other issues:

		It is not a good idea to abandon asynchronous upward messages.
		Even if we fork to get asynchronous behavoir, the forkCycle will
		block downward messages while waiting for Alltalk or some other
		node to respond.

	Speeding up local configuration

		The biggest time sink is the supervisor vm.c socket traffic to the
		dsp. If we could move some of this without pain to the DSP, we would
		see faster startups. Maybe we should compile class Vm on both
		machines. When debugging, we do SuperVm.new. In the deployed system
		we do DspVm.new. Class Vm would be exactly the same on both machines.
		We just have to include it in the link.

April 7, 2003 (Monday) HVS

	Outline of connection mechanism from Alltalk's Downlink:

	Host tables and route table are used to get destination IP and port
	number.

	An event loop tries to make a connection.

	If if the connection effort times out, the socket is closed and we
	try again.

	When the connection succeeds, we start polling for upward messages.
	If the link goes down, we revert to the connect/timeout loop.

	When a message tries to go through, it is synchronous up to the
	message timeout, then we throw and error that goes back to the
	sender's machine for display.

	*********************

	Retry last Thursday's test without automatic polling...
	Two tests:
	1) Add Downlink to the TBL supervisor.
	2) Add Downlink to the TBL controller.
		Either scheme can work.
		It is probably better to add the downlink to the
		dsp...

	*********************
	Get shutdown to work properly. A "missing sentinel" message has
	been reported for the last month or two...

	Downlink.c
		Add message for #shutdown.
	generic.dat
		New message #shutdown
	Uplink.c
		Don't shutdown on close(Uplink), just close all the links.
		Move the shutdown code into the mtShutdown handler.
	configsup.c
		Degauss. Respool.

	Shutdowns now work correctly and the DSP reboots.

	*********************

	If the Downlinks are created on demand, we only need to let
	each coops node read the nodemap. Even the dsp can open the
	file if it's in the bin directory. 

	For now, we code up the nodeMap and let Downlink connect on 
	demand. To do this, we add protocol to class Node to
	maintain the host map.

	This follows the Alltalk code closely.

	********************

	Node.alt
		Add protocol to maintain node map.
		Create Downlinks on demand.

	Vm.c
		Don't connect to the dsp. Just let it happen.

	configsup.c
		After creating the node, populate the node map.

	So far so good: Individual DSP's & hosts all work.

	Now for the Grand connector...
	It hangs up. Forgot:

	OutConnector.c
		Don't fork the #attach. Do it directly.
		Don't fork the #connect. Do it directly.

	The CON works all the way through connection SVZ to TBL.
	Then it hangs connecting TBL to SVZ. It appears to be
	the connector itself.

	
April 8, 2003 (Tuesday) HVS

	Instrumenting the connectors.
	Connecting SVZ to TBL seems to work and all the terminal connections
	seem to work.
	Connecting TBL to SVZ fails: outConnTBL.connect[inpConnSVZ]

	The method OutConnector.connect send a #connect the partner InpConnector
	on SVZ. This connect fails when trying to get the type string for the 
	message.
	
	1) Timeouts are failing to operate on messages going through the Downlink.
	2) SVZ is not cycling through the Uplinks for some reason. (It is blocked
	somewhere?)

TODO:	In Alltalk, when a socket fails, all traffic on the associated link must
	fail. Periodic polling should be stopped to prevent a cascade of errors.
	Similarly, the DspModels should be detached.

	Status:
	In what way are TBL and SVZ asymmetric?
	Why does SVZ connect to TBL, but not the other way around?

	IDEA:

	In the Grand Connector, try connecting TBL to SVZ first. 
	Maybe this is the asymmetry?
	
	Indeed this was the case: connecting TBL to SVZ first works.
	When SVZ tries to connect to TBL, everything hangs up.

	The problem is some kind of deadlock from having made the
	previous connection.

	GUESS:
	
	Even with timeouts, deadlock can occur.
	Experiment: Modify Downlink.c so it can have a non-upward message mode.
	IT WORKS!

	Problems:
	The DOC/DLG machine does not have Service Pack 2 for Windows 2000.
	For some reason the DOC will not run on this machine.
	
	Network.dat
	I moved the DOC to the SVX/SVY host.
	This machine is very old and slow. 
	Things seem to work better if you start X, Y, & DOC one at a time.

	The CON likes to be stopped before the other applications.
	This is because (I think) it is the target of all the default
	uplinks. This may no longer be necessary since we don'r route
	upward messages to complete connections. FIXED.

	TODO
	I'm getting "Firmware did not start up" messages from the
	SVZ, DOC (rarely.)

April 9, 2003 (Wednesday) HVS

	Scramnet salesmen consume the morning.
	The Scramnet analyser shows 4uSec latency around the rign.
	We are using stead-state bandwidth of 4 MByte/sec.
	Every 200mS, we see a 7 MByte/sec "pulse" in the bandwidth.
	What is that?

	The new nodes should be just as fast as the old ones when	
	creating the vm. This seems not to be the case.
	Fire up the old software and measure the startup times.
	FIXED: They are the same now.

	Could it be TCP_NODELAY? or the buffer size?
	No, it was measurement error: Using stdout writes to
	monitor the stages doesn't work because Windows events
	get behind the supervisor.exe. The times for each step
	are correct. (This was found by raising the priority of
	the supervisor.)

	Experiment 1: How long does it take to create the vm?
	15-20 seconds to create the conditioners. (This is a known limit.)
	20 seconds to do everything else. (Whis is reasonable.)

	The rest of the time is spent downloading the machine parameters.
	Are these somehow going through the supervisor? 
	No, the total time is 45 seconds which is comparable to the DLL
	supervisor system.

TODO:
	Fix MySystem so it will work from a "system.start" on the command
	line after building the GUI app. Otherwise, we can't start debugging
	from the Alltalk side.

	MySystem.alt
		Changed so it starts correctly no matter how long it
		takes to launch the supervisor. All the apps work
		in any combination on any hosts now.

	MySystemXXX.alt
		After connecting the supervisor, configure a notify
		event to continue doing the attachModels.

	Node.c
		Removed timed wait. Blocking for socket events in the
		doit is o.k. because the Downlinks to this node keep
		things moving.

	Link.alt
		Add a method for #tryRead. 
		Downlink uses this for #getMessages.
		#getMessages has the dual purpose of handling the 
		status.
	Downlink.alt
		Use #tryRead for getMessages.
TODO:		Use the result to maintain the "connected" status.
		This will eliminate the premature #notify on connect.
		That, in turn, will eliminate the need for lengthy
		timeouts.

	MainPanel.alt (In niedCON)
		The polling for the table dimension currently 
		prevents a correct shutdown of niedTBL.
		This will be fixed by the previous "TODO".

	After installing SP3 on the DOC/DLG host, it works
	robustly.

May 28, 2003 (Wednesday) HVS

	Retrench:
	Put Alltalk back to restore Brad's GUI.
	Redo the node-number-passing from the modified links.
	Test.

	1) Apply corrected updates to the working system:

	Passing the node to the Uplink.
	This is done so we can eliminate the default Uplink concept.
	This (in turn) is done so we don't have to identify the first
	Uplink created as the default.
	This (in turn) is done because we don't control the order Uplinks
	are created. In particular, the CON will re-establish an Uplink
	before the SVC host.

	Why do we want polling of Downlinks in all cases?
	Because we won't always get a proper close notification on the
	Downlink. The only we we can safely find out about a closed connection
	is when we fail to get a reply. In this case, the Downlink will try
	to re-establish a connection. This could be done in-line...	

	Why does a race condition occur when uplinks are polled?
	This happens because select returns a non-zero value on an invalid
	socket. This releases the block and lets doit(Uplink) run. If the
	Uplink socket is now bad, that block will release as well and we
	hang reading from a bad socket.

	2) Find out if we really need sockBlock.
	It would be nice to get rid of this feature in both coops and Alltalk.
	The alternative is a spin-out on sockReadable. Does this do any harm?
	Yes, probably it does because the Windows supervisor has nothing else
	to do.

	RESULT:
	SockBlock makes no measureable difference for two machines.
	This would not be true when other apps on the same host are running.

	Compromise:
	Use sockblock, but follow up with readable tests.
	If the test causes an error, close the socket without protocol.
	This could be build into sockBlock(). The idea would be to test
	rdfds, wrfds and exfds. If select returns -1 or if exfds returns 
	a bit set, we know that a socket is hosed up. The subsequent pass
	through the tests will find the offending socket. This suggests
	that readable() should always check exfds as well.

	How can select behave better when a socket is invalid?
	We will have to detect an error return and find the offending socket.
	This can be done by doing a select on each socket until we find the
	one that returns an error. How can we enumerate all the sockets?
	They are in the socketMap bitmap. We would have to implement another
	structure or keep a list of all active sockets...

	TODO:
	1) Restore node passing and table management.
	2) Restore Alltalk changes and see what's wrong with brad's chansel.
	3) Make sure Modal windows stay on top.
	4) Do a diff on the defective backup to see what was broken.
	5) Add the close protocol.
	6) Find out if Tornado really does exceptions when a connection
	   is broken. (ECONRESET)
	-> Alltalk needed exception handling for this error at one time.
	   What has changed?


June 03, 2003 (Tuesday)

	Rearrange todo:

	1) Reproduce existing system with new Alltalk.
	2) Restore node-passing protocol.
	4) Replace BOTH vxSocket and winSocket.
	5) Add the eof test to Downlink.
	6) Add link polling.

	QED.

	This should enable fault-tolerance for both normal
	and abnormal shutdown of the nodes.

	TODO:
	Deal with reboot propagation on fatal errors:
	The "CON" should be able to reboot any PPC 
	and restart the HOST program. This can be done
	using the winsys tools.


June 04, 2003 (Wednesday) HVS

	Yet another Alltalk socket package:
	This time, the integration of timeouts, select, and read/writes
	are transparently integrated. The following methods were removed
	from the public interface in Alltalk and Coops:

		socket.readable
		socket.writable

	The method for socket.count is not required by Node or any other
	normal networks, but it was retained for debugging.
	
	Issue: Should time be in floating or integer units?
	Traditionally, Alltalk has used 1/100 second integer tics.
	The coops sockets use floating-point fractions of a second...

	Add protocol to Node to tell it when to accept connections.
	This controls when remote systems start sending messages.
	We don't need to defer responding to mtGetMessage anymore.

	TODO: Work on normal shutdown testing.


	When a connection attempt succeeds and a subseqent message
	times out, there are two cases:
	
	1) The destination system is gone.
	In this case, the source system should simply close the connection
	and resume trying to make a good connection.

	2) The destination system was too busy to deal with the message.
	In this case, if the source system closes the connection, the
	destination system will never see the close even after it accepts
	the connection.

	Downlink.alt
	Uplink.alt
	Node.alt
	Link.alt
		Remove support for mtClose & mtShutdown.

	Supervisors accept only one connection for their link to the GUI.
	The GUI will accept any number of connections, as will the PPC.

	When an Uplink.c detects a close, it simply does a socket.close and
	puts itself back on the free list.

	How does the simultion.exe avoid becomming a zombie then?
	
	Normally, the app sends a request to a coops object that
	forks a self.exit. This will close all the sockets.

	We need a protocol to tell an uplink that it is supposed to
	close the app when it gets a close event. This cannot
	be done directly because Uplinks are anonymous.
	Instead, we must tell the node that another node is our
	'special' supervisor.

	This is further complicated by the fact that we have the same
	code on every supervisor and every dsp.

	1) Add the node-passing protocol so we don't get a default Uplink-is-first
	problem.
	
	We need protocol in Node to support messages to a remote Uplink.
	Idea:
		node.uplink[15, #lookup, "A name"]
		node.uplink[15, #slave]

	The #slave message tells an Uplink that it should exit the application
	when the link closes.

	The dsp will automagically reboot when it exits.

	Issue: meta protocol in Node:
	Now, we have special protcol for asking a node to do things.
	By adding a "meta" message, we only need two message formats:

	1) Sending messages to an object.
	2) Sending messages to the node itself.

	When a node is created, it adds itself to the dictionary.
	All the former special messages can be directed to the node.
	
	Later.

June 5, 2003 (Thursday) HVS

	Spent the day testing new Node - socket protocol changes.
	(It works!)

June 9, 2003 (Monday) HVS

	Agenda:

	1) Test new Nodes.alt against working controller.

	2) Re-introduce node-passing. This needs to be done first because
	we can't test the new Node error recovery without getting rid of
	default Uplink. This also makes it easier to diff against the
	previous version that had node passing.
	
	3) Revise winSocket, vxSocket, Node.c, Downlink.c, Uplink.c to match Alltalk.
	
	4) Test new Nodes.c against working controller.

	5) Test the system for failure recovery.

	QED.


June 16, 2003 (Monday) HVS

	Results from new Socket package:
	The build-in connection verification fails during the polling cycle.
	This is because the old version on the coops side doesn't shut down
	the Uplink. 

	TODO: Test this by slowing down the tryRead cycle.

	GuiCom\MySystem.alt
		The system.connect is commented out so the startup process
		can be tested from the DLL debugger.


	
June 17, 2003 (Tuesday) HVS
	F'd.

June 18, 2003 (Wednesday) HVS

	TODO: Revise the configureNode methods in all subclasses:
	With direct connections, most of these can be eliminated.
	(Maybe all?)

	Breakthrough: (Sorry Omar...)
	The timeouts failed when they were turned up for debugging.
	It turns out that the conversion back to microseconds in the
	kernel was overflowing a 32 bit integer.

June 19, 2003 (Thursday) HVS

	Back to normal with the new socket package.
	Continue with June 9 agenda.

	Uplink protocol idea:

		node.uplink[15].lookup["A name"]
		node.uplink[15].slave

	When the node has the selected uplink, it simply returns the object.
	When the node has a downlink to the selected uplink, a special protocol
	is used to return the remote uplink.

	Downlink.uplink : Return the remote Uplink object.

	How does shutdown work?

BRAD:
	You can't send messages to the machine in the detach methods.
	This is because we detach when we detect a socket failure and
	those method's can assume we are able to talk to the machine.

	Sys.detach
	MessageAction.detach
		Please look at these and decide what to do...

	MySystem.attachModels
		Do the node.open after everything else.
		This elminiates the need for weird timeouts in the
		CON.

	Timeouts:
		We are down to one setting.
		This has to be kept because we have the special vm.create
		that takes a long time.

	Shutdown:

		When an Uplink gets an EOF, it should close the socket and
		then exit the application. This applies to any Uplink.
		When a remote application closes normally, it will send
		the mtClose message. This will cause the Uplink to close
		itself and keep the application going.

		This takes care of the DSP automatically:
		If the supervisor crashes, the o.s. will close the sockets.
		The DSP will see this and reboot.
	
	vxSocket.c
	winSocket.c
		Make all socket EOF and error event call shellQuit();

	Result:
		When everything is up, quiting the host CON causes
		the dsp's to get a VxWorks program exception.
		It appears that shellQuit() is failing, maybe because
		of a socket connReset? There should be a way to
		disable this behavior...

	Status:
		The new code is robust at startup but it can't be shut
		down normally yet. All timeouts and related settings
		are good to go. The apps can be started in any order.

		1) Put back the mtShutdown/mtClose message.
		   This takes care of normal shutdowns.
		2) Figure out why vxWorks does an exception on connReset.
		   If this can be configured to return a normal error 
		   instead, socket errors of all kinds will be handled
		   correctly.

TODO:	Reconsider calling shellQuit from vxSocket and winSocket.
	When the new versions are installed, this would not be correct.
	A better place is in the Downlink/Uplink module.


June 20, 2003 (Friday) HVS

	Problems:
	When the supervisor is killed, we get an exception in the
	DSP. This should not occur if we correctly handle the 
	TCP FIN packet. (shutdown(2) sends this packet)

	Fixed: shellQuit was indirect in VxWorks.
	The correct behavior should be closing all sockets, waiting,
	and then rebooting.

	To avoid linking problems, vxSocket and winSocket should have
	a functional parameter to determine what happens on socket
	errors.

	When dsp's are connected via the scramnet, they end up connected
	via Downlink/Uplink connections as well.

	When a dsp is shutdown (normally or abnormally) the associated
	Downlink may fail when it polls for messages.

	Question: What happens to the connected Downlink on a DSP when
	the Uplink on the other DSP dies? Is it a EPIPE exeception?
	Do we get a readable zero?

	Question: When a Downlink becomes unexpectedly readable, is
	this an indication that the link has failed?

	If excecptions are detected in the same way, maybe the 
	sockEOF function should include a test of the exception
	fields as well?

	Results:
	When the DSP reboots, a connected socket in windows never
	sees and error or eof until another message is written.
	This does not cause and EPIPE: Instead, the attempt to
	read a reply returns EOF. If this holds true for 
	VxWorks as the sender, we are in business.

	When a Downlink polls for messages and gets and EOF, it
	should simply shut itself down and go back to connection
	polling.

	When a Uplink gets an EOF on input, it should simply shut
	itself down and recirculate UNLESS it is marked as a "master"
	Uplink. In that case, it should shutdown all attached sockets,
	wait and then reboot (VxWorks) or exit (Windows)

	How is the master state determined?
	We can't use the first Uplink, because it may not be
	the supervisor connection.
	In the previous attempt, we used node passing to identify
	the node number of the associated Downlink. This made it
	possible to identify the proper destination for upward
	messages without using a default uplink. We need this feature.
	
	mtMeta: Direct a message to the Uplink itself.
	Add protocol for setSync. When this is TRUE, the Uplink will
	exit the application on closing.

	TODO 
	1) Revise winSocket and vxSocket.
	2) Add the meta protocol for links.
	
	IDEA
	If we extend this to Alltalk and the psLaunch tools,
	the grand connector will be able to start and stop
	the whole controller.

	NEXT: 
	Revise winSocket (because it's easier to test.)
	
	NOTE:
	Whenever we read a reply, the test for EOF must come
	first in case the remote process crashed in between.

	Snapshot:
	niedProj-2003-06-20AM
	*********************

June 25, 2003 HVS

	Brad made several updates.
	This version works well as a demo.

	ActionSequence.alt
		In the method for #detach, remove self.dispose because
		it sends a remote message. (This was done before but not
		documented.)

	Snapshot:
	niedProj-2003-06-25-BradAMWorking
	*********************************

	Update winSocket.c to the new Alltalk-style sockets.
	Check for zombies... Good!

	TODO: All Downlinks should throw errors, so the protocol to
	configure this can be removed.
	Node.alt should do the catch in the method for #forward.
	After catching the error, Node should have a configurable
	notification. In the case of NIED, the response should be
	to detach the vm.

	TODO: What about messages that go through the Downlink as
	a result of some message from a remote system? These error
	need to be returned to the remote process...

	DONE: Brad fixed the method for #attach in MySystem.
	
June 26, 2003 HVS
	
	Got the simulation.exe working.

	WinSimClock.c:
		Could not use elevated priority on the old computers.
		I turned off all the priority elevation stuff for now.
		It would be good to explore this on a faster computer.

	TODO:

	In the coops method for vm.new, the setSync aimed at the downlink
	is going to the Uplink instead when we simulate. This prevents
	the simulation.exe for quiting as it should.

	Node.h
		I turned up the read timeout slightly because Z takes
		longer than SVX and SVY. (It was set too close, about
		15 seconds.)


	1) Disconnects don't work yet because vxSocket is not
	   updated to match winSocket.
	2) The MemoryTerminal stuff is commented out of vmTBL because
	   the vxWorks side has not been recompiled yet. 

	Snapshot: (Preserve everything before updating the vxSocket stuff.)

	niedProj-2003-06-26AM
	**********************

		Simulations work.
		Real system works.
		Grand connection works.
	
	The new vxSocket works.
	All Brad's changes are compiled on the dsp...

	Problem: The Grand Connector is BROKEN!!
	
	Snapshot:
	
	niedProj-2003-06-26PM
	*********************

July 7, 2003 (Monday) HVS

	(I was on vacation last week.)

	Update to Alltalk 2.982: This has support for socket timer
	overflow detection.

	winSocket.c
		Fix an error in timeout overflow.

	vxSocket.c
		Got sysTics() working!!!
		Fix an error in timeout overflow.

	vxSocket.c
		Use EINPROGRESS instead of EWOULDBLOCK in connect.
		This is an old issue. It got fixed and unfixed...

	Status:
	Everything starts and interconnects correctly.
	Because of the removal of mtClose and mtShutdown, the application
	cannot quit normally.

	TODO: Remove default node stuff so we can start out of order.
	TODO: Revise shutdown logic to use the eof detection.
	TODO: Pass node numbers in all error messages.
	DONE: Update aaChanges for Alltalk.

	Snapshot:

	niedProj-2003-07-07 
	*******************

July 8, 2003 (Tuesday) HVS

	DONE: Remove default node stuff.
	2) Add logic to "designate" the reboot/shutdown Uplink.
	(Possibly #setSync because this isn't needed by the new Downlink.)

	TODO:
	Get rid of the old shutdown and close stuff in Node, Uplink & Downlink.c

	Change the default value for Uplink.synchronize to FALSE:
	When a Downlink closes, the remote Uplink will not reboot.
	This will allow the CON to close normally.
	
	How should the setSync[TRUE] be propagated from Alltalk to the
	supervisor to the DSP?

	Alltalk should do explicit settings?

		node.downlink[nodeNumber].setSync[TRUE]

		This message will propagate to the associated Uplink.
	
	Downlink also has a #setSync message. This is used to control
	polling for upward messages. The default value is TRUE, which
	means we don't poll (no async messages). It gets set to NIL
	in the supervisor method for vm.new. This makes the supervisor
	Downlink poll the DSP for upward messages.
	TODO: This is commented out right now, so fix this and test
	upward messages.

	Now that the default Uplink is gone, it should be ok for
	Downlinks to poll in all cases. If the polling message
	fails, they should go back to trying to reconnect.

	TODO: The subclasses of MySystem that do #configureNode have
	redundant #host configuration commands. These can be removed.
	This would be a good place to handle #setSync however.

	Downlink.c
	Use the shutdown protocol in the message for _close:
	Send a TCP FIN, then wait for the FIN-ACK or timeout.

	When an uplink closes, what should happen to the associated
	Downlink?
	
	There are two cases: 1) The uplink closes normally.
	2) The uplink process crashes.

	In case 1, the Uplink should send a shutdown to the socket.
	The Downlink should be scanning the socket when it reads
	upward messages AND before each transmit. If it sees an
	EOF, it should do a close(socket) and then return itself
	to the pool.

	In case 2, the Downlink won't know anything is wrong until
	it a) sends a message or b) polls for an upward message.

	In either case a or b, we will get a timeout when we try
	to read the reply. In case a) we report the error. In case
	b) we quietly close ourself.

	This is why Downlinks must poll for upward messages.

	TODO:
	1) Enable Downlink polling for all cases. When this is
	debugged, remove the setSync method from Downlink.
	(It is confusing to have a method with the same selector
	in Uplink.)


	2) Add the scan socket logic to Downlink to handle the two
	cases described above.

	3) Figure out how to do the setSync method for Uplink.
	The best solution is to handle all meta-messages to the
	Uplink through a special protocol in Node. This will
	get rid of a bunch of special messages: mtLookup, etc.

	At this point we should be able to:

		1) Create all the machines. CHECK
		2) Do the grand connect. CHECK
		3) Quit any app without hanging the CON. CHECK
		3) Quit from the CON. CHECK
		4) Start any host while the CON is running. CHECK

	This is Good Thing.(tm)

	Because the setSync is commented out, no reboots or
	shutdowns will occur and it is not possible to restart
	a host while the CON is running (Because the Downlink sockets
	arn't shutdown properly. (The addition of scanSocket to Downlink
	will fix this.)

	Q: WHY DOES the Supervisor quit when Alltalk quits if
	setSync is NIL?
	A: Alltalk explicity kills the supervisor.exe

	TODO: Add scanSocket and polling to Downlink.alt and Downlink.c

	Snapshot: niedProj-2003-07-08AM
	*******************************

	First attempt at continuous Downlink polling with auto-close
	failed during grand connection:

		SVZ->TBL worked
		TBL->SVZ got Socket Read Timeout on the CON.
		Got a "Cannot complete requred connection" on one
		of the hosts. Can't tell if it was SVZ or TBL.
		SVZ dsp did a spontainious reboot and then
		got an exception after restarting. The exception
		occured because the CON was trying to restore
		the connection.

	Next attempt: Enable polling only from supervisor to dsp.
	This is done by removing the comment in vm.new in the supervisor.
	It works!
	So this example has everything working except shutdown.

	Snapshot (overwrite) niedProj-2003-07-08AM
	******************************************

	We need all Downlinks to poll so we can detect app shutdown.
	If this is not done, the grand connector will reuse the
	broken DSP->DSP link and this will cause an exception.

	Re-enable polling to make sure:
	It's still broken.

	SVZ->TBL worked.
	At this point, there is a Downlink on dsp SVZ connected
	to an Uplink on TBL. The Downlink on dsp SVZ will start
	polling the dsp TBL.

	When we try to connect TBL->SVZ, TBL will send a message
	to SVZ. So the messages cross... So TBL can be waiting for
	a reply from SVZ while SVZ is waiting for a reply from TBL.

	Nice try #1: Make node alternate between polling Downlinks
	and fielding messages from Uplinks.

	This won't work because if a message is pending on an uplink,
	we will be hung if we try to poll a downlink to the sending node,
	even if we ignore the pending uplink message.

	The alternative is to disallow connection status polling between
	the DSPs. The problem with this is how to get Downlinks to close
	when a DSP reboots.

	Idea:
	When a Downlink is configured not to poll, it still tests the
	socket for EOF. If an EOF is detected, the Downlink closes itself.
	This will work well if we don't have crashes.

	This code is now in Downlink.c, but it is not tested.
	To make it work, we have to get the Uplink to close properly
	on the DSP. This means that setSynch must be symmetric on
	Uplink and Downlink.

	TODO: Deal with the Uplink side of setSync and modify Alltalk
	Node to set this state on each host.

	Snapshot: niedProj-2003-07-08PM
	*******************************

July 9, 2003 (Wednesday) HVS

	Review:
	Connection status polling is necessary to prevent ECONRESET
	when the grand connector re-creates a connection between
	the DSPs.
	
	Solution 1:
	Make the polling timeout much shorter than the normal readTimeout.
	When the timeout occurs, close the connection quietly. When a 
	new (real) message goes through, the connection will be recreated.

	Experiment:
	It should be possible to create the error entirely between two
	Alltalk nodes. The development system didn't see the problem because
	the message rate was too slow.

	The experiment shows that the problem does occur between Alltalk nodes,
	so the fix can be done at that level as well.

	The fix works! The tryTimeout is kept short and the result of a timeout
	is to close the Downlink. Bilateral connections with polling now operate
	correctly.

	Experiment 2:
	Try the same thing in Coops...
	It didn't work on the first try...
	Several timeout adjustments... Still doesn't work.

	Solution 2:
	By default Downlinks don't poll and last only for one messages.
	This only applies to Downlink.c. When setSync is used, they work
	normally.

	This keeps them from causing ECONRESETs when the DSP's crash...

	CoopsDSP:
	Replace OutConnector and friends from the Hugh Template.

	TODO: The CON notify method in main panel must reconnect the
	node explicity.

	Testing:
	The whole ring must be operating so the shares are updated.
	Result: It works, but there are some strange slowdowns during
	the reconnection. A connect timout occured during testing.
	Something is makeing the connection go up and down perhaps?
	
	TODO: Put back reboot on close for DSP.
	TODO: Add method to DspModel so we can selectively detach
	when a remote node goes down.

	Just a thought: Why not go back to using upward messages to complete
	connections? Ans: This will only work if we don't have to restore 
	a crashed valve controller. The negotiation of a share or reshared
	memory block must be synchronous.

	Snapshot: niedProj-2003-07-09
	*****************************

	The system starts up normally, but the DSP doesn't reboot on close.
	This was done so debugging could be done in the Hyperterminal window.
	Reconnections almost work. (Timeout issues.)

July 10, 2003 (Thursday) HVS

	Crashes vs normal shutdown:
	When a valve controller crashes, we cannot expect to restore the
	running controller because the DSP will initialize the scramnet
	and destroy all the connection state information.

	When a valve controller closes normally, we would like to able
	to start it again without shutting off everything else. This
	makes debugging much less costly.

	After a crash, the goal is to keep the other controllers operating,
	avoiding any GUI hangups. The host GUI associated with the failed
	controller should detach from the DSP but preserve all other state
	information for debugging.

	To deal with the normal shutdown/restart situation: 
	1) We must not clear the scram space when a processor starts.
	2) We must find a way to propagate the scram allocation counter
	without using scram space. (The LAN?)

	Currently, the host CON keeps track of the scram space allocation
	counter. If this is done correctly, we can get rid of the shared
	allocation count by passing the value as a parameter to OutConnection
	#connect. The value returned will be the new count. The procedures
	for scramAlloc and scramFree will also explicitly accept and return
	this index. This means that scramAlloc would have to return two values:
	the alocated memory address and the updated free index. This is ugly
	business for Alltalk.

	Goals for today:
	Restore the auto reboot/quit logic for the DSP and supervisors.
	Enable the auto detach for the GUI applications.
	Investigate why state polling fails on the DSP but works on
	Alltalk.

	To enable auto reboot/quit, we need a method in class Uplink
	and a way to reach the Uplink object. It would be most consistant
	to do this through the node.

	node.setSync[nodeNumber, state]
		Controls the 'one-shot' connection mode for the Downlink.

	I would prefer to get rid of this method in Downlink by making the
	auto-polling work correctly.

	If this can be done, the setSync selector can be used to set the
	Uplink state instead.

	Downlink.c
		Connection polling now work.
		Got rid of the method for #setSync.
	
	vm.c	
		Remove #setSync message to the node.


	Notes on the share problem.
	
	After rebooting one dsp, the scramNet allocation counter is set
	to zero for all nodes.

	The grand connector shareCount is correct, so it will be sent
	to the nodes as required.

	Reconnection works correctly.

	********************

	Now the #setSync selector is free to be used by the Uplink for
	setting the master status. When setSync is TRUE for an Uplink,
	it will do a shellQuit when it is closed. This will call userClose
	and then exit the application (supervisor.exe) or reboot. (vxworks)

	********************

	How should #setSync get to the Uplink?
	The default value should be FALSE (no reboot.)
	
	node.setSync[nodeNumber, flag]

	This has to get to the Uplink somehow.
	We could add a special message type...
	Or use the proposed meta-message concept.

	node.uplink[nodeNumber].setSync[flag]

	Instead of having a special protocol to ask for the Uplink,
	we could make the connection process return the Uplink:
	After the socket is connected, we write the Downlink's node
	number and read back the remote object id for the Uplink.

	We would no longer need special messages for mtLookup, mtClose,
	mtShutdown, etc.

	CoopsNet/
	Get rid of mtClose, mtShutdown and all associated code.

	CoopsNet/
	Get rid of mtLookup and all associated code.

	CoopsNet/
	Get rid of mtGetSelector and all associated code.

	BRAD TODO:
	MySystemXXX
		There is no longer any need for these subclasses.

	DONE:
	supervisor.exe
		The method for tryRead reports an error in the dialog window.
		This should be silent. FIXED.

	supervisor.exe
		The supervisor exits when tryRead fails because the dialog
		hangs up the application. FIXED.

	xxxExcept.c
		The error message should not be displayed from the handler.
		Instead, the catch should call errorMessage explicity.
		This gives us control over how errors are displayed and
		prevents the supervisor from hanging up the GUI application.
		FIXED.
	
	Uplink.c
		After the message processing is underway, socket errors
		should probably be handled differently.
		The close on error response is only appropriate for detecting
		when the remote node crashes. Other error should be reported
		in the dialog window.

	GuiCON/MainPanel.alt
		When a target node goes down, resume connection polling.
		This must be done explicity now.
		DONE.

	TODO:
	DSPModel autodetach in the GUI applications. DONE.

	TODO:
	When trying to reconnect SVX with everything flying, a
	"Socket read timeout" was reported during one test.
	The timeout is long enough, so something else may be
	wrong...

	TODO:
	Downlink.flush on close should be tested again.

	TODO:
	When the CON restarts the connection attempts, it may
	succeed while the remote host GUI application is still
	in the process of quiting. To prevent this, the GUI
	apps should stop their node from accepting connections
	before they shut down the dsp. DONE.

	TODO:
	Lots of writelns & printfs need to be removed now. DONE.

	BRAD TODO:
	"Scramnet: Redundant Tx Rx fault" occurs after SVZ shutdown.
	I think the scramnet.c driver is doing bad things to the
	running loop.

	TODO:
	Node.alt - Method for close should shutdown, rather than
	closing the Downlinks. 
	
	vxMain.c
	winShell.c
	configdsp.c
	configsup.c
	configsim.c
		Move sockActivate and sockDeactivate out of sight.

	MySystem.alt
		Use Model.forAll[#detachNode, aNodeNumber] when
		notified that the link state to that node is NIL.

	MySystemXXX.alt
		Remove the explicit connection to notify #attachModels.
		This is now done in MySystem.

	Model.alt
		Add method for #detachNode[aNodeNumber].

	Things are in a good order now.

	Snapshot: niedProj-2003-07-10
	*****************************

July 14, 2003 (Monday) HVS

	Uplink.alt
		Try using self.shutdown in Uplink.close instead of socket.close.
		This is a better idea because it makes the socket shutdown 
		sequence the same for uplinks and downlinks.

	TODO: Get rid of the delay when the handshake is complete.
	TODO: Remove the socket option settings for NODELAY.


	TEST 1:
	Normal shutdown and restart of a valve controller:

		1) Grand Connector detects shutdown and reconnects when
		the GUI is started again. WORKS.

		2) Supervisor.exe exits normally. WORKS

		3) DSP exits normally and reboots. WORKS

	Unexplected crash of a valve controller GUI:

		1) Grand Connector detects shutdown and reconnections when	
		the GUI is started again. WORKS.
	
		2) Supervisor.exe on the valve controller automatically quits.
		(Zombie detection.) WORKS.

		3) DSP automatically reboots. WORKS.

	Unexpected crash of a valve controller supervisor.exe

		1) The valve controller GUI quietly disconnects from the supervisor.exe.
		The connection the the DSP continues to operate normally.
		GUI messages to the supervisor don't cause errors even though they don't
		do anything because we have sucessfully detached from that node.
		Other features of the GUI operate normally.
		The Grand Connector thinks everything's o.k. becuase the GUI is app
		it monitors.
		(In a sense, everything is o.k. because the supervisor isn't needed
		for normal controller operation? Is this true Brad?)
		When we quit from the GUI, everything restarts, reboots and reconnects
		normally.

		TODO: We have a "hook" to do whatever we like in the System object.
		For debugging, the behavior described above is convienient because
		it allows the developer to look around and figure out what went
		wrong. For the customer, we might want to have a different mode that
		exits the GUI?

		Brad: Maybe we need an offline/online lamp on the main panel?

	Unexpected crash of a valve controller DSP.

		The GUI reports a "Socket read timeout".
		The supervisor continues to operate normally.
		(It has detatched itself.)
		The GUI continues to operate normally.
		(It has detatched itself.)
		The Grand Connector hangs up with "Object NIL doesn't understand
		#setCount.
		TODO: Fix this. (See notes below)

	Some ideas:

	Brad: It would be very nice to automatically wait for the DSP to reboot before
	attempting to connect from the GUI. This is the last remaining "awfull thing" that the
	customer can do. It would improve all of our products, IMHO.

	We can do this by making each app work like the Grand Connector with respect to the
	DSP. Rather than hauling off and making the required connections, we wait for the
	notification from the node on the DSP.

	A problem:
	When a DSP is crashed, the supervisor.exe exits and the GUI detaches.
	The grand connector is polling the GUI, and this polling method will
	cause a hard timeout because the GUI must timeout to detect that
	the DSP has gone down.

	The CON will interpret this as a GUI down event, but as soon as the
	GUI reports the DSP timeout, it resumes normal operation.

	The CON will detect this and assume that the GUI is back up again.
	It will try to reconnect, and this causes the #setCount error because
	it will as the GUI for a DSP object that has been detached.

	The fix:
	When the GUI for the valve controller detects a DSP failure, it closes
	the uplink associated with the grand connector and refuses further connections
	until the DSP is up again.

	Details:
	
	Node.alt
		Change the method for #stop so it also closes the Uplinks.

	MySystem.alt
		When the dspLink goes down, stop the Node.

	************************

	Busted!
	I had neglected to evaluate all the features after making these
	changes today. I discovered that an obscure error occured when	
	shutting down SVX and SVZ. After several efforts to locate the
	problem, I restore the 7/10 backup and then applied on the 
	"Trivial cosmetec changes" made today. The problem still occurred!

	Two backups were made for 7/14: "slightly hosed" and "really hosed".	
	The "slightly hosed backup contains only the trivial changes."
	The "really hosed" backup contains everything done today.

	TODO: Apply each trivial change to figure out what broke the
	shutdown sequence.

	Review of "trivial" changes:

	Node.alt
		Rename activeLinks to activeUplinks.
		Remove the defaultNode stuff.

	Downlink.alt
		Improved method for #show.

	Uplink.alt
		In the method for close, do a self.shutdown instead
		of socket.close. (This might be the problem...)

	GuiCon\MainPanel.alt
		In the method for #notify, change the variable name to "connected".

	GuiCon\MySystem.alt
		Add logic for #reallyQuit.
	
	BradStuff\
		Comments changed in many of the aadefines.
	
	Non-trivial changes: (Not in the current niedProj)

	GuiCom\MySystem.alt
		Move the node.open to the linkChanged method.
		Make the method for linkChanged bring the node up when
		it sees that the dsp is up.

		When linkChanged sees the link go down, close the node
		(or at least close the Uplink for the GrandConnector and
		refuse further connections.)
		One way to do this is to close all the Uplinks in the method
		for Node.stop.

	CoopsNet\Node.alt
		Change the method for #stop so it also closes the Uplinks.
 
	Terry needs to use the machine in the A.M. and it all has to be
	working, so as of now, niedProj is at the 7/10 level except for this file.

July 15, 2003 (Tuesday) HVS

	Agenda:
	1) Figure out which "trivial change" broke the controller.
	2) Implement the Uplink close to fake out the CON when a DSP
	goes down.

	Repeat the Diff: Here are the changes one-by-one between the
	working controller and the "slightly hosed" controller:

	*Downlink.alt
		Only the enhanced #show. This is safe.

	*Uplink.alt
		Different in blanks only.

	Node.alt
		1) Rename activeLinks to activeUplinks.
		2) Remove default link logic. This needs to be tested,
		but it appears that the default link was never set because
		after removing the message, no errors occured at runtime.

	GuiCon\MainPanel.alt
		Rename 'status' to 'connected'
		Add 'reallyQuit' logic.

	*GuiCom\sys.alt
		Only comments.

	*GuiDlg\aadefine.alt
		Only comments.

	*GuiDoc\aadefine.alt
		Only comments.

	*GuiSvc\aadefine.alt
		Only comments.

	*GuiTbl\aadefine.alt
		Only comments.

	*** It's really hard to see what harmed the controller...

	Phase 1: (All * items above.)
	Put in all the comments.
	Put in the changes to Downlink.alt
	Test Results: Everything works.
	
	Phase 2: Recompile everything to make sure.
	Test Results: Everything works.

	Phase 3: Apply these two changes:

	Node.alt
		1) Rename activeLinks to activeUplinks (benign)
		2) Remove defaultLink logic

	Test Results: Everything works.
	
	Phase 4: Apply these changes:

	GuiCon\MainPanel.alt
		Rename 'status' to 'connected'
	
	GuiCon\MySystem.alt
		Add 'reallyQuit' logic.

	Test Results: Everything works.

	This is a good one:

	Phase 5: 
	Uplink.alt
		In method for #close, try doing self.shutdown instead
		of socket.close.

	Test result: Everything came up except SVZ: The DSP had some kind
	of hardware lockup. It would not reboot even by pushing the PPC
	reset button. I had to cycle power to the whole cabinet.

	Next trial:
	Everything works.

	TODO: After an error dialog event, erase all modal dialogs 
	(or at least the modalNotifier.)

	Phase 6:
	Downlink.c
	Put back the extended shutdown/close protocol.
	Result: Everything came up.
	The CON reports this error: "(Share.map) No share to reach this node"
	The SVZ reports "Socket.read timeout".
	The closeTimeout may simply be too long...
	
	Node.h
		Reduce the closeTimeout from 50 to 25.

	Try again to make sure the problem is repeatable:
	Still doesn't work: errors reported in the CON:
	"Object NIL doesn't understand #out" followed by
	"(Share.map) No share to reach this node"

	Restore the closeTimeout to 50.
	It turns out that the closeTimeout was only used by
	Downlink.c (In all the coopsNet c code.)
	Put back the old code for Downlink.close in Downlink.c
	(Do sockShutdown followed immediately by sockClose.)
	TODO: Is shutdown redundant if immediately followed by close?

	Result: Still have a bug! Somehow, the code didnt' get restored...
	Rebuild the supervisor and the node stuff...
	Result: Everything works. I appears that bin/coops.o was busy
	when the PPC linker tried to update the image.
	
	This is a good one:

	Snapshot: niedProj-2003-07-15AM-Working
	***************************************

	Try to add auto-recovery capability to all the GUI apps:

	GuiCom\MySystem.alt
		In the method for #stop, just close the node.

	CoopsNet\Node.alt
		Remove method for shutdown.

	The Problem:

	1) When a GUI detects that it's dsp is gone, it should
	close the Uplink to the CON and refuse further connections
	from the CON until the dsp has returned.

	2) The system.start should not proceed to attach the DSP
	until the node notifies the system that the dsp is up.

	We will tackle #2 first...
	Summary: It works!
	Any node can crash and the GUI app will recover.
	Any GUI app can fail and the Grand Connector will recover.
	This is major Juju.

	MySystem.alt
		First, start trying to connect the node to the dsp.
		When the notice arrives, start the supervisor and
		start trying to connect.
		When the notice arrives, create the vm.

		If the supNode or dspNode goes down, detach the
		models on the sup and dsp, stop the supervisor
		and resume trying to connect the dsp. When it
		reboots, all will proceed as above.

	Node.alt
		When we stop the Node, also close the Uplinks.
		They will be recreated automagically.
		
	MySystem.alt
		Stop the node when we see a problem.
		Start the node when we have recovered.
		This takes care of the Grand Connector.

	IDEA: The Grand Connector could be synched to the other GUI nodes
	in the same way. All we need is a utility to start/stop remote
	applications. (I have this...)

	TODO:
	1) DONE: NAN detection, counting and blocking for OutConnectors.
	2) DONE: Scramnet.c should not clear main memory.
	3) DONE: Routing tables should be set up by Alltalk, not configxxx.c
	4) DONE: SVCs nodes  must stop while rebooting so CON doesn't lockup.
	5) Maybe we should have MySystemSVN after all because of the case statement symptom...
	6) We need to lock out the panels when restarting since this is now a concurrent process.
	7) Show the beach ball when restarting.
	8) Append node numbers to error messages. This is really needed.
	9) Error dialogs must erase the modal status reporting dialogs.
	10) When an app has to restart, the user should get a chance to save settings?
	11) If a DSP reboots when another host is in the middle of sending a message,
	the other app may restart as well... This is probably ok? (But what about the settings?)
	12) When an SVC quits, the TBL controller reports:
	"Scramnet error: Redundant TxRx fault." What does this mean for the samples
	on the ring?

	OutConnector.c
		Replace the overrun detector with a NAN blocker and counter.

	Scramnet.c
		Don't clear main memory on restart.
	
	MySystem.alt
		Send down the routing tables, rather than configuring
		them in the configxxx.c

	Things look good:

	Snapshot: niedProj-2003-07-15PM-Working
	***************************************

July 16, 2003 (Wednesday) HVS

	Uplink.c
		Prepend the node number to all up-going error messages.
		(This was TODO number 8 above.)

	Fiddle-with-the-timeouts day.
	The goal is to simplify or eliminate some of the time settings.

	Current settings: (Integer values are in 1/100 Sec. tics)

	Link.alt:
	messageDelay	:= 1,		! Delay for Uplinks polling for downward messages
	updateDelay	:= 25		! Delay for Downlinks polling for upward messages
	readTimeout     := 1000,	! Read timeout
	writeTimeout	:= 1000,	! Write timeout
	tryTimeout	:= 100,		! Link down detected
	connectTimeout  := 2000,	! Connect timeout
	shutdownTimeout := 1.0		! Time to outlast close-wait

	Node.h:
	#define tryTimeout 100
	#define closeTimeout 25
	#define readTimeout 2000
	#define writeTimeout 1000
	#define connectTimeout 2000

	This probably needs some revision:
	The Coops-level tryTimeout should be shorter than the Alltalk tryTimeout
	so that Alltalk won't see a good node go down because it detected a
	bad node. This is the "Transitive-shutdown-cascade" problem.

	**********************************************
	When all the nodes are started, we sometimes get a read timeout...

	Fix #1 attempt:
		Raise the Alltalk tryTimeout to 200.
		Raise the Alltalk readTimeout to 2000.
		
	MySystem.attachModels raises the readTimeout when creating the 
	vm. Then it restores the timeout setting to 2000

	Result: No effect. I think it may be the connect timeout...
		Raise the read timeout to 4000 in Alltalk and Coops.
		This is only temporary.

	The problem has something to do with the timeout-on-deadlock that
	is a normal part when pairs of nodes are cross-connected. The
	key is to keep the tryTimeout relatively small for these nodes
	so deadlocked connections are promptly removed. Keeping the
	polling rate for upward messages moderate also helps.

	New timeouts:

	Link.alt:
	messageDelay	:= 1,		! Delay for Uplinks polling for downward messages
	updateDelay	:= 25		! Delay for Downlinks polling for upward messages
	readTimeout     := 1000,	! Read timeout
	writeTimeout	:= 1000,	! Write timeout
	tryTimeout	:= 25,		! Link down detected
	connectTimeout  := 2000,	! Connect timeout
	shutdownTimeout := 1.0		! Time to outlast close-wait

	Node.h:
	#define tryTimeout 25
	#define closeTimeout 25
	#define readTimeout 1000
	#define writeTimeout 1000
	#define connectTimeout 2000

	******************************

	No Good.
	Try the original settings:

	Link.alt:
	messageDelay	:= 1,		! Delay for Uplinks polling for downward messages
	updateDelay	:= 25		! Delay for Downlinks polling for upward messages
	readTimeout     := 1000,	! Read timeout
	writeTimeout	:= 1000,	! Write timeout
	tryTimeout	:= 100,		! Link down detected
	connectTimeout  := 2000,	! Connect timeout
	shutdownTimeout := 1.0		! Time to outlast close-wait

	Node.h:
	#define tryTimeout 100
	#define closeTimeout 25
	#define readTimeout 2000
	#define writeTimeout 1000
	#define connectTimeout 2000

	This works well with 4 nodes: X, Z, TBL and CON.
	It fails (with a timeout) when running all the nodes...

	Snapshot: niedProj-2003-07-16AM-Working
	***************************************

	--> Brad put in a very large group of changes that mostly concern
	the vm and configuration process. This made it possible to get rid
	of configSim.c.

	The timeout problem seems to occur because of an exponential
	message overhead as we add nodes. This may occur because
	each normal downward messages causes the Node to poll for
	upward messages. Perhaps it would be better if this polling
	cycle only occured when the sockWait times out. When sockWait
	returns zero, it means that the timeout occured...

	Node.c
		"Smarten" the method for #receive so it
		1) Doesn't poll for upward messages unless
		   the sockWait times out.
		2) Doesn't process upward messages on the same cycle
		   that creates a new Uplink.

	This made a big improvment. All the nodes start without problems
	using the original timeouts. 

	Snapshot: niedProj-2003-07-16PM-Working
	***************************************

July 17, 2003 (Thursday) HVS

	All the controller ran overnight.
	One timeout error was reported on X, but the electrical
	team tampered with the consoles, so I'm not sure about
	the validity of the test.

	Some kind of data corruption occurs on the scramnet:
	The oscilloscope trace on X sees "digital" data every
	few traces.
	
	Share.c :
		Don't set the initial count. Let the CON do this.
		Otherwise, a bogus reset of scram space will occur
		when a new DSP joins the ring. The same issue would
		occur with shared memory if we allow nodes to join
		after connections have been made...

		It worked: The CON now manages the scramCount.

	TODO: This should probably be a "mode" in share.c

	****
	There is a timeout problem somewhere:
	
		Start CON
		Start TBL
		Start X
		Start the Fg on TBL and watch it on the X scope.

		At this point, the system will run indefinitely.

		Start Y

		The CON will report a read timeout.
		This does not occur if a signal is not being watched.

	The scope is keeping X busy, but Y should be free to respond to the
	CON...

	Summary of current settings:

		#define tryTimeout 100
		#define readTimeout 2000
		#define writeTimeout 1000
		#define connectTimeout 2000

		tryTimeout	:= 100,		! Link down detected
		readTimeout     := 2000,	! Read timeout
		writeTimeout	:= 1000,	! Write timeout
		connectTimeout  := 2000,	! Connect timeout

	IDEA: Maybe the ping should not expect a reply.
	Instead, each side will periodically issue a ping.
	The reader on a node will accept pings as well as normal
	replies. If the ping rate goes too low, we decide that the
	remote node is gone...


	*******************

	Another bug:
	With everything running, I quit the TBL host.
	The CON saw this by a ping failure.
	The Downlink on the CON did a self.close, which
	does the shutdown protocol with timed-wait.
	The MainPanel then did a node.connect[hostNodeTBL].
	This connection was accepted (somehow???) but the
	first read (for the remote Uplink id) failed with
	an EOF. This strongly suggests that the EOF was
	on the way and the shutdown timeout was too short.
	A better solution is to make Link.shutdown read
	until it gets the EOF or does a timeout...

	Experiment:
	I added the full socket-shutdown-flush-close logic
	to Alltalk and Coops Uplink and Downlink.
	Result: 
	With everything connected, quiting TBL caused
	other DOF's to reboot. Something is wrong with the
	flush loop logic.

	I abandoned this approach, but we may want to revisit this
	issue. Here is the code from Link.alt, Downlink.c and Uplink.c:

	METHOD shutdown OF Link IS
		Break the socket connection
	VAR
		result
	BEGIN
		IF socket THEN
			socket.shutdown
			result := 1
			WHILE NOT socket.eof AND NOT socket.error AND result > 0 DO
				result = socket.read[flushBuf, 1, 1, closeTimeout]
			END WHILE
			socket.close
			socket := NIL
		END IF
	END METHOD

	method _close(self)
		/* Close the Downlink */
		ivars *self ;
	{	char flushBuf[2] ;
		int result = 1 ;
		self->remoteUplink = NIL ;
		sockShutdown(self->socket) ;
		while (!sockEof(self->socket) && !sockError(self->socket) && result > 0)
		{	result = sockRead(self->socket, flushBuf, 1,1, closeTimeout) ;
		}
		sockClose(self->socket) ;
		removeValue(activeLinks, self) ;
		add(freeLinks, self) ;
		nodeUndefineDownlink(self->remoteNode) ;
		return self ;
	}

	method _close(self)
		/* Close this Uplink */
		ivars *self ;
	{	char flushBuf[2] ;
		int result = 1 ;
		sockShutdown(self->socket) ;
		while (!sockEof(self->socket) && !sockError(self->socket) && result > 0)
		{	result = sockRead(self->socket, flushBuf, 1, 1, closeTimeout) ;
		}
		sockClose(self->socket) ;
		removeValue(activeLinks, self) ;
		add(freeLinks, self) ;
		nodeUndefineUplink(self->nodeNumber) ;
		return NIL ;
	}

	************************

	Since the problem only happened in Alltalk, I'm going to leave the flush
	loop in Link and try again...
	It made no difference.
	The close logic matches yesterdays system...
	I restore the backup. The same problem occured last night.
	The testing was not complete...

	The last change was the "improvement" to Node.c that alternates messages.
	This made it possible to create the whole controller and not worry about
	timeouts. But it seems to have broken something else:

	method _doit(self)
		/* Process connection requests and incoming messages */
		ivars *self ;
	{	int result ;
		int count = sockWait(100) ;
		if (count == 0)
			doit(Downlink) ;
		else
		{	result = sockAccept(self->serverSocket, 0) ;
			if (result > 0)
			{	new(Uplink, self, result) ;
			}
			else
			{	doit(Uplink) ;
			}
		}
		return self ;
	}

	TODO: Try the "old way" and see if it is possible to restart
	a node...

	Snapshot: niedProj-2003-07-17
	*****************************


July 18, 2003 (Friday) HVS

	Somehow, we lost the restart capability.
	When the TBL node is restarted, the other valve
	node crashes as soon as the CON sends the connection message.
	It is getting a requrest to close from somewhere.
	It is not comming from the CON or the SVC Alltalk program.
	It is not comming from the SVC Supervisor either.
	Could it be coming from the TBL? 

	I tried rebuilding with the 7/10 CoopsNet.
	The 7/10 backup is the last version with a working restart.
	This didn't work. Too many changes.

	I instrumented the DSP Downlink on Z.

	When the TBL was stopped, it reported

	"ping error to node 0xE" after a considerable delay.

	When TBL was restarted, the CON worked correctly!!

	I stopped TBL again.
	This time, dsp never reported the ping error...

	I started TBL again.
	DSP Z reported:
	"socket error to node 0xE" which is what I'd expect if
	the polling loop was not running.
	The socket error causes a reboot of the DSP.
	Even if it didn't reboot, it would be a fatal error because
	this is the #connect message tryting to go through to TBL.

	Conclusion: Somehow, the polling loop from DSP Z to TBL
	is not detecting the link down state. When the CON sees
	
	Experiment 2:
	I shortened the timeout in Node.c for sockWait.
	This should detect Downlink timeouts sooner...

	It works! Nodes can enter and leave loop as before.
	There are some startup problems...
	I increased the tryTimeout in Node.h to 200.

	Very close! Everything comes up.
	When I quit the TBL, X rebooted. This occured because
	the connection from dsp X to dsp TBL caused a socket
	error. This should be a quit error because the transaction
	was only a ping... It must have be caught in the middle of
	the ping.

	Probably Downlink socket errors should simply close the link,
	rather than reporting a socket error. If the message was
	"required" the higher level protocol will report the problem.

	X restarted by itself correctly.

	I then started TBL: It came up correctly and the CON reconnected
	everything.

	Snapshot: niedProj-2003-07-18AM
	*******************************

	Theory: A ping is getting caught doing a write when the other side
	goes down. This is detected as a fatal socket error, which causes
	the DSP to reboot.

	The best fix is to get rid of the "optional" message stuff and just
	catch the transmit as well as the receive errors. The handler for
	#transmit can do the fatal thing as before. The handler for #receive
	can close the link quietly.
	
	I tried this and it cleaned up Downlink a lot.
	Unfortunately, it didn't work...
	
	Maybe the checking takes too much time.
	Move the error tests out of the innermost loop...
	No good.
	
	Keep this for further study: Downlink.exp.c
	I put back the old Downlink.c.

	All nodes can be started at the same time.
	The CON handles everything correctly.

	Restarts are "iffy". The DOC and TBL with large
	numbers of connection sometimes cause a timeout.
	There is some tweaking yet to do.

	->Is there some way to avoid the ping timeout
	complexity? If this could be done at the O.S.
	level, everything would be much faster.

	One last try for the day: Reduce the connectionTimeout
	to a much smaller value: (From 2000 to 500...)
	Not a good idea. Got "Cannot complete required connection."
	Put back the old value.

	Everthing comes up!

	To get restarts working reliably, we have to avoid the
	"interrupted write" in the ping logic. This can be done
	by getting the Downlink.exp.c to work...

	Snapshot: niedProj-2003-0718PM
	******************************

July 19, 2003 (Saturday) HVS

	What is wrong?	
	1) The nodes are too slow.
	2) It takes too long to find out if a connection is down.
	3) Timeouts need to be absurdly large.

	When a node goes down, we want remote nodes to notice this quickly.
	The reason is that cross-connected nodes are each trying to ping
	each other. When a node tries to send a normal message, the remote
	system may be hung up waiting for a ping reply. The sender is also
	waiting for a reply, so the link is deadlocked. 

	To prevent an error, the ping timeouts are made smaller than the
	normal message timeouts. That way, the ping will fail and one
	of the cross connections will be passively closed.

	The faster the ping timeout, the quicker the orignal message will	
	get through.

	Quick ping timeouts have a drawback: When a synchronized node is
	closed, the Uplink on the receiving side shuts down the program!
	
	A ping is also a complex message. It possible that the ping will
	get a ECONRESET exception while sending the data structure to
	a node that closes after we've started sending the message.

	Another problem:
	How do we deal with crossed messages?
	Ans: Keep the upward-message mechanism as it is, but
	write upward messages to another connection immediately.
	The Downlink reads all available messages from this
	connection and processes the upward messages.

	With this solution, the Downlink never asks for upward
	messages, it simply reads them from the socket when they
	are available.

	Could this be used for connection status checking?
	Suppose that the Uplink sends a ping upward periodically?
	The Downlink can check to see if this ping is not happening.
	If it doesn't get pinged for some time, it closes the link.

	Who does the Uplink send the message to?
	When we make a connection, we pass down the node number and
	the Downlink object. The Uplink returns itself. Pings by
	the Uplink are sent to the Downlink.

	Could these upward going pings block the sending node?
	The socket should be marked asynchronous. If the EWOULDBLOCK
	error occurs, the uplink should close itself.

	Can all sockets be asynchronous?
	Quite possibly...

	Experiment:
	Make all sockets asynchronous and test the idea.
	If all is well, try writing upward messages without the queue
	and getting rid of mtGetMessage.

	The concept in detail:

	Each link has a pair of sockets:
	
	Downlink
		outSocket : Used to write messages and read replies.
		inSocket  : Used to read upward messages.
		noCount   : Count tries that had no upward messages.
		noLimit   : Limit for noCount before we close the connection.		

	Uplink:
		inSocket  : Used to read messages and write replies.
		outSocket : Used to write upward asynchronous messages.

	When we make a connection, we write down the node number and
	the object id of the Downlink itself.

	1) Send the Downlink id along with the node number.
	   Record this in the uplink.

	2) Add the outSocket, inSocket logic.
	When we make a connection the Downlink does a sockListen on
	nodeNumber+maxNode. When the connection succeeds, it loops
	until the inSocket connection can be accepted.
	Alternative:

	If we are doing a nodeConnect, we can defer the accept to the
	event loop for this Downlink. The event loop deals with the
	half-connected state and polls for completion. When this occurs,
	it notifies us that the remoteNode is up.
	If we are doing a message, the nodeMustConnect is used instead.
	This code loops for completion and throws an error if we don't
	get a return connection.

	The Node accepts the socket for the new Uplink, which immediately
	connection the outSocket. This completes the circult.

	Using this mechanism, we don't have to make the grand connector
	hang up trying to make connections.

	What happens when the person trying to form a connection give up?

	The receiver will eventually accept the connection and try to make
	the reverse connection. This will fail at once becase the Downlink
	is not listening. When this occurs, the remote Uplink will close itself.

	Implementation and testing

	What is the essential idea that can be tried with
	minimal changes?

	The key idea is an extra connection used to handle 
	asynchronous upward messages.

	Why is this a good thing?

	Several reasons:
	1) We don't have to send a complex "request" data structure
	which could be interrupted by a remote Uplink crash.
	2) We don't have the crossing message problem that occured
	when we had to send a message to poll the link status.

	How do we detect link-down?
	1) If the asyncSocket gets and error or an eof we are down.
	2) If the regular socket gets an error or an eof we are down.
	3) If we don't get any upward messages after N cycles, we are
	down.

	How does an Uplink decide to go down?
	If it doesn't get any messages after N cycles.

	How could all this be tested in the current package?
	1) Add the protocol to pass the Downlink to the Uplink
	and store it in the Uplink object.
	TEST: DONE
	2) Add the protocol to create an extra connection.
	TEST: DONE
	3) Send upward messages through this new connection.
	Don't queue them at all.
	On the downlink side, read and process any pending
	upward messages from the new socket.
	TEST: DONE
	4) Add counter logic to both sides to automatically close
	the link if it doesn't get any messages after N cycles.
	TEST: DONE
	See if this works well...

	Result:
	It works very well in Alltalk.

July 20, 2003 (Sunday) HVS

	TODO: Should the null limits be tic based rather than message count based?
	Each method is pretty much the same because the update loops are timed.
	A count might be better for this reason:

	The Uplink sends a ping each pass through the message cycle.
	This rate is controlled by the sockWait in Node unless a real
	message comes through. When a real message is processed, we reset
	the nullTimer to zero. When we have no message to process, we
	add the sockWait value to the nullTimer and also send back a ping.

	The Downlink checks for messages each cycle.
	The rate is determined by the sockWait in Node as well.
	If no async messages are available, it increments the nullTimer by
	the sockWait value. If async messages are available, the nullTimer
	is set to zero and all of them are read and processsed.

	When a normal downward message is sent and a reply is received,
	this also resets the nullTimer.

	If we used real time instead, it would be necessary to deal with
	overflows, etc, etc. Best to use the counts. They get reset 
	frequently and only count up to the nullLimit for the link.

	Q: If the Downlink goes away, what keeps the Uplink for getting
	blocked by the sockWrites that send the async pings?

	A: The Uplink is also incrementing a nullCount each time though the loop
	when no messages arrive. When this value times out, the link gets closed.

	Link.shutdown
	Modified to handle socket and async separately.
	If the connection negotiation interlocks, async may be NIL.

	Problem:
	A connect time, the other node may be sending us messages.
	This will cause the mustRead in Downlink.connect to fail.

	Idea for deadlocks:
	Either side can send message though a Downlink at any time.	
	This is uncontrollable.
	Once this happens, the sender is locked up reading the reply.
	While waiting for a reply, the sender should cycle the Uplink
	for that node and install a recursion detector.

	- We need a method for node.uplink[aNode].
	node.unblock[aNode]
	IF uplinkTable.get[aNode] THEN
		uplinkTable.get[aNode].update
	END IF

	TODO: This is the "corrected" link shutdown. DONE.

	METHOD shutdown IS
		Break the socket connection
	VAR
		result
	BEGIN
		IF socket THEN
			socket.shutdown
		END IF
		IF async THEN
			async.shutdown
		END IF
		system.wait[closeTimeout]
		IF socket THEN
			socket.close
			socket := NIL
		END IF
		IF async THEN
			async.close
			async := NIL	
		END IF
	END METHOD

	An uplink needs to read its remote node number.
	So it can't unblock that node.
	Fix:
	Disallow recursion?
	If recursion is not allowed, we can make the uplinkTable and downlinkTable fixed.
	Now the Uplink always knows the remote node number.

	NOT TRUE! When we get a connection request, we have to
	read the remote node number. The remote system has to
	be waiting for us to send ourself back. So Uplink.open
	is not the problem.
	The problem is with Downlink.transmit (and possibly connect)
	These methods will write to the remote Uplink and expect a 
	reply. If the remote system is reading for any reason, we will
	block.

	Becuase handling connection requests and incomming messages both
	result in the remote Downlink doing a read, we must serialize
	these events on the Uplink side:

	The Node event must handle one connection request OR one incomming
	message on an Uplink per cycle. So Uplinks can't have their own
	update event.

	TODO: Node.c cannot use an uplinkTable. It must use a list.
	There can be more than one Uplink from a node.
	Also, Uplink.close must do parent.removeUplink[self]

	TODO:
	An Uplink can decide to close at any time.
	What happens if a remote downlink tries to send a message to the
	still-open socket before it has closed itself due to a ping timeout?

	ANS:
	Downlink must have an update loop that checks the socket for EOF and
	error. If one is encountered, the Downlink closes.

	ANS2:
	Uplinks probably shouldn't close unless the remote downlink sends an EOF.
	Otherwise, a race condition will exist when a Downlink sends a message
	and the Uplink closes in the middle.

	Revise the connection async exchange protocol...
	OK. The damn thing works with no deadlocks.
	The test: Both nodes send messages to each other at full speed for
	30,000 cycles. It looks good, Zeke!

	Snapshot: B3_CoopsNet.

	The event in Downlink should probably be removed.
	The logic is more clear and matches the Coops version.
	
	Node.connect[target]
		This method creates a Downlink and starts an event
		loop inside the Downlink that tries to complete the connection.
		When the connection succeeds, the Downlink adds itself to 
		the activeDownlinks in the Node. The Node.update then polls for
		the link state and pulls in upward messages.

	Downlink.alt
		Removed the update event.
		The Node takes care of this now.
	TESTED. It works.

	Uplink.alt
	Downlink.alt
	Node.alt
		Revised beyond recognition.
		Crossed message now work perfectly.
		Speed is very goood.

	Snapshot: B4_CoopsNet
	*********************

	To tackle the Coops nodes, we need comprehensive test programs...
	For the first cut, we will test the Coops Uplink against an Alltalk node.
	The Coops application will launch Alltalk and then wait for messages.

	Review of key modifications to the protocol:

	1) Add the protocol to pass the Downlink to the Uplink
	and store it in the Uplink object.
	TEST: DONE
	2) Add the protocol to create an extra connection.
	TEST: DONE
	3) Send upward messages through this new connection.
	Don't queue them at all.
	On the downlink side, read and process any pending
	upward messages from the new socket.
	TEST: DONE
	4) Add counter logic to both sides to automatically close
	the link if it doesn't get any messages after N cycles.
	TEST: DONE

	It works very well. This is the best yet.

	Only Downlink.c is untested...

	Snapshot: niedProj-2003-07-20
	*****************************

July 21, 2003 (Monday) HVS

	Uplink.c
	Downlink.c
	Node.c
		Add deadlock unwinding to the Coops classes.
		It works! We may survive this thing yet...
		This required a new selector "unblock". Sorry Brad.

	Node.c
		Changes to Node.c protocol were made to make it work
		like the Alltalk version:
		
		new(Node, nodeNumber) ! Moved from "open"
		open(node) ; 	! Start accepting connections
		close(node) ; 	! Stop accepting connections and messages

	TODO: The table management in Node.c should probably use messages.
	TODO: There is a global variable left in Node.c  Fix this.

	Experiments with the real hardware:

	As might be expected, timeouts were hosed up.
	It turns out that the pings are comming too fast from the DSP and
	plugging up the async socket, which then does a block on the process.
	The pings need to be decimated or turned off while the vm is being
	created.

	Everything works with the pings turned off, but we have to have
	pings! (Upward messages do work on the async socket.)

	Pings are working.

	TODO: Node.c
		Get rid of the uplinkTable.
		This can't work with recursion.
		Use a list instead.

	TODO:
	The ping problem is complex:
	We want to shutdown the Downlink if it doesn't get enough
	pings but the number (or rate) needs to be flexible.
	->It might be better to use real time values rather than
	cycle counts as the basis. Investigate this.

	Node.alt
		Make init populate the protocol table for all nodes.
		We don't have any other protocols now.
		This was needed for the CON because it wants to
		make connections on demand and the DSP links are
		not pre-connected.

	Test the CON with TBL:

		The TBL failed with a null ping overflow.
-------->Downlink.alt
		Disable null ping shutdown and estimate the
		nullMax instead...

	CON, TBL & Z
		Interconnect succeeded!

	Added X...
		The CON reported

		[Node 11](Downlink.new) Async connection failed.

		I presume this was to the TBL...

	This time, just CON, TBL & X

		Same message.
		SVX is somehow different...
	
	Repeat test with CON, TBL, Z...

		This time, it failed.
		
		[Node 13](Downlink.new) Async connection failed.

		It turns out that the TBL supervisor closed and
		exited.

-------->Downlink.c
		Disable null ping count for now.

	***An obvious error:
	The temporary async server is created using the node number
	of the host node. After accepting a connection, it is closed.
	But it lingers! It appears that closing the asyncServer socket
	does not free the port right away even when the reuse address
	option is specified.

	To test this idea, start Z and TBL and leave them along for
	a while before starting the CON...
	It still didn't work.
	Maybe VxWorks can't unbind a socket?

	IDEA: Don't create and destroy the async server.
	Create it along with the Node.
	When we need a connection, ask the Node.
	This is a better idea anyway because it keeps the node
	related stuff in one place.
	Tomorrow.

	IDEA: Put back the alternator for Downlink/Uplink in
	Uplink receive. This made a big difference in earlier
	versions...


	Snapshot: niedProj-2003-07-21PM-NotWorking
	****************************************

July 22, 2003 (Tuesday) HVS

	Node, Uplink, Downlink:
		New protocol for handling the asynchronous connection.

	TESTING:
	Simulations work.
	Hardware works point-to-point.

	TBL, Z, CON works.

	TBL, Z, X, CON works.

	TBL, Z, X, DOC CON
		Got a timeout from TBL dsp.

	Notes on appropriate error handling:

	The CON reported the error from the Node.update.
	This broke the update loop.
	TODO: Defer the update notices to another event
	so the Node event loop isn't broken.

	After the TBL came up automatically, the CON
	failed to notice even when the Node was started again
	by hand.

	TODO: Downlinks should have a ping counter that continuously
	runs when the Downlink is getting upward messages.
	This lets us guage the rate of operation for tuning purposes.
	DONE.


	TODO: It appears that the connection timeout can be a lot
	smaller now...
	DONE. It can be "10" on Alltalk. 

	TODO: Try the short timeouts on the Coops side...

	TODO: The Downlink state reporting should include the target
	node number. "Connection to node 3 closed by socket EOF" etc.

	TODO: By using the debug message, we can include these messages
	on the supervisor.exe as well. They will do nothing in WIN32
	and write on the console with VxWorks. This provides a good
	place for breakpoints in win32... Or we could send them
	up to the host as messages...

	TODO: The beachball dialog fails to get selected when a connection
	is made after the initial startup.

	Node.h
		nodeTimeout changed from 10 to 1.
		See if this speeds things up...
		Result: The DSP rebooted while starting the TBL app.
	
		Try again:
		pingRate changed from 1000 to 10000
		(Speeding up the nodeTimeout means we would get more pings...)

		It works and it's fast!
		BUT: Why 10000:1 ???
		ANS: Because we are sending a lot of messages at config time.
		But after config, almost no pings will get sent.
	TODO:	This really needs to be clock based...

	Testing:
		SVX, SVY, SVZ, TBL, CON All work together.
		Connecting the DOC causes a big timeout catastrophy.
		
	It's too bad we have to slow down for the DOC...
	Experiment:
	Try the deadlock code...
	Everything worked.
	Could it be a fluke?

	Try again...
	A timeout!
	BUT it was not a timeout...
	I put a breakpoint in the TBL error handler:
	The message was from async reader: It was a missing sentinel.
	It turned out that the partial read loop recovery in vxSocket
	and winSocket was turned off. (This was restored to Alltalk
	for 2.983.) When this was fixed, everything came up perfectly.

	Now try removing the deadlock-unlocker...
	It works without deadlock protection.
	
	Downlink.c
		Comment out the deadlock protection.
		It slows things down in this application and
		we don't need it.

	Now deal with the Beach ball... DONE. (It was being erased.)

	Downlink.c
		I moved the ping count stat vars to globals so I could
		see it easily from VxWorks.

	Some results:
		For TBL sup: nullMax is 403.
		This was measured after everything was created.
		It gained 50 when creating the DOC. 
		The DOC consumes enormous network time.

	TODO:
		Reconnects need work.
		Reduce connectTimeout in Coops.
		Explore readTimeout again.
		Finish measuring ping rates on all nodes.
		Sort out connector overlap. (If that's the problem...)
		Deal with the TBL dio hardware issue. FIXED!


	IDEA:	We need to have the wait notifier up the whole time
		we're starting so the user can't fool with the controls.
		Put a level counter in the wait notifier.
		Center the wait notifier on the main panel.
		(Give it the concept of an optional parent window.)
		That way, it won't block the view of other apps and
		we can identify which app it belongs to...

	Things are in good shape.

	Snapshot: niedProj-2003-07-22
	*****************************

July 23, 2003 (Wednesday) HVS

	New scripts:

	ZScramChecker.alt
		Check for overlapping allocations in scram space.

	ZNANChecker.alt
		Check for NANs on the OutConnectors.

	ZShowDOCTestpoints.alt
		Write out all the testpoint names and numbers.

	*****************************

	I'm not happy with detecting the link state by counting things.
	This whole thing needs to be based on time instead.

	Link.alt
	Uplink.alt
	Downlink.alt
		Change to real time base.

	Uplink.c
	Downlink.c
		Change to real time base

	This works great! Null detection is right on time and doesn't depend
	on the processor speed. Link traffic is vastly reduced because unnecessary
	pings are never sent.

	Now we have the right machinery to handle reconnection.

	TODO:
		Fix the scramnet overlap. 
	TODO:
		Restore the reconnect logic and test.
		(It was removed because it couldn't work without
		reliable link state detection.)

	A good day.

	Snapshot: niedProj-2003-07-23
	*****************************

July 24, 2003 (Thursday) HVS

	Downlink.alt
		Should not do self.stop when mustConnect fails.
		Just do self.error and return.
		Should wantConnection be cleared?
		It could be that someone simply sent a message
		before the notification arrived. In that case,
		at least for debugging, it would be ok to keep
		trying to make the connection.
		So don't clear wantConnection either.

	Using ZScramChecker, I found overlaps in scram space when
	everything was connected.

	Using ZNANChecker, I found NANS. It is possible that the NANS
	were caused by data corruption because of the overlap, so it
	seems reasonable to deal with that first.

	Review of the concept:
	The Share module does not intialize the free space index
	in scram space. This was done so that the CON could manage
	this index. When a node comes up when the others are already
	running and partially interconnected, we want it to allocate
	from scramspace using the current index. The CON explicity
	manages this by writing the index to new nodes when they
	come up and reading it back after each OutConn->InConn connection.

	Test 1:
	Bring up all nodes and check the local value of the index.
	It should contain uninitialized scram memory.
	Write a value to the index on one node and then start another.
	The index value should NOT propagate from the new node back to
	the previous nodes.

	Result:
	First, I started SVX.
	The vm.share.remote.count was zero.
	I set the value to 3.

	Next, I brought up TBL.
	It's vm.share.remote.count was zero.

	When I went back and checked the count on SVX it was also zero.

	I set the value of count on SVX.
	It appeared on TBL.

	I set a new value on TBL.
	It appeared on SVX.

	Conclusion: Starting the driver is clearing the memory.

	This proved to be true.

	Scramnet.c
		Changed so it does not clear main memory.

	Repeat experiment:
		Now the values don't change when the nodes are brought up!

	Every node now comes up and interconnects correctly except SVZ.
	For some reason, when the CON sets the shareCount on this node,
	it fails to "stick"...

	That wasn't it: The share count is correct, but when the outConn
	is connected to the inpConn on TBL, the allocation count does not
	increase. This could happen if the outConn were connected to
	an inpConn that was already in use: The inpConn would think
	the outConn was returning from a crash and return it's allocation
	index. The outConn would use this instead.

	I observer that when Z fails, it has

	vmSVZ.outConn[scramNodeTBL].min = vmSVX.outConn[scramNodeTBL].min

	This error would occur if vmSVZ.outConn[scramNodeTBL] was accidentally
	connected to vmTBL.inpConn[scramNodeSVX].

	TODO: Get rid of sleep in userClose.
	TODO: Lower the timeouts now that everything works.
	TODO: Figure out what's wrong with Z's scramnet connection.

	Everything is good to go except for this weirdness with SVZ.

	Snapshot: niedTBL-2003-07-24
	****************************

July 28, 2003 (Monday) HVS

	Some small things:
	Experiment: Remove the socket.setLinger[0] This should not be
	necessary because we are closing down the connection correctly.
	Experiment: remove the SLEEP in userClose().
	Experiment: Put back the flush loops to close connections.

	First priority: Deal with SVZ connections.

	Experiment 1:
		What happens if Z and TBL are first?
		Is Z really special or was the problem caused
		by a previous connection error?

	TODO: Make sure we don't need an #ifdef WIN32 around the
	code that (currently doesn't) intialize the share count
	in Share.c

	TODO: It would be better to put back the pre-allocated Downlinks.
	1) Bad: We would have to give up recursion.
	2) Good: We CAN tell if a node is connected even if there is no route.
	   (This could probably be fixed in the variable-allocation version.)
	3) Good: We wouldn't have to reconnect notifications every time a Downlink
           comes up.

	ZConnectionTester.alt
		This is a big script that looks up all the hosts,
		shares and connectors. Then it connects the OutConnectors
		to the InpConnectors one at a time.

		It worked perfectly. There were no overlaps.
		This suggests that something is wrong with the
		CON or perhaps a race condition...

	Bring up the whole network except for SVZ and then debug
	its path in detail.

	Uplink.alt
	Downlink.alt
		Add more information to the state transition display.

	Here are the conditions to display the bug:

	Bring up all machines, but don't start the CON.
	Comment out the notify section for SVZ in the CON.
	Start the CON and let everything but SVZ connect.

	Run ZScramChecker. Everything is ok.
	Check the share counts on all nodes: Everything is ok.
	Now do this step by hand:

	inpConnTBLomSVZ := vmTBL.inpConn[scramNodeSVZ].remote
	outConnSVZtoTBL := vmSVZ.outConn[scramNodeTBL].remote
	outConnSVZtoTBL.connect[inpConnTBLomSVZ]

	Run ZScramChecker to see that the allocation for the
	outConn to TBL on node dspNodeSVZ is wrong.
	We have:

		outConnSVXtoTBL.min = outConnSVZtoTBL.min

	Also: The shareCount does not advance. It was 7200
	before making the connection and it is still 7200 on
	all nodes after.

	The outConnSVZtoTBL should have been a new allocation.
	The share count on dspSVZ was correct before the connection...
	This suggests that the OutConnector on dspSVZ negotiated an
	alternative allocation value during the connect...

	This could only happen if someone else made a connection
	to inpConnTBLomSVZ...

	This could occur if the wrong connector was returned by
	vmTBL.inpConn[scramNodeSVX]

	-> All the connectors are unique and have the proper node
	numbers.

	********************

	Instrument OutConnector.connect:

	Result:
	As expected, a negotiated value was used.
	The value returned by the remote InpConnector was 0x10000005.
	This should only happen if the remote InpConnector already has
	a partner.

	Next, instrument InpConnector on TBL:


	Result:
	The previous "partner" is 0xb00f8e81.
	This is, again as expected, outConnSVXtoTBL.

	So there we have it: Somehow, someway, outConnSVXtoTBL is
	begin connected to inpConnTBLomSVZ...

	Some of the messages scrolled off the terminal.
	Repeat without the OutConnector messages.

	Result:

	(InpConnector.connect) self: 0xe004c8b1 source: 0xb00f8e81 index: 0x10000005
        I have no partner. Local value of index is: 0x2000007c

	This is the very first connection to TBL from SVX.
	The value of self is wrong! It is inpConnTBLomSVZ !!!!

	Found it: In the CON MainPanel method for #connectSVXtoTBL, the wrong
	scramNode was specified. ARRRG.

	****************************

	Bring up the system.
	Do a scram check. All is well.
	Run Fg Long on TBL and check all scopes. Perfect.
	We be done.

	What's left? These are all minor issues:

	TODO: Put back pre-allocated Downlinks. Get rid of recycling.
	TODO: Eliminate node recycling in Alltalk. This shouldn't be allowed.
	TODO: Get rid of sleep in userClose.
	TODO: Lower the timeouts now that everything works.
	TODO: Put back socket flush-on-close everywhere and test with crashes.
	TODO: Test reconnection logic.
	TODO: Test crash recovery in many situations.

	Update documentation for Nodes. (After we ship.)

	*****************************

	Testing reconnect:

	Try taking down DOC and bringing it up again:
	The connection from dspSVX to dspDOC failed to timeout
	when dspDOC was restarted. This caused a timeout on SVX
	and on the CON.
	It should not have to timeout because dspDOC was properly
	shutdown...

	Why didn't dspSVX see the EOF from Downlink to dspDOC?
	It may be that dspDOC rebooted too quickly...

	-> It looks like the activeList in both Uplink and Downlink
	are recusively manipulated: When we close(Uplink) it does
	a forAll(activeList, s_close). But the instance method for
	#close does a removeValue(activeList, self). This is a
	Bad Thing(tm). To do this properly, we need to construct
	a new list of links to shutdown. Then we can forAll close
	this list without recursive access to the activeList.
	
	This needs to be done for Uplink.c, Downlink.c, Uplink.alt
	and Downlink.alt.

	-> The timeout should still have taken care of disconnecting
	the Downlink from dspSVX to dspDOC, so this must be set too
	long OR we need to keep the closeWait time when shuting down
	a dsp so the remote downlink has time to shutdown. That would
	(currently) take 10 seconds. Not good. Maybe this time can
	be shortened...

	Add the closeList to Uplink.c to test this idea. It should
	enable reconnects at once.

	It did! DOC reconnected and the oscillocope trace showed
	the correct signals from the TBL.

	Uplink.c
	Downlink.c
	Uplink.alt
	Downlink.alt
		Add the closeLinks list to avoid the list interlock
		at shutdown time. 

		
	********

		There is no bug like an old bug
		That wastes away our tics.
		No puzzle like its symptoms,
		No homage like its fix.

		Working software's like a sunflower,
		With gaudy crown of gold,
		But an old bug is a breathing rose
		With sweets in every fold.

	********

	Powering off DOC:
	This test fails because the pingTimeout is too long.

	Current settings:

		pingTimeout  := 1000, ! Link idle timeout
		pingTime     := 100   ! Time between sending pings

	Experimental settings:

		pingTimeout  := 500, ! Link idle timeout
		pingTime     :=  50  ! Time between sending pings

	Speeding up the ping time caused no problems, but dspSVX
	still had a problem with dspDOC going away. For some reason,
	the timeout is not quietly shutting down the link. When
	DOC comes up again and the CON tries to remake the connection,
	the old Downlink on dspSVX to dspDOC is being used...

	TODO: For now, leave the new ping times in effect.
	TODO: When an error dialog appears on a host, all other
	Modeless dialogs should be erased.
	TODO: Make another pass through Downlink protocol vs 
	"normal" error handling. Is this divided up correctly in
	all cases?

	Where are we?
	
	+Everything comes up in parallel with no errors.
	+Nodes can be shutdown and restarted and everthing reconnects.
	+Powerdown on a host recovers.
	+Powerdown on the supervisor process recovers.
	-Powerdown on the DSP does not recover properly.

	This is the best ever:

	Snapshot: niedProj-2003-07-28
	*****************************

July 29, 2003 (Tuesday)

	Remove debugging overhead in the whole package.
	Restructure Node and Downlink to eliminate recursion
	in favor of speed.

	Node.alt
		Preallocate downlinks.
		Get rid of ipNames table.
		Eliminate need to resassert notification events
		when a link goes down and comes up again.

	Downlink.alt
		Keep ip names local.

	TODO: Make the connectEvent loop part of Downlink
	rather than using the Node to poll for connections.
	The connect timeout has to be fairly large (5 sec)
	and we don't want to hang up the CON.

	TODO: Investigate message deadlock avoidance and 
	see how much performance hit it costs.

	TODO: Work on the dsp power off handling.
	(It works, but makes a mess.)

	TODO: Remove vestigal mtGetMessage stuff.

	TODO: Test Alltalk Api stuff. [Not required...]

	Snapshot: niedProj-2003-07-29
	*****************************

July 30, 2003 (Wednesday) HVS

	Deadlock unwinding is not needed for this application.
	The code is currently commented out. I suppose we should
	have a "mode" in class "Node"...

	Socket shutdown via handshake and flush is not needed.
	This is because we handshake every high-level transaction
	anyway unless we are abandoning the socket. A simple close
	is good enough. Symptoms to the contrary were caused by
	previous errors.

	When a node is closed, we have to use a closeList because
	closing the individual links causes them to do "self.close",
	which removes them from their activeList. But we want to
	traverse the activeList in order to close the sockets.
	This corrupts the list.

	TODO:
	Another occasion for this error happens when a link closes
	itself due to a socket error or timeout error. To deal with
	this case, we must defer removing the link from the activeList
	until the Node isn't traversing the list in the update cycle.
	
	The same solution will fix this problem and the older problem:
	The method for "self.close" in the link classes ask the parent
	node to remove them. This is done in Node by adding them to the
	closeList. The update loop for the node will traverse this list
	if necessary and remove all the values it finds from the active
	list.

	TODO:
	The same solution must be applied to the Coops side.
	
	A better way:
	
	List.alt
	List.c
		Modified to prevent race conditions when an element is
		removed during a #forAll.

	This cleans everything up! No need for closeLists or two-stage
	close operations. Code is smaller.

	All Node and Link classes:

		Get rid of special lists for close and shutdown.

	Test everything tried to date...
	It works!

	****************

	Now for the last Big Kahuna: Powering off the dsp...
	Our story so far:

	1) Powering off the host: Works.
	2) Powering off the supervisor.exe: Works.
	3) Powering off the DSP: Doesn't work.

	The symptoms:
	When dspX is shutoff (rebooted actually), the first to notice
	was CON. (This is by chance, more frequently, the hostSVX notices.)
	
	The CON reports that dspSVX is gone, then it reports that hostSVX is
	gone. This happens because hostSVX shuts off its node while recovering.

	But then:

		TBL reports an EOF on connection from CON.
		This occurs because CON didn't get a ping from TBL.
		TBL got a read timeout from it's DSP.
		Why did this happen?

		The table DSP had a connection to and from svxDSP.
		This connection will not get any pings from svxDSP
		and it may get an error sooner while trying to read
		a ping... Somehow, this error is crashing the TBL dsp.

	Finally, CON reports that the table host and dsp are gone
	due to ping timeouts.

	Two fixes were necessary:

	1) Install an "ignore" signal handler in VxWorks for SIGPIPE.
	This makes vxSocket act (almost) like winSocket.

	2) Raise the ping timeout and lower the ping interval. This
	make the net handle variable loads and still get some pings
	through. When nodes go down, they send a lot of messages to
	get going.

	The ping timeout must be larger because the messages
	that restart X slow down the network enough to cause the count
	to fall behind the clock. A 20% overhead fixes the problem.
	The 100 meg ethernet will probably fix this.

	vmSocket.c
		Ignore SIGPIPE.
		We need this because the Uplink will continue sending
		pings to a Downlink that has gone away. The Uplink doesn't
		quit until it gets a socket error. Maybe we need two-way
		pings? Arrg.

	Node.h
	Link.alt
		pingTime = 25
		pingTimeout = 2000

	Downlink.c
	Uplink.c
		Make the socket error scanning work exactly the same
		way as the Alltalk classes. This eliminated a lot
		of extra tests.

	Downlink.alt
	Uplink.alt
		Display more information when the socket state changes.
	
	TODO: Make the error displays use names instead of node numbers.

	**************

	Notes for psTools:

	psExec starts the target appliation, but in the wrong directory.
	We need to pass a parameter to tell the target that it has been
	started over the network.
	
	Example:

	psexec \\148.150.13.30 -i -d -u Administrator -p admin c:\niedProj\niedSVX.exe

	The parameters:

		-i 	Interact with desktop
		-d	Detach: Don't wait on this side for exit.
		-u	User name
		-p	Password

	psexec returns this status line to the calling program:

	c:\niedProj\niedSVX.exe started on 148.150.13.30 with process ID 292.

	We need to get this process ID from inside alltalk.
	**************

	Everything works except remote launch, which we don't have to do.

	This is pretty cool:

		Start the TBL and the Fg.
		Bring up a scope on X to see the waveform.
		Reboot dsp SVX!
		Wait a bit and the scope trace will return!

	Try the same thing by using the task manager to kill the
	supervisor.exe on host SVX:

	It just keeps on running!

	How is this done?
	The host SVX application will notice if either the
	supervisor or dsp fail. The dsp will automatically
	reboot if the supervisor fails. The supervisor will
	automatically quit if the host application fails.
	When the host sees either supervisor or dsp go away,
	it waits for the dsp to come back. Then it restarts
	the supervisor and reloads all the parameters.

	In the mean time, the Grand Connector has also noticed
	that host SVX and the associated dsp have gone away.
	Actually, the host is still there, but it hides from
	the connector while waiting for the dsp to come back
	and get reconfigured.

	When host SVX gets everything going, it makes itself
	visible on the net. The Grand Connectors sees host X
	come back and then reconnects everything.

	The scope panel has been running all this time, so
	it starts drawing the trace again.

	Quod Erat Demonstrandum.

	Snapshot: niedProj-2003-07-30
	*****************************

July 31, 2003 (Thursday) HVS

	Downlink.c
		Socket parameters for the asych socket were
		not set up correctly. As a result, there were
		extra flow-control events.

	Idea: Maybe the async connection should be async at
	the socket level. Make the buffers small and let the
	link go down when the write seeds an EWOULDBLOCK.

	TODO: In Alltalk, only one ModalDialog should be visible
	at a time. DONE.

	Experiment:
	Make the async connections async at socket level.
	Result:
	Everything comes up correctly except for TBL.
	The dsp side is rebooting for some reason...

	I raised the ping timeout in Coops from 2000 to 3000.
	The TBL came up ok.
	Then I tried the reboot test on svx dsp.
	The table did not reboot.
	This means that the async fix worked.
	
	So why the big ping timeout just to create TBL?
	SVZ takes longer, but it worked with the smaller timeout.
	This is a mystery...
	
	When we are creating TBL, messages are being turned around	
	constantly, so who is closing the connection to the dsp?
	It can't be the supervisor, so it must be Alltalk.
	
	Here is a possibility:
	Donwlink.c
		Did not reset last ping time when doing a lookup types.
		A lot of these happend during startup...

	Now try a pingTimeout of 500 with a pingTime of 25:

	It works! Can we do better? We are sending idle pings at 4 per
	second. It takes 5 seconds with no message to timeout. What happens
	if we make the number even smaller?

	Now try the connectTimeout: It is 5 in Alltalk but 2000 in Coops.
	Let's try 5 in coops as well...
	Works perfectly.
	Alltalk needs the short connect timeout to keep the CON responsive.
	Coops does not, so I left its connectTimeout at 100.

	Now for the read timeout. It is now 2000 (20 seconds) everywhere.
	Let's live dangerously and try one second (100)
	Too aggressive.
	Try 500...
	Too big...

	Node.alt
	Link.alt
		Add protocol to save and restore the default read timeout
		so it doesn't have to appear in two places.

	Try 1000...
	This works when only one node starts at a time, but network congestion
	makes it take longer.
	Back to 2000. Where does the time go?
	
	I decided to go with an asymmetric read timeout: Alltalk uses 1000 and
	Coops uses 2000. There is some kind of deadlock involved here, but I
	can't see where.

	Pulling off the ethernet cable and reconnecting inside the timeout 
	is ok... Leaving it off until we get the timeout seems to upset things
	more, but every controller comes back. The mystery is that the TBL had
	to restart as well. It may be that poking around trying to plug in the
	wire caused other problems. This needs study.

	Overall, it seem very robust.
	Time to get Medieval with the testing. I think I'll go get Rod...

	Doing demos for people uncovered some small issues:

	1) The DOC has an electrical problem: The firmware fails to load on
	a random card and after this occurs, rebooting the processor will
	not let the card operation. The console itself must be powered down
	and up again.

	Downlink.alt
		Added a cleanup event: Not for normal messages that go down,
		but for upward messages that could distrupt the Node update
		loop.

	ModalDialog.alt
		Erase any existing modal windows before drawing a new one.

	The path to Alltalk generated at startup is wrong for SVX, SVY,
	SVZ, but not for the CON. There must be some configuration statement
	out of step. The path on the SVXYZ's is to the local copy, not to
	the network copy.
	FIXED: It was the use of "browser.reset" instead of "browser.forget"

	TODO: Omar says: Put in the Japanese translation framework.

	Snapshot: niedProj-2003-07-31
	*****************************

August 4, 2003 (Monday) HVS

	More on pstools:

	The start directory problem is solved by using a batch file on each
	target system to run the controller. Example:

		REM startSVX.bat - Start niedSVX.exe
		chdir /D m:
		start niedSVX.exe

	To start a remote controller:

		psexec \\niedHost1 -i -d -u Administrator -p admin c:\startSVX.bat

	To stop a remote controller:

		pskill \\niedHost1 -u Administrator -p admin niedSVX

	The computer names are in the local hosts file.

	ZTestStartup.alt
	This script will demonstrate auto starting/stop the whole controller.
	It makes a mess with DOS windows on all the hosts.
	
	niedProj\bin\
		startSVX.bat
		startSVY.bat
		startSVZ.bat
		startTBL.bat
		startDOC.bat

		This are backups of the files that must be placed in the root directory
		of each host to autostart the controller GUI.

	niedProj\bin\
		psexec.exe
		pskill.exe
		
		These are the programs from the PSTools kit to start and
		stop remote programs.

	Network configuration checklist:

	1) Static IPs configured for the controller LAN.
	2) The hosts file contains all the host names and IPs.
	3) Autostart files in all the root directories.
	4) "M" drive mapped to the TBL host on all machines.
	5) Source installed on the TBL host.

	TODO: Should the "main" file server be CON instead?

	Before switching to new PCs:

	Snapshot: niedProj-2003-08-04
	*****************************

August 5, 2003 (Tuesday) HVS

	On the new hosts in the MTS nied lab.
	
	Windows 2000 Setup:
	
	Install driver for additional LinkSys ethernet card.
	Configure the windows GUI for non-obnoxiousness.
	Enable the FTP server on the TBL controller.


	Configure the PPC boot prom for the new HOSTTBL.
	The HOSTTBL servers software to all the PPCs.
	
	There is no need for an mts_rt account.
	This was an artifact of a defect in the WindowNT
	FTP server that was fixed long ago. Simply use
	anonymous/guest and you don't need another account.

	TODO: Revise Brad's how-to installation guide to
	reflect this (and other) changes.

	Setup the share for the niedProj on all machines:

		Share name: \\niedtbl\niedProj
		Drive letter: M
		Reconnect at boot time.

	Create the start icons for each machine.

	Edit Network.dat for the new numbers.

	Rebuild the apps.

	It works!

	TODO: Track down why the CON gets both a ping-timeout and
	and EOF notification. The first event should have closed out
	the Downlink...

	Partial answer: The CON may detect a DSP as down before the
	SVC does. In that case, CON will try to reconnect and may
	succeed before SVC notices and closes its node.

	This is not fatal, but it produces a confusing error message.
	To fix: Make the CON wait before re-issuing the connect request.
	Perhaps Downlink needs a deferred connect method. This would 
	use an event to delay the reconnect. Otherwise, the CON MainPanel
	would need data structures to keep track of the connect-defer
	events.

	Another way: The CON should really wait for both the DSP and
	the host to be ready. This should be done in two stages as
	is the case in the SVC hosts: First wait for the DSP to come
	back, then wait for the host to come back. Only then should
	the CON attempt reconnection. This gives plenty of time for
	the SVC host to stop its node as well.
	
	This sound reasonable, but first:

	Snapshot: niedProj-2003-08-05AM (subsequently removed)
	*******************************

	A simple delay before reconnecting in the CON MainPanel
	fixes the early connect problem.

	The second notice about EOF after a ping timeout occurs
	because the #notify method in CON MainPanel does a 
	node.connect on the same link. We are inside the update
	loop of the node, so the downlink gets added again. The
	socket isn't open, so we get the EOF notice.

	Downlink.alt
		Don't use the Node update event to repeat connection
		requests. It's too fast and bogs down the application.
		Instead, use a connectEvent inside Downlink.alt.
		This event drives the reconnect requests until one
		succeeds. Then the Downlink is added to the node's
		active list.

	Important: We must have: connectDelay >= pingTimeout.
	Otherwise, a remote node may not stop before a reconnect succeeds.

	Downlink.alt
	Node.alt
		Change the method for #connect so it defers the
		request. This lets us request new connections from
		inside #notify methods.

	This is P.F.M.:

	StartAll
	StopAll
		Shortcuts to command files:

	StartAll.bat
	StopAll.bat
		Command files to start the whole system from 
		any host. 

	/bin
		psexec.exe
		pskill.exe
		SysInternals commands to start and stop remote programs.

	Snapshot: niedProj-2003-08-05
	*****************************

August 6, 2003 (Wednesday) HVS

	Add utility software & VNC to all machines.

	Put VisualStudio on hostTBL.

	Reinstall everything on hostDLG. (The configuration was
	mangled during the first boot.)

	Node.alt
		Add protocol for #disconnect[targetNodeNumber]
	
	Downlink.alt
		Enable deadlock resolution for the demo.

	TODO: Dig up 469DUJ and make sure all the Japanese font stuff
	is ready on niedTBL.

	Snapshot: niedProj-2003-08-06
	*****************************

August 12, 2003 (Tuesday) HVS

	A discovery: The automatic startup does not work immediately
	after booting the hosts. This appears to be due to the connection
	limit on the niedTBL machine. Only 10 connections are allowed
	for "Windows 2000 Professional". To remove this limitation we
	would have to use "Server".

	The limit gets hit right away because the machines on the local
	lan are talking to each other trying to negotiate the smb 
	identification protocol for the local LAN. All the machines
	are in a workgroup, and they keep trying to elect a bus master
	for a few minutes. Everything works when they settle down.
	There may be a way to hurry this up by configuring TBL as
	a WINS server.

	Active Connections right after booting:

	  Proto  Local Address          Foreign Address        State
	  TCP    HOSTTBL:microsoft-ds   HOSTTBL:1028           ESTABLISHED
	  TCP    HOSTTBL:1028           HOSTTBL:microsoft-ds   ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    niedhost1.mts.com:1032  ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    niedhost2.mts.com:1031  ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    niedhost3.mts.com:1034  ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    hostdoc.mts.com:1028   ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    hostcon.mts.com:1028   ESTABLISHED
	  TCP    HOSTTBL:1030           niedhost1.mts.com:netbios-ssn  TIME_WAIT
	  TCP    HOSTTBL:1032           niedhost2.mts.com:netbios-ssn  TIME_WAIT
	  TCP    HOSTTBL:1034           niedhost3.mts.com:netbios-ssn  TIME_WAIT
	  TCP    HOSTTBL:1036           hostdoc.mts.com:netbios-ssn  TIME_WAIT
	  TCP    HOSTTBL:1038           hostcon.mts.com:netbios-ssn  TIME_WAIT
 	 TCP    HOSTTBL:1039           niedhost2.mts.com:netbios-ssn  TIME_WAIT

	We need a firewall to prevent this Sh... stuff.

	After 3 minutes:

	  Proto  Local Address          Foreign Address        State
	  TCP    HOSTTBL:microsoft-ds   HOSTTBL:1028           ESTABLISHED
	  TCP    HOSTTBL:1028           HOSTTBL:microsoft-ds   ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    niedhost1.mts.com:1032  ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    niedhost2.mts.com:1031  ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    niedhost3.mts.com:1034  ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    hostdoc.mts.com:1028   ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    hostcon.mts.com:1028   ESTABLISHED
	  TCP    HOSTTBL:1039           niedhost2.mts.com:netbios-ssn  TIME_WAIT

	Note the netbios connectionsto "niedhost1,2,3" These names should
	never have been in the MTS DNS. Some snoop has put our machines into
	the corporate DNS!

	After 2 more minutes:

	Active Connections

	  Proto  Local Address          Foreign Address        State
	  TCP    HOSTTBL:microsoft-ds   HOSTTBL:1028           ESTABLISHED
	  TCP    HOSTTBL:1028           HOSTTBL:microsoft-ds   ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    niedhost1.mts.com:1032  ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    niedhost2.mts.com:1031  ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    niedhost3.mts.com:1034  ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    hostdoc.mts.com:1028   ESTABLISHED
	  TCP    HOSTTBL:netbios-ssn    hostcon.mts.com:1028   ESTABLISHED

	At this point, all but one of our hosts can connect to TBL...
	The killer are the two snoop connection from hostdoc.mts.com.

	After 5 minutes, it works.

	Active Connections

	  Proto  Local Address          Foreign Address        State
	  TCP    HOSTTBL:microsoft-ds   HOSTTBL:1028           ESTABLISHED
	  TCP    HOSTTBL:1028           HOSTTBL:microsoft-ds   ESTABLISHED

	This is the "normal" state we must wait to achieve.

	The consoles will ship with this software:

	Snapshot: niedProj-2003-08-12
	*****************************

************************************************
*            At NIED (First Visit)             *
************************************************


2003-10-21 (Tuesday) HVS

	One of the modules in the Z 493 refused to start.
	The module was replaced and all is well.

	TODO:
	Switch the Y and TBL hosts boxes. The TBL host
	has a an extra CD writer.

	Put the Grand Connector on TBL.

	*************

	Some Zone Alarm configuration stuff remains active
	even when it is removed from the autostart folder.
	This kept my laptop from being visible on the 
	Nied lab subnet.

	Network.dat
	Put Grand Connector on the TBL machine.
	This is not so easy, because the names we use in the
	auto-start batch files use NetBIOS names of the computers.
	We need to start using the local hosts/lmhosts files instead.
	Then we can map the applications anywhere.

	On EACH host we have two operating system network-to-name
	mapping files:

	c:\winnt\system32\drivers\etc\hosts
	c:\winnt\system32\drivers\etc\lmhosts

	Here are the current settings:

	127.0.0.1       localhost
	148.150.13.30	hostSVX
	148.150.13.35	hostSVY
	148.150.13.37	hostSVZ
	148.150.13.32	hostTBL
	148.150.13.39	hostDOC
	148.150.13.41	hostDLG
	148.150.13.32	hostCON 

	148.150.13.31	dspSVX
	148.150.13.36	dspSVY
	148.150.13.38	dspSVZ
	148.150.13.42	dspTBL
	148.150.13.43	dspDOC
	148.150.13.52	dspDLG

	These numbers must agree with those configured in:

	c:\niedProj\network.dat
	

	Testing:
	Everything worked except the DOC, which has some hardware
	changes.

	Snapshot: niedProj-2003-10-21

2003-10-22 (Wednesday) HVS

	Switch the hosts for SVY and TBL.
	Install VC++ on the new TBL.
	
	The DLG was in bad shape.
	
	GuiDLG\MySystemDLG.alt
		Create this class to override the methods for:

		configureNode
		attachModels

		The idea is to use DLG wherever DOC appeared before.
		The DLG doesn't need to know about the other nodes,
		so these references were deleted.

	DLG is working.

2003-10-23 (Thursday) HVS

	Uplink.alt
		Missing element type code for short integer arrays: "H".
		The case for handling these was also missing in one
		method. I don't think niedProj uses this type.

2003-10-24 (Friday) HVS

	Worked on the safety system hardware with Rod.

2003-10-27 (Monday) HVS

	Rod and I completed the repairs to the safety system.
	Brad made many polarity adjustments in the digital I/O logic.
	

2003-10-28 (Tuesday) HVS

	Brad's new Scramnet driver is tested and installed.
	
	vmTBL.c
	vmSVC.c
	vmDOC.c
		Fixed a bug caused by removing the Simulink node.

	OutConnector.c
		Fixed a bug introduced by changing the method for
		#max so it would compile without error in the
		simulation.

	******************************
	Snapshot: niedProj-2003-10-28

2003-10-29 (Wednesday) HVS

	Brad updates some DIO polarities after Mitsubishi test.

	*******************************
	Snapshot before IP re-numbering: niedProj-2003-10-29AM

	We are switching the controller LAN to use the add-on 
	ethernet cards and also to use the un-routed private
	network 192.168.x.y: See details in Documents/LANConfiguration.txt.

	The network numbers need to be consistant in three places:

		c:\niedProj\Documents\LanConfiguration.txt
		c:\niedProj\Network.dat
		c:\winnt\system32\drivers\etc\hosts

	We also keep a backup of the hosts file in:

		c:\niedProj\Documents\niedHosts.txt

	Steps:

		1) Renumber the PowerPC eproms.
		2) Switch the ethernet connections to the hosts.
		3) Reconfigure the two ethernet cards in each host.
		4) Update the "hosts" file on each host.
		5) Rebuild the niedProj applications.
		6) Reboot the hosts to get the ftp server unscrewed.
		7) Test.

	Done.
	Everything works but the auto starter.
	This thing may need lmhosts to work properly.
TODO:	Put in lmhosts and test autostart again.

	The scope has a hesitation every 3 seconds.
	This may be due to network activity on the PPC.
	
	Try #1:
		Change the nodeTimeout from 1 to 2.
	Result:
		The PPC process loads went down about 4%.
		Turning on & off the converters made a MUCH
		bigger difference.

	Try #2:
		Switch from the optical link to the 100Tx 
		ethernet connection to the basement.
	Result:
		It seems a little slower this way.
		The result is not conclusive.

	Try #3:
		Change the nodeTimeout from 2 to 4.
	Result:
		No difference.

	Try #4:
		Change the nodeTimeout to zero.
	Result:
		No difference.


2003-10-30 (Thursday) HVS

	It turned out to be the extra connections left over from
	interconnecting the dsps on the Scramnet.

	By closing all the downlinks on each dsp, the problem goes
	away.

	GuiCon\MainPanel.alt:

		In each method that interconnects two nodes, an 
		expression like the one shown below was added:
		
		node.lookup[dspNodeSVZ, 'node'].downlink[dspNodeDOC].close

		The code was also rearranged so the wait notifier doesn't
		appear unless both nodes are ready to connect.

	Uplink.alt
		The constant maxArray was redefined here, overriding the
		value in Link.alt. This was removed.

	Link.alt
		The value of maxArray was increased from 8192 to 16384.
		This is an experiment.

TODO:	Node.h
	Link.alt
		The value of nodeTimeout remains zero.
		Is this what we want?

	We find out that we may need 64 DAQ channels. That is a
	bit much for one LAN if it has to run on every node.

	Brad did several modifications to the data acquistion
	classes. I don't know exactly what has changed...

	The MHI accellerometers want 24 volt excitation.
	They appear to be defective, but we are only supplying
	20 volts.

	
2003-10-31 (Friday) HVS

	Brad changed the recording buffer size to 8192.
	By limiting this buffer size, the overall performance is
	greatly increased.

	We were able to record 64 channels at 1000Hz on all the
	hosts at the same time. Then we added two channels of
	scope on every host. It still worked well.

	Finally we tried the Grand Connector with all this running.
	It caused a timeout after nearly all the connections were
	made. 

	This suggests that we can max out the recorder as long as
	the connections are all completed first. This is the normal
	state when all the hosts are operating.

	Alltalk currently has a limitation of 40,000 bytes per 
	record. This gives us a little more than 8192 floating
	point samples per record when recording files.

	The independent controller was tested and seems to work
	well. (IND) 

	IMPORTANT: You cannot run the DOC when the IND is running.

	*******************
	Snapshot: niedProj-2003-10-31

	End of visit to Miki.


*****************************************************************
NIED fixes:  Sent 28-Nov-03, but not installed until 05-Jan-04 trip


	#1

	Problem:  In local mode, clamping would work, but unclamping would cause the
	s/v commands to go to zero.

	Fix:  The C interface to the clamp ramping fg "Ramp.c" has changed since the
	prototype project, yet the Alltalk interface has not.  Problem was setting
	the "offLevel", which in Clamp.alt would do a remote.setLevel[], but with
	the current version of Ramp.c should do a remote.setMax[] instead.

	Noticed another potential bug in method setInterval of Clamp.alt--- if you
	put in a zero interval, you get a divide by zero error.  Fix was to change
	the clipping to not use the intervalAttr (which was worthless anyway) and
	instead make sure interval is never less than one sample interval.

	Also took the opportunity to fix nomenclature inside of ClampPanel.alt---
	used to refer to "vm" and "vmDev"; change to "clamp" and "clampDev".


	#2

	Problem:  Changing clamp level would have no effect unless you saved settings,
	quit, and restarted.

	Fix:  There really wasn't a problem.  The bug in Problem #1 could cause such
	weirdness that by starting over the problem could seem to go away.  Also,
	the clamp level is not used until a clamp event occurs--- the effect of
	changing the clamp level will not be seen until the next clamp event occurs.


	#3

	Problem:  Servovalve controller come up in Remote mode when the table
	controller is not running.

	Fix:  Changed polarity of remoteSvcDI bit in SvcDio.alt from high to low.


	#4

	Problem:  Cannot allow the TBL or IND fg to start when there is e-stop
	and MHI Stop 1, 2, or 3. Also, in TBL, cannot run when in PARK position.

	Fix:  Add to method runOkay in MainPanel.alt checks for these digital
	inputs.  In TBL's method runOkay, also check for park and static lift
	conditions.  To facilitate system checkout, these checks are not
	performed unless hydraulics is on.


	#5

	Problem:  In remote mode, individual s/v commands go to zero, regardless
	of clamp state.

	Fix:  In method disconnect in DiagnosticFg.alt, there was a section of
	code from the original prototype project that reconnects the external
	command that was commented out with a comment "TBD", because the code
	was no longer valid with the new software.  So in remote mode the connection
	between the command input and the individual s/v commands was not getting
	done.  Changes:

	ActChannel.alt method commandInput:  Delete as no longer necessary.
	DiagnosticFg.alt methods connect and disconnect:  Extensive changes.
	vmSVC.c:  clampInp[i] (which is a 2-input Mixer) is now being used as
		a switch:  TBL/IND controller output connects to input "inp"
		as always, but diagnostic fg "ufg" connects permanently to
		all clampInp[i] instances.  Gain 0 and gain 1 terminal inputs
		of clampInp[i] are used to switch between "inp" and "xinp".


*****************************************************************
NIED trip 05-Jan-04 to 10-Jan-04	BKT


	Incorporation of Rod's fixes of the last several months:

	* Get rid of Translate Text<->Binary--- causes network timeouts on long files.
	* IND & TBL VirtualMachine:  Rod moved location of dio.stopDO.forAll[#clear]
	in method  resetIntlks, and he fixed erroneous methods hydraulicsHi and hydraulicsLo.
	* IND & TBL MainPanel:  Lots of hydraulic logic changes by Rod.  I streamline this
	considerably.


	MainPanel method attach for all controllers do a vm.resetIntlks so that when
	the software comes up, the desktop LEDs light up.

	When TBL or IND drives SVC at 1024 Hz, the lead compensation of the 4th stage
	controller causes huge spikes because it runs at 2048 Hz and thus every two samples
	are identical.  Fixed by adding upsamplers to servovalve controller command inputs.
	Changed:
	* vmSVC.alt:  Added upsampler "cmdfoh".
	* GuiCON MainPanel.alt:  Connect to cmdfoh rather than clampInp.
	* GuiSVC VirtualMachine.alt:  Add to method init:
		proc.seqLo.setDependents[UpSampler]
	* GuiSVC Actchannel.alt:  Added ivar "cmdfoh" of class Upsampler.
	* GuiSVC aadefine.alt: Include "Upsampler.alt"

	NOTE:  The first fix for the above problem was to reduce SVC's sample rate from
	2 kHz to 1 kHz.  But after tuning serveral servovalves, I felt that it was slightly
	more difficult to tune at 1 kHz rate as opposed to 2 kHz.  So the sample rate was
	restored to 2 kHz and upsamplers added.

	MySystem method linkChanged used to automatically restart the supervisor or dsp
	if it crashed.  This is probably not a good idea because we should know if such
	a thing occurs.  Added code to this method to throw a dialog then quit the application.

	Used SUNY BSP vxWorks & vxWorks.sym that has increased heap space. Increase heap space
	from 10M to 15M.  Doubled size of data recorder buffer from 1M to 2M.

	For some reason, the 4th-stage loops have bad tuning. They do not have the same FRFs
	that they did in Minneapolis.  Perhaps it is because when the valves are installed
	on the actuator they behave a little differently than when they were on the flow bench.
	Or different cable lengths?  Verified that ValveCtlr.c used in niedSVUProj that was
	used to tune in Mpls. is the same as used now except the addition of a reset integrator,
	so it is NOT a controller difference that is causing the tuning difference.

	The changes to niedIND.exe to streamline the hydraulic logic were not installed
	as of 10-Jan, because of lack of opportunity to try them out.  The new niedIND.exe and
	the source code GuiIND is in a folder "NewSoftware", to be tried in the future.

	Noted that SVC data recorder rates and spectrum analyzer sample rates max out at 1 kHz
	rather than 2 kHz like they should.  Added code to GuiSVC aadefine.alt to double the
	standard rates defined in GuiCom constants.alt.  You must also edit the SVC settings
	files to remove the reference to tfe ivar "rates".

	While tuning one day, I saw 3 Scramnet errors on SVX (redundant Tx/Rx fault) within
	a span of four hours.

	POSSIBLE BUG (look into on a future trip):
	*  When software is first started, clamping and unclamping from IND does not cause
	the clamp display on the SVCs to change.  Found out this was because the estop chain
	had not been reset, so all digital outputs were unpowered.  After resetting, it worked
	fine.  THIS IS A HARDWARE DESIGN FLAW, not a software problem.

	Tuned X1, X2, X3, x4, Y1, Y2, Y3, Y4, Y5.  Did only a cursory tuning on X5 because
	it had a leak and was to be repaired the following week, and so would need retuning.
	Shu tuned Y1 & Y2, and I tuned the rest.

*****************************************************************

2004-05-18 (Tuesday) HVS

	Uplink.alt
		Add a metaclass method for #update that sends 
		the update message to all the instances. This
		is used to prevent ping timeouts when time-
		consuming methods block normal Event loops.

	MySystem.alt
		Do Uplink.update from the #yieldTime method.
		This prevents ping timeouts when restoring
		the settings.

2004-05-19 BKT  Problem list and resolution:

	1) Restoring settings on SVC cause Grand Connector light to go off.

		Added Uplink.update to GuiCom\MySystem.alt method yieldTime.
		Added metaclass method update to CoopsNet\Uplink.alt.

		Timeouts may still have to be changed to cope with programs
		other than Alltalk, or large file transfers.

	2) Change Win2kSetup.txt to show how IIS is really set up.

		Made new document "Software Installation Procedure.txt".
		Delete old document "Production Setup Win2k.txt".

	3) Put software on individual hosts to prevent hostTBL overloading.

		Software moved off to individual host PCs.  PowerPC boot rom
		host IP parameter changed to reflect this.

		New policy regarding sources:  No sources of any kind to be left on the
		machine.  When needed, copy GUI sources to host PC as described in
		"Software Installation Procedure.txt".

	4) SVC should not allow restoring settings or calibration file except in local mode.

		Added conditional to GuiSVC\MainPanel methods restoreSettings
		and restoreCalibration.

	5) Remove autostart software.
		Done.

	6) Reprogram DOC boot eeprom.
		Done.

	7) Starting up systems in other than the standard order causes SVC problem.
		Done.
	
	8) Resolve Alltalk font issue.
		Done.


2004-05-19 HVS
	
	CoopsNet\Link.alt
	CoopsNet\Node.alt
	CoopsNet\Link.alt

		The CoopsNet package has been updated to permit dynamic tuning
		of all the timeout parameters. This is done through the metaclass
		protocol:

		Node.setTimeout[index, value]

			Set the selected timeout value

		Node.timeout[value]

			Return the selected timeout value

		The index is used to select the parameter:

			n_readTimeout    := 1,
			n_writeTimeout   := 2,
			n_connectTimeout := 3,
			n_asyncTimeout   := 4,
			n_pingTime       := 5,
			n_pingTimeout    := 6,
			n_max		 := 6

		The default values are:

			readTimeout     := 1000,  ! Read timeout
			writeTimeout	:= 1000,  ! Write timeout
			connectTimeout  := 5,     ! Connect timeout
			asyncTimeout	:= 100,   ! Asych connect timeout
			pingTime	:= 25,    ! Time between sending pings
			pingTimeout     := 500    ! Link idle timeout

	AppCon\Generic.dat
		
		Add selectors for #timeout and #setTimeout to match
		the Alltalk versions.

	CoopsNet\Node.c

		On the coops side, the protocol is also implemented in
		Node.class:

		setTimeout(Node, index, value)

			Set the timeout value selected by the index.

		timeout(Node, index)

			Return the selected timeout value.

	CoopsNet\Node.h

		Define the index values with the name names used
		on the Alltalk side.

	GuiDLG\MySystemDLG.alt
		
		Use the new protocol for setting the read timeout.

	GuiCOM\MySystem.alt

		Use the new protocol for setting the read timeout.

2004-05-20 HVS

	Alltalk\
		Updated to version 2.985.
		- Improved socket timeout behavior.
		- More portable fonts. (Works in Japan.)
		- Created with new compiler: VisualStudio 7.1

	
	vxSocket.c
	winSocket.c
		Improved socket timeout behavior.

2005-02-23 HVS

	The change log has not been maintained since May 20, 2004.
	The changes listed in this section only cover the period
	between now and the January 2005 visit.

	GuiCON\MainPanel.alt
		
		In the method for #update, remove the comment that
		was used to disabled updateDimension

		In the method for #updateTBLtoDOC, add a test
		so the code will not crash if the vmDOC and vmTBL
		are not ready.

	GuiIND\MainPanel

		In the method for #update, disable reporting
		of the "MHI hydraulic shutdown." It has been
		reported to cause problems. I did not have time
		to investigate on this visit.

		In the method for #checkStop, perform vm.reconnectDrv
		if the vm.driven was disconnecte for preview.

	GuiTBL\MainPanel

		In the method for #update, disable reporting
		of the "MHI hydraulic shutdown." It has been
		reported to cause problems. I did not have time
		to investigate on this visit.

		In the method for #checkStop, perform vm.reconnectDrv
		if the vm.driven was disconnecte for preview.

	C:\MTS Archive
	
		This directory contains assorted ilth I collected from
		the desktop and niedTBL folder. Please review this
		when you're hear and throw away what you can.

	C:\NIED Archive

		This directory contains assorted ilth I collected from
		the niedTBL folder. I believe it is data that might
		belong to the NIED or MHI people. Perhaps they will
		thrown these things away when appropriate.

2005-06-23 (HVS)

	The changelog has not been maintained since Feb 23, 2005
	There have been several undocumented changes that attemped
	to fix host timeout problems when downloading settings files.
	Most of these efforts were misguided.

	We now believe that the downloading process in several
	key classes never properly yielded time at all. This
	set of changes address this problem in two ways:

	1) The classes that didn't yield time in their #download
	methods now do so correctly.
	2) Some very large downloads have additional system.yieldTime
	messages.
	3) The method for #yieldTime in MySystem has been revised to
	use the clock, rather than a counter. See details below.

	Maicx.alt
		Add a method for #downloadElement. Change the
		#download method to use this so time will be
		yielded through the super.download between
		each element.

	Matrix.alt
		Add a method for #collect.
		This method is used by the Maicx to download MaicxElements
		with better time sharing.

	MySystem.alt
		Change the method for #yieldTime so it uses real time
		rather than an arbitrary counter. Constants for tuning
		this were introduced. The best values need to be found
		by experimentation, but the current behavior is reported
		to be "much faster."

	GuiSVC\Table.alt
		The method for #download was modified to do a 
		super.download.

	GuiTBL\Table.alt
		The method for #download was modified to add several
		explicit system.yieldTime expressions.

	Uplink.alt
	Downlink.alt
		Code was added as overflow protection for the timeout.
		Some of this turns out to be unnecessary. It should be
		removed in a subsequent revision.

		New class variables:

			yieldTime := 100

		This is the time in 1/100 sec tics between yields
		to the watchdog and network.

	Link.alt
		Add definition for timeModulus. Part of the timeout
		overflow protection.

		The pingTimeout in this this class is probably absurdly
		too large, but I was afraid to change it and not be at
		NIED for testing. Maybe we can fix this later.

	***********************
	Outstanding issues:

	Some error reporting code was commented out in the
	MainPanel for the table controller. This was done because
	of "lockups" reportedly due to a race condition. This issue
	needs to be explored.

	Yutaka couldn't boot the DOC but no hardware errors were
	reported. He had to run up and down the stairs 15 times
	swapping cards until the problem was fixed. The software
	normally reports the card identity when a failure occurs.

	The old pingTimeouts are still in effect. They effectively
	prevent any reasonable action when a host crashes because
	the timeouts are very large. This needs retuning on site
	in light of the successful changes made this time.

	Backup: niedProj-2005-06-22

	An experimental version of the code was created for
	Fuku so he could demonstrate and document the controller.
	It allows all the hosts to run and interconnect on the
	PC with no hardware. The scramnet is simulated.

	The simulation update also contains serveral fixes so
	that DIO doesn't prevent the simulation from running.
	These changes should be safe to merge into the offical
	controller, but I was afraid to send them to Yutaka
	when I'm not there to test them. This version of the
	software is:

	Backup: niedProj-2005-06-23x


************************** BKT visit May 2005 **************************

Windiffed master source with machine source.  Found these differences:

	Startup scripts startDLG/DOC/SVX/SVY/SVZ/TBL on DLG/DOC/SVX/SVY/SVZ
	machines were old versions that did not have the fix to prevent
	three-stage valve burnout.  The versions on TBL were correct, however.
	This is a serious oversight!

	CoopsNet Downlink.alt, Link.alt, and Uplink.alt were different;
	new versions anded system.tics with "timeMod"; "pingTime" and
	"pingTimeout" constants were different.
	Probably should leave this alone, or just use the bit-anding but leave
	the constants unchanged.

**	Documents BadScramCables.txt, ChangeLog.txt on machine were out of
	date, and NIED Hosts.txt in master source was out of date.
	No effect on software.

	GuiCom Maicx.alt, Matrix.alt, and MySystem.alt in master source
	had update to cause yield time to system during download to prevent
	watchdog timeout.  These were not present on machine.

	GuiCom MySystem.alt method download in master source has data recorder
	fix whereas machine source does not.

**	GuiIND MainPanel.alt method update and VirtualMachine.alt method run
	have comment differences.  Master source has better comments.
	No effect on software.

	GuiSVC Table.alt method download on master source does a super.download
	that is missing in the machine source.  Not an important difference.

**	GuiTBL MainPanel.alt method update and VirtualMachine.alt method run
	have comment differences.  Master source has better comments.
	No effect on software.

Since the above items marked ** have no effect on software, the master and
machine sources were brought into alignment immediately.

NOTE:  The ModalDialog.alt problem where the restore settings dialog won't
erase if there is a window focus change does not appear to be a problem
in NIED.  The Alltalk Views that NIED uses seems to have lots of differences
from that used in seismic.  So don't change out ModalDialog.alt.


First round of fixes (get this approved by MHI/NIED):

1) On DLG/DOC/SVX/SVY/SVZ machines, replace old PowerPC startup scripts
   startXXX.vxc files with new ones that prevent three-stage valve thermal
   failures when software is shut off and power is left on.

2) Change GuiCom MySystem.alt to fix two problems:
   a) Smarter system yieldTime to speed up downloading settings files while
      preventing spurious watchdog trips, and
   b) Fix to data recorder problem where settings file restoral while
      the data recorder is running causes the controller to freeze up.

3) To prevent spurious watchdog trips when restoring large AIC matrices,
   add improved GuiCom Maicx.alt, Matrix.alt, and MySystem.alt that yield
   time to the system when downloading.

4) Add missing super.download to GuiSVC Table.alt method download to bring
   it into alignment with standard programming procedure.

*************

Step fg bug:  Get a "(Ufg) Unknown shape." error message when hitting Run.

Problem was that StepFg.alt method attach statement
	
	remoteMeta := node.lookup[supNode, 'Ufg']

was returning NIL, so the table wasn't getting downloaded.
This was because "Ufg" was not in the supervisor's lookup table.
Solution is to add this statement to configsup.c procedure supClassExport():

	add(node, "Ufg", Ufg);	/* for stepped sine fg */

*************

Restore of settings in Basic access level:  If the default directory is
changed by navigating to a different directory using the Data Recorder
(for example), then selecting one of the four settings files causes a
file not found error.  This is because MySystem method restoreSettings
assumes that the input parameter "fname" was formed using the FilePicker
and hence has a valid directory prepended to it.  When the SettingsDialog
is the source of fname, then there is no prepended directory name, so the
assumed directory is the current directory, which might be anything.

Solution is to add a method "restoreSet" to MySystemTBL, which checks if
the current mode is Basic, and if so, prepend startDirectory to the
file name.  Then super.restoreSet is called.

*************

Preview in External Analog clears Run Enable bug:

To MainPanel method update added:
		
	! NOTE: MHI's controller logic is inflexible and they cannot stop
	! a preview request even though it is not allowed in displacement
	! mode.  So the following logic will cause the request to be ignored.
	runRequest := dio.runRequest
	IF (vm.dimension = displDim) AND (runRequest = 2) THEN
		runRequest := NIL
	END IF

so that the preview request is completely ignored.

However there is still a problem that after the ignored request, the preview
button gets activated.  This is fixed by adding the following to MainPanel
method setRun with v = 1:

	Change
		IF vm.stopped THEN
			run.get[2].setActive[TRUE]
			run.get[3].setActive[TRUE]
		END IF
	to
		IF vm.stopped THEN
			run.get[2].setActive[vm.dimension <> displDim]
			run.get[3].setActive[TRUE]
		END IF

This is a bug that exists in all seismic projects but has never occurred
for some reason.  It occurs in this application because run.setValue[1]
is called from MainPanel method update from the following code:

		! respond to program preview and run requests from MHI
		IF runRequest THEN
			IF dio.runEnDO.value THEN
				run.setValue[runRequest]
			END IF
		END IF

with runRequest = 1 (stop).

*************

In GuiTBL\aadefine.alt, forgot to tell FrfPanel and IrfPanel to show the multichannel
grid display.  Fixed by changing ".init" to ".init[nTbl]".

*************

Added Hugh's new Downlink.alt, Link.alt, and Uplink.alt, which are different than
the old ones in the following ways:

Downlink method update:
	Changed
		ELSEIF (system.tics - lastPing) > pingTimeout THEN
	to
		ELSEIF (system.tics - lastPing).and[timeMod] > pingTimeout THEN

Link.alt class vars:
	Added
		timeMod := 0xFFFF ! Modulus to prevent negative time

Uplink method update:
	Changed
		ELSEIF (system.tics - lastPing) > pingTimeout THEN
	to
		ELSEIF (system.tics - lastPing).and[timeMod] > pingTimeout THEN

All the timeout parameters in Link.alt were left the same--- didn't want to risk
screwing something up.

*************

Bumped up version of niedTBL.exe from 1.0 to 2.0 in GuiTbl\constants.alt

*************

Tried starting in random order.  Valve drives to TBL were NOT zero as Rod says
when you start in random order!  Was not able to run hydraulics so this test was
not definitive, but it is likely that starting in any order is okay.

