1414 */
1515package com .amazonaws .dynamodb .bootstrap ;
1616
17- import java .util .ArrayList ;
18- import java .util .List ;
19- import java .util .concurrent .ArrayBlockingQueue ;
20- import java .util .concurrent .ExecutionException ;
21- import java .util .concurrent .ExecutorService ;
22- import java .util .concurrent .ThreadPoolExecutor ;
23- import java .util .concurrent .TimeUnit ;
24-
2517import com .amazonaws .AmazonServiceException ;
18+ import com .amazonaws .ClientConfiguration ;
19+ import com .amazonaws .auth .DefaultAWSCredentialsProviderChain ;
2620import com .amazonaws .client .builder .AwsClientBuilder ;
21+ import com .amazonaws .dynamodb .bootstrap .constants .BootstrapConstants ;
22+ import com .amazonaws .dynamodb .bootstrap .consumer .DynamoDBConsumer ;
23+ import com .amazonaws .dynamodb .bootstrap .exception .NullReadCapacityException ;
24+ import com .amazonaws .dynamodb .bootstrap .exception .SectionOutOfRangeException ;
25+ import com .amazonaws .dynamodb .bootstrap .worker .DynamoDBBootstrapWorker ;
2726import com .amazonaws .regions .Region ;
2827import com .amazonaws .regions .Regions ;
2928import com .amazonaws .services .dynamodbv2 .AmazonDynamoDB ;
3029import com .amazonaws .services .dynamodbv2 .AmazonDynamoDBClientBuilder ;
31- import com .amazonaws .services .dynamodbv2 .model .*;
30+ import com .amazonaws .services .dynamodbv2 .model .DescribeTableRequest ;
31+ import com .amazonaws .services .dynamodbv2 .model .ProvisionedThroughput ;
32+ import com .amazonaws .services .dynamodbv2 .model .ProvisionedThroughputDescription ;
33+ import com .amazonaws .services .dynamodbv2 .model .ResourceNotFoundException ;
34+ import com .amazonaws .services .dynamodbv2 .model .TableDescription ;
3235import com .amazonaws .waiters .WaiterParameters ;
3336import com .amazonaws .waiters .WaiterTimedOutException ;
3437import com .amazonaws .waiters .WaiterUnrecoverableException ;
35- import com .google .common .annotations .VisibleForTesting ;
36- import com .google .common .base .Optional ;
37- import lombok .extern .log4j .Log4j ;
38-
39- import com .amazonaws .ClientConfiguration ;
40- import com .amazonaws .auth .DefaultAWSCredentialsProviderChain ;
41- import com .amazonaws .dynamodb .bootstrap .constants .BootstrapConstants ;
42- import com .amazonaws .dynamodb .bootstrap .exception .NullReadCapacityException ;
43- import com .amazonaws .dynamodb .bootstrap .exception .SectionOutOfRangeException ;
4438import com .beust .jcommander .JCommander ;
4539import com .beust .jcommander .ParameterException ;
40+ import com .google .common .base .Preconditions ;
41+ import lombok .extern .log4j .Log4j ;
42+
43+ import java .util .Optional ;
44+ import java .util .SortedSet ;
45+ import java .util .TreeSet ;
46+ import java .util .concurrent .ArrayBlockingQueue ;
47+ import java .util .concurrent .ExecutionException ;
48+ import java .util .concurrent .ExecutorService ;
49+ import java .util .concurrent .ThreadPoolExecutor ;
50+ import java .util .concurrent .TimeUnit ;
4651
4752/**
4853 * The interface that parses the arguments, and begins to transfer data from one
@@ -54,7 +59,7 @@ public class CommandLineInterface {
5459 public static final String ENCOUNTERED_EXCEPTION_WHEN_EXECUTING_TRANSFER = "Encountered exception when executing transfer." ;
5560
5661 static AwsClientBuilder .EndpointConfiguration createEndpointConfiguration (Region region , Optional <String > endpoint , String endpointPrefix ) {
57- return new AwsClientBuilder .EndpointConfiguration (endpoint .or ("https://" + region .getServiceEndpoint (endpointPrefix )), region .getName ());
62+ return new AwsClientBuilder .EndpointConfiguration (endpoint .orElse ("https://" + region .getServiceEndpoint (endpointPrefix )), region .getName ());
5863 }
5964
6065 private final AwsClientBuilder .EndpointConfiguration sourceEndpointConfiguration ;
@@ -66,72 +71,37 @@ static AwsClientBuilder.EndpointConfiguration createEndpointConfiguration(Region
6671 private final int maxWriteThreads ;
6772 private final boolean isConsistentScan ;
6873 private final boolean createDestinationTableIfMissing ;
74+ private final boolean createAllGsi ;
75+ private final boolean createAllLsi ;
76+ private final SortedSet <String > includeGsi ;
77+ private final SortedSet <String > includeLsi ;
6978 private final boolean copyStreamSpecification ;
7079 private final int sectionNumber ;
7180 private final int totalSections ;
7281
7382 private CommandLineInterface (final CommandLineArgs params ) {
7483 sourceEndpointConfiguration = createEndpointConfiguration (Region .getRegion (Regions .fromName (params .getSourceSigningRegion ())),
75- Optional .fromNullable (params .getSourceEndpoint ()), AmazonDynamoDB .ENDPOINT_PREFIX );
84+ Optional .ofNullable (params .getSourceEndpoint ()), AmazonDynamoDB .ENDPOINT_PREFIX );
7685 sourceTable = params .getSourceTable ();
7786 destinationEndpointConfiguration = createEndpointConfiguration (Region .getRegion (Regions .fromName (params .getDestinationSigningRegion ())),
78- Optional .fromNullable (params .getDestinationEndpoint ()), AmazonDynamoDB .ENDPOINT_PREFIX );
87+ Optional .ofNullable (params .getDestinationEndpoint ()), AmazonDynamoDB .ENDPOINT_PREFIX );
7988 destinationTable = params .getDestinationTable ();
8089 readThroughputRatio = params .getReadThroughputRatio ();
8190 writeThroughputRatio = params .getWriteThroughputRatio ();
8291 maxWriteThreads = params .getMaxWriteThreads ();
8392 isConsistentScan = params .isConsistentScan ();
8493 createDestinationTableIfMissing = params .isCreateDestinationTableIfMissing ();
94+ createAllGsi = params .isCreateAllGsi ();
95+ createAllLsi = params .isCreateAllLsi ();
96+ includeLsi = new TreeSet <>(params .getIncludeLsi ());
97+ Preconditions .checkArgument (includeLsi .size () == params .getIncludeLsi ().size (), "list of LSI names must be unique" );
98+ includeGsi = new TreeSet <>(params .getIncludeGsi ());
99+ Preconditions .checkArgument (includeGsi .size () == params .getIncludeGsi ().size (), "list of GSI names must be unique" );
85100 copyStreamSpecification = params .isCopyStreamSpecification ();
86101 sectionNumber = params .getSection ();
87102 totalSections = params .getTotalSections ();
88103 }
89104
90- static List <GlobalSecondaryIndex > convertGlobalSecondaryIndexDescriptions (List <GlobalSecondaryIndexDescription > list ) {
91- final List <GlobalSecondaryIndex > result = new ArrayList <>(list .size ());
92- for (GlobalSecondaryIndexDescription description : list ) {
93- result .add (new GlobalSecondaryIndex ()
94- .withIndexName (description .getIndexName ())
95- .withKeySchema (description .getKeySchema ())
96- .withProjection (description .getProjection ())
97- .withProvisionedThroughput (getProvisionedThroughputFromDescription (description .getProvisionedThroughput ())));
98- }
99- return result ;
100- }
101-
102- static List <LocalSecondaryIndex > convertLocalSecondaryIndexDescriptions (List <LocalSecondaryIndexDescription > list ) {
103- final List <LocalSecondaryIndex > result = new ArrayList <>(list .size ());
104- for (LocalSecondaryIndexDescription description : list ) {
105- result .add (new LocalSecondaryIndex ()
106- .withIndexName (description .getIndexName ())
107- .withKeySchema (description .getKeySchema ())
108- .withProjection (description .getProjection ()));
109- }
110- return result ;
111- }
112-
113- @ VisibleForTesting
114- static CreateTableRequest convertTableDescriptionToCreateTableRequest (TableDescription description ,
115- String newTableName ,
116- boolean copyStreamSpecification ) {
117- List <GlobalSecondaryIndexDescription > gsiDesc = description .getGlobalSecondaryIndexes ();
118- List <GlobalSecondaryIndex > gsi = gsiDesc == null ? null : convertGlobalSecondaryIndexDescriptions (gsiDesc );
119- List <LocalSecondaryIndexDescription > lsiDesc = description .getLocalSecondaryIndexes ();
120- List <LocalSecondaryIndex > lsi = lsiDesc == null ? null : convertLocalSecondaryIndexDescriptions (lsiDesc );
121- ProvisionedThroughput pt = getProvisionedThroughputFromDescription (description .getProvisionedThroughput ());
122- CreateTableRequest ctr = new CreateTableRequest ()
123- .withTableName (newTableName )
124- .withProvisionedThroughput (pt )
125- .withAttributeDefinitions (description .getAttributeDefinitions ())
126- .withKeySchema (description .getKeySchema ())
127- .withGlobalSecondaryIndexes (gsi )
128- .withLocalSecondaryIndexes (lsi );
129- if (copyStreamSpecification ) {
130- ctr .withStreamSpecification (description .getStreamSpecification ());
131- }
132- return ctr ;
133- }
134-
135105 private static ProvisionedThroughput getProvisionedThroughputFromDescription (ProvisionedThroughputDescription description ) {
136106 return new ProvisionedThroughput (description .getReadCapacityUnits (), description .getWriteCapacityUnits ());
137107 }
@@ -159,8 +129,16 @@ private void bootstrapTable() throws InterruptedException, ExecutionException, S
159129 throw new IllegalArgumentException ("Destination table " + destinationTable + " did not exist" , e );
160130 }
161131 try {
162- destinationClient .createTable (convertTableDescriptionToCreateTableRequest (readTableDescription ,
163- destinationTable , copyStreamSpecification ));
132+ final TableDescriptionToCreateTableRequestConverter converter =
133+ TableDescriptionToCreateTableRequestConverter .builder ()
134+ .copyStreamSpecification (copyStreamSpecification )
135+ .newTableName (destinationTable )
136+ .createAllGsi (createAllGsi )
137+ .gsiToInclude (includeGsi )
138+ .createAllLsi (createAllLsi )
139+ .lsiToInclude (includeLsi )
140+ .build ();
141+ destinationClient .createTable (converter .apply (readTableDescription ));
164142 destinationClient .waiters ().tableExists ().run (new WaiterParameters <>(new DescribeTableRequest (destinationTable )));
165143 } catch (WaiterUnrecoverableException | WaiterTimedOutException | AmazonServiceException ase ) {
166144 throw new IllegalArgumentException ("Unable to create destination table" , ase );
0 commit comments