mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Valery Kharseko
2 days ago 97dbf50dd56ee7640411ac61e6aa288f208a4375
opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/JDBCStorage.java
@@ -1043,6 +1043,16 @@
         }
      }
   }
   /**
    * A transaction able to write, unless the storage was opened read-only: then it may open an existing tree and
    * read it, and every mutating operation throws {@link ReadOnlyStorageException} instead.
    * <p>
    * The mode is checked per operation rather than refused here, because {@code RootContainer.open(AccessMode)}
    * asks for a write transaction even in read-only mode - that is where it opens the compressed schema and the
    * entry containers - so refusing to hand one out failed the offline {@code export-ldif}, {@code verify-index}
    * and {@code backendstat} before they read anything (#874). Both other storages of this server already have
    * this shape: {@code PDBStorage.ReadOnlyStorageImpl} and {@code CASStorage.TransactionImpl.checkReadOnly()}.
    */
   private final class WriteableTransactionTransactionImpl extends ReadableTransactionImpl implements WriteableTransaction {
      // Shared by every table this transaction stamps: opening a backend opens all its trees,
@@ -1052,10 +1062,17 @@
      public WriteableTransactionTransactionImpl(Connection con) {
         super(con);
         if (!accessMode.isWriteable()) {
         //captured once rather than read per operation: the access mode of the storage is mutable state -
         //ImporterImpl reopens the storage READ_WRITE under its caller - and a transaction has to keep the mode
         //it was created with. It also drives isReadOnly, so that a cursor this transaction opens refuses
         //delete() as well.
         isReadOnly = !accessMode.isWriteable();
      }
      void checkReadOnly() {
         if (isReadOnly) {
            throw new ReadOnlyStorageException();
         }
         isReadOnly = false;
      }
      boolean isExistsTable(TreeName treeName) {
@@ -1096,6 +1113,7 @@
      @Override
      public void openTree(TreeName treeName, boolean createOnDemand) {
         if (createOnDemand) {
            checkReadOnly();
            if (!isExistsTable(treeName)) {
               try (final PreparedStatement statement=con.prepareStatement("create table "+getTableName(treeName)+" ("+getTableDialect()+")")){
                  execute(statement);
@@ -1158,6 +1176,7 @@
      }
      
      public void clearTree(TreeName treeName) {
         checkReadOnly();
         try (final PreparedStatement statement=con.prepareStatement("delete from "+getTableName(treeName))){
            execute(statement);
            con.commit();
@@ -1168,6 +1187,7 @@
      @Override
      public void deleteTree(TreeName treeName) {
         checkReadOnly();
         if (isExistsTable(treeName)) {
            try (final PreparedStatement statement = con.prepareStatement("drop table " + getTableName(treeName))) {
               execute(statement);
@@ -1183,6 +1203,7 @@
      @Override
      public void put(TreeName treeName, ByteSequence key, ByteSequence value) {
         checkReadOnly();
         try {
            upsert(treeName, key, value);
         } catch (SQLException e) {
@@ -1250,6 +1271,9 @@
      @Override
      public boolean update(TreeName treeName, ByteSequence key, UpdateFunction f) {
         //checked before the read, so that a read-only transaction reports the mode rather than the value it
         //computed being equal to the stored one
         checkReadOnly();
         final ByteString oldValue=read(treeName,key);
         final ByteSequence newValue=f.computeNewValue(oldValue);
         if (Objects.equals(newValue, oldValue))
@@ -1266,6 +1290,7 @@
      @Override
      public boolean delete(TreeName treeName, ByteSequence key) {
         checkReadOnly();
         try (final PreparedStatement statement=con.prepareStatement("delete from "+getTableName(treeName)+" where h="+hashParam(con)+" and k=?")){
            statement.setString(1,key2hash.get(ByteBuffer.wrap(key.toByteArray())));
            statement.setBytes(2,real2db(key.toByteArray()));