// Must be a new repository (or one created before 3.0.0.Final) ...
this.repoKey = NodeKey.keyForSourceName(this.name);
this.sourceKey = NodeKey.keyForSourceName(configuration.getStoreName());
DateTime now = context.getValueFactories().getDateFactory().create();
// Store this info in the repository info document ...
EditableDocument doc = Schematic.newDocument();
doc.setString(REPOSITORY_NAME_FIELD_NAME, this.name);
doc.setString(REPOSITORY_KEY_FIELD_NAME, this.repoKey);
doc.setString(REPOSITORY_SOURCE_NAME_FIELD_NAME, configuration.getStoreName());
doc.setString(REPOSITORY_SOURCE_KEY_FIELD_NAME, this.sourceKey);
doc.setDate(REPOSITORY_CREATED_AT_FIELD_NAME, now.toDate());
doc.setString(REPOSITORY_INITIALIZER_FIELD_NAME, initializerId);
doc.setString(REPOSITORY_CREATED_WITH_MODESHAPE_VERSION_FIELD_NAME, ModeShape.getVersion());
doc.setNumber(REPOSITORY_UPGRADE_ID_FIELD_NAME, upgrades.getLatestAvailableUpgradeId());
// store the repository info
if (this.documentStore.localStore().putIfAbsent(REPOSITORY_INFO_KEY, doc) != null) {
// if clustered, we should be holding a cluster-wide lock, so if some other process managed to write under this
// key,
// smth is seriously wrong. If not clustered, only 1 thread will always perform repository initialization.
// in either case, this should not happen
throw new SystemFailureException(JcrI18n.repositoryWasInitializedByOtherProcess.text(name));
}
repositoryInfo = this.documentStore.get(REPOSITORY_INFO_KEY);
// We're doing the initialization ...
initializingRepository = true;
LOGGER.debug("Initializing the '{0}' repository", name);
} else {
// Get the repository key and source key from the repository info document ...
Document info = repositoryInfo.getContent();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Repository '{0}' already initialized at '{1}'", name,
info.get(REPOSITORY_INITIALIZED_AT_FIELD_NAME));
}
String repoName = info.getString(REPOSITORY_NAME_FIELD_NAME, this.name);
String sourceName = info.getString(REPOSITORY_SOURCE_NAME_FIELD_NAME, configuration.getStoreName());
this.repoKey = info.getString(REPOSITORY_KEY_FIELD_NAME, NodeKey.keyForSourceName(repoName));
this.sourceKey = info.getString(REPOSITORY_SOURCE_KEY_FIELD_NAME, NodeKey.keyForSourceName(sourceName));
// See if this existing repository needs to be upgraded ...
lastUpgradeId = info.getInteger(REPOSITORY_UPGRADE_ID_FIELD_NAME, 0);
upgradeRequired = upgrades.isUpgradeRequired(lastUpgradeId);
if (upgradeRequired && info.getString(REPOSITORY_UPGRADER_FIELD_NAME) == null) {
int nextId = upgrades.getLatestAvailableUpgradeId();
LOGGER.debug("The content in repository '{0}' needs to be upgraded (steps {1}->{2})", name, lastUpgradeId, nextId);
// The repository does need to be upgraded and nobody is yet doing it. Note that we only want one process in the
// cluster to do this, so we need to update the document store in an atomic fashion. So, first attempt to
// lock the document ...
this.upgradingRepository = runInTransaction(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
LocalDocumentStore store = documentStore().localStore();
store.prepareDocumentsForUpdate(Collections.unmodifiableSet(REPOSITORY_INFO_KEY));
EditableDocument editor = store.edit(REPOSITORY_INFO_KEY, true);
if (editor.get(REPOSITORY_UPGRADER_FIELD_NAME) == null) {
// Make sure that some other process didn't sneak in and already upgrade ...
int lastUpgradeId = editor.getInteger(REPOSITORY_UPGRADE_ID_FIELD_NAME, 0);
if (upgrades.isUpgradeRequired(lastUpgradeId)) {
// An upgrade is still required, and we get to do it ...
final String upgraderId = UUID.randomUUID().toString();
editor.setString(REPOSITORY_UPGRADER_FIELD_NAME, upgraderId);
return true;
}
}
// Another process is upgrading (or has already upgraded) the repository ...
return false;