2525import java .io .UncheckedIOException ;
2626import java .util .ArrayList ;
2727import java .util .Arrays ;
28+ import java .util .Collections ;
29+ import java .util .HashMap ;
2830import java .util .List ;
31+ import java .util .Map ;
2932import org .apache .commons .lang3 .mutable .MutableLong ;
3033import org .apache .hadoop .conf .Configuration ;
3134import org .apache .hadoop .fs .FileStatus ;
4548import org .apache .hadoop .hbase .client .TableDescriptor ;
4649import org .apache .hadoop .hbase .client .TableDescriptorBuilder ;
4750import org .apache .hadoop .hbase .log .HBaseMarkers ;
51+ import org .apache .hadoop .hbase .master .assignment .AssignProcedure ;
52+ import org .apache .hadoop .hbase .master .assignment .MoveRegionProcedure ;
53+ import org .apache .hadoop .hbase .master .assignment .UnassignProcedure ;
54+ import org .apache .hadoop .hbase .master .procedure .RecoverMetaProcedure ;
55+ import org .apache .hadoop .hbase .master .procedure .ServerCrashProcedure ;
4856import org .apache .hadoop .hbase .procedure2 .Procedure ;
4957import org .apache .hadoop .hbase .procedure2 .ProcedureUtil ;
5058import org .apache .hadoop .hbase .procedure2 .store .LeaseRecovery ;
6573import org .slf4j .LoggerFactory ;
6674
6775import org .apache .hbase .thirdparty .com .google .common .annotations .VisibleForTesting ;
76+ import org .apache .hbase .thirdparty .com .google .common .collect .ImmutableSet ;
6877import org .apache .hbase .thirdparty .com .google .common .math .IntMath ;
6978
7079import org .apache .hadoop .hbase .shaded .protobuf .generated .ProcedureProtos ;
@@ -298,6 +307,46 @@ private HRegion open(Configuration conf, FileSystem fs, Path rootDir) throws IOE
298307 null );
299308 }
300309
310+ @ SuppressWarnings ("deprecation" )
311+ private static final ImmutableSet <Class <?>> UNSUPPORTED_PROCEDURES =
312+ ImmutableSet .of (RecoverMetaProcedure .class , AssignProcedure .class , UnassignProcedure .class ,
313+ MoveRegionProcedure .class );
314+
315+ /**
316+ * In HBASE-20811, we have introduced a new TRSP to assign/unassign/move regions, and it is
317+ * incompatible with the old AssignProcedure/UnassignProcedure/MoveRegionProcedure. So we need to
318+ * make sure that there are none these procedures when upgrading. If there are, the master will
319+ * quit, you need to go back to the old version to finish these procedures first before upgrading.
320+ */
321+ private void checkUnsupportedProcedure (Map <Class <?>, List <Procedure <?>>> procsByType )
322+ throws HBaseIOException {
323+ // Confirm that we do not have unfinished assign/unassign related procedures. It is not easy to
324+ // support both the old assign/unassign procedures and the new TransitRegionStateProcedure as
325+ // there will be conflict in the code for AM. We should finish all these procedures before
326+ // upgrading.
327+ for (Class <?> clazz : UNSUPPORTED_PROCEDURES ) {
328+ List <Procedure <?>> procs = procsByType .get (clazz );
329+ if (procs != null ) {
330+ LOG .error ("Unsupported procedure type {} found, please rollback your master to the old" +
331+ " version to finish them, and then try to upgrade again." +
332+ " See https://hbase.apache.org/book.html#upgrade2.2 for more details." +
333+ " The full procedure list: {}" , clazz , procs );
334+ throw new HBaseIOException ("Unsupported procedure type " + clazz + " found" );
335+ }
336+ }
337+ // A special check for SCP, as we do not support RecoverMetaProcedure any more so we need to
338+ // make sure that no one will try to schedule it but SCP does have a state which will schedule
339+ // it.
340+ if (procsByType .getOrDefault (ServerCrashProcedure .class , Collections .emptyList ()).stream ()
341+ .map (p -> (ServerCrashProcedure ) p ).anyMatch (ServerCrashProcedure ::isInRecoverMetaState )) {
342+ LOG .error ("At least one ServerCrashProcedure is going to schedule a RecoverMetaProcedure," +
343+ " which is not supported any more. Please rollback your master to the old version to" +
344+ " finish them, and then try to upgrade again." +
345+ " See https://hbase.apache.org/book.html#upgrade2.2 for more details." );
346+ throw new HBaseIOException ("Unsupported procedure state found for ServerCrashProcedure" );
347+ }
348+ }
349+
301350 @ SuppressWarnings ("deprecation" )
302351 private void tryMigrate (FileSystem fs ) throws IOException {
303352 Configuration conf = server .getConfiguration ();
@@ -311,7 +360,8 @@ private void tryMigrate(FileSystem fs) throws IOException {
311360 store .start (numThreads );
312361 store .recoverLease ();
313362 MutableLong maxProcIdSet = new MutableLong (-1 );
314- MutableLong maxProcIdFromProcs = new MutableLong (-1 );
363+ List <Procedure <?>> procs = new ArrayList <>();
364+ Map <Class <?>, List <Procedure <?>>> activeProcsByType = new HashMap <>();
315365 store .load (new ProcedureLoader () {
316366
317367 @ Override
@@ -321,16 +371,13 @@ public void setMaxProcId(long maxProcId) {
321371
322372 @ Override
323373 public void load (ProcedureIterator procIter ) throws IOException {
324- long procCount = 0 ;
325374 while (procIter .hasNext ()) {
326375 Procedure <?> proc = procIter .next ();
327- update (proc );
328- procCount ++;
329- if (proc .getProcId () > maxProcIdFromProcs .longValue ()) {
330- maxProcIdFromProcs .setValue (proc .getProcId ());
376+ procs .add (proc );
377+ if (!proc .isFinished ()) {
378+ activeProcsByType .computeIfAbsent (proc .getClass (), k -> new ArrayList <>()).add (proc );
331379 }
332380 }
333- LOG .info ("Migrated {} procedures" , procCount );
334381 }
335382
336383 @ Override
@@ -347,6 +394,22 @@ public void handleCorrupted(ProcedureIterator procIter) throws IOException {
347394 }
348395 }
349396 });
397+
398+ // check whether there are unsupported procedures, this could happen when we are migrating from
399+ // 2.1-. We used to do this in HMaster, after loading all the procedures from procedure store,
400+ // but here we have to do it before migrating, otherwise, if we find some unsupported
401+ // procedures, the users can not go back to 2.1 to finish them any more, as all the data are now
402+ // in the new region based procedure store, which is not supported in 2.1-.
403+ checkUnsupportedProcedure (activeProcsByType );
404+
405+ MutableLong maxProcIdFromProcs = new MutableLong (-1 );
406+ for (Procedure <?> proc : procs ) {
407+ update (proc );
408+ if (proc .getProcId () > maxProcIdFromProcs .longValue ()) {
409+ maxProcIdFromProcs .setValue (proc .getProcId ());
410+ }
411+ }
412+ LOG .info ("Migrated {} existing procedures from the old storage format." , procs .size ());
350413 LOG .info ("The WALProcedureStore max pid is {}, and the max pid of all loaded procedures is {}" ,
351414 maxProcIdSet .longValue (), maxProcIdFromProcs .longValue ());
352415 // Theoretically, the maxProcIdSet should be greater than or equal to maxProcIdFromProcs, but
0 commit comments