OPENDJ-2159 CR-7527 PDB Storage is read-only when using verify-index tool on Windows.
The real problem is the server is killed before flushing has a chance to run and the fact operations for tree creation
do not appear in the journal file. Adding a flag to open tree operations so that we can skip errors on missing trees
while the storage is read only.
Moreover, verify-index was trying to verify indexes already known to be in degraded state, and printing weird stats
about them.
1 files added
21 files modified
| | |
| | | verifyID2Children = true; |
| | | verifyID2Subtree = true; |
| | | } |
| | | attrIndexList.addAll(entryContainer.getAttributeIndexes()); |
| | | for (AttributeIndex index : entryContainer.getAttributeIndexes()) |
| | | { |
| | | if (index.isTrusted()) |
| | | { |
| | | attrIndexList.add(index); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | |
| | | import org.opends.server.admin.std.server.PDBBackendCfg; |
| | | import org.opends.server.api.Backupable; |
| | | import org.opends.server.api.DiskSpaceMonitorHandler; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.Cursor; |
| | | import org.opends.server.backends.pluggable.spi.Importer; |
| | | import org.opends.server.backends.pluggable.spi.ReadOnlyStorageException; |
| | |
| | | |
| | | /** Common interface for internal WriteableTransaction implementations. */ |
| | | private interface StorageImpl extends WriteableTransaction, Closeable { |
| | | |
| | | } |
| | | |
| | | /** PersistIt implementation of the {@link WriteableTransaction} interface. */ |
| | | private final class WriteableStorageImpl implements StorageImpl |
| | | { |
| | | private final Map<TreeName, Exchange> exchanges = new HashMap<>(); |
| | | private final String DUMMY_RECORD = "_DUMMY_RECORD_"; |
| | | |
| | | @Override |
| | | public void put(final TreeName treeName, final ByteSequence key, final ByteSequence value) |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void openTree(final TreeName treeName) |
| | | public void openTree(final TreeName treeName, boolean createOnDemand) |
| | | { |
| | | Exchange ex = null; |
| | | try |
| | | if (createOnDemand) |
| | | { |
| | | ex = getNewExchange(treeName, true); |
| | | openCreateTree(treeName); |
| | | } |
| | | catch (final PersistitException e) |
| | | else |
| | | { |
| | | throw new StorageRuntimeException(e); |
| | | } |
| | | finally |
| | | { |
| | | db.releaseExchange(ex); |
| | | try |
| | | { |
| | | getExchangeFromCache(treeName); |
| | | } |
| | | catch (final PersistitException e) |
| | | { |
| | | throw new StorageRuntimeException(e); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | private void openCreateTree(final TreeName treeName) |
| | | { |
| | | Exchange ex = null; |
| | | try |
| | | { |
| | | ex = getNewExchange(treeName, true); |
| | | // Work around a problem with forced shutdown right after tree creation. |
| | | // Tree operations are not part of the journal, so force a couple operations to be able to recover. |
| | | ByteString dummyKey = ByteString.valueOf(DUMMY_RECORD); |
| | | put(treeName, dummyKey, ByteString.empty()); |
| | | delete(treeName, dummyKey); |
| | | } |
| | | catch (final PersistitException e) |
| | | { |
| | | throw new StorageRuntimeException(e); |
| | | } |
| | | finally |
| | | { |
| | | db.releaseExchange(ex); |
| | | } |
| | | } |
| | | |
| | | private Exchange getExchangeFromCache(final TreeName treeName) throws PersistitException |
| | | { |
| | | Exchange exchange = exchanges.get(treeName); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void openTree(TreeName treeName) |
| | | public void openTree(TreeName treeName, boolean createOnDemand) |
| | | { |
| | | if (createOnDemand) |
| | | { |
| | | throw new ReadOnlyStorageException(); |
| | | } |
| | | Exchange ex = null; |
| | | try |
| | | { |
| | |
| | | } |
| | | catch (final TreeNotFoundException e) |
| | | { |
| | | throw new ReadOnlyStorageException(); |
| | | // ignore missing trees. |
| | | } |
| | | catch (final PersistitException e) |
| | | { |
| | |
| | | |
| | | private StorageImpl newStorageImpl() { |
| | | final WriteableStorageImpl writeableStorage = new WriteableStorageImpl(); |
| | | return accessMode.equals(AccessMode.READ_ONLY) ? new ReadOnlyStorageImpl(writeableStorage) : writeableStorage; |
| | | return accessMode.isWriteable() ? writeableStorage : new ReadOnlyStorageImpl(writeableStorage); |
| | | } |
| | | |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | |
| | | dbCfg.setLogFile(new File(backendDirectory, VOLUME_NAME + ".log").getPath()); |
| | | dbCfg.setJournalPath(new File(backendDirectory, JOURNAL_NAME).getPath()); |
| | | dbCfg.setCheckpointInterval(config.getDBCheckpointerWakeupInterval()); |
| | | // Volume is opened read write because recovery will fail if opened read-only |
| | | dbCfg.setVolumeList(asList(new VolumeSpecification(new File(backendDirectory, VOLUME_NAME).getPath(), null, |
| | | BUFFER_SIZE, 4096, Long.MAX_VALUE / BUFFER_SIZE, 2048, true, false, false))); |
| | | final BufferPoolConfiguration bufferPoolCfg = getBufferPoolCfg(dbCfg); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public final void open(WriteableTransaction txn) throws StorageRuntimeException |
| | | public final void open(WriteableTransaction txn, boolean createOnDemand) throws StorageRuntimeException |
| | | { |
| | | txn.openTree(name); |
| | | txn.openTree(name, createOnDemand); |
| | | open0(txn); |
| | | } |
| | | |
| | |
| | | * Open the attribute index. |
| | | * |
| | | * @param txn a non null transaction |
| | | * @param createOnDemand true if the tree should be created if it does not exist |
| | | * @throws StorageRuntimeException if an error occurs while opening the index |
| | | */ |
| | | void open(WriteableTransaction txn) throws StorageRuntimeException |
| | | void open(WriteableTransaction txn, boolean createOnDemand) throws StorageRuntimeException |
| | | { |
| | | for (Index index : indexIdToIndexes.values()) |
| | | { |
| | | index.open(txn); |
| | | index.open(txn, createOnDemand); |
| | | } |
| | | config.addChangeListener(this); |
| | | } |
| | |
| | | { |
| | | for (MatchingRuleIndex addedIndex : addedIndexes.values()) |
| | | { |
| | | openIndex(txn, addedIndex, ccr); |
| | | createIndex(txn, addedIndex, ccr); |
| | | } |
| | | } |
| | | }); |
| | |
| | | return ccr; |
| | | } |
| | | |
| | | private static void openIndex(WriteableTransaction txn, MatchingRuleIndex index, ConfigChangeResult ccr) |
| | | private static void createIndex(WriteableTransaction txn, MatchingRuleIndex index, ConfigChangeResult ccr) |
| | | { |
| | | index.open(txn); |
| | | index.open(txn, true); |
| | | if (!index.isTrusted()) |
| | | { |
| | | ccr.setAdminActionRequired(true); |
| | |
| | | import org.opends.server.backends.RebuildConfig; |
| | | import org.opends.server.backends.VerifyConfig; |
| | | import org.opends.server.backends.pluggable.ImportSuffixCommand.SuffixImportStrategy; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.Storage; |
| | | import org.opends.server.backends.pluggable.spi.Storage.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.StorageInUseException; |
| | | import org.opends.server.backends.pluggable.spi.StorageRuntimeException; |
| | | import org.opends.server.backends.pluggable.spi.WriteOperation; |
| | |
| | | try |
| | | { |
| | | // The base DN was added. |
| | | EntryContainer ec = rootContainer.openEntryContainer(baseDN, txn); |
| | | EntryContainer ec = rootContainer.openEntryContainer(baseDN, txn, AccessMode.READ_WRITE); |
| | | rootContainer.registerEntryContainer(baseDN, ec); |
| | | DirectoryServer.registerBaseDN(baseDN, this, false); |
| | | } |
| | |
| | | import org.opends.server.api.VirtualAttributeProvider; |
| | | import org.opends.server.api.plugin.PluginResult.SubordinateDelete; |
| | | import org.opends.server.api.plugin.PluginResult.SubordinateModifyDN; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.Cursor; |
| | | import org.opends.server.backends.pluggable.spi.ReadOperation; |
| | | import org.opends.server.backends.pluggable.spi.ReadableTransaction; |
| | |
| | | @Override |
| | | public void run(WriteableTransaction txn) throws Exception |
| | | { |
| | | index.open(txn); |
| | | index.open(txn, true); |
| | | if (!index.isTrusted()) |
| | | { |
| | | ccr.setAdminActionRequired(true); |
| | |
| | | public void run(WriteableTransaction txn) throws Exception |
| | | { |
| | | VLVIndex vlvIndex = new VLVIndex(cfg, state, storage, EntryContainer.this, txn); |
| | | vlvIndex.open(txn); |
| | | vlvIndex.open(txn, true); |
| | | if(!vlvIndex.isTrusted()) |
| | | { |
| | | ccr.setAdminActionRequired(true); |
| | |
| | | * Opens the entryContainer for reading and writing. |
| | | * |
| | | * @param txn a non null transaction |
| | | * @param accessMode specifies how the container has to be opened (read-write or read-only) |
| | | * @throws StorageRuntimeException If an error occurs in the storage. |
| | | * @throws ConfigException if a configuration related error occurs. |
| | | */ |
| | | void open(WriteableTransaction txn) throws StorageRuntimeException, ConfigException |
| | | void open(WriteableTransaction txn, AccessMode accessMode) throws StorageRuntimeException, ConfigException |
| | | { |
| | | boolean shouldCreate = accessMode.isWriteable(); |
| | | try |
| | | { |
| | | DataConfig entryDataConfig = |
| | |
| | | rootContainer.getCompressedSchema()); |
| | | |
| | | id2entry = new ID2Entry(getIndexName(ID2ENTRY_TREE_NAME), entryDataConfig); |
| | | id2entry.open(txn); |
| | | id2childrenCount.open(txn); |
| | | dn2id.open(txn); |
| | | state.open(txn); |
| | | dn2uri.open(txn); |
| | | id2entry.open(txn, shouldCreate); |
| | | id2childrenCount.open(txn, shouldCreate); |
| | | dn2id.open(txn, shouldCreate); |
| | | state.open(txn, shouldCreate); |
| | | dn2uri.open(txn, shouldCreate); |
| | | |
| | | for (String idx : config.listBackendIndexes()) |
| | | { |
| | | BackendIndexCfg indexCfg = config.getBackendIndex(idx); |
| | | |
| | | final AttributeIndex index = new AttributeIndex(indexCfg, state, this); |
| | | index.open(txn); |
| | | index.open(txn, shouldCreate); |
| | | if(!index.isTrusted()) |
| | | { |
| | | logger.info(NOTE_INDEX_ADD_REQUIRES_REBUILD, index.getName()); |
| | |
| | | BackendVLVIndexCfg vlvIndexCfg = config.getBackendVLVIndex(idx); |
| | | |
| | | VLVIndex vlvIndex = new VLVIndex(vlvIndexCfg, state, storage, this, txn); |
| | | vlvIndex.open(txn); |
| | | |
| | | vlvIndex.open(txn, shouldCreate); |
| | | if(!vlvIndex.isTrusted()) |
| | | { |
| | | logger.info(NOTE_INDEX_ADD_REQUIRES_REBUILD, vlvIndex.getName()); |
| | |
| | | { |
| | | for(Tree tree : allTrees) |
| | | { |
| | | tree.open(txn); |
| | | tree.open(txn, false); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | |
| | | { |
| | | for(Tree tree : allTrees) |
| | | { |
| | | tree.open(txn); |
| | | tree.open(txn, true); |
| | | } |
| | | |
| | | for (Tree tree : allTrees) |
| | |
| | | } |
| | | finally |
| | | { |
| | | tree.open(txn); |
| | | tree.open(txn, true); |
| | | } |
| | | if(logger.isTraceEnabled()) |
| | | { |
| | |
| | | this.dataConfig = dataConfig; |
| | | } |
| | | |
| | | @Override |
| | | void open0(WriteableTransaction txn) throws StorageRuntimeException |
| | | { |
| | | // Make sure the tree is there and readable, even if the storage is READ_ONLY. |
| | | txn.getRecordCount(getName()); |
| | | } |
| | | |
| | | /** |
| | | * Decodes an entry from its tree representation. |
| | | * <p> |
| | |
| | | import org.opends.server.backends.pdb.PDBStorage; |
| | | import org.opends.server.backends.pluggable.AttributeIndex.MatchingRuleIndex; |
| | | import org.opends.server.backends.pluggable.ImportLDIFReader.EntryInformation; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.Cursor; |
| | | import org.opends.server.backends.pluggable.spi.Importer; |
| | | import org.opends.server.backends.pluggable.spi.ReadOperation; |
| | | import org.opends.server.backends.pluggable.spi.ReadableTransaction; |
| | | import org.opends.server.backends.pluggable.spi.Storage; |
| | | import org.opends.server.backends.pluggable.spi.Storage.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.StorageRuntimeException; |
| | | import org.opends.server.backends.pluggable.spi.TreeName; |
| | | import org.opends.server.backends.pluggable.spi.UpdateFunction; |
| | |
| | | { |
| | | tempDN = baseDN.parent().child(tempDN); |
| | | } |
| | | entryContainer = rootContainer.openEntryContainer(tempDN, txn); |
| | | entryContainer = rootContainer.openEntryContainer(tempDN, txn, AccessMode.READ_WRITE); |
| | | break; |
| | | case INCLUDE_EXCLUDE_BRANCHES: |
| | | break; |
| | |
| | | @Override |
| | | public void run(WriteableTransaction txn) throws Exception |
| | | { |
| | | txn.openTree(dnCache); |
| | | txn.openTree(dnCache, true); |
| | | } |
| | | }); |
| | | } |
| | |
| | | import org.opends.server.backends.pluggable.AttributeIndex.MatchingRuleIndex; |
| | | import org.opends.server.backends.pluggable.ImportLDIFReader.EntryInformation; |
| | | import org.opends.server.backends.pluggable.OnDiskMergeBufferImporter.DNCache; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.Cursor; |
| | | import org.opends.server.backends.pluggable.spi.Importer; |
| | | import org.opends.server.backends.pluggable.spi.ReadOperation; |
| | | import org.opends.server.backends.pluggable.spi.ReadableTransaction; |
| | | import org.opends.server.backends.pluggable.spi.SequentialCursor; |
| | | import org.opends.server.backends.pluggable.spi.Storage; |
| | | import org.opends.server.backends.pluggable.spi.Storage.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.StorageRuntimeException; |
| | | import org.opends.server.backends.pluggable.spi.StorageStatus; |
| | | import org.opends.server.backends.pluggable.spi.TreeName; |
| | |
| | | { |
| | | tempDN = baseDN.parent().child(tempDN); |
| | | } |
| | | entryContainer = rootContainer.openEntryContainer(tempDN, txn); |
| | | entryContainer = rootContainer.openEntryContainer(tempDN, txn, AccessMode.READ_WRITE); |
| | | break; |
| | | case INCLUDE_EXCLUDE_BRANCHES: |
| | | break; |
| | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ByteStringBuilder; |
| | | import org.opends.server.api.CompressedSchema; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.Cursor; |
| | | import org.opends.server.backends.pluggable.spi.Storage; |
| | | import org.opends.server.backends.pluggable.spi.StorageRuntimeException; |
| | |
| | | * @param storage |
| | | * A reference to the storage in which the trees will be held. |
| | | * @param txn a non null transaction |
| | | * @param accessMode specifies how the storage has been opened (read only or read/write) |
| | | * |
| | | * @throws StorageRuntimeException |
| | | * If a problem occurs while loading the compressed schema |
| | | * definitions from the tree. |
| | |
| | | * If an error occurs while loading and processing the compressed |
| | | * schema definitions. |
| | | */ |
| | | PersistentCompressedSchema(final Storage storage, WriteableTransaction txn) |
| | | PersistentCompressedSchema(final Storage storage, WriteableTransaction txn, AccessMode accessMode) |
| | | throws StorageRuntimeException, InitializationException |
| | | { |
| | | this.storage = storage; |
| | | load(txn); |
| | | load(txn, accessMode.isWriteable()); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Loads the compressed schema information from the tree. |
| | | * |
| | | * @throws StorageRuntimeException |
| | | * If an error occurs while loading the definitions from the tree. |
| | | * @throws InitializationException |
| | | * If an error occurs while loading and processing the definitions. |
| | | */ |
| | | private void load(WriteableTransaction txn) throws StorageRuntimeException, InitializationException |
| | | private void load(WriteableTransaction txn, boolean shouldCreate) |
| | | throws StorageRuntimeException, InitializationException |
| | | { |
| | | txn.openTree(adTreeName); |
| | | txn.openTree(ocTreeName); |
| | | txn.openTree(adTreeName, shouldCreate); |
| | | txn.openTree(ocTreeName, shouldCreate); |
| | | |
| | | // Cursor through the object class database and load the object class set |
| | | // definitions. At the same time, figure out the highest token value and |
| | |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.server.PluggableBackendCfg; |
| | | import org.opends.server.api.CompressedSchema; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.ReadOperation; |
| | | import org.opends.server.backends.pluggable.spi.ReadableTransaction; |
| | | import org.opends.server.backends.pluggable.spi.Storage; |
| | | import org.opends.server.backends.pluggable.spi.Storage.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.StorageRuntimeException; |
| | | import org.opends.server.backends.pluggable.spi.StorageStatus; |
| | | import org.opends.server.backends.pluggable.spi.WriteOperation; |
| | |
| | | /** |
| | | * Opens the root container. |
| | | * |
| | | * @param accessMode specifies how the container has to be opened (read-write or read-only) |
| | | * |
| | | * @throws StorageRuntimeException |
| | | * If an error occurs when opening the storage. |
| | | * @throws ConfigException |
| | | * If an configuration error occurs while opening the storage. |
| | | */ |
| | | void open(AccessMode accessMode) throws StorageRuntimeException, ConfigException |
| | | void open(final AccessMode accessMode) throws StorageRuntimeException, ConfigException |
| | | { |
| | | try |
| | | { |
| | |
| | | @Override |
| | | public void run(WriteableTransaction txn) throws Exception |
| | | { |
| | | compressedSchema = new PersistentCompressedSchema(storage, txn); |
| | | openAndRegisterEntryContainers(txn, config.getBaseDN()); |
| | | compressedSchema = new PersistentCompressedSchema(storage, txn, accessMode); |
| | | openAndRegisterEntryContainers(txn, config.getBaseDN(), accessMode); |
| | | } |
| | | }); |
| | | } |
| | |
| | | * The base DN of the entry container to open. |
| | | * @param txn |
| | | * The transaction |
| | | * @param accessMode specifies how the container has to be opened (read-write or read-only) |
| | | * @return The opened entry container. |
| | | * @throws StorageRuntimeException |
| | | * If an error occurs while opening the entry container. |
| | | * @throws ConfigException |
| | | * If an configuration error occurs while opening the entry container. |
| | | */ |
| | | EntryContainer openEntryContainer(DN baseDN, WriteableTransaction txn) |
| | | EntryContainer openEntryContainer(DN baseDN, WriteableTransaction txn, AccessMode accessMode) |
| | | throws StorageRuntimeException, ConfigException |
| | | { |
| | | EntryContainer ec = new EntryContainer(baseDN, backendId, config, storage, this); |
| | | ec.open(txn); |
| | | ec.open(txn, accessMode); |
| | | return ec; |
| | | } |
| | | |
| | |
| | | * |
| | | * @param baseDNs |
| | | * The base DNs of the entry containers to open. |
| | | * @param accessMode specifies how the containers have to be opened (read-write or read-only) |
| | | * |
| | | * @throws StorageRuntimeException |
| | | * If an error occurs while opening the entry container. |
| | | * @throws InitializationException |
| | |
| | | * If a configuration error occurs while opening the entry |
| | | * container. |
| | | */ |
| | | private void openAndRegisterEntryContainers(WriteableTransaction txn, Set<DN> baseDNs) throws StorageRuntimeException, |
| | | InitializationException, ConfigException |
| | | private void openAndRegisterEntryContainers(WriteableTransaction txn, Set<DN> baseDNs, AccessMode accessMode) |
| | | throws StorageRuntimeException, InitializationException, ConfigException |
| | | { |
| | | EntryID highestID = null; |
| | | for (DN baseDN : baseDNs) |
| | | { |
| | | EntryContainer ec = openEntryContainer(baseDN, txn); |
| | | EntryContainer ec = openEntryContainer(baseDN, txn, accessMode); |
| | | EntryID id = ec.getHighestEntryID(txn); |
| | | registerEntryContainer(baseDN, ec); |
| | | if (highestID == null || id.compareTo(highestID) > 0) |
| | |
| | | import org.forgerock.opendj.config.server.ConfigException; |
| | | import org.forgerock.opendj.ldap.ByteSequence; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.Cursor; |
| | | import org.opends.server.backends.pluggable.spi.Importer; |
| | | import org.opends.server.backends.pluggable.spi.ReadOperation; |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void openTree(final TreeName name) |
| | | public void openTree(final TreeName name, boolean createOnDemand) |
| | | { |
| | | txn.openTree(name); |
| | | txn.openTree(name, createOnDemand); |
| | | logger.trace("Storage@%s.WriteableTransaction@%s.openTree(%s, %s)", |
| | | storageId(), id(), backendId, name); |
| | | } |
| | |
| | | interface Tree |
| | | { |
| | | /** |
| | | * Opens a tree. If the provided configuration is transactional, |
| | | * Opens a tree, optionally creating it. If the provided configuration is transactional, |
| | | * a transaction will be created and used to perform the open. |
| | | * |
| | | * @param txn |
| | | * a non null transaction |
| | | * @param createOnDemand true if the tree should be created if it does not exist |
| | | * @throws StorageRuntimeException |
| | | * if an error occurs while opening the index. |
| | | */ |
| | | void open(WriteableTransaction txn) throws StorageRuntimeException; |
| | | void open(WriteableTransaction txn, boolean createOnDemand) throws StorageRuntimeException; |
| | | |
| | | /** |
| | | * Deletes this tree and all of its contents. |
| | |
| | | { |
| | | verifyDN2ID = true; |
| | | verifyID2ChildrenCount = true; |
| | | attrIndexList.addAll(entryContainer.getAttributeIndexes()); |
| | | for (AttributeIndex index : entryContainer.getAttributeIndexes()) |
| | | { |
| | | if (index.isTrusted()) |
| | | { |
| | | attrIndexList.add(index); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at legal-notices/CDDLv1_0.txt. |
| | | * If applicable, add the following below this CDDL HEADER, with the |
| | | * fields enclosed by brackets "[]" replaced with your own identifying |
| | | * information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Copyright 2015 ForgeRock AS |
| | | */ |
| | | package org.opends.server.backends.pluggable.spi; |
| | | |
| | | /** Defines access modes of a Storage. */ |
| | | public enum AccessMode { |
| | | /** Constant used to open the Storage in read-only mode; implies missing trees will be ignored. */ |
| | | READ_ONLY(false), |
| | | /** Constant used to open the Storage in read-write mode; implies trees will be created if not already present. */ |
| | | READ_WRITE(true); |
| | | |
| | | private boolean readWrite; |
| | | |
| | | AccessMode(boolean update) |
| | | { |
| | | this.readWrite = update; |
| | | } |
| | | |
| | | /** |
| | | * Returns if the storage is being opened READ_WRITE. |
| | | * |
| | | * @return true if the storage is being opened READ_WRITE |
| | | */ |
| | | public boolean isWriteable() |
| | | { |
| | | return readWrite; |
| | | } |
| | | } |
| | |
| | | public interface Storage extends Closeable |
| | | { |
| | | |
| | | /** Defines access modes of a Storage. */ |
| | | public enum AccessMode { |
| | | /** Constant used to open the Storage in read-only mode. */ |
| | | READ_ONLY, |
| | | /** Constant used to open the Storage in read-write mode. */ |
| | | READ_WRITE; |
| | | } |
| | | |
| | | /** |
| | | * Starts the import operation. |
| | | * |
| | |
| | | public interface WriteableTransaction extends ReadableTransaction |
| | | { |
| | | /** |
| | | * Opens the tree identified by the provided name. The tree is created if it does not already exist. |
| | | * Opens the tree identified by the provided name. |
| | | * |
| | | * @param name |
| | | * the tree name |
| | | * @param createOnDemand true if the tree should be created if it does not exist |
| | | */ |
| | | void openTree(TreeName name); |
| | | void openTree(TreeName name, boolean createOnDemand); |
| | | |
| | | /** |
| | | * Renames the tree from the old to the new name. |
| | |
| | | import org.opends.server.admin.std.server.BackendIndexCfg; |
| | | import org.opends.server.admin.std.server.PDBBackendCfg; |
| | | import org.opends.server.backends.pdb.PDBStorage; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.Cursor; |
| | | import org.opends.server.backends.pluggable.spi.ReadOperation; |
| | | import org.opends.server.backends.pluggable.spi.ReadableTransaction; |
| | | import org.opends.server.backends.pluggable.spi.SequentialCursor; |
| | | import org.opends.server.backends.pluggable.spi.Storage.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.TreeName; |
| | | import org.opends.server.backends.pluggable.spi.WriteOperation; |
| | | import org.opends.server.backends.pluggable.spi.WriteableTransaction; |
| | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.opends.server.DirectoryServerTestCase; |
| | | import org.opends.server.backends.pluggable.State.IndexFlag; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.Cursor; |
| | | import org.opends.server.backends.pluggable.spi.ReadableTransaction; |
| | | import org.opends.server.backends.pluggable.spi.StorageRuntimeException; |
| | |
| | | public void setUp() { |
| | | txn = new DummyWriteableTransaction(); |
| | | index = newIndex("test", 5, EnumSet.of(TRUSTED, COMPACTED));; |
| | | index.open(txn); |
| | | index.open(txn, true); |
| | | } |
| | | |
| | | @Test |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void openTree(TreeName name) |
| | | public void openTree(TreeName name, boolean createOnDemand) |
| | | { |
| | | storage.put(name, new TreeMap<ByteString, ByteString>()); |
| | | } |
| | |
| | | import org.opends.server.admin.std.server.BackendIndexCfg; |
| | | import org.opends.server.admin.std.server.PDBBackendCfg; |
| | | import org.opends.server.backends.pdb.PDBStorage; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.ReadOperation; |
| | | import org.opends.server.backends.pluggable.spi.ReadableTransaction; |
| | | import org.opends.server.backends.pluggable.spi.Storage.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.TreeName; |
| | | import org.opends.server.backends.pluggable.spi.WriteOperation; |
| | | import org.opends.server.backends.pluggable.spi.WriteableTransaction; |
| | |
| | | import org.opends.server.api.Backend.BackendOperation; |
| | | import org.opends.server.api.ClientConnection; |
| | | import org.opends.server.backends.VerifyConfig; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.ReadOnlyStorageException; |
| | | import org.opends.server.backends.pluggable.spi.ReadOperation; |
| | | import org.opends.server.backends.pluggable.spi.ReadableTransaction; |
| | | import org.opends.server.backends.pluggable.spi.Storage; |
| | | import org.opends.server.backends.pluggable.spi.Storage.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.TreeName; |
| | | import org.opends.server.backends.pluggable.spi.WriteOperation; |
| | | import org.opends.server.backends.pluggable.spi.WriteableTransaction; |
| | |
| | | import org.opends.server.admin.std.server.PDBBackendCfg; |
| | | import org.opends.server.backends.pdb.PDBStorage; |
| | | import org.opends.server.backends.pluggable.State.IndexFlag; |
| | | import org.opends.server.backends.pluggable.spi.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.ReadOperation; |
| | | import org.opends.server.backends.pluggable.spi.ReadableTransaction; |
| | | import org.opends.server.backends.pluggable.spi.Storage.AccessMode; |
| | | import org.opends.server.backends.pluggable.spi.TreeName; |
| | | import org.opends.server.backends.pluggable.spi.WriteOperation; |
| | | import org.opends.server.backends.pluggable.spi.WriteableTransaction; |