Attached patch increases the maximum possible log file number to 2^31 -1 and keeps the old limit of 2^22-1 on soft upgrade. Earlier patch for this problem increased it to 2^33 -1 , but that fix created upgrade problems because of the additional bits that are used from the file position field, so the limit is being reduced to 2^31-1.

Thanks
-suresht


Mike Matrigali wrote:

This seems like a reasonable 1st step, that would solve current
upgrade issues.  I suggest you submit this patch, close the current
jira, and submit a new future improvement jira noting what would
have to be done to eek out the last few bits (or documenting it
somewhere appropriate in the code is also fine - just rather not see
you have learned lost).  Given that this
soft upgrade stuff is new I would rather be safe this time.

/mikem

Suresh Thalamati wrote:

By looking at the code , it is kind of tricky to handle upgrade, because users can crash in the middle of recovery and reboot again N times , which can generate new log for uncommitted transaction and also all the constant that manipulates LSN are static now and are used by static routines in org.apache.derby.impl.store.raw.log.LogCounter.java, like :makeLogInstantAsLong().

To handle upgrade:
1) all static methods in LogCounter.java has to be replaced by instance methods , so that in the same JVM, one can run a database that is in softupgrade mode and one that is new/upgraded.. 2) modify the code to update the version number on disk(log control file ) to only when the recovery is complete;
     currently it is updated in the boot code itself.
3) perform a checkpoint after recovery on upgrade, so that new log file limits can be uses, As it will make
   sure that no old log instant format will be in use.

Instead of doing all of the above , I can reduce the limit to 2^31 -1 instead of 2^33-1 ; this way I would not need to change LogCounter.FILE_NUMBER_SHIFT from 32 (old value) to 30,
which causes all upgrade issues.

with 2^31 -1 it will take approximately 68 years (2147483647/(24 * 60 * 60 * 365)) to hit the log file number limit if a new log file is generated every second., instead of 272 years
with 2^33-1.

If no one has objections , I would prefer to increase the log file number limit to 2^31 -1 and avoid major upgrade issues. If any one strongly believes it should be 2^33 -1 , I will try
to do the necessary upgrade changes.

Any comments/suggestions ?

Thanks
-suresht




Suresh Thalamati wrote:

I just realized , this patch actaully break's hard upgrade also, if log needs to be replayed. Becuase I extract the log file number and log file postion from the instant that is on disk ,
differently after my change.

If any one else on the list is testing upgrade is hitting this problem, please let me know.
I can post a patch to backout the portion that cause upgrade issues.


Thanks
-suresht


Mike Matrigali wrote:

I am looking at committing this.  The changes look good to me, but I
believe there are upgrade issues to handle.

For a hard upgrade either new or old databases are fine.
For a soft upgrade I think there is a problem if the db generates enough log files to start using the new bits, and then the software is reverted
to before the fix.

Seems like using the bits needs to be somehow only enabled for hard
upgrade.  It would be best if it was controlled just by hard upgrade,
but if that is not possible then just doing it for databases created
since this version would also work - but still leave problems with old
hard upgraded databases.

I have reviewed the code and am running tests.  I plan on committing
this part of the fix and let you address upgrade issues with a follow on
patch.

Suresh Thalamati wrote:











Index: java/engine/org/apache/derby/impl/store/raw/log/LogCounter.java
===================================================================
--- java/engine/org/apache/derby/impl/store/raw/log/LogCounter.java     
(revision 171180)
+++ java/engine/org/apache/derby/impl/store/raw/log/LogCounter.java     
(working copy)
@@ -60,18 +60,18 @@
        
        /** A well defined value of an invalid log instant. */
        public static final long INVALID_LOG_INSTANT = 0;
+       
+       // max possible log file number in versions before 10.1 is 2^22 -1
+       public static final long DERBY_10_0_MAX_LOGFILE_NUMBER = 
(long)0x003FFFFFL; // 4194303
+       // max possible log file number is 2^31 -1
+       public static final long MAX_LOGFILE_NUMBER     = (long)0x7FFFFFFFL; // 
2147483647 
+       // lower end of 32 bits in long type are used to store the log file 
position
+       private static final long FILE_NUMBER_SHIFT     = 32;
 
-
-       // max possible log file number is 2^33 -1 (8589934591)
-       public static final long MAX_LOGFILE_NUMBER     = (long)0x1FFFFFFFFL; 
-
-       // lower end of 30 bits in long type are used to store the log file 
position
-       private static final long FILE_NUMBER_SHIFT     = 30;
-
-       // reserve top 2 bits in log file size for future use
+       // reserve top 4 bits in log file size for future use
        public static final long MAX_LOGFILE_SIZE           = 
(long)0x0FFFFFFFL; // 268435455
-       // 30 bits are used to store the log file postion
-       private static final long FILE_POSITION_MASK    = (long)0x3FFFFFFFL;
+       // 32 bits are used to store the log file postion
+       private static final long FILE_POSITION_MASK    = (long)0x7FFFFFFFL;
 
        private long fileNumber;
        private long filePosition;
Index: java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java
===================================================================
--- java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java      
(revision 171180)
+++ java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java      
(working copy)
@@ -333,7 +333,7 @@
                                                                // must be 
synchronized with this to access
                                                                // or change.
        
-
+       private long              maxLogFileNumber = 
LogCounter.MAX_LOGFILE_NUMBER;
        private CheckpointOperation              currentCheckpoint;
                                                                // last 
checkpoint successfully taken
                                                                // 
@@ -1831,11 +1831,11 @@
                        // used.
                        StorageFile newLogFile = 
getLogFileName(logFileNumber+1);
 
-                       if (logFileNumber+1 >= LogCounter.MAX_LOGFILE_NUMBER)
+                       if (logFileNumber+1 >= maxLogFileNumber)
             {
                                throw StandardException.newException(
                         SQLState.LOG_EXCEED_MAX_LOG_FILE_NUMBER, 
-                        new Long(LogCounter.MAX_LOGFILE_NUMBER)); 
+                        new Long(maxLogFileNumber)); 
             }
 
                        StorageRandomAccessFile newLog = null;  // the new log 
file
@@ -3059,6 +3059,21 @@
                {
                        throw Monitor.exceptionStartingModule(ioe);
                }
+                       
+               // Number of the log file that can be created in Derby is 
increased from 
+               // 2^22 -1 to 2^31 -1 in version 10.1. But if the database is 
running on
+               // engines 10.1 or above on a  softupgrade  from versions 10.0 
or
+               // before, the max log file number  that can be created is  
+               // still limited to 2^22 -1, because users can revert back to 
older  versions 
+               // which does not have logic to handle a log file number 
greater than
+               // 2^22-1. 
+
+               // set max possible log file number to derby 10.0 limit, if the 
database is not 
+               // fully upgraded to or created in version 10.1 or above. 
+               if (!checkVersion(RawStoreFactory.DERBY_STORE_MAJOR_VERSION_10, 
+                                                 
RawStoreFactory.DERBY_STORE_MINOR_VERSION_1))
+                       maxLogFileNumber = 
LogCounter.DERBY_10_0_MAX_LOGFILE_NUMBER;
+
        } // end of boot
 
     private void getLogStorageFactory() throws StandardException

Reply via email to