> -----Original Message-----
> From: Dag H. Wanvik [mailto:dag.wan...@oracle.com] 
> Sent: Tuesday, 31 May 2011 04:43
> To: Derby Discussion
> Subject: Re: Disappearing service.properties file
> 
> 
> Hi Brett,
> 
> some possibilities below.
> 
> "Brett Mason" <b.ma...@adinstruments.com> writes:
> 
> > We've recently had some of customer reports come in where 
> Derby is failing
> > with problems related to "service.properties". There are 
> three different
> > cases but all appear to be similar:
> >
> > Case 1:
> > "ERROR XBM0S: Unable to rename file 
> 'C:\PATH_TO_DB\service.properties' to
> > 'C:\PATH_TO_DB\service.propertiesold' " is thrown when 
> trying to call
> > SYSCS_DISABLE_LOG_ARCHIVE_MODE(1). Both "service.properties" and
> > "service.propertiesold" are present in the database 
> directory. Removing
> > "service.propertiesold" corrects the problem.
> 
> The relevant code is in
> StorgaeFactoryService#saveServiceProperties(String, StorageFactory,
> Properties, boolean replace) called with  replace == true.
> 
> I think we have seen in some cases on Windows that file 
> handles are open
> longer than expected. In any case, the rename fails here, and 
> the reason
> for this is intrinsically platform specific, cf. the Java API
> Properties, boolean)File#renameTo.
> 
> >
> > Case 2:
> > "SQLException: Database 'C:\PATH_TO_DB' not found" is 
> thrown when booting
> > the database. The file service.properties does not exist in 
> the database
> > directory but service.propertiesold does exist. Renaming 
> the file back to
> > "service.properties" corrects the problem.
> 
> In this case, the rename has been performed ("old" backup exists), but
> Derby hasn't been able to write the new version of the 
> properties file.
> If Derby tried but failed to write the new version, one should see the
> exception XBM01 (cf. throw Monitor.exceptionStartingModule(ioe) in the
> code).
> 
> "Startup failed due to an exception. See next exception for details"
> 
> on derby.log.
> 
> One could see the described scenario if Derby (or the system) was
> forcibly stopped at this point: the next boot would then not find
> "derby.properties".
> 
> >
> > Case 3: 
> > Same as Case 2, except both "service.properties" and 
> "service.propertiesold"
> > are missing. We will probably use a backup to restore 
> service.properties in
> > this case.
> 
> Looking at the code, it seems the only way this can happen is if Derby
> thinks the writing of the new "derby.properties" file went 
> ok. The code
> performs an explicit "sync" call to make sure the change is 
> persisted to
> disk before it goes on the delete the backup file. One could, perhaps,
> see this if the file system or driver didnt really honor the 
> write sync
> call, but the delete somehow got persisted, followed by a system
> crash(?).
> 
> Thanks,
> Dag
-- snip --

Thanks for your replies.

It does seem that Cases 1 & 2 are fairly easy to reproduce by terminating
the Java process while it is updating service.properties. I've included some
sample code which will trigger the problem quite reliably when it is
terminated on the following environments:

Windows 7 64-bit, Sun 32-bit JRE 1.6u20, Derby 10.6.1.0
Windows 7 64-bit, Sun 32-bit JDK 1.6u25, Derby 10.8.1.2
Debian Linux 5.0, 32-bit, Sun JRE 1.6u20, Derby 10.6.1.0 (running within
Virtual Box)

Is this issue worth reporting as a bug?

Are there other scenarios where the file might be updated as part of
"normal" database usage? Particularly for regular INSERT/UPDATE/DELETE
statements, but also maintenance procedures such as SYSCS_BACKUP_DATABASE,
SYSCS_CHECK_TABLE, SYSCS_COMPRESS_TABLE, SYSCS_UPDATE_STATISTICS.

Thanks,
Brett.



import java.sql.*;
import org.apache.derby.jdbc.*;

public class DerbyLogArchiveModeTest {
    
    public static void main(String[] args) {
        final EmbeddedDataSource ds = new EmbeddedDataSource();
        ds.setDatabaseName("derbyTest");
        ds.setCreateDatabase("create");

        try {
            final Connection conn = ds.getConnection();

            try {
                final Statement stmt = conn.createStatement();

                try {
                    while (true) {
                        stmt.execute("call
SYSCS_UTIL.SYSCS_DISABLE_LOG_ARCHIVE_MODE(1)");
                    }
                } finally {
                    stmt.close();
                }
            } finally {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Reply via email to