Improve framework state change checking in ResolverImpl.deploy()
----------------------------------------------------------------
Key: FELIX-3422
URL: https://issues.apache.org/jira/browse/FELIX-3422
Project: Felix
Issue Type: Improvement
Components: Bundle Repository (OBR)
Affects Versions: bundlerepository-1.6.6
Environment: All platforms
Reporter: Declan Cox
Priority: Minor
Currently the ResolverImpl deploy method checks to see if the last modified
time of a repository instance is greater than the last updated resolution start
timestamp, indicating a possible inconsistent state between the repository
resources and the set of resolved resources. However it appears that the last
modified time on a repository instance can be updated by the framework without
it affecting the resolve state of the contained resources. The following
comment indicates that the original implementer is aware of this, viz:
// Check to make sure that our local state cache is up-to-date
// and error if it is not. This is not completely safe, because
// the state can still change during the operation, but we will
// be optimistic. This could also be made smarter so that it checks
// to see if the local state changes overlap with the resolver.
for (int repoIdx = 0; (m_repositories != null) && (repoIdx <
m_repositories.length); repoIdx++)
{
if (m_repositories[repoIdx].getLastModified() > m_resolveTimeStamp)
{
throw new IllegalStateException("Framework state has changed,
must resolve again.");
}
}
I have encountered this error on an upgrade from version 1.0.3 to 1.6.6
recently (we have a provisioning agent which delegates to the bundle repository
). What we have seen is that between a call to resolve() and deploy() the local
repository last modified timestamp is updated, however on investigation all
contained resources have been resolved but we get the IllegalStateException
nonetheless.
We are not sure why this update happens and where it comes from (this we will
investigate further), however we could avoid the unnecessary exception by
checking the overlap with the resolved set as suggested above.
To this end I added the following private method to ResolverImpl in a local
copy, which seems to do the trick:
/**
* Check to see if the repository state has changed and whether
* this state change requires re-resolving
*
* @param repository - repository instance
* @return true if state has changed requiring re-resolving, otherwise false
*/
private boolean hasStateChanged(final Repository repository) {
if (repository.getLastModified() > m_resolveTimeStamp.get()) {
// check overlap with resolver
final Resource[] resources = repository.getResources();
for (int i = 0; i < resources.length; i++) {
if (!m_resolveSet.contains(resources[i])) {
return true;
}
}
}
return false;
}
The corresponding change to the deploy method is as follows:
// Check to make sure that our local state cache is up-to-date
// and error if it is not. This is not completely safe, because
// the state can still change during the operation, but we will
// be optimistic. This could also be made smarter so that it checks
// to see if the local state changes overlap with the resolver.
for (int repoIdx = 0; (m_repositories != null) && (repoIdx <
m_repositories.length); repoIdx++)
{
final Repository repository = m_repositories[repoIdx];
if (hasStateChanged(repository))
{
throw new IllegalStateException("Framework state has changed,
must resolve again.");
}
}
I am not sure if this is the most efficient way to do this and if all
considerations about state change have been taken into account (I am new to
Felix) but I thought would submit it for consideration as a potential patch.
Thanks,
Declan
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators:
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira