23
23
import org .elasticsearch .common .blobstore .ImmutableBlobContainer ;
24
24
import org .elasticsearch .common .blobstore .support .BlobStores ;
25
25
26
+ import org .apache .cassandra .thrift .Column ;
27
+ import org .apache .cassandra .thrift .ColumnParent ;
28
+ import org .apache .cassandra .thrift .ColumnOrSuperColumn ;
29
+ import org .apache .cassandra .thrift .ConsistencyLevel ;
30
+ import org .apache .cassandra .thrift .Cassandra ;
31
+ import org .apache .cassandra .thrift .InvalidRequestException ;
32
+ import org .apache .cassandra .thrift .Mutation ;
33
+ import org .apache .cassandra .thrift .SlicePredicate ;
34
+ import org .apache .cassandra .thrift .SliceRange ;
35
+ import org .apache .cassandra .thrift .TimedOutException ;
36
+ import org .apache .cassandra .thrift .UnavailableException ;
37
+
38
+ import org .apache .thrift .TException ;
39
+
40
+ import java .io .DataInputStream ;
26
41
import java .io .IOException ;
27
42
import java .io .InputStream ;
43
+ import java .nio .ByteBuffer ;
44
+ import java .util .ArrayList ;
45
+ import java .util .HashMap ;
46
+ import java .util .List ;
47
+ import java .util .Map ;
28
48
29
49
/**
30
50
* @author Tom May ([email protected] )
@@ -35,12 +55,24 @@ public CassandraImmutableBlobContainer(BlobPath path, CassandraBlobStore blobSto
35
55
super (path , blobStore );
36
56
}
37
57
58
+ // InputStream is a completely shitty abstraction for something to
59
+ // write via thrift. And passing a sizeInBytes along with an
60
+ // InputStream is a sign that it's a shitty abstraction in
61
+ // general. At least we can use the sizeInBytes to allocate a
62
+ // ByteBuffer and copy to it then hand it to thrift.
38
63
@ Override public void writeBlob (final String blobName , final InputStream is , final long sizeInBytes , final WriterListener listener ) {
39
64
blobStore .executor ().execute (new Runnable () {
40
65
@ Override public void run () {
41
66
try {
42
- // XXX TODO
43
- logger .debug ("TODO writeBlob blobName={}, sizeInBytes={}, is={}" , blobName , sizeInBytes , is );
67
+ logger .debug ("writeBlob blobName={}, sizeInBytes={}, is={}" , blobName , sizeInBytes , is );
68
+ Cassandra .Client client =
69
+ CassandraClientFactory .getCassandraClient ();
70
+ try {
71
+ writeBlob (client , blobName , is , sizeInBytes );
72
+ }
73
+ finally {
74
+ CassandraClientFactory .closeCassandraClient (client );
75
+ }
44
76
listener .onCompleted ();
45
77
} catch (Exception e ) {
46
78
listener .onFailure (e );
@@ -52,4 +84,58 @@ public CassandraImmutableBlobContainer(BlobPath path, CassandraBlobStore blobSto
52
84
@ Override public void writeBlob (String blobName , InputStream is , long sizeInBytes ) throws IOException {
53
85
BlobStores .syncWriteBlob (this , blobName , is , sizeInBytes );
54
86
}
87
+
88
+ private void writeBlob (Cassandra .Client client , String blobName , InputStream is , long sizeInBytes )
89
+ throws InvalidRequestException , TimedOutException , UnavailableException , TException , IOException
90
+ {
91
+ long timestamp = System .currentTimeMillis ();
92
+
93
+ Map <String , Map <String , List <Mutation >>> mutationMap =
94
+ new HashMap <String , Map <String , List <Mutation >>>();
95
+
96
+ // Insert the blob data into Blobs.
97
+
98
+ int intSizeInBytes = (int ) sizeInBytes ;
99
+ if (intSizeInBytes != sizeInBytes ) {
100
+ throw new IllegalArgumentException (
101
+ "Blob " + blobName + " size " + sizeInBytes +
102
+ " is too large." );
103
+ }
104
+ ByteBuffer blobData = ByteBuffer .allocate (intSizeInBytes );
105
+ new DataInputStream (is ).readFully (blobData .array ());
106
+
107
+ List <Mutation > blobsMutations = new ArrayList <Mutation >();
108
+ blobsMutations .add (createInsert ("data" , blobData , timestamp ));
109
+
110
+ Map <String , List <Mutation >> blobsMutationMap =
111
+ new HashMap <String , List <Mutation >>();
112
+ blobsMutationMap .put ("Blobs" , blobsMutations );
113
+
114
+ mutationMap .put (blobPath + '/' + blobName , blobsMutationMap );
115
+
116
+ // Insert the blobName into BlobNames.
117
+
118
+ ByteBuffer size = utf8 .encode (Long .toString (sizeInBytes ));
119
+
120
+ List <Mutation > blobNamesMutations = new ArrayList <Mutation >();
121
+ blobNamesMutations .add (createInsert (blobName , size , timestamp ));
122
+
123
+ Map <String , List <Mutation >> blobNamesMutationMap =
124
+ new HashMap <String , List <Mutation >>();
125
+ blobNamesMutationMap .put ("BlobNames" , blobNamesMutations );
126
+
127
+ mutationMap .put (blobPath , blobNamesMutationMap );
128
+
129
+ client .batch_mutate (
130
+ keySpace , mutationMap , ConsistencyLevel .QUORUM );
131
+ }
132
+
133
+ private Mutation createInsert (String name , ByteBuffer value , long timestamp ) {
134
+ return new Mutation ().setColumn_or_supercolumn (
135
+ new ColumnOrSuperColumn ().setColumn (
136
+ new Column (
137
+ utf8 .encode (name ),
138
+ value ,
139
+ timestamp )));
140
+ }
55
141
}
0 commit comments