Differences between revisions 6 and 9 (spanning 3 versions)
Revision 6 as of 2015-02-03 17:01:55
Size: 4676
Editor: KaiJaeger
Comment:
Revision 9 as of 2018-03-03 11:39:17
Size: 145
Editor: KaiJaeger
Comment:
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
~-<<SeeSaw(section="table-of-contents", show="true", seesaw="false", toshow="<<(Show>> table-of-contents)", tohide="<<(Hide>> table-of-contents)", speed="Slow")>>-~
<<TableOfContents>>

`ServiceState` is part of the CategoryAplTree project.

== Overview ==
{{{ServiceState}}} is a class that offers an interface between the Windows SCM (Service Control Manager) and a Dyalog APL application running as a service.
 
In you application workspace you need to have a function on `⎕LX` like this:

{{{
      Start
[1] #.WinFile.PolishCurrentDir
[2] rideFlag←0
[3] timeout←3
[4] #.myServiceState←⎕NEW #.ServiceState rideFlag timeout
[5] '#'⎕WS'Event' #.myServiceState.Event_QuitDQ 1
[6] :If myServiceState.IsRunningAsService
[7] {}myServiceState.EstablishServiceCallback ⍬ ⍝ This does not work!
[8] {#.TestService.Run ⍵}&⍬
[9] ⎕DQ'.'
[10] #.TestService.Off
[11] :Else
[12] #.TestService.Run ⍬
[13] :EndIf
}}}

Note that this example focuses just on getting the application running as a service.

Remarks:

'''[1]''': This makes sure that if the workspace carries a path the work (or current) directory is set accordingly.

'''[2]''': Flags that indicates whether the service is expected to connect to Ride or not.

'''[3]''': Timeout: this defines how long the `ServiceState` class will wait for the application to conform a requested state change.

'''[4]''': This instantiates the `ServiceState` class.

'''[5]''': `#.myServiceState.Event_QuitDQ` is a variable carrying an (any) integer. The application is supposed to send the same integer to `#` (when it wants to stop) in order to quit the `⎕DQ` on line 9.

'''[6]''': Checks whether the application is actually running as a Windows Service.

'''[7]''': This establishes `#.ServiceState.EstablishServiceCallback` as a callback that will handle all messages send by the Windows SCM. Well, it should. At the time of writing an instance methods that is associated with an event cause a NONCE ERROR, so we must circumvent thus Dyalog bug for the time being with something like this:

{{{
     '.'⎕WS'Event' 'ServiceNotification' '#.OnServiceHandler'
}}}

The `#.OnServiceHandler` function in turn calls the instance method:

{{{
 OnServiceHandler←{
   #.myServiceState.OnServiceHandler ⍵
 }
}}}

That works.

'''[8]''': Here we start the real application. Note that this '''must''' run in its own thread because otherwise the application might well become unresponsive.

'''[9]''': We need to execute `⎕DQ '.'` in order to make sure that the interpreter processes all events.

'''[10]''': At this stage we need to execute `⎕OFF`; that's what `#.TestService.Off` is doing.

== The application ==

The application must make sure that it checks whether a state change was requested. This can be done by calling certain helpers as shown in this example:

{{{
      MainLoop dummmy;buffer;data;event;obj;rc;r;msg;cs
[1] Log 'Server got started'
[2] :While 1
[3] ⎕DL 1
[4] :If #.myServiceState.ShallServicePause
[5] {}#.myServiceState.ConfirmStateChange ⍬
[6] Log'The service is pausing'
[7] {}#.myServiceState.WaitForContinue ⍬
[9] {}#.myServiceState.ConfirmStateChange ⍬
[10] Log'The service is no longer pausing'
[11] :EndIf
[12] :If #.myServiceState.ShallServiceQuit
[13] {}#.myServiceState.ConfirmStateChange ⍬
[14] Log'The service is in the process of shutting down...'
[15] :Leave
[16] :EndIf
[17] :EndWhile
[18] ⎕NQ'#'#.ServiceState.Events.QuitDQ
}}}

Remarks:

'''[14]''': This makes sure that the `⎕DQ` in `Start[7]` quits.

Apart from `ShallServicePause` and `ShallServiceQuit` there is also a function `ShallServiceContinue` but this is called by this function:

{{{
      {r}←WaitForContinue dummy
[1] ⍝ Returns always ⍬.
[2] ⍝ Consider calling this in case ShallServicePause has returned a 1 and you don't _
[3] ⍝ have to do any particular gymnastics but just want to wait for a state change.
[4] ⍝ It just waits until the status changes, although not necessarily to "continue".
[5] r←⍬
[6] :While 0=ShallServiceContinue
[7] ⎕DL 1
[8] :EndWhile
}}}

== Project Page ==

For bug reports, future enhancements and a full version history see [[ServiceState/ProjectPage]]

== Version Information ==
||Original author: ||KaiJaeger ||
||Responsible: ||KaiJaeger ||
||Email: || kai@aplteam.com ||

<<Include(APLTreeDownloads)>>

----
CategoryAplTree
The project has been relocated to [[https://github.com/aplteam/ServiceState]] on 2018-03-03.

ServiceState: interface between SCM and APL

The project has been relocated to https://github.com/aplteam/ServiceState on 2018-03-03.

ServiceState (last edited 2018-03-03 11:39:17 by KaiJaeger)