Board index » cppbuilder » TService - Stop/Start/Resume

TService - Stop/Start/Resume


2004-02-11 07:34:49 PM
cppbuilder69
I am writing a simple service for in-house use and it is working fine. The
problem is that although you _can_ start/stop/pause/resume it from the
Service Controller the SC will display an error incorrectly stating that it
failed to do what you wanted.
How do I stop this error appearing?
void __fastcall TVogonFreeSpacer::ServiceExecute(TService *Sender)
{
while( !Terminated )
{
std::auto_ptr<TStringList>sl( new TStringList() );
for( int index=2;
index<MyConfigFile->Count;
++index )
{
AnsiString line=MyConfigFile->Strings[ index ];
int posn=line.Pos( ',' );
__int64 freeSpace=DiskFree( UpperCase( line )[ 1 ]-'A'+1 );
sl->Add( line.SubString( posn+1, line.Length() )+"="+freeSpace );
}
sl->SaveToFile( MyOutputPath );
ServiceThread->ProcessRequests( false );
Sleep( MyDelay );
}
}
void __fastcall TVogonFreeSpacer::ServiceStop(TService *Sender,
bool &Stopped)
{
ServiceThread->Terminate();
Stopped=true;
}
void __fastcall TVogonFreeSpacer::ServicePause(TService *Sender,
bool &Paused)
{
ServiceThread->Suspend();
Paused=true;
}
void __fastcall TVogonFreeSpacer::ServiceContinue(TService *Sender,
bool &Continued)
{
ServiceThread->Resume();
Continued=true;
}
--
Andrue Cope
[Bicester UK]
 
 

Re:TService - Stop/Start/Resume

"Andrue Cope" < XXXX@XXXXX.COM >wrote in message
Quote
The problem is that although you _can_ start/stop/pause/resume
it from the Service Controller the SC will display an error
incorrectly stating that it failed to do what you wanted.
That is because you are pausing the TService's underlying ServiceThread
directly. That is the same thread that handles SCM requests, thus you are
effecting the service's ability to respond to the SCM correctly. You should
not be touching the ServiceThread directly except under extreme
circumstances when you have no other option.
Quote
How do I stop this error appearing?
You should not use the OnExecute event at all, but instead move your code to
a separate thread of its own. Every time I have ever seen people using the
OnExecute event, they have had problems because they do not allow the
service to handle SCM messages correctly. TService already has an adequate
implementation for that, but it is disabled whenever the OnExecute event is
used.
Try this instead:
class TMyThread : public TThread
{
private:
TString *sl;
protected:
void __fastcall Execute();
public:
__fastcall TMyThread();
__fastcall ~TMyThread();
};
__fastcall TMyThread::TMyThread()
: TThread(true)
{
sl = new TStringList;
Resume();
}
__fastcall TMyThread::~TMyThread()
{
delete sl;
}
void __fastcall TMyThread::Execute()
{
while( !Terminated )
{
sl->Clear();
for( int index=2; index < MyConfigFile->Count; ++index )
{
AnsiString line = MyConfigFile->Strings[ index ];
int posn = line.Pos( ',' );
__int64 freeSpace = DiskFree( UpperCase( line )[
1 ]-'A'+1 );
sl->Add( line.SubString( posn+1, line.Length() ) + "=" +
freeSpace );
}
sl->SaveToFile( MyOutputPath );
Sleep( MyDelay );
}
}
class TVogonFreeSpacer : public TService
{
private:
TMyThread *FThread;
//...
};
void __fastcall TVogonFreeSpacer::ServiceStart(TService *Sender, bool
&Started)
{
FThread = new TMyThread;
Started = true;
}
void __fastcall TVogonFreeSpacer::ServiceStop(TService *Sender, bool
&Stopped)
{
ServiceShudown(Sender);
Stopped = true;
}
void __fastcall TVogonFreeSpacer::ServiceShudown(TService *Sender)
{
if( FThread )
{
FThread->Terminate();
FThread->WaitFor();
delete FThread;
FThread = NULL;
}
}
void __fastcall TVogonFreeSpacer::ServicePause(TService *Sender, bool
&Paused)
{
if( FThread )
FThread->Suspend();
Paused = true;
}
void __fastcall TVogonFreeSpacer::ServiceContinue(TService *Sender, bool
&Continued)
{
if( FThread )
FThread->Resume();
Continued = true;
}
Gambit
 

Re:TService - Stop/Start/Resume

On Wed, 11 Feb 2004 10:28:41 -0800, Remy Lebeau (TeamB) wrote:
Quote
That is because you are pausing the TService's underlying ServiceThread
directly. That is the same thread that handles SCM requests, thus you are
effecting the service's ability to respond to the SCM correctly. You should
not be touching the ServiceThread directly except under extreme
circumstances when you have no other option.
Ah. That's not quite what the documentation says though :)
The help and C++ Builder 4 Unleashed say you only need to create a thread
if you're servicing multiple clients or doing something that might take a
long time - neither actively discourages you from using the TService
thread.
Ho hum.
Anyway it's working now, thank you.
In case you wondered this is to get round the volume free space issue we
have. There may be some API calls I can make from a client to get the
information but I can't find them. Our solution is to have this service
create a file for the client in the directory above the mount points.
Hi-tech or what? :)
--
Andrue Cope
[Bicester UK]
 

{smallsort}

Re:TService - Stop/Start/Resume

"Andrue Cope" < XXXX@XXXXX.COM >wrote in message
Quote
The help and C++ Builder 4 Unleashed say you only need to
create a thread if you're servicing multiple clients or doing
something that might take a long time - neither actively
discourages you from using the TService thread.
You are missing the point. There is nothing wrong with using the TService's
events to put the functionality of the service inside the TService directly
instead of putting it in its own thread. Depending on the complexity of
your service code, a separate thread may or may not be desired. However,
you still should *not* be touching the TService's ServiceThread property for
any reason. TService itself is executed in its own thread, which the
ServiceThread property points to. That thread needs to run uninterrupted in
order to continue processing SCM requests and forwarding them to the
TService for handling. If you suspend the ServiceThread, you are
effectively suspending the entire service indefinately, and the SCM will
start failing operations because your service can no longer respond to them.
Quote
In case you wondered this is to get round the volume free space
issue we have.
Which is what exactly?
Quote
There may be some API calls I can make from a client to get
the information but I can't find them.
What information are you referring to exactly?
Gambit
 

Re:TService - Stop/Start/Resume

On Thu, 12 Feb 2004 11:23:40 -0800, Remy Lebeau (TeamB) wrote:
Quote
>In case you wondered this is to get round the volume free space
>issue we have.

Which is what exactly?
It's best described by example.
Our server has two data volumes D: and E:.
These are mounted on a third volume at mount points 'Vol1' and 'Vol2'.
The clients see:
H:\DrVols\Vol1
H:\Drvols\Vol2
We need to be able to determine the free space on Vol1 and Vol2 from the
client.
We initially had high hopes for GetDiskFreeSpaceEx() since it takes a
directory path but that doesn't work - it just returns the free space on
H:. It doesn't even include 'Vol1' and 'Vol2' in that figure let alone
allow us to distinguish between them.
My guess is that it's because the client just doesn't know that
"h:\drvols\vol1" is a mounted volume. Presumably if run server side it
would give the answers we need.
Almost certainly there is some series of API calls that we can make from
the client side that will allow us to obtain this information but the
couple of routes we considered still result in the client having to ask the
server what the free space on 'D:' and 'E:' is.
In any case there is still one real fly in the ointment. Most of the
programs creating data on those volumes (and it's disk images so 50GB can
be easily consumed in an hour by one program) are running on DOS machines.
Even if we can find a Windows API route to get this information it still
doesn't help the DOS clients :(
--
Andrue Cope
[Bicester UK]