33
33
import org .apache .doris .catalog .Env ;
34
34
import org .apache .doris .catalog .HashDistributionInfo ;
35
35
import org .apache .doris .catalog .MTMV ;
36
+ import org .apache .doris .catalog .MetaIdGenerator ;
36
37
import org .apache .doris .catalog .OlapTable ;
37
38
import org .apache .doris .catalog .Partition ;
38
39
import org .apache .doris .catalog .PartitionItem ;
45
46
import org .apache .doris .common .FeConstants ;
46
47
import org .apache .doris .common .Pair ;
47
48
import org .apache .doris .common .util .AutoBucketUtils ;
49
+ import org .apache .doris .common .util .DebugPointUtil ;
48
50
import org .apache .doris .common .util .DynamicPartitionUtil ;
49
51
import org .apache .doris .common .util .MasterDaemon ;
50
52
import org .apache .doris .common .util .PropertyAnalyzer ;
51
53
import org .apache .doris .common .util .RangeUtils ;
52
54
import org .apache .doris .common .util .TimeUtils ;
55
+ import org .apache .doris .datasource .InternalCatalog ;
56
+ import org .apache .doris .persist .PartitionPersistInfo ;
53
57
import org .apache .doris .thrift .TStorageMedium ;
54
58
55
59
import com .google .common .base .Strings ;
71
75
import java .util .List ;
72
76
import java .util .Map ;
73
77
import java .util .Set ;
78
+ import java .util .stream .Collectors ;
74
79
75
80
/**
76
81
* This class is used to periodically add or drop partition on an olapTable which specify dynamic partition properties
@@ -582,9 +587,60 @@ private void executeDynamicPartition(Collection<Pair<Long, Long>> dynamicPartiti
582
587
}
583
588
584
589
if (!skipAddPartition ) {
585
- for (AddPartitionClause addPartitionClause : addPartitionClauses ) {
590
+ // get partitionIds and indexIds
591
+ List <Long > indexIds = new ArrayList <>(olapTable .getCopiedIndexIdToMeta ().keySet ());
592
+ List <Long > generatedPartitionIds = new ArrayList <>();
593
+ if (executeFirstTime && Config .isCloudMode () && !addPartitionClauses .isEmpty ()) {
594
+ AddPartitionClause addPartitionClause = addPartitionClauses .get (0 );
595
+ DistributionDesc distributionDesc = addPartitionClause .getDistributionDesc ();
586
596
try {
587
- Env .getCurrentEnv ().addPartition (db , tableName , addPartitionClause );
597
+ DistributionInfo distributionInfo = distributionDesc
598
+ .toDistributionInfo (olapTable .getBaseSchema ());
599
+ if (distributionDesc == null ) {
600
+ distributionInfo = olapTable .getDefaultDistributionInfo ()
601
+ .toDistributionDesc ().toDistributionInfo (olapTable .getBaseSchema ());
602
+ }
603
+ long allPartitionBufferSize = 0 ;
604
+ for (int i = 0 ; i < addPartitionClauses .size (); i ++) {
605
+ long bufferSize = InternalCatalog .checkAndGetBufferSize (indexIds .size (),
606
+ distributionInfo .getBucketNum (),
607
+ addPartitionClause .getSingeRangePartitionDesc ()
608
+ .getReplicaAlloc ().getTotalReplicaNum (),
609
+ db , tableName );
610
+ allPartitionBufferSize += bufferSize ;
611
+ }
612
+ MetaIdGenerator .IdGeneratorBuffer idGeneratorBuffer = Env .getCurrentEnv ()
613
+ .getIdGeneratorBuffer (allPartitionBufferSize );
614
+ addPartitionClauses .forEach (p -> generatedPartitionIds .add (idGeneratorBuffer .getNextId ()));
615
+ // executeFirstTime true
616
+ Env .getCurrentInternalCatalog ().beforeCreatePartitions (db .getId (), olapTable .getId (),
617
+ generatedPartitionIds , indexIds , true );
618
+ } catch (Exception e ) {
619
+ LOG .warn ("cloud in prepare step, dbName {}, tableName {}, tableId {} indexId {} exception {}" ,
620
+ db .getFullName (), tableName , olapTable .getId (), indexIds , e .getMessage ());
621
+ recordCreatePartitionFailedMsg (db .getFullName (), tableName , e .getMessage (), olapTable .getId ());
622
+ throw new DdlException ("cloud in prepare step err" );
623
+ }
624
+ }
625
+
626
+ List <PartitionPersistInfo > partsInfo = new ArrayList <>();
627
+ for (int i = 0 ; i < addPartitionClauses .size (); i ++) {
628
+ try {
629
+ boolean needWriteEditLog = true ;
630
+ // ATTN: !executeFirstTime, needWriteEditLog
631
+ // here executeFirstTime is create table, so in cloud edit log will postpone
632
+ if (Config .isCloudMode ()) {
633
+ needWriteEditLog = !executeFirstTime ;
634
+ }
635
+ PartitionPersistInfo info =
636
+ Env .getCurrentEnv ().addPartition (db , tableName , addPartitionClauses .get (i ),
637
+ executeFirstTime ,
638
+ executeFirstTime && Config .isCloudMode () ? generatedPartitionIds .get (i ) : 0 ,
639
+ needWriteEditLog );
640
+ if (info == null ) {
641
+ throw new Exception ("null persisted partition returned" );
642
+ }
643
+ partsInfo .add (info );
588
644
clearCreatePartitionFailedMsg (olapTable .getId ());
589
645
} catch (Exception e ) {
590
646
recordCreatePartitionFailedMsg (db .getFullName (), tableName , e .getMessage (), olapTable .getId ());
@@ -594,6 +650,55 @@ private void executeDynamicPartition(Collection<Pair<Long, Long>> dynamicPartiti
594
650
}
595
651
}
596
652
}
653
+ List <Long > succeedPartitionIds = partsInfo .stream ().map (partitionPersistInfo
654
+ -> partitionPersistInfo .getPartition ().getId ()).collect (Collectors .toList ());
655
+ if (executeFirstTime && Config .isCloudMode () && !addPartitionClauses .isEmpty ()) {
656
+ try {
657
+ // ATTN: failedPids = generatedPartitionIds - succeedPartitionIds,
658
+ // means some partitions failed when addPartition, failedPids will be recycled by recycler
659
+ if (DebugPointUtil .isEnable ("FE.DynamicPartitionScheduler.before.commitCloudPartition" )) {
660
+ LOG .info ("debug point FE.DynamicPartitionScheduler.before.commitCloudPartition, throw e" );
661
+ // not commit, not log edit
662
+ throw new Exception ("debug point FE.DynamicPartitionScheduler.before.commitCloudPartition" );
663
+ }
664
+ Env .getCurrentInternalCatalog ().afterCreatePartitions (db .getId (), olapTable .getId (),
665
+ succeedPartitionIds , indexIds , true );
666
+ LOG .info ("begin write edit log to add partitions in batch, "
667
+ + "numPartitions: {}, db: {}, table: {}, tableId: {}" ,
668
+ partsInfo .size (), db .getFullName (), tableName , olapTable .getId ());
669
+ // ATTN: here, edit log must after commit cloud partition,
670
+ // prevent commit RPC failure from causing data loss
671
+ if (DebugPointUtil .isEnable ("FE.DynamicPartitionScheduler.before.logEditPartitions" )) {
672
+ LOG .info ("debug point FE.DynamicPartitionScheduler.before.logEditPartitions, throw e" );
673
+ // committed, but not log edit
674
+ throw new Exception ("debug point FE.DynamicPartitionScheduler.before.commitCloudPartition" );
675
+ }
676
+ for (int i = 0 ; i < partsInfo .size (); i ++) {
677
+ Env .getCurrentEnv ().getEditLog ().logAddPartition (partsInfo .get (i ));
678
+ if (DebugPointUtil .isEnable ("FE.DynamicPartitionScheduler.in.logEditPartitions" )) {
679
+ if (i == partsInfo .size () / 2 ) {
680
+ LOG .info ("debug point FE.DynamicPartitionScheduler.in.logEditPartitions, throw e" );
681
+ // committed, but log some edit, others failed
682
+ throw new Exception ("debug point FE.DynamicPartitionScheduler"
683
+ + ".in.commitCloudPartition" );
684
+ }
685
+ }
686
+ }
687
+ LOG .info ("finish write edit log to add partitions in batch, "
688
+ + "numPartitions: {}, db: {}, table: {}, tableId: {}" ,
689
+ partsInfo .size (), db .getFullName (), tableName , olapTable .getId ());
690
+ } catch (Exception e ) {
691
+ LOG .warn ("cloud in commit step, dbName {}, tableName {}, tableId {} exception {}" ,
692
+ db .getFullName (), tableName , olapTable .getId (), e .getMessage ());
693
+ recordCreatePartitionFailedMsg (db .getFullName (), tableName , e .getMessage (), olapTable .getId ());
694
+ throw new DdlException ("cloud in commit step err" );
695
+ }
696
+ }
697
+ // cloud mode, check recycle key not remained
698
+ if (Config .isCloudMode () && executeFirstTime ) {
699
+ Env .getCurrentInternalCatalog ().checkCreatePartitions (db .getId (), olapTable .getId (),
700
+ succeedPartitionIds , indexIds );
701
+ }
597
702
}
598
703
}
599
704
}
0 commit comments