11
11
12
12
import org .apache .logging .log4j .LogManager ;
13
13
import org .apache .logging .log4j .Logger ;
14
- import org .apache .lucene .util .SetOnce ;
15
14
import org .elasticsearch .TransportVersions ;
16
15
import org .elasticsearch .cluster .ClusterState ;
17
16
import org .elasticsearch .cluster .Diff ;
53
52
54
53
import java .io .IOException ;
55
54
import java .util .ArrayList ;
56
- import java .util .Collection ;
57
55
import java .util .Collections ;
58
56
import java .util .EnumSet ;
59
57
import java .util .HashMap ;
@@ -997,12 +995,11 @@ private MetadataDiff(StreamInput in) throws IOException {
997
995
multiProject = null ;
998
996
} else {
999
997
fromNodeBeforeMultiProjectsSupport = false ;
1000
- // Repositories metadata is sent as Metadata#customs diff from old node. We need to
1001
- // 1. Split it from the Metadata#customs diff
1002
- // 2. Merge it into the default project's ProjectMetadataDiff
1003
- final var bwcCustoms = maybeReadBwcCustoms (in );
1004
- clusterCustoms = bwcCustoms .v1 ();
1005
- final var defaultProjectCustoms = bwcCustoms .v2 ();
998
+ clusterCustoms = DiffableUtils .readImmutableOpenMapDiff (
999
+ in ,
1000
+ DiffableUtils .getStringKeySerializer (),
1001
+ CLUSTER_CUSTOM_VALUE_SERIALIZER
1002
+ );
1006
1003
1007
1004
reservedStateMetadata = DiffableUtils .readImmutableOpenMapDiff (
1008
1005
in ,
@@ -1011,61 +1008,15 @@ private MetadataDiff(StreamInput in) throws IOException {
1011
1008
);
1012
1009
1013
1010
singleProject = null ;
1014
- multiProject = readMultiProjectDiffs (in , defaultProjectCustoms );
1015
- }
1016
- }
1017
-
1018
- private static
1019
- Tuple <
1020
- MapDiff <String , ClusterCustom , ImmutableOpenMap <String , ClusterCustom >>,
1021
- MapDiff <String , ProjectCustom , ImmutableOpenMap <String , ProjectCustom >>>
1022
- maybeReadBwcCustoms (StreamInput in ) throws IOException {
1023
- if (in .getTransportVersion ().before (TransportVersions .REPOSITORIES_METADATA_AS_PROJECT_CUSTOM )) {
1024
- return readBwcCustoms (in );
1025
- } else {
1026
- return new Tuple <>(
1027
- DiffableUtils .readImmutableOpenMapDiff (in , DiffableUtils .getStringKeySerializer (), CLUSTER_CUSTOM_VALUE_SERIALIZER ),
1028
- null
1011
+ multiProject = DiffableUtils .readJdkMapDiff (
1012
+ in ,
1013
+ PROJECT_ID_SERIALIZER ,
1014
+ ProjectMetadata ::readFrom ,
1015
+ ProjectMetadata .ProjectMetadataDiff ::new
1029
1016
);
1030
1017
}
1031
1018
}
1032
1019
1033
- @ SuppressWarnings ("unchecked" )
1034
- private static MapDiff <ProjectId , ProjectMetadata , Map <ProjectId , ProjectMetadata >> readMultiProjectDiffs (
1035
- StreamInput in ,
1036
- MapDiff <String , ProjectCustom , ImmutableOpenMap <String , ProjectCustom >> defaultProjectCustoms
1037
- ) throws IOException {
1038
- final var multiProject = DiffableUtils .readJdkMapDiff (
1039
- in ,
1040
- PROJECT_ID_SERIALIZER ,
1041
- ProjectMetadata ::readFrom ,
1042
- ProjectMetadata .ProjectMetadataDiff ::new
1043
- );
1044
-
1045
- // If the defaultProjectCustoms has content, the diff is read from an old node. We need to merge it into the
1046
- // default project's ProjectMetadataDiff
1047
- if (defaultProjectCustoms != null && defaultProjectCustoms .isEmpty () == false ) {
1048
- return DiffableUtils .updateDiffsAndUpserts (multiProject , ProjectId .DEFAULT ::equals , (k , v ) -> {
1049
- assert ProjectId .DEFAULT .equals (k ) : k ;
1050
- assert v instanceof ProjectMetadata .ProjectMetadataDiff : v ;
1051
- final var projectMetadataDiff = (ProjectMetadata .ProjectMetadataDiff ) v ;
1052
- return projectMetadataDiff .withCustoms (
1053
- DiffableUtils .merge (
1054
- projectMetadataDiff .customs (),
1055
- defaultProjectCustoms ,
1056
- DiffableUtils .getStringKeySerializer (),
1057
- BWC_CUSTOM_VALUE_SERIALIZER
1058
- )
1059
- );
1060
- }, (k , v ) -> {
1061
- assert ProjectId .DEFAULT .equals (k ) : k ;
1062
- return ProjectMetadata .builder (v ).clearCustoms ().customs (defaultProjectCustoms .apply (v .customs ())).build ();
1063
- });
1064
- } else {
1065
- return multiProject ;
1066
- }
1067
- }
1068
-
1069
1020
@ SuppressWarnings ("unchecked" )
1070
1021
private static
1071
1022
Tuple <
@@ -1109,105 +1060,16 @@ public void writeTo(StreamOutput out) throws IOException {
1109
1060
buildUnifiedCustomDiff ().writeTo (out );
1110
1061
buildUnifiedReservedStateMetadataDiff ().writeTo (out );
1111
1062
} else {
1112
- final var multiProjectToWrite = multiProject != null
1113
- ? multiProject
1114
- : DiffableUtils .singleEntryDiff (DEFAULT_PROJECT_ID , singleProject , PROJECT_ID_SERIALIZER );
1115
-
1116
- if (out .getTransportVersion ().before (TransportVersions .REPOSITORIES_METADATA_AS_PROJECT_CUSTOM )) {
1117
- writeDiffWithRepositoriesMetadataAsClusterCustom (out , clusterCustoms , multiProjectToWrite , reservedStateMetadata );
1063
+ clusterCustoms .writeTo (out );
1064
+ reservedStateMetadata .writeTo (out );
1065
+ if (multiProject != null ) {
1066
+ multiProject .writeTo (out );
1118
1067
} else {
1119
- clusterCustoms .writeTo (out );
1120
- reservedStateMetadata .writeTo (out );
1121
- multiProjectToWrite .writeTo (out );
1068
+ DiffableUtils .singleEntryDiff (DEFAULT_PROJECT_ID , singleProject , PROJECT_ID_SERIALIZER ).writeTo (out );
1122
1069
}
1123
1070
}
1124
1071
}
1125
1072
1126
- @ SuppressWarnings ({ "rawtypes" , "unchecked" })
1127
- private static void writeDiffWithRepositoriesMetadataAsClusterCustom (
1128
- StreamOutput out ,
1129
- MapDiff <String , ClusterCustom , ImmutableOpenMap <String , ClusterCustom >> clusterCustoms ,
1130
- MapDiff <ProjectId , ProjectMetadata , Map <ProjectId , ProjectMetadata >> multiProject ,
1131
- MapDiff <String , ReservedStateMetadata , ImmutableOpenMap <String , ReservedStateMetadata >> reservedStateMetadata
1132
- ) throws IOException {
1133
- assert out .getTransportVersion ().onOrAfter (TransportVersions .MULTI_PROJECT )
1134
- && out .getTransportVersion ().before (TransportVersions .REPOSITORIES_METADATA_AS_PROJECT_CUSTOM ) : out .getTransportVersion ();
1135
-
1136
- // For old nodes, RepositoriesMetadata needs to be sent as a cluster custom. This is possible when (a) the repositories
1137
- // are defined only for the default project or (b) no repositories at all. What we need to do are:
1138
- // 1. Iterate through the multi-project's MapDiff to extract the RepositoriesMetadata of the default project
1139
- // 2. Throws if any repositories are found for non-default projects
1140
- // 3. Merge default project's RepositoriesMetadata into Metadata#customs
1141
- final var combineClustersCustoms = new SetOnce <MapDiff <String , MetadataCustom , Map <String , MetadataCustom >>>();
1142
- final var updatedMultiProject = DiffableUtils .updateDiffsAndUpserts (multiProject , ignore -> true , (k , v ) -> {
1143
- assert v instanceof ProjectMetadata .ProjectMetadataDiff : v ;
1144
- final var projectMetadataDiff = (ProjectMetadata .ProjectMetadataDiff ) v ;
1145
- final var bwcCustoms = DiffableUtils .split (
1146
- projectMetadataDiff .customs (),
1147
- RepositoriesMetadata .TYPE ::equals ,
1148
- PROJECT_CUSTOM_VALUE_SERIALIZER ,
1149
- type -> RepositoriesMetadata .TYPE .equals (type ) == false ,
1150
- PROJECT_CUSTOM_VALUE_SERIALIZER
1151
- );
1152
- // Simply return if RepositoriesMetadata is not found
1153
- if (bwcCustoms .v1 ().isEmpty ()) {
1154
- return projectMetadataDiff ;
1155
- }
1156
- // RepositoriesMetadata can only be defined for the default project. Otherwise throw exception.
1157
- if (ProjectId .DEFAULT .equals (k ) == false ) {
1158
- throwForVersionBeforeRepositoriesMetadataMigration (out );
1159
- }
1160
- // RepositoriesMetadata is found for the default project as a diff, merge it into the Metadata#customs
1161
- combineClustersCustoms .set (
1162
- DiffableUtils .<String , MetadataCustom , ClusterCustom , ProjectCustom , Map <String , MetadataCustom >>merge (
1163
- clusterCustoms ,
1164
- bwcCustoms .v1 (),
1165
- DiffableUtils .getStringKeySerializer ()
1166
- )
1167
- );
1168
- return projectMetadataDiff .withCustoms (bwcCustoms .v2 ());
1169
- }, (k , v ) -> {
1170
- final ProjectCustom projectCustom = v .customs ().get (RepositoriesMetadata .TYPE );
1171
- // Simply return if RepositoriesMetadata is not found
1172
- if (projectCustom == null ) {
1173
- return v ;
1174
- }
1175
- // RepositoriesMetadata can only be defined for the default project. Otherwise throw exception.
1176
- if (ProjectId .DEFAULT .equals (k ) == false ) {
1177
- throwForVersionBeforeRepositoriesMetadataMigration (out );
1178
- }
1179
- // RepositoriesMetadata found for the default project as an upsert, package it as MapDiff and merge into Metadata#customs
1180
- combineClustersCustoms .set (
1181
- DiffableUtils .<String , MetadataCustom , ClusterCustom , ProjectCustom , Map <String , MetadataCustom >>merge (
1182
- clusterCustoms ,
1183
- DiffableUtils .singleUpsertDiff (RepositoriesMetadata .TYPE , projectCustom , DiffableUtils .getStringKeySerializer ()),
1184
- DiffableUtils .getStringKeySerializer ()
1185
- )
1186
- );
1187
- return ProjectMetadata .builder (v ).removeCustom (RepositoriesMetadata .TYPE ).build ();
1188
- });
1189
-
1190
- if (combineClustersCustoms .get () != null ) {
1191
- combineClustersCustoms .get ().writeTo (out );
1192
- } else {
1193
- clusterCustoms .writeTo (out );
1194
- }
1195
-
1196
- reservedStateMetadata .writeTo (out );
1197
- updatedMultiProject .writeTo (out );
1198
- }
1199
-
1200
- private static void throwForVersionBeforeRepositoriesMetadataMigration (StreamOutput out ) {
1201
- assert out .getTransportVersion ().before (TransportVersions .REPOSITORIES_METADATA_AS_PROJECT_CUSTOM ) : out .getTransportVersion ();
1202
- throw new UnsupportedOperationException (
1203
- "Serialize a diff with repositories defined for multiple projects requires version on or after ["
1204
- + TransportVersions .REPOSITORIES_METADATA_AS_PROJECT_CUSTOM
1205
- + "], but got ["
1206
- + out .getTransportVersion ()
1207
- + "]"
1208
- );
1209
- }
1210
-
1211
1073
@ SuppressWarnings ("unchecked" )
1212
1074
private Diff <ImmutableOpenMap <String , ?>> buildUnifiedCustomDiff () {
1213
1075
assert multiProject == null : "should only be used for single project metadata" ;
@@ -1361,34 +1223,19 @@ public static Metadata readFrom(StreamInput in) throws IOException {
1361
1223
builder .put (ReservedStateMetadata .readFrom (in ));
1362
1224
}
1363
1225
} else {
1364
- List <ProjectCustom > defaultProjectCustoms = List .of ();
1365
- if (in .getTransportVersion ().before (TransportVersions .REPOSITORIES_METADATA_AS_PROJECT_CUSTOM )) {
1366
- // Extract the default project's repositories metadata from the Metadata#customs from an old node
1367
- defaultProjectCustoms = new ArrayList <>();
1368
- readBwcCustoms (in , builder , defaultProjectCustoms ::add );
1369
- assert defaultProjectCustoms .size () <= 1
1370
- : "expect only a single default project custom for repository metadata, but got "
1371
- + defaultProjectCustoms .stream ().map (ProjectCustom ::getWriteableName ).toList ();
1372
- } else {
1373
- readClusterCustoms (in , builder );
1374
- }
1226
+ readClusterCustoms (in , builder );
1375
1227
1376
1228
int reservedStateSize = in .readVInt ();
1377
1229
for (int i = 0 ; i < reservedStateSize ; i ++) {
1378
1230
builder .put (ReservedStateMetadata .readFrom (in ));
1379
1231
}
1380
1232
1381
1233
builder .projectMetadata (in .readMap (ProjectId ::readFrom , ProjectMetadata ::readFrom ));
1382
- defaultProjectCustoms .forEach (c -> builder .getProject (ProjectId .DEFAULT ).putCustom (c .getWriteableName (), c ));
1383
1234
}
1384
1235
return builder .build ();
1385
1236
}
1386
1237
1387
1238
private static void readBwcCustoms (StreamInput in , Builder builder ) throws IOException {
1388
- readBwcCustoms (in , builder , projectCustom -> builder .putProjectCustom (projectCustom .getWriteableName (), projectCustom ));
1389
- }
1390
-
1391
- private static void readBwcCustoms (StreamInput in , Builder builder , Consumer <ProjectCustom > projectCustomConsumer ) throws IOException {
1392
1239
final Set <String > clusterScopedNames = in .namedWriteableRegistry ().getReaders (ClusterCustom .class ).keySet ();
1393
1240
final Set <String > projectScopedNames = in .namedWriteableRegistry ().getReaders (ProjectCustom .class ).keySet ();
1394
1241
final int count = in .readVInt ();
@@ -1404,9 +1251,9 @@ private static void readBwcCustoms(StreamInput in, Builder builder, Consumer<Pro
1404
1251
if (custom instanceof PersistentTasksCustomMetadata persistentTasksCustomMetadata ) {
1405
1252
final var tuple = persistentTasksCustomMetadata .split ();
1406
1253
builder .putCustom (tuple .v1 ().getWriteableName (), tuple .v1 ());
1407
- projectCustomConsumer . accept ( tuple .v2 ());
1254
+ builder . putProjectCustom ( tuple . v2 (). getWriteableName (), tuple .v2 ());
1408
1255
} else {
1409
- projectCustomConsumer . accept ( custom );
1256
+ builder . putProjectCustom ( custom . getWriteableName (), custom );
1410
1257
}
1411
1258
} else {
1412
1259
throw new IllegalArgumentException ("Unknown custom name [" + name + "]" );
@@ -1473,42 +1320,13 @@ public void writeTo(StreamOutput out) throws IOException {
1473
1320
combinedMetadata .addAll (singleProject .reservedStateMetadata ().values ());
1474
1321
out .writeCollection (combinedMetadata );
1475
1322
} else {
1476
- if (out .getTransportVersion ().before (TransportVersions .REPOSITORIES_METADATA_AS_PROJECT_CUSTOM )) {
1477
- if (isSingleProject () || hasNoNonDefaultProjectRepositories (projects ().values ())) {
1478
- // Repositories metadata must be sent as Metadata#customs for old nodes
1479
- final List <VersionedNamedWriteable > combinedCustoms = new ArrayList <>(customs .size () + 1 );
1480
- combinedCustoms .addAll (customs .values ());
1481
- final ProjectCustom custom = getProject (ProjectId .DEFAULT ).custom (RepositoriesMetadata .TYPE );
1482
- if (custom != null ) {
1483
- combinedCustoms .add (custom );
1484
- }
1485
- VersionedNamedWriteable .writeVersionedWriteables (out , combinedCustoms );
1486
- } else {
1487
- throw new UnsupportedOperationException (
1488
- "Serialize metadata with repositories defined for multiple projects requires version on or after ["
1489
- + TransportVersions .REPOSITORIES_METADATA_AS_PROJECT_CUSTOM
1490
- + "], but got ["
1491
- + out .getTransportVersion ()
1492
- + "]"
1493
- );
1494
- }
1495
- } else {
1496
- VersionedNamedWriteable .writeVersionedWriteables (out , customs .values ());
1497
- }
1323
+ VersionedNamedWriteable .writeVersionedWriteables (out , customs .values ());
1498
1324
1499
1325
out .writeCollection (reservedStateMetadata .values ());
1500
1326
out .writeMap (projectMetadata , StreamOutput ::writeWriteable , StreamOutput ::writeWriteable );
1501
1327
}
1502
1328
}
1503
1329
1504
- /**
1505
- * @return {@code true} iff no repositories are defined for non-default-projects.
1506
- */
1507
- private static boolean hasNoNonDefaultProjectRepositories (Collection <ProjectMetadata > projects ) {
1508
- return projects .stream ()
1509
- .allMatch (project -> ProjectId .DEFAULT .equals (project .id ()) || project .custom (RepositoriesMetadata .TYPE ) == null );
1510
- }
1511
-
1512
1330
public static Builder builder () {
1513
1331
return new Builder ();
1514
1332
}
0 commit comments