99package org .locationtech .geomesa .accumulo .data
1010
1111import org .apache .accumulo .core .client .AccumuloClient
12+ import org .apache .accumulo .core .client .ScannerBase .ConsistencyLevel
1213import org .apache .accumulo .core .data .{Mutation , Range , Value }
1314import org .apache .accumulo .core .security .Authorizations
1415import org .apache .hadoop .io .Text
1516import org .locationtech .geomesa .accumulo .util .{GeoMesaBatchWriterConfig , TableManager }
16- import org .locationtech .geomesa .index .metadata .{GeoMesaMetadata , KeyValueStoreMetadata , MetadataSerializer }
17+ import org .locationtech .geomesa .index .metadata .{KeyValueStoreMetadata , MetadataSerializer }
1718import org .locationtech .geomesa .utils .collection .CloseableIterator
18- import org .locationtech .geomesa .utils .io .{ CloseQuietly , WithClose }
19+ import org .locationtech .geomesa .utils .io .WithClose
1920
20- class AccumuloBackedMetadata [T ](val connector : AccumuloClient , val table : String , val serializer : MetadataSerializer [T ])
21- extends KeyValueStoreMetadata [T ] {
21+ class AccumuloBackedMetadata [T ](
22+ val client : AccumuloClient ,
23+ val table : String ,
24+ val serializer : MetadataSerializer [T ],
25+ consistency : Option [ConsistencyLevel ] = None
26+ ) extends KeyValueStoreMetadata [T ] {
2227
2328 import scala .collection .JavaConverters ._
2429
@@ -28,15 +33,15 @@ class AccumuloBackedMetadata[T](val connector: AccumuloClient, val table: String
2833
2934 private val empty = new Text ()
3035
31- override protected def checkIfTableExists : Boolean = connector .tableOperations().exists(table)
36+ override protected def checkIfTableExists : Boolean = client .tableOperations().exists(table)
3237
33- override protected def createTable (): Unit = new TableManager (connector ).ensureTableExists(table)
38+ override protected def createTable (): Unit = new TableManager (client ).ensureTableExists(table)
3439
3540 override protected def createEmptyBackup (timestamp : String ): AccumuloBackedMetadata [T ] =
36- new AccumuloBackedMetadata (connector , s " ${table}_ ${timestamp}_bak " , serializer)
41+ new AccumuloBackedMetadata (client , s " ${table}_ ${timestamp}_bak " , serializer, consistency )
3742
3843 override protected def write (rows : Seq [(Array [Byte ], Array [Byte ])]): Unit = {
39- WithClose (connector .createBatchWriter(table, config)) { writer =>
44+ WithClose (client .createBatchWriter(table, config)) { writer =>
4045 rows.foreach { case (k, v) =>
4146 val m = new Mutation (k)
4247 m.put(empty, empty, new Value (v))
@@ -47,15 +52,16 @@ class AccumuloBackedMetadata[T](val connector: AccumuloClient, val table: String
4752
4853 override protected def delete (rows : Seq [Array [Byte ]]): Unit = {
4954 val ranges = rows.map(r => Range .exact(new Text (r))).asJava
50- WithClose (connector .createBatchDeleter(table, Authorizations .EMPTY , 1 , config)) { deleter =>
55+ WithClose (client .createBatchDeleter(table, Authorizations .EMPTY , 1 , config)) { deleter =>
5156 deleter.setRanges(ranges)
5257 deleter.delete()
5358 }
5459 }
5560
5661 override protected def scanValue (row : Array [Byte ]): Option [Array [Byte ]] = {
57- WithClose (connector .createScanner(table, Authorizations .EMPTY )) { scanner =>
62+ WithClose (client .createScanner(table, Authorizations .EMPTY )) { scanner =>
5863 scanner.setRange(Range .exact(new Text (row)))
64+ consistency.foreach(scanner.setConsistencyLevel)
5965 val iter = scanner.iterator
6066 if (iter.hasNext) {
6167 Some (iter.next.getValue.get)
@@ -68,77 +74,12 @@ class AccumuloBackedMetadata[T](val connector: AccumuloClient, val table: String
6874 override protected def scanRows (prefix : Option [Array [Byte ]]): CloseableIterator [(Array [Byte ], Array [Byte ])] = {
6975 // ensure we don't scan any single-row encoded values
7076 val range = prefix.map(p => Range .prefix(new Text (p))).getOrElse(new Range (" " , " ~" ))
71- val scanner = connector .createScanner(table, Authorizations .EMPTY )
77+ val scanner = client .createScanner(table, Authorizations .EMPTY )
7278 scanner.setRange(range)
79+ consistency.foreach(scanner.setConsistencyLevel)
7380 CloseableIterator (scanner.iterator.asScala.map(r => (r.getKey.getRow.copyBytes, r.getValue.get)), scanner.close())
7481 }
75- }
76-
77- object AccumuloBackedMetadata {
78-
79- /**
80- * Old single row metadata kept around for back-compatibility
81- */
82- class SingleRowAccumuloMetadata [T ](metadata : AccumuloBackedMetadata [T ]) {
83-
84- import scala .collection .JavaConverters ._
85-
86- // if the table doesn't exist, we assume that we don't ever need to check it for old-encoded rows
87- private val tableExists = metadata.connector.tableOperations().exists(metadata.table)
8882
89- def getFeatureTypes : Array [String ] = {
90- if (! tableExists) { Array .empty } else {
91- val scanner = metadata.connector.createScanner(metadata.table, Authorizations .EMPTY )
92- // restrict to just one cf so we only get 1 hit per feature
93- // use attributes as it's the only thing that's been there through all geomesa versions
94- scanner.fetchColumnFamily(new Text (GeoMesaMetadata .AttributesKey ))
95- try {
96- scanner.iterator.asScala.map(e => SingleRowAccumuloMetadata .getTypeName(e.getKey.getRow)).toArray
97- } finally {
98- scanner.close()
99- }
100- }
101- }
102-
103- /**
104- * Migrate a table from the old single-row metadata to the new
105- *
106- * @param typeName simple feature type name
107- */
108- def migrate (typeName : String ): Unit = {
109- if (tableExists) {
110- val scanner = metadata.connector.createScanner(metadata.table, Authorizations .EMPTY )
111- val writer = metadata.connector.createBatchWriter(metadata.table, GeoMesaBatchWriterConfig ())
112- try {
113- scanner.setRange(SingleRowAccumuloMetadata .getRange(typeName))
114- scanner.iterator.asScala.foreach { entry =>
115- val key = entry.getKey.getColumnFamily.toString
116- metadata.insert(typeName, key, metadata.serializer.deserialize(typeName, entry.getValue.get))
117- // delete for the old entry
118- val delete = new Mutation (entry.getKey.getRow)
119- delete.putDelete(entry.getKey.getColumnFamily, entry.getKey.getColumnQualifier)
120- writer.addMutation(delete)
121- }
122- } finally {
123- CloseQuietly (scanner)
124- if (writer != null ) {
125- CloseQuietly (writer)
126- }
127- }
128- }
129- }
130- }
131-
132- object SingleRowAccumuloMetadata {
133-
134- private val MetadataTag = " ~METADATA"
135- private val MetadataRowKeyRegex = (MetadataTag + """ _(.*)""" ).r
136-
137- def getRange (typeName : String ): Range = new Range (s " ${MetadataTag }_ $typeName" )
138-
139- def getTypeName (row : Text ): String = {
140- val MetadataRowKeyRegex (typeName) = row.toString
141- typeName
142- }
143- }
83+ @ deprecated(" Use `client`" )
84+ def connector : AccumuloClient = client
14485}
0 commit comments