Page 1 of 1

[patch_done] PingServer functionality for FireBird

Posted: 10.03.2009, 10:41
by MerijnB
I've implemented something which seems to come as close to a ping implementation for FireBird as possible. I'm not very into this, so I hope I didn't make any stupid mistakes :P

Added to ZDbcInterbase6.pas:

Code: Select all

{**
  Checks if a connection is still alive by doing a call to isc_database_info
  It does not matter what info we request, we are not looking at it, as long
  as it is something which should _always_ work if the connection is there.
  We check if the error returned is one of the net_* errors described in the
  firebird client documentation (335544721 .. 335544727).
  Returns 0 if the connection is OK
  Returns non zeor if the connection is not OK
}
function TZInterbase6Connection.PingServer: integer;
var
  DatabaseInfoCommand: Char;
  Buffer: array[0..IBBigLocalBufferLength - 1] of Char;
  ErrorCode: ISC_STATUS;
begin
  DatabaseInfoCommand := Char(isc_info_reads);

  ErrorCode := FPlainDriver.isc_database_info(@FStatusVector, @FHandle, 1, @DatabaseInfoCommand,
                           IBLocalBufferLength, Buffer);

  if (ErrorCode >= 335544721) and (ErrorCode <= 335544727) then
   result := -1
  else
   result := 0;
end;

Posted: 10.03.2009, 13:33
by seawolf
Hi, your idea would be great but there is a problem:
How much traffic generate that procedure? I mean we a need a statement the generated low net traffic and low complexity for the server side

Posted: 10.03.2009, 14:02
by MerijnB
From what I understand from the documentation, the actual command and the answer is just a couple of bytes. I don't know what the protocol overhead is though. I'll try to check it with a sniffer lateron, though I'm not sure if I can see what's what.

Posted: 11.03.2009, 09:46
by MerijnB
I've hooked up wireshark, and found the following:

The 'ping request' I send is 24 bytes long, which makes 78 bytes when you add all tcp overhead.

The server response is 40 bytes longs, which makes 94 bytes including all tcp overhead.

This is followed by a TCP ACK, although I think you shouldn't add that to the totals (not fair).

All in all it's peanuts, as I see now, there are 2 minor disadvantages:

- The server is actually doing something at this request, though it's nearly nothing.
- Since it's sync, there is a delay point when using the Ping() function at the moment the connection is gone. If the connection is not there, it takes about 3 seconds to figure it out in my tests. What I've done is that I've made a class which guards the connection by pinging at an interval. At the moment the connection drops (3 seconds stall in the main thread), I start up a separate thread which tries to reconnect at a regular interval. This works quite well.
Please note I had to make this adjustment to get this working: http://zeos.firmos.at/viewtopic.php?t=2275

Posted: 20.03.2009, 23:48
by mdaems
Committed to SVN (Rev 606)

I didn't test. Can somebody confirm this really works?

Mark

Posted: 24.02.2010, 15:34
by duzenko
I had to change it a bit

Code: Select all

    FTrHandle := nil;
    result := -1
Otherwise it would try to close transaction (?) when performing disconnect and give an error

Posted: 24.02.2010, 22:34
by mdaems
What's the error returned? Is it descriptive? Then it's better to leave it where it is and let de developer who's using ping handle it.

Mark

Posted: 15.04.2011, 15:10
by duzenko
long time no fix
right now if the connection is lost and you try to call reconnect it will raise exception
what is more serious, even after manual call to connect it seems to damage the process memory causing random AVs
it is a bug, is it not?