Subject Re: [firebird-support] Strange restore problem in embedded firebird
Author Helen Borrie
At 06:45 PM 10/12/2005 +0000, you wrote:
>Hi,
>
>For a few months I've been working on an application using the Embedded
>Firebird database engine (currently using the latest 1.5 release,
>1.5.2.4731). However, I've been encountering a strange problem
>when restoring databases from a backup. I've managed to workaround the
>problem, but it's a horrible method which I suspect is bound to fail at
>some point, and I'd really like to find out how to fix it properly...
>
>Without going into too much boring detail, a "document" in this
>application is essentially a *backup* of a Firebird database (the
>application needs to use ALTER TABLE quite a bit, so using backups
>in this way mitigates the problem of a database freezing after a table
>has been altered 200 or so times). Hence, the usual operations in the
>File menu are implemented as follows:
>
>
>New
>===
>1. Use isc_dsql_execute_immediate to execute a CREATE DATABASE
>statement, which creates a new firebird database in the system's TEMP
>directory
>2. Open a connection to the database and execute some SQL to
>create various tables and views in the database that the application
>needs
>
>Save
>====
>1. Close the connection to the database
>2. Use isc_service_attach to attach to the local service manager
>3. Use isc_service_start with action isc_action_svc_backup to backup the
>database from the system's TEMP directory to whatever file the user
>specified in a save dialog
>4. Use isc_service_detach to detach from the local service manager
>5. Reopen the connection to the database
>
>Close
>=====
>1. Close the connection to the database
>2. Delete the database from the TEMP directory
>
>Open
>====
>1. Use isc_service attach to attach to the local service manager
>2. Use isc_service_start with action isc_action_svc_restore to restore
>the file specified by the user in an open dialog to a database in the
>system's TEMP directory
>3. Use isc_service_detach to detach from the local service manager
>4. SLEEP...
>5. Open a connection to the database
>
>
>The problem is step 4 in the Open operation. If, after restoring the
>database from the user-specified file I *immediately* open a connection
>to it and start running queries I always wind up with one of two errors:
>
>1. Either the Firebird engine throws an error stating that the database
>was truncated and it hit the end of the file before it expected to
>2. Or, the first query to get run fails complaining that the view or
>table it's trying to access doesn't exist
>
>However, if I have the application sleep for at least a second after
>restoring the database, but before opening a connection and querying
>things then it works perfectly! This feels like a race condition to me,
>as though the restore operation is happening in a background thread and
>hasn't really finished by the time isc_service_detach returns.
>
>So, are there any steps I'm missing? Should I be waiting on something
>before trying to open a connection to the newly restored database? Or
>is it possibly a bug in the embedded engine itself?
>
>For reference, I'm writing the application in Delphi, and using the
>ZeosDBO components (zeoslib.sourceforge.net) for connecting to the
>embedded Firebird database engine (as well as other remote databases).
>Any suggestions gratefully accepted!

Without going into a step-by-step breakdown, may I suggest that what's
happening here is not what you think is happening? From your description,
you *think* you are doing all this stuff using the embedded client/server...

However, whenever your application (of gbak) is connecting to localhost (or
any other "remote'" server (as it must to use service_mgr) the client
inside the fbembed library looks for a running server at that remote
location (which will be the local machine if it's
localhost). Why? Because the embedded server can't accept remote
connections *at all*.

It looks to me as though, at one point or another, the version of gbak you
are running is not the one that matches the database's structure. Also,
depending on where the application call lands, it might not even be using
the client library that you think it is, since service_mgr attaches through
the client that is local to it.

The fact that you are actually getting backup files and restores at all by
the described steps indicates that, at the very least, the service_mgr call
from the embedded library is actually finding a running server. But
because you are getting only partial restores, the obvious conclusion is
that the restore bombs out and your application isn't intercepting that
fact - it's only concluding that, because the call to gbak returned, it
must have finished all the way to the end.

We can definitely conclude that the restore DID finish, at some point
before the end, since the embedded client - requiring, as it does ,an
exclusive lock - would not be able to connect to the restored database at
all if gbak were still connected to it.

This message does not in any way endorse the concept that designing an
application such that it's allowed to modify a table 200+ times is in any
way as an intelligent design strategy....or try to comprehend why you need
to even try to perform service operations through the embedded server when
you have a full server running on the same machine....

./heLen