[Setools] Mercurial

2007-05-27 Thread Keith Hodges

Gjallar Folks,

I have been struggling to commit my changes into the mercurial 
repsitory. I discover that this is because i dont really know how 
mercurial works.


I found this:

http://hgbook.red-bean.com/hgbook.pdf

and there is a video on google video about it.

cheers

Keith
___
Setools mailing list
Setools@lists.squeakfoundation.org
http://lists.squeakfoundation.org/mailman/listinfo/setools


[Setools] Gjallar and latest seaside code submitted

2007-05-28 Thread Keith Hodges

Dear All,

I am pleased to announce that the building script can now run without 
human intervention needed. It auto-answers any questions that packages 
may ask on installation.


With a little help from Installer, the script has been written without 
any variables, so as to be easily runnable in a workspace, bit by bit or 
as a whole. This is a really good resource to have in a workspace, for 
quickly updating packages if they change, simply select the lines in the 
script for that package and execute them. The script is (hopefully) 
readable enough for you to get a good idea of the context of each 
package, the order of install etc.


To run the script from the command line, instructions are given in the 
Readme files in dist/scripts


My working repository for the gjallar build scripts is being served at: 
http://squeak.warwick.st:8002/newgjallar


On demo.gjallar.se, there is a built image in 
/home/gjallar/keith/gjallar , this working copy is a clone from 
hg.gjallar.se + a pull from the above repository. When we are satisfied 
with the scripts the push can be made back to hg.gjallar.se.


Minor Bug: The script sets the seaside/config user/password to 
seaside/seaside


At present the build from the scripts, includes the latest seaside, but 
not a Gjallar release that can use it. This is because the script loads 
the most recent gk edition, you will need (or need to merge) the latest 
kph version from the MC repository.


I hope that is enough to get everyone started with Seaside2.7a1 latest

best regards

Keith

--

From Q2v0.4-kph.263

(found the missing methods - the men in white coats had them)
WADispatcher allInstances
- Q2Session initialize callse super
- Q2Canvas has key and allocateKey, I couldnt see any reason why these 
should be in WACanvaRenderer
- WAAnchorTag text: deprecated in favour of with: (silly I think but 
this gets rid of the red deprecated sign in the tool bar)
- WATagBrush-tabIndex is now included in Seaside, recategorised this 
method as an override see method comment for details.
- Added Q2MacOSSwishEWrapper, www.darwinports.com installs at default 
path of /opt/local/bin/swish-e


- Added 'Magma seaside' has potential for the future.
- Added Q2MagmaLocalLocation being a database location that is defined 
in the ini file, thus being chooseable but not editable in 
seaside/config whereas MagmaLocalLocation represents a database 
configurable by setting the path, as can be set in seaside/config.


Although Q2Session ignores the WAMagmaConfiguration setting but 
MagmaControl panel can use it to access the gjallar repository since it 
knows nothing about gjallar.


___
Setools mailing list
Setools@lists.squeakfoundation.org
http://lists.squeakfoundation.org/mailman/listinfo/setools


Re: [Setools] Introduction

2007-06-09 Thread Keith Hodges

Hello All,

I was dissappointed when we decided to remove images from the main 
gjallar repository, so I have been seeking a solution.


For managing gjallar images with mercurial I have attempted to use 
mecurial queues but this was not really workable. Instead I have been 
successfully using nested repositories.


To set this up,

You clone the main repository as usual.
so the gjallar/.hg directory is the repository.

Then in the dist directory where you are typically working you 
initialize a second repository.


hg init

then you

hg add Gjallar0.4.image
hg add Gjallar0.4.changes
hg commit

these are added and committed to the new inner gjallar/dist/.hg repository!

So when you want to make changes to the outer repository just cd .. , 
into the outer gjallar directory and make your changes 
adds/updates/commits/push/pulls from there


This scheme theoretically allows you to commit a snapshot of your image 
and also the database state if you add that as well. You can of course 
return to any previous snapshotted state, and I dont think it uses as 
much disk as having lots of images as per my usual practice. Its great!


Keith
___
Setools mailing list
Setools@lists.squeakfoundation.org
http://lists.squeakfoundation.org/mailman/listinfo/setools


[Setools] Re: MagmaReadStrategies

2007-06-14 Thread Keith Hodges

RESEND slightly more recent version of previous mail


Hear is an outline of my readStrategy creation/management/understanding
scheme!

enjoy

Keith

=
buildReadStrategyAggressiveOn: strategy

Very highly aggressive read everything unless it is gated.

This analogy uses the idea of attempting to collect information from a 
guarded space,
perhaps a normal KEEP describes the scene. (OT: What a cool name for a 
database!)


Essentially this is how it works, whatever you can see you can have.

BIG GATES (typically -20)
Stop everything except what is explicitly visible through a KEYHOLE
- MagmaCollections are natural gates,
- MagmaCollection's query mechanism is the little 'porter window' where 
you ask for service.

- e.g. In GJallar Q2Model has a BIG GATE to gate most things
- When the GATE is defined for the whole class (on all attributes) it 
applies to

  subclasses also including extra attributes the subclass may define.

KEYHOLE (typically 0)
- allows any reasonably agressive (+ve) read strategy to pass through 
the BIG/SMALL GATE.

- will loose one in 'range'.
BIG KEYHOLE (typically 1)
- allows any read strategy that gets this far to pass through to the 
next level without cost.


OPEN ACCESS (typically 99)
- Everything inside the area/object is visible.
- Setting objects for OPEN ACCESS is not relevant when OPEN ACCESS is 
the default behaviour.
  These items may be left marked as such to indicate intent and to 
facilitate future variations.


SMALL GATE - Non-Solid See Through (typically -10)
- Most attributes are not visible unless made ACQUIRABLE meaning 
explicitly placed in the line

 of sight by their owner for easy 'target aquisition'.
- In Gjallar domain objects are gated with a SMALL GATE (e.g. Q2Process 
Q2Case)


ACQUIRABLE - (typically 15)
- Contents of default index like attributes are set to be visible 
through small gates whatever they are.

- i.e.  id, name, description

BLOCKADED (typically -2)
- Some specific object attributes are never retrieved unless explicitly 
requested.
Precedence is such that BLOCKADED objects, if accidentally, placed in an 
OPEN ACCESS space

or in line of sight are still protected, where as lesser barriers are not.

 - i.e. In Gjallar the wikiPage content is only ever needed when 
explicitly requested


ALARMED (typically -99)
-  Access to this object will raise an error in the Log. Use this if you 
want to be informed

when this object is used. (This is the equivalent of a self halt!)

RECONNAISANCE
--
GLANCING - minimumDepth 1 - top level OPEN ACCESS, KEYHOLES, and their 
ACQUIRABLES only
LOOKING - minimumDepth 5 - to view any OPEN ACCESS, even through 
KEYHOLES, and ACQUIRABLES

SMALL KEY - minimumDepth 15 - to retrieve anything behind one SMALL GATE
BIG KEY - minimumDepth 25 - to retrive anything behind one BIG GATE



strategy minimumDepth: 5. LOOKING

big first read  not needed due to high min depth
strategy onAny: Q2RepositoryRoot readToDepth: 5.

the main BIG GATE
strategy onAny: Q2Model readToDepth: -20.

tiny KEY HOLES
strategy forVariableNamed: 'caseCounter' onAny: Q2Model readToDepth: 0.
strategy forVariableNamed: 'useIndexing' onAny: Q2Model readToDepth: 99.


ProtoObject  - 
  Object  - 
Q2Object  - 
  Q2CasePanel  -  filter tableCaseForm numberOfCases name description
  Q2CodeHolder  -  code selection result error
  Q2CustomObjectLoader  - 
Q2CustomObjectFileLoader  -  fileName separator
Q2CustomObjectODBCLoader  -  dsn user password query
  Q2Event  - 
Q2CaseEvent  -  case
  Q2CreatedCaseEvent case  - 
  Q2ModifiedCaseAssignedToMeEvent case  -  assigned
  Q2ModifiedCaseEvent case  - 
  Q2ModifiedCaseResponsibleEvent case  -  newResponsible
Q2ModifiedCaseResponsibleToMeEvent case newResponsible  - 
  Q2ModifiedCaseRolesEvent case  - 
  Q2ModifiedRelatedCaseEvent case  - 
  Q2NoteAddedEvent case  - 
  Q2StageTransitionEvent case  -  newStage
Q2StageTransitionForRelatedCaseEvent case newStage  - 
Q2UserEvent  -  user
  Q2UserAddedEvent user  - 
  Q2File  -  fileName content
strategy onAny: Q2File readToDepth: -2. BLOCKADE
	strategy forVariableNamed: 'fileName' onAny: Q2File readToDepth: 15. 
ACQUIRABLE


  Q2FilterOperator  -  selector label
Q2FilterOperatorReversed selector label  - 
  Q2FilterPredicate  -  operator value rank filter
Q2FilterFieldPredicate operator value rank filter  -  field
Q2FilterProcessPredicate operator value rank filter  - 
Q2FilterResponsiblePredicate operator value rank filter  - 
Q2FilterSelectorPredicate operator value rank filter  - 
selector description label values operators multi

Q2FilterStagePredicate operator value rank filter  - 

[Setools] MagmaServerRequests

2007-06-15 Thread Keith Hodges

Dear All,

I have uploaded an add-on package to 
http://www.squeaksource.com/MagmaTester called 'Magma server requests'. 
This is as mentioned in a previous email to this list but it is now 
packaged in a generic form independent of Gjallar.


to install with Installer use:

Installer mc http: 'http://www.squeaksource.com'; project: 
'MagmaTester'; install: 'Magma server requests'.


After installing the package into a working Magma installation, you will 
need to do a MagmaSession cleanUp to get it adopted by the 
MagmaRepositoryController's


I have made it fairly generic since it passes arbitrary messages, and 
returns any values, trapping server-side errors, it transports them back 
over the wire in order to signal them in the client.


Actions are atomic since, and I quote from the Magma client server 
read-me text. The answer block is only ever evaluated for one client 
request at a time.


So to use this all you have to do is implement the Client side and the 
server side in MyOwnServerRequestResponder


e.g. Client side:

MyClass-counterValue

   ^ (self magmaSession serverRequest counterValue) submit

e.g Server side

MagmaRequestResponder subclass: MyOwnRequestResponder
--
MyOwnRequestResponder-#counterValue

   ^ Count := Count + 1
--
RequestResponder-class-#requestsSupported

^ #( #counterValue )
--

You can send a batch of requests like so...

(self magmaSession serverRequest counterIncrement; counterIncrement; 
counterIncrement; counterValue) submit


--
Then there is a handy server backdoor!

Normally each request in a batch of requests is sent to the responder 
which can handle each  request. However if we enable requests to be 
chained, such that the next request is sent to the result of the 
previous request we can gain full remote control of the server. This is 
enabled by MagmaServerBackdoorResponder which in itself only serves one 
request:  #login:password:


e.g.

((self magmaSession serverRequest login: 'admin' password: 'magma 
rocks') repositoryController isReadOnly) submit


To do:

The login  could be tied in to magma's exisitng users management.
Some responders need simple persistence for their use which I do not 
know how to do


enjoy 


Keith

___
Setools mailing list
Setools@lists.squeakfoundation.org
http://lists.squeakfoundation.org/mailman/listinfo/setools


[Setools] Clock Faking Test Resource

2007-06-16 Thread Keith Hodges

Dear Ralph,

you asked about a clock faking test resource.

A while ago I developed a ClassClonerTestResource, this allows you to 
take a current class which is normally a singleton that is in use, e.g. 
DateAndTime, and to clone it especially for testing purposes so as to be 
able to test the clone separately. This would allow me to set my clock 
under test to some crucial rollover points and test its behaviour.


I developed this especially to test bug fix 474 on mantis. [ Edgar/Ralph 
- here is a fix with tests for you!]


However what this doesn't do is replace DateAndTime, so if you want to 
run code which calls DateAndTime now and have it do something clever 
like run last week, or run backwards it will not work.


However you raise an interesting problem which I think it may be worth 
solving for everyone, and I think that as a result of my recent 
discovery of the amazing ProcessLocalVariables I may have an answer.


At present ProcessLocalVariables only support value and #value:  As it 
happens I added a #doesNotUnderstand: handler as an experiment in 
allowing gjallar Sessions to spoof as MagmaSessions for Magma. At the 
time I thought that this would have some interesting possibilities. For 
us it means that a ProcessLocalVariable can spoof a class for us within 
a defined scope (process or block).


ProcessSpecificVariable-doesNotUnderstand: aMessage

   ^ aMessage sendTo: self value

So I made a DateAndTimeWarp a subclass of DynamicVariable (a variant of 
the ProcessLocalVariable which has block scope as well as process scope) 
and set the default to return DateAndTime.  We now have a psuedo 
DateAndTime class which is pluggable on a per process basis. 

If we swap DateAndTime in the system dictionary for DateAndTimeWarp, it 
works! (i.e. nothing breaks!!!)


DateAndTimeWarp-installImposter

(DateAndTime respondsTo: #installImposter) ifTrue: [ self error: 
'DateAndTime is already spoofed' ].


   DateAndTimeReal := Smalltalk at: #DateAndTime.
   Smalltalk at: #DateAndTime put: self.

Now we can substitute our clone with some modifications. The fixed 
DateAndTime implementation available on mantis via Installer mantis 
fixBug: 474. (tested in 3.8 and Gjallar0,4) has already been refactored 
to refer to its ClassVar ClockProvider for all clock references. 
(default setting is class Time) So all we need to do is replace 
ClockProvider, we will replace it with an instance of DateAndTimeWarp,


DateAndTimeWarp-class-warpedClockBeginAt: t speed: s

   | newClock newSystemClockProvider |

   newSystemClockProvider := self new setStart: t speed: s.

   newClock := ClassClonerTestResource cloneOf: DateAndTimeReal.
   newClock classPool at: #ClockProvider put: newSystemClockProvider.

   clock initializeOffsets.

   ^ newClock

We instantiate our new clock provider with a start time, (nil for now), 
and a speed. The new clock provider saves some offsets, and 
re-implements #totalSeconds, #millisecondClockValue and 
#secondsWhenClockTicks (this method waits until the clock ticks and is 
used for syncing the seconds and milliseconds clocks together.


The new clock is substituted for the default clock with the following code:

DateAndTimeWarp-class-beginAt: start warpSpeed: s during: aBlock

   ^ self value: (self warpedClockBeginAt: start speed: s) during: aBlock

To Test:

DateAndTime beginAt: DateAndTime yesterday warpSpeed: 3 during: [

   10 timesRepeat: [
   Transcript cr; show: DateAndTime now.
   (Delay forSeconds: 1) wait.
   ]

].


I thought that was pretty impressive stuff. I am well impressed with 
these process local variables!


Also speed wise:

au natural, DateAndTime nowBenchmark. '6.84 µs' (I did improve 
DateAndTime now by a factor of 50-80 in fix 474) The equivalent 
benchmark spoofed using process local variable DynamicVariable, 
benchmark gives: 29.09 µs, i.e. not slow.


This code is available in Gjallar monticello repository 
'http://mc.gjallar.se' in the ProcessSpecific package.


enjoy


Keith








___
Setools mailing list
Setools@lists.squeakfoundation.org
http://lists.squeakfoundation.org/mailman/listinfo/setools


Re: [Setools] MagmaServerRequests

2007-06-17 Thread Keith Hodges

Chris Muller wrote:

I have made it fairly generic since it passes arbitrary messages, and
returns any values, trapping server-side errors, it transports them back
over the wire in order to signal them in the client.


Ma client server does not support a dynamic protocol; only fixed
which must be established just before session negotiation.  How do you
handle this?
My MagmaServerRequest being a subclass of RepositoryRequest is 
registered as part of the Magma protocol as you say. It has an attribute 
'requests'. This is passed as an Array of Message' instances, both of 
these appear to be understood by Magma for serialization. At the other 
end I check that the Message-#selector's are defined in the 
#requestsSupported and simply send them to the class that implements 
that selector.


cheers

Keith

___
Setools mailing list
Setools@lists.squeakfoundation.org
http://lists.squeakfoundation.org/mailman/listinfo/setools


[Setools] Gjallar settings contd.

2007-07-14 Thread Keith Hodges
I used a variety of settings and the autoLogin feature for debugging UI, 
so I thought that it would be useful to promote all the relevant 
settings into the ini file and Q2GjallarSettings interface.


Keith

=
(*optional - indicates defaults supplied by Q2GjallarSettings)

new iniFile settings

[globals] (required)
serverPort=8081
mirrorServerPort=8090

(optional)
autoLoginUsername=  #empty indicates autoLogin disabled
autoLoginPassword=

[seaside] (optional)
sessionClass=Q2Session  #alternative for debugging UI - 
Q2SessionWithoutMagma
rootComponentClass=Q2Main #alternative for debugging UI - use the 
component you are working on as root.
resourcesLibraryClass=Q2Resources #alternative in-image resource set 
(must be subclass of Q2Resources)

magmaLocationClass=Q2MagmaLocalLocation

These settings are used in Q2Main initialize, which is called before 
starting the server.



___
Setools mailing list
Setools@lists.squeakfoundation.org
http://lists.squeakfoundation.org/mailman/listinfo/setools


[Setools] [Fwd: Re: Hi Chris]

2007-08-08 Thread Keith Hodges


---BeginMessage---
On 8/7/07, Keith Hodges [EMAIL PROTECTED] wrote:
 We in the gjallar camp have been trying to get a remote server
 connection without success. I am using beta2.

The Magma test cases run all tests across via the remote connection;
hundreds of them with multiple connects, disconnects and even quitting
the server image (twice!) in the middle of a huge commit and the
clients reconnect succesfully after the server recovery..

So can you tell me what code you are using to start the server and
then what code to connect the clients?

 It appears that it is sending 'connect' and it is being recieved as an
 MAMalformed etc due to the class id not being recognized. It is #207
 when the largest id in the ClassIdManager is 206.

This 'connect' request is sent only by the lower-level framework, Ma
client server, on behalf of Magma, to establish the #protocol (merely
a list of classes).  You should check what class the client thinks is
207.  207 seems awfully high too, something is almost certainly not
configured correctly.

You should try two vanilla Magma images (without Gjaller), establish a
server on one:

  MagmaServerConsole new
open: '/path/to/the/repository' ;
processOn: 1010 ;
inspect

and connect from another image:

  (MagmaSession host: 'serverName' port: 1010)
connectAs: 'test' ;
inspect

Note you can connect to a Gjaller repository even without the Gjaller
code in the client; the missing classes will be created on the fly in
order to instantiate the domain instances (but with no methods).

 I also notice that the error occurs when it tries to send
 repositoryController to this MaMalformed error instance and this occurs
 outside of the MaError handler.

Yes.  The Malformed check is actually in
MaTcpRequestServer#materializeRequest:.

 Is there some initialization that I need to do to get the class id's set
 up correctly?

No, not for Magma.

 Secondly sig tried opening a telnet to the magma port and sending random
 characters in. he got a rather drastic Out of Memory error and a
 corrupted image.

On the server or telnet client?  I assume on the client right?
That'll learn him.  :)

So he told Magma to listen on the port reserved for telnet?

Actually the server should have signaled a MalformedRequest error
which would have been serialized and shipped back to the telnet
client.  Is that what happened?

I'm curious about this story, but this version of Magma is not
designed to be strong against misuse or attack, so I don't know how
concerned I'll be about it (again, for this version).

 It is late and I am not feeling very coherent. If you need more to go on
 I can give you an image tomorrow

Send me more information about what is being done, what steps
including the code snippets.

Regards,
  Chris

---End Message---
___
Setools mailing list
Setools@lists.squeakfoundation.org
http://lists.squeakfoundation.org/mailman/listinfo/setools


[Setools] Re: Counter in Gjallar

2007-08-22 Thread Keith Hodges

Göran Krampe wrote:

Hi Chris!

  

Hi Göran, no, I'm sorry to hear that since I spent a good 4 days on it
and ended up quite pleased with the result.



No need to be sorry! :) I haven't looked but IIRC from your post you
implemented an RC counter a la GemStone, right? Which is quite useful for
counting stuff of course. :)

  

What's the problem with it?



Well, we have multiple MagmaSessions creating Q2Txn objects, giving them a
strictly increasing unique number and adding them to a MagmaCollection. In
short we want the illusion of a very long OrderedCollection. :)

In an OrderedCollection each object of course has its position and if you
succeed adding an object to it (without conflicts) then its number == its
position.

With a MagmaCollection we need to give it a number ourselves (and use an
index for it) - and the problem is how we generate that number so that we
don't end up with multiple Q2Txns with the same number - and not having to
do multiple commits.

In other words - an integer series generator is not exactly the same
problem as a reduced conflict counter. Note btw that I am describing
this from MY understanding - Balazs and Levente are the ones who are
coding on this and perhaps I have misunderstood some parts :)

The simplistic solution is of course to let all MagmaSessions make a
server call (to the Magma server) which has a counter wrapped up in
critical: blocks for increasing it. Thus making sure we serialize all
increments. This is what Keith implemented which apparently did not work
  
I simply implemented a request-response which uses the existing 
protocol. It has a class which handles both ends of the communication. 
Of course this class (these classes) has to be present in the server for 
it to work. This effectively bypasses the database altogether, so there 
are no critical blocks involved. Since the server handles requests 
serially it does ensure that the counter does not conflict.


The bit that I did not know how to do was  how to persist the counter 
values. I just used a file on the server to serialize read/ unserialize 
write a dictionary with the counter values in it on every increment.


I myself have not looked at MagmaCounter yet.


in the Magma version I tried a week ago (the server seems to not deal with
the MagmaServerRequest properly when running as a separate image - causing
the client image to hang waiting for a response. I logged all Magma
  
The server image has to have the responder classes loaded in order to 
respond.



requests going and all seems fine until this MagmaServerRequest coming
through the line, haven't debugged it further on the server side - failed
to see where to put the darn halt. :)).
  

best regards

Keith

___
Setools mailing list
Setools@lists.squeakfoundation.org
http://lists.squeakfoundation.org/mailman/listinfo/setools


[Setools] [Ann] Logging updated

2008-12-01 Thread Keith Hodges
The logging front end to the 3 logging frameworks has been refactored
and simplified. In the process it has
become much more powerful.

Highlights:

Output Adapters, and AdapterSets: You can now easily set up as many
output adapters as you like on any or all processes, each with different
filters etc. Processes can share sets of adaptors.

Lots of different output adapters are supported:

Logging Frameworks: LogEngine, SimpleLog, Toothpick(not ready yet)
Also direct support for: Transcript, nil, SLLogMorph, SLLogWatchDog
(email), SLSyslogSender, SLLogFile

New Feature: LogHistory.

This adapter logs a given number of messages to memory. Then when you
connect another adapter, it outputs the history to the new adapter. Thus
giving you fast logging to memory, but still allowing you to catch up
with a hard copy if you need it. It will only be a matter of time before
we have an automatic, when a big error occurs dump the in memory logs
to a file feature.

If you are using Rio or Logging, please join the
setools@lists.squeakfoundation.org list and put your feedback there or
find me on irc #squeak.

best regards

Keith

Installation:
=

Installer mantis ensureFix: '7219 Streams readability'.
Installer squeaksource project: 'Logging'; install: 'Logging'.
Installer squeaksource project: 'Logging'; install: 'SimpleLog'.


Architecture:


LogCurrent the class is also a ProcessSpecific variable that returns an
different instance of LogCurrent for each process. Each of these
maintains a buffer for that process's log output.

Users use 'self log' to obtain a LogCurrent buffer instance for the
current process from 'LogCurrent value'. Since LogCurrent buffers are
per-process they are threadsafe, and can maintain state between calls
(self log properties).

Each LogCurrent instance maintains a stream (on its buffer) and provides
the users front end interface for convenient logging.

Each LogCurrent instance maintains an adapter, when a log line is
completed (#endEntry), the line is sent to the adapter, the adapter
being the backend interface.

The adapter may be any class that implements  #logTime: stamp line: line
level: level category: category sender: sender pid: pid
e.g. Transcript.

The adapter may also be a LogAdapterSet, in which case, the line is sent
to each adapter contained in the set in turn. LogAdapterSets may be used
to allow a number of processes to share the same set of adapters.
LogAdapterSets may be arbitrarily nested, and may define a filterBlock.
e.g. self filterBlock: [ :level :category |  #(#error #debug #info)
includes: level ]. AdapterSet may be subclassed if more specific
filtering behaviour is required.

Any changes to LogAdapterSets anywhere are protected by a single
Semaphore, but use of adapters for output is protected instead by using
a safer implementation of #do: to iterate over the set should an adapter
be removed by a different thread.

All processes that do not have a LogCurrent instance defined will copy
the default LogCurrent instance, and will therefore share the same
adapter/adapterset as the default.

When you assign a bespoke  LogCurrent instance to a specific process, it
is up to you to set its adapter. It can include the global
adapter/adapterset, nested within the new set you give it.

Additional logging utilities and tools may be defined by subclassing
LogCurrent. LogAdapterSet may be subclassed to provide more interesting
filtering behaviour. And individual Adapters may also be configured or
subclassed as desired.

Adapters:
===

1) LogHistory e.g. LogHistory size: 20.
If the LogHistory adapter is present in a LogAdapterSet, then any new
adapters added to that set have the recorded history sent to them
immediately. Only one LogHistory adapter per set is allowed.

2) Blocks, LogAdapterSet may contain a block which returns a real adaper
or nil. This enables adapters to be written to if enabled, or ignored if
not available (see SLLogMorph below).

3) Transcript - the standard Transcript is used, and the line is output
in one hit within the Transcripts own protection semaphore.  

4) LogEngine e.g. LogEngine for: 'seaside'.
This adapter is for the LogEngine backend.

5) SLLog
This adapter is for the SimpleLog backend.

6) Toothpick
This adapter is for the Toothpick backend. (Not yet supported)

Direct to 'SimpleLog' Components
7) SLSyslogSender e,g, SLSyslogSender new addHost: 'log.somewhere.else'.
or SLSyslogSender localhost.

8) SLLogWatchdog e.g. SLLogWatchdog default.
Emails log entries over the given threshold

9) SLLogMorph e.g. [ SLLogMorph current ].
The block will be evaluated for every log entry. Therefore this construct
will only write to LogMorph if it is open.

10) SLLogFile named: 'current.log'.
Subclass and override #output*, or add #output* methods for additional
file output formats.
Or use (SLLogFile named: 'custom.log') output: [ :entry | entry stamp,
'-', entry line ]

Configuration:

To change the global, or local LogCurrent