[ https://issues.apache.org/jira/browse/FELIX-3422?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14052422#comment-14052422 ]
Denis Rossi commented on FELIX-3422: ------------------------------------ I found that LocalRepositoryImpl is registering itself as AllServiceListener. In the serviceChanged method the m_snapshotTimeStamp, that is used by getLastModified() method, is updated and the bundle is removed and re-added: public void serviceChanged(ServiceEvent event) { Bundle bundle = event.getServiceReference().getBundle(); if (bundle.getState() == Bundle.ACTIVE && event.getType() != ServiceEvent.MODIFIED) { synchronized (this) { removeBundle(bundle, m_logger); addBundle(bundle, m_logger); m_snapshotTimeStamp = System.currentTimeMillis(); } } } > 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 > Labels: patch > > 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 was sent by Atlassian JIRA (v6.2#6252)