Ok, I understand - many thanks!
Andy
-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
Sent: 30 September 2008 15:50
To: Derby Discussion
Subject: Re: Derby Encryption AND Replication
Andrew,
Right, this kind of problem (the NPE) is a good example of things that would
need to be fixed. As I said, encryption/backup hasn't been tested together and
can only be considered experimental functionality at this stage.
Regarding the question: Yes, it makes sense to me why startSlave has to be
called before recover. Replication is based on not letting the slave leave
recovery while replication is running. I.e, the slave is constantly doing
recovery of the log records received from the master.
The startSlave method does some initialization work that is needed before log
can be received from the master.
That being said, the NPE problem can be fixed by setting the rawStoreFactory
variable in LTF before parsing the log files (the second while loop in
LTF#initializeReplicationSlaveRole). I tested this by writing a little hack:
SlaveController#startSlave already knows about rawStore, so I just passed it to
LTF#initializeReplicationSlaveMode and set it there. That removed the NPE. I
created a bug report for this issue:
https://issues.apache.org/jira/browse/DERBY-3890
You are more than welcome to create a patch for it if you think the suggested
solution is sound. However, I think maybe the LTF#rawStoreFactory should be
initialized somewhere else than through SlaveController.
Regards,
Jørgen Løland
Andrew Lawrenson wrote:
> Jorgen,
>
> I've possibly found where the problem is being caused. (This
> is with v 10.4.2.0)
>
> When booting my slave database, a nullpointer exception is being thrown
> whilst trying to decrypt data:
>
> Exception in thread "derby.slave.boot-DRS-H3G" java.lang.NullPointerException
> at
> org.apache.derby.impl.store.raw.log.LogToFile.decrypt(LogToFile.java:4327)
> at
> org.apache.derby.impl.store.raw.log.Scan.getNextRecordForward(Scan.java:844)
> at
> org.apache.derby.impl.store.raw.log.Scan.getNextRecord(Scan.java:206)
> at
> org.apache.derby.impl.store.raw.log.LogToFile.initializeReplicationSlaveRole(LogToFile.java:5228)
> at
> org.apache.derby.impl.store.replication.slave.SlaveController.startSlave(SlaveController.java:232)
> at org.apache.derby.impl.store.raw.RawStore.boot(RawStore.java:328)
> at
> org.apache.derby.impl.services.monitor.BaseMonitor.boot(BaseMonitor.java:2019)
> at
> org.apache.derby.impl.services.monitor.TopService.bootModule(TopService.java:291)
> at
> org.apache.derby.impl.services.monitor.BaseMonitor.startModule(BaseMonitor.java:573)
> at
> org.apache.derby.iapi.services.monitor.Monitor.bootServiceModule(Monitor.java:427)
> at
> org.apache.derby.impl.store.access.RAMAccessManager.boot(RAMAccessManager.java:1019)
> at
> org.apache.derby.impl.services.monitor.BaseMonitor.boot(BaseMonitor.java:2019)
> at
> org.apache.derby.impl.services.monitor.TopService.bootModule(TopService.java:291)
> at
> org.apache.derby.impl.services.monitor.BaseMonitor.startModule(BaseMonitor.java:573)
> at
> org.apache.derby.iapi.services.monitor.Monitor.bootServiceModule(Monitor.java:427)
> at
> org.apache.derby.impl.db.BasicDatabase.bootStore(BasicDatabase.java:780)
> at org.apache.derby.impl.db.BasicDatabase.boot(BasicDatabase.java:196)
> at
> org.apache.derby.impl.db.SlaveDatabase.bootBasicDatabase(SlaveDatabase.java:424)
> at
> org.apache.derby.impl.db.SlaveDatabase.access$000(SlaveDatabase.java:70)
> at
> org.apache.derby.impl.db.SlaveDatabase$SlaveDatabaseBootThread.run(SlaveDatabase.java:311)
> at java.lang.Thread.run(Thread.java:619)
>
> As I see it, when you call SlaveController.startSlave(), you pass in a
> LogFactory object (which is actually a LogToFile object).
> This LogToFile object needs its "rawStoreFactory" object set before it can
> call decrypt() which is called as above - and this rawStoreFactory object is
> only set during a call to LogToFile.recover().
>
> However, in RawStore.boot(), where the LogFactory is created,
> LogFactory.recover() is only called _after_ SlaveController.startSlave():
>
> // If SlaveFactory is to be booted, the boot has to happen
> // before logFactory.recover since that method will be blocked
> // when in replication slave mode.
> if (inReplicationSlaveMode) {
> // The LogFactory has already been booted in slave mode.
> // Can now start slave replication by booting the
> // SlaveFactory service
> slaveFactory = (SlaveFactory)
> Monitor.bootServiceModule(create, this,
> getSlaveFactoryModule(),
> properties);
> slaveFactory.startSlave(this, logFactory);
> }
>
> // no need to tell log factory which raw store factory it belongs to
> // since this is passed into the log factory for recovery
> // after the factories are loaded, recover the database
> logFactory.recover(this, dataFactory, xactFactory);
>
> The comments here imply the order has to be this way round - however, it
> seems to be this ordering which is causing the problem in my case.
>
> At this point, I'm starting to feel quite out of my depth - does this make
> sense to you?