Testing multi-threaded applications can drive anyone to drink. Modifying Tymeac, without an IDE to single step code,
is a guarantee to
failure. Even with a good IDE there are storage areas of interest to developers
during execution that cannot be displayed by the IDE. (Before object-oriented
you could get the address of the storage area you needed and go peek at what was
in memory or get a core dump and spend your life with a hex calculator.)
The client directory contains classes for general purpose. Anyone can look at
what stage the thread are in, how many of these and those have happened. But
what we really need to know is the internal status of the environment. That is,
what does a Queue Area look like, right now. How many sync/async requests are
active and what are the details of each.
We also have a few quickies to modify the DBMS tables (delete, insert,
retrieve.)
The Tymeac management modules are all in
com.tymeac.base.
Tymeac accepts a client request syncRequest() / asyncRequest()
Tymeac creates a RequestDetail object for the request and saves it in
the RequestHeader detail list (ConcurrentLinkedQueue.) Each client request
returns a pointer to the newly created RequestDetail object. The purpose of these objects is to hold the information necessary to
track the request and to recover from exceptions. When the current request finishes, Tymeac frees the RequestDetail.
To free the object, Tymeac sets the status of the RequestDetail to 64 and removes the RequestDetail from the RequestHeader
ConcurrentLinkedQueue. This should be the last live reference to the object so
garbage collection may proceed. Since remove() doesn't remove the element
immediately, iterating the list returns these freed objects. Eventually, the
freed objects disappear.
Prior to release 5.3, Tymeac used a home-grown method of managing the
RequestDetail objects. When each RequestDetail was free, it was reused saving
allocate/de-allocate overhead. The garbage collection algorithms are so good
today, the home-grown method is no longer efficient.
The RequestHeader contains methods to iterate the detail list, add and remove
elements.
SyncRequest()'s time-out. After a very long
interval, Tymeac will free the RequestDetail.
AsyncRequest()'s stall and may be manually freed by
an administrator.
Tymeac places the pointer to the RequestDetail object into a wait
list (Class WaitLists) in each Queue required by the Function. The threads
retrieve that pointer to process the request. Waitlists arrays for the pointers
are actually ConcurrentLinkedQueue<RequestDetail>.
Tymeac then MAY inform a thread on each Queue (Class AreaHeader) to do the
work. (When threads finish processing other requests they look in the wait lists
for more work.)
Each Queue has one or more threads but they are not the
traditional "thread pool" type. The Queue contains a Class, AreaDetail, for each
thread so Tymeac can manage each thread individually. This is the big difference
between Tymeac and the concurrent utility Thread Pool classes.
Think of thread
pools as a pool of sharks swimming around looking for prey. You wouldn't want to
venture into that pool. Tymeac's Queue Threads are well-behaved, leashed threads
that fetch prey, consume it and then return to the corral all under the watchful
eye of the Tymeac Monitor.
- When no thread is working,
Tymeac starts a new thread.
- When a thread is 'waiting for work', Tymeac uses a Condition.signal() to wake up the thread.
- For the steps Tymeac uses to inform
the thread, see method AreaHeader.schedule().
Tymeac waits for all the Queues to finish for syncRequest() and passes back
the Object[] to the caller or returns immediately for asyncRequest().
Additionally, for asyncRequest(), Tymeac may schedule an output agent (new
asynchronous process) when the original processing completes.
Of concern to developers are the internal arrays Tymeac uses to process the
requests.
AreaHeader -- Queue data and pointer to Wait Lists
AreaDetail -- Queue Threads (one for
each thread)
RequestHeader -- Requests array (anchor point for details)
RequestDetail -- Request data
The main Tymeac interface is TymeacInterface. Implementing that interface is
TymeacImpl. The implementation contains a method diagnose(). You can put
anything in there you want. Naturally, you must also add code to the Tymeac
classes you want to look at. What is in there now is code to display (System.out.println)
the contents of the various arrays. These display on the Server window since
they run in the Server JVM. The clients display an 'ok' message.
For example: to display all sync requests currently in the system, the client
fills in the Class TyParm (String, int, int, int) by setting the first two int's
to 1, 2 respectively. The client calls the Tymeac Server diagnose() method. The
diagnose() calls the RequestHeader object like so:
request_tbl.dsplyActiveSyncDetails();
diagnose() returns an OK message to the client. dsply...() prints the
list of active sync requests on the console window such as:
Total ALL Slots in use = 160, SR Slots in use at first scan = 50, total requests handled = 2000
Next
Detail
In=000000000000000000 Na=2 #Q=2 Now=1 Next Output=1 Backout=false Waittime=20000
Status=1
What this means for a sync request is:
- Total slots is the total RequestDetail objects in the RequestHeader
ConcurrentLinkedQueue. These are the Sync, Async and the freed objects mentioned
above (status=64.)
- Total requests handled is just that.
- ...In use at first scan is the total busy details Tymeac found by
enumerating the number busy. Since there is no locking, when Tymeac prints the
busy elements (below) the number may change.
- When the count is zero, Tymeac says so and terminates. Otherwise Tymeac
prints each busy detail. Tymeac starts at the beginning of the array and
prints each busy entry as it finds it. Since there is no locking, the number
of printed entries may not match the above first scan number.
- Next Detail is just a marker between details.
- In= is the input to the request using method: toString().
- Na= is the sequence number of this request starting at one (1).
- #Q= is the total number of Queues for this request.
- Now= is the number of Queues still to process. If the total is 3
and Now= 1, then two finished and one is remaining.
- Next output= is the next available subscript to put a return object
from a Queue Thread. The return of your Processing Application Class may be an
object. Tymeac saves all the objects from all the Queues in the request and
returns that array to the client. Tymeac puts the return object into an array
of objects using an AtomicInteger starting at zero (0). Next Output is that
integer. For the above, the integer is 1. This means that element 0 was used
and 1 is next.
- Backout= true, the request timed-out or was cancelled. false
otherwise.
- Waittime= The time in milliseconds this request will wait for all
Queues to finish.
- Status= This is an integer. See RequestDetail for the values. (1 is
busy)
Remember -- Tymeac does not use locking to gather this information.
The in-use-at-first-scan may be one and two details may print or no details may
print or anything else. Even the information contained in each detail may have
changed since it was fetched and printed.
Displaying this information for an active system may be useless. We use it
when we think there are timed-out requests or when the system is quiet and we
use the Overall_Display and it says there are
active (a)sync requests. So, we run this diagnose() to see what is going on.
To use the supplied clients, duplicate any of the supplied client access scripts and change the class to
execute from com.tymeac.demo... to com.tymeac.test.?? where ?? is as follows:
TyDisplayAreaAAAA (AAAA - DDDD and Notify) these are the supplied
demonstration Queues Alter these as necessary for your own Queues.
TyDisplay??table -- Where ?? is AR for the async RequestDetail elements, SR for the sync
RequestDetail elements
and STALL for the stall array.
TyDisplayFUNCtable -- To display the current functions. (similar to the
client display but displays all the functions in the system)
TyDisplayFUNCques -- To display the current functions with their queue names.
You can add anything you like here without impacting Tymeac.