3
3
import java .math .BigInteger ;
4
4
import java .util .Collection ;
5
5
import java .util .Collections ;
6
- import java .util .Comparator ;
7
6
import java .util .Date ;
8
7
import java .util .List ;
9
8
import java .util .Set ;
10
9
import java .util .UUID ;
10
+ import java .util .concurrent .ExecutionException ;
11
11
import java .util .stream .Collectors ;
12
12
13
- import org .slf4j .Logger ;
14
- import org .slf4j .LoggerFactory ;
15
-
16
13
import com .datastax .driver .core .BatchStatement ;
17
14
import com .datastax .driver .core .CodecRegistry ;
18
15
import com .datastax .driver .core .ConsistencyLevel ;
23
20
import com .datastax .driver .core .ResultSetFuture ;
24
21
import com .datastax .driver .core .Row ;
25
22
import com .datastax .driver .core .Session ;
26
- import com .datastax .driver .core .SocketOptions ;
27
23
import com .datastax .driver .core .utils .UUIDs ;
28
24
import com .google .common .base .Optional ;
29
- import com .google .common .collect .ComparisonChain ;
30
25
import com .google .common .collect .ImmutableList ;
31
26
import com .google .common .collect .Lists ;
32
27
import com .google .common .collect .Sets ;
28
+ import com .google .common .util .concurrent .Futures ;
33
29
import com .spotify .reaper .ReaperApplication ;
34
30
import com .spotify .reaper .ReaperApplicationConfiguration ;
35
31
import com .spotify .reaper .core .Cluster ;
47
43
import com .spotify .reaper .service .RingRange ;
48
44
import com .spotify .reaper .storage .cassandra .DateTimeCodec ;
49
45
import com .spotify .reaper .storage .cassandra .Migration003 ;
50
-
46
+ import io . dropwizard . setup . Environment ;
51
47
import org .apache .cassandra .repair .RepairParallelism ;
52
48
import org .cognitor .cassandra .migration .Database ;
53
49
import org .cognitor .cassandra .migration .MigrationRepository ;
54
50
import org .cognitor .cassandra .migration .MigrationTask ;
55
51
import org .joda .time .DateTime ;
52
+ import org .slf4j .Logger ;
53
+ import org .slf4j .LoggerFactory ;
56
54
57
- import io .dropwizard .setup .Environment ;
58
55
import systems .composable .dropwizard .cassandra .CassandraFactory ;
59
56
60
57
public final class CassandraStorage implements IStorage , IDistributedStorage {
@@ -103,10 +100,10 @@ public CassandraStorage(ReaperApplicationConfiguration config, Environment envir
103
100
CassandraFactory cassandraFactory = config .getCassandraFactory ();
104
101
// all INSERT and DELETE statement prepared in this class are idempotent
105
102
cassandraFactory .setQueryOptions (java .util .Optional .of (new QueryOptions ().setDefaultIdempotence (true )));
106
- cassandra = config .getCassandraFactory ().build (environment );
107
-
103
+ cassandra = cassandraFactory .build (environment );
108
104
if (config .getActivateQueryLogger ())
109
105
cassandra .register (QueryLogger .builder ().build ());
106
+
110
107
CodecRegistry codecRegistry = cassandra .getConfiguration ().getCodecRegistry ();
111
108
codecRegistry .register (new DateTimeCodec ());
112
109
session = cassandra .connect (config .getCassandraFactory ().getKeyspace ());
@@ -171,12 +168,7 @@ public Collection<Cluster> getClusters() {
171
168
172
169
@ Override
173
170
public boolean addCluster (Cluster cluster ) {
174
- try {
175
- session .execute (insertClusterPrepStmt .bind (cluster .getName (), cluster .getPartitioner (), cluster .getSeedHosts ()));
176
- } catch (Exception e ) {
177
- LOG .warn ("failed inserting cluster with name: {}" , cluster .getName (), e );
178
- return false ;
179
- }
171
+ session .execute (insertClusterPrepStmt .bind (cluster .getName (), cluster .getPartitioner (), cluster .getSeedHosts ()));
180
172
return true ;
181
173
}
182
174
@@ -187,24 +179,25 @@ public boolean updateCluster(Cluster newCluster) {
187
179
188
180
@ Override
189
181
public Optional <Cluster > getCluster (String clusterName ) {
190
- Cluster cluster = null ;
191
- for ( Row clusterRow : session . execute ( getClusterPrepStmt . bind ( clusterName ))){
192
- cluster = new Cluster ( clusterRow . getString ( "name" ), clusterRow . getString ( "partitioner" ), clusterRow . getSet ( "seed_hosts" , String . class ));
193
- }
194
-
195
- return Optional .fromNullable ( cluster );
182
+ Row r = session . execute ( getClusterPrepStmt . bind ( clusterName )). one () ;
183
+
184
+ return r != null
185
+ ? Optional . fromNullable (
186
+ new Cluster ( r . getString ( "name" ), r . getString ( "partitioner" ), r . getSet ( "seed_hosts" , String . class )))
187
+ : Optional .absent ( );
196
188
}
197
189
198
190
@ Override
199
191
public Optional <Cluster > deleteCluster (String clusterName ) {
200
- session .execute (deleteClusterPrepStmt .bind (clusterName ));
192
+ session .executeAsync (deleteClusterPrepStmt .bind (clusterName ));
201
193
return Optional .fromNullable (new Cluster (clusterName , null , null ));
202
194
}
203
195
204
196
@ Override
205
197
public RepairRun addRepairRun (Builder repairRun , Collection <RepairSegment .Builder > newSegments ) {
206
198
RepairRun newRepairRun = repairRun .build (UUIDs .timeBased ());
207
199
BatchStatement repairRunBatch = new BatchStatement (BatchStatement .Type .UNLOGGED );
200
+ List <ResultSetFuture > futures = Lists .newArrayList ();
208
201
209
202
repairRunBatch .add (insertRepairRunPrepStmt .bind (
210
203
newRepairRun .getId (),
@@ -222,9 +215,6 @@ public RepairRun addRepairRun(Builder repairRun, Collection<RepairSegment.Builde
222
215
newRepairRun .getSegmentCount (),
223
216
newRepairRun .getRepairParallelism ().toString ()));
224
217
225
- session .execute (insertRepairRunClusterIndexPrepStmt .bind (newRepairRun .getClusterName (), newRepairRun .getId ()));
226
- session .execute (insertRepairRunUnitIndexPrepStmt .bind (newRepairRun .getRepairUnitId (), newRepairRun .getId ()));
227
-
228
218
for (RepairSegment .Builder builder :newSegments ){
229
219
RepairSegment segment = builder .withRunId (newRepairRun .getId ()).build (UUIDs .timeBased ());
230
220
@@ -241,17 +231,39 @@ public RepairRun addRepairRun(Builder repairRun, Collection<RepairSegment.Builde
241
231
segment .getFailCount ()));
242
232
243
233
if (100 == repairRunBatch .size ()){
244
- session .execute (repairRunBatch );
234
+ futures . add ( session .executeAsync (repairRunBatch ) );
245
235
repairRunBatch = new BatchStatement (BatchStatement .Type .UNLOGGED );
246
236
}
247
237
}
248
- session .execute (repairRunBatch );
238
+ futures .add (session .executeAsync (repairRunBatch ));
239
+ futures .add (session .executeAsync (insertRepairRunClusterIndexPrepStmt .bind (newRepairRun .getClusterName (), newRepairRun .getId ())));
240
+ futures .add (session .executeAsync (insertRepairRunUnitIndexPrepStmt .bind (newRepairRun .getRepairUnitId (), newRepairRun .getId ())));
241
+
242
+ try {
243
+ Futures .allAsList (futures ).get ();
244
+ } catch (InterruptedException | ExecutionException ex ) {
245
+ LOG .error ("failed to quorum insert new repair run " + newRepairRun .getId (), ex );
246
+ }
249
247
return newRepairRun ;
250
248
}
251
249
252
250
@ Override
253
251
public boolean updateRepairRun (RepairRun repairRun ) {
254
- session .execute (insertRepairRunPrepStmt .bind (repairRun .getId (), repairRun .getClusterName (), repairRun .getRepairUnitId (), repairRun .getCause (), repairRun .getOwner (), repairRun .getRunState ().toString (), repairRun .getCreationTime (), repairRun .getStartTime (), repairRun .getEndTime (), repairRun .getPauseTime (), repairRun .getIntensity (), repairRun .getLastEvent (), repairRun .getSegmentCount (), repairRun .getRepairParallelism ().toString ()));
252
+ session .execute (insertRepairRunPrepStmt .bind (
253
+ repairRun .getId (),
254
+ repairRun .getClusterName (),
255
+ repairRun .getRepairUnitId (),
256
+ repairRun .getCause (),
257
+ repairRun .getOwner (),
258
+ repairRun .getRunState ().toString (),
259
+ repairRun .getCreationTime (),
260
+ repairRun .getStartTime (),
261
+ repairRun .getEndTime (),
262
+ repairRun .getPauseTime (),
263
+ repairRun .getIntensity (),
264
+ repairRun .getLastEvent (),
265
+ repairRun .getSegmentCount (),
266
+ repairRun .getRepairParallelism ().toString ()));
255
267
return true ;
256
268
}
257
269
@@ -343,9 +355,9 @@ public Collection<RepairRun> getRepairRunsWithState(RunState runState) {
343
355
public Optional <RepairRun > deleteRepairRun (UUID id ) {
344
356
Optional <RepairRun > repairRun = getRepairRun (id );
345
357
if (repairRun .isPresent ()){
346
- session .execute ( deleteRepairRunPrepStmt .bind (id ));
347
- session .execute (deleteRepairRunByClusterPrepStmt .bind (id , repairRun .get ().getClusterName ()));
348
- session .execute ( deleteRepairRunByUnitPrepStmt .bind (id , repairRun . get (). getRepairUnitId () ));
358
+ session .executeAsync ( deleteRepairRunByUnitPrepStmt .bind (id , repairRun . get (). getRepairUnitId () ));
359
+ session .executeAsync (deleteRepairRunByClusterPrepStmt .bind (id , repairRun .get ().getClusterName ()));
360
+ session .executeAsync ( deleteRepairRunPrepStmt .bind (id ));
349
361
}
350
362
return repairRun ;
351
363
}
@@ -394,7 +406,7 @@ assert hasLeadOnSegment(newRepairSegment.getId())
394
406
if (newRepairSegment .getStartTime () != null ) {
395
407
startTime = newRepairSegment .getStartTime ().toDate ();
396
408
}
397
- session .executeAsync (insertRepairSegmentPrepStmt .bind (
409
+ session .execute (insertRepairSegmentPrepStmt .bind (
398
410
newRepairSegment .getRunId (),
399
411
newRepairSegment .getId (),
400
412
newRepairSegment .getRepairUnitId (),
@@ -553,12 +565,11 @@ public RepairSchedule addRepairSchedule(com.spotify.reaper.core.RepairSchedule.B
553
565
554
566
@ Override
555
567
public Optional <RepairSchedule > getRepairSchedule (UUID repairScheduleId ) {
556
- RepairSchedule schedule = null ;
557
568
Row sched = session .execute (getRepairSchedulePrepStmt .bind (repairScheduleId )).one ();
558
- if ( sched != null ){
559
- schedule = createRepairScheduleFromRow ( sched );
560
- }
561
- return Optional .fromNullable ( schedule );
569
+
570
+ return sched != null
571
+ ? Optional . fromNullable ( createRepairScheduleFromRow ( sched ))
572
+ : Optional .absent ( );
562
573
}
563
574
564
575
private RepairSchedule createRepairScheduleFromRow (Row repairScheduleRow ){
@@ -625,18 +636,19 @@ public Collection<RepairSchedule> getAllRepairSchedules() {
625
636
ResultSet scheduleResults = session .execute ("SELECT * FROM repair_schedule_v1" );
626
637
for (Row scheduleRow :scheduleResults ){
627
638
schedules .add (createRepairScheduleFromRow (scheduleRow ));
628
-
629
639
}
630
-
640
+
631
641
return schedules ;
632
642
}
633
643
634
644
@ Override
635
645
public boolean updateRepairSchedule (RepairSchedule newRepairSchedule ) {
636
646
final Set <UUID > repairHistory = Sets .newHashSet ();
637
647
repairHistory .addAll (newRepairSchedule .getRunHistory ());
648
+ RepairUnit repairUnit = getRepairUnit (newRepairSchedule .getRepairUnitId ()).get ();
649
+ List <ResultSetFuture > futures = Lists .newArrayList ();
638
650
639
- session .execute (insertRepairSchedulePrepStmt .bind (newRepairSchedule .getId (),
651
+ futures . add ( session .executeAsync (insertRepairSchedulePrepStmt .bind (newRepairSchedule .getId (),
640
652
newRepairSchedule .getRepairUnitId (),
641
653
newRepairSchedule .getState ().toString (),
642
654
newRepairSchedule .getDaysBetween (),
@@ -647,18 +659,22 @@ public boolean updateRepairSchedule(RepairSchedule newRepairSchedule) {
647
659
newRepairSchedule .getIntensity (),
648
660
newRepairSchedule .getCreationTime (),
649
661
newRepairSchedule .getOwner (),
650
- newRepairSchedule .getPauseTime ())
651
- );
652
- RepairUnit repairUnit = getRepairUnit (newRepairSchedule .getRepairUnitId ()).get ();
662
+ newRepairSchedule .getPauseTime ())));
653
663
654
- session .execute (insertRepairScheduleByClusterAndKsPrepStmt
655
- .bind (repairUnit .getClusterName (), repairUnit .getKeyspaceName (), newRepairSchedule .getId ()));
664
+ futures . add ( session .executeAsync (insertRepairScheduleByClusterAndKsPrepStmt
665
+ .bind (repairUnit .getClusterName (), repairUnit .getKeyspaceName (), newRepairSchedule .getId ()))) ;
656
666
657
- session .execute (insertRepairScheduleByClusterAndKsPrepStmt
658
- .bind (repairUnit .getClusterName (), " " , newRepairSchedule .getId ()));
667
+ futures . add ( session .executeAsync (insertRepairScheduleByClusterAndKsPrepStmt
668
+ .bind (repairUnit .getClusterName (), " " , newRepairSchedule .getId ()))) ;
659
669
660
- session .execute (insertRepairScheduleByClusterAndKsPrepStmt
661
- .bind (" " , repairUnit .getKeyspaceName (), newRepairSchedule .getId ()));
670
+ futures .add (session .executeAsync (insertRepairScheduleByClusterAndKsPrepStmt
671
+ .bind (" " , repairUnit .getKeyspaceName (), newRepairSchedule .getId ())));
672
+
673
+ try {
674
+ Futures .allAsList (futures ).get ();
675
+ } catch (InterruptedException | ExecutionException ex ) {
676
+ LOG .error ("failed to quorum update repair schedule " + newRepairSchedule .getId (), ex );
677
+ }
662
678
663
679
return true ;
664
680
}
@@ -668,16 +684,17 @@ public Optional<RepairSchedule> deleteRepairSchedule(UUID id) {
668
684
Optional <RepairSchedule > repairSchedule = getRepairSchedule (id );
669
685
if (repairSchedule .isPresent ()){
670
686
RepairUnit repairUnit = getRepairUnit (repairSchedule .get ().getRepairUnitId ()).get ();
671
- session .execute (deleteRepairSchedulePrepStmt .bind (repairSchedule .get ().getId ()));
672
687
673
- session .execute (deleteRepairScheduleByClusterAndKsPrepStmt
688
+ session .executeAsync (deleteRepairScheduleByClusterAndKsPrepStmt
674
689
.bind (repairUnit .getClusterName (), repairUnit .getKeyspaceName (), repairSchedule .get ().getId ()));
675
690
676
- session .execute (deleteRepairScheduleByClusterAndKsPrepStmt
691
+ session .executeAsync (deleteRepairScheduleByClusterAndKsPrepStmt
677
692
.bind (repairUnit .getClusterName (), " " , repairSchedule .get ().getId ()));
678
693
679
- session .execute (deleteRepairScheduleByClusterAndKsPrepStmt
694
+ session .executeAsync (deleteRepairScheduleByClusterAndKsPrepStmt
680
695
.bind (" " , repairUnit .getKeyspaceName (), repairSchedule .get ().getId ()));
696
+
697
+ session .executeAsync (deleteRepairSchedulePrepStmt .bind (repairSchedule .get ().getId ()));
681
698
}
682
699
683
700
return repairSchedule ;
0 commit comments