Subject Services manager and timeout
Author tradesignalenterprise
Hello there,

I am using Firebird 1.5 embedded implementation. To my knowledge,
using the embedded dll, I cannot use the gbak tool to do a live
backup while my application has a connection due to database locking.

That's why I try to use the Services Manager to accomplish this task
(isc_service_start with isc_action_svc_backup).
The backup seems to work fine, as long as everything is succesful.
To check, if the backup actually completes successfully, I use
isc_service_query with isc_info_svc_line to retrieve the results line
by line (resembles the output of gbak using verbose mode).

However, I am having problems retrieving the backup results when the
backup runs into trouble. To test this, I simply tried to backup a
large database onto a floppy disk. The result is that at some point,
the call to isc_service_query does not return.
To handle this situation, I set a timeout of 60 seconds using
isc_info_svc_timeout, but this seems to take no effect, so the
function still won't return (I've waited for quite a while).
This is highly unsatisfying. Does anyone know a work-around or maybe
I am doing something wrong?

Here is my code used to retrieve the lines:
// retrieve the results
char spbBuf[128] = {0};
char* pSPB = spbBuf;
char requestBuf[] = { isc_info_svc_line };
ISC_STATUS status[20];
char resultBuf[1024] = {0};
char* p = resultBuf;
char* x = NULL;
*pSPB++ = isc_info_svc_timeout;
ADD_SPB_NUMERIC(pSPB, 60); // 60 seconds timeout
unsigned short nSPBLen = static_cast<unsigned short>(pSPB - spbBuf);

do
{
ZeroMemory(resultBuf, sizeof(resultBuf));
if (isc_service_query(status, &m_hService,
NULL, nSPBLen, spbBuf,
sizeof(requestBuf), requestBuf,
sizeof(resultBuf), resultBuf))
{
CString sErr;
CDBMgr::GetError(status, sErr);
LOG(_WARNING_, _T("Error querying backup result from
database services manager: '%s'"), sErr);
break; // do/while
}

// if the query is successful, start processing the return
buffer
x = p = resultBuf;
if (*p++ == isc_info_svc_line)
{
/* Get the length of the data being returned */
ISC_USHORT len = 0, chTmp = 0;
len = (ISC_USHORT)isc_vax_integer(p, sizeof
(ISC_USHORT));
p += sizeof(ISC_USHORT);

// if there is no length, then we should be done ..
let's check
if (!len)
{
if (*p != isc_info_end)
{
ASSERT(0);
LOG(_WARNING_, _T("Unexpected format
error <%d>"), *p);
}
break; // do/while
}
CString sLine(p);
sLine.Remove(1); // for some reason, an ASCII==1
character will be added
LOG(_DEBUG_, _T("%s"), sLine);


// since we only requested one item this time, we
should be at the end of
// the buffer terminated by isc_info_end after moving
the pointer past the
// data we just printed out
p += len;
if (*p != isc_info_truncated && *p != isc_info_end)
{
ASSERT(0);
LOG(_WARNING_, _T("Unexpected format error <%
d>"), *p);
break; // do/while
}
}
} while (*x == isc_info_svc_line);