Skip to content

Commit f366b1d

Browse files
author
Evie Boland
committed
Implement tableName translations
1 parent c7b5195 commit f366b1d

File tree

6 files changed

+223
-107
lines changed

6 files changed

+223
-107
lines changed

hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,9 @@ public enum OperationStatusCode {
968968
public static final String REPLICATION_SINK_SERVICE_CLASSNAME_DEFAULT =
969969
"org.apache.hadoop.hbase.replication.ReplicationSinkServiceImpl";
970970
public static final String REPLICATION_BULKLOAD_ENABLE_KEY = "hbase.replication.bulkload.enabled";
971+
public static final String REPLICATION_SINK_TRANSLATOR = "hbase.replication.sink.translator";
972+
public static final String REPLICATION_SINK_TRANSLATOR_DEFAULT =
973+
"org.apache.hadoop.hbase.replication.regionserver.DefaultReplicationSinkTranslator";
971974
public static final boolean REPLICATION_BULKLOAD_ENABLE_DEFAULT = false;
972975
/** Replication cluster id of source cluster which uniquely identifies itself with peer cluster */
973976
public static final String REPLICATION_CLUSTER_ID = "hbase.replication.cluster.id";

hbase-server/src/main/java/org/apache/hadoop/hbase/replication/master/ReplicationSinkTrackerTableCreator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ private ReplicationSinkTrackerTableCreator() {
8080

8181
/*
8282
* We will create this table only if hbase.regionserver.replication.sink.tracker.enabled is
83-
* enabled and table doesn't exists already.
83+
* enabled and table doesn't exist already.
8484
*/
8585
public static void createIfNeededAndNotExists(Configuration conf, MasterServices masterServices)
8686
throws IOException {

hbase-server/src/main/java/org/apache/hadoop/hbase/replication/regionserver/HFileReplicator.java

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,20 @@ public class HFileReplicator implements Closeable {
9494
private int maxCopyThreads;
9595
private int copiesPerThread;
9696
private List<String> sourceClusterIds;
97+
private ReplicationSinkTranslator translator;
9798

9899
public HFileReplicator(Configuration sourceClusterConf, String sourceBaseNamespaceDirPath,
99100
String sourceHFileArchiveDirPath, Map<String, List<Pair<byte[], List<String>>>> tableQueueMap,
100-
Configuration conf, AsyncClusterConnection connection, List<String> sourceClusterIds)
101-
throws IOException {
101+
Configuration conf, AsyncClusterConnection connection, List<String> sourceClusterIds,
102+
ReplicationSinkTranslator translator) throws IOException {
102103
this.sourceClusterConf = sourceClusterConf;
103104
this.sourceBaseNamespaceDirPath = sourceBaseNamespaceDirPath;
104105
this.sourceHFileArchiveDirPath = sourceHFileArchiveDirPath;
105106
this.bulkLoadHFileMap = tableQueueMap;
106107
this.conf = conf;
107108
this.connection = connection;
108109
this.sourceClusterIds = sourceClusterIds;
110+
this.translator = translator;
109111

110112
userProvider = UserProvider.instantiate(conf);
111113
fsDelegationToken = new FsDelegationToken(userProvider, "renewer");
@@ -131,29 +133,30 @@ public void close() throws IOException {
131133

132134
public Void replicate() throws IOException {
133135
// Copy all the hfiles to the local file system
134-
Map<String, Path> tableStagingDirsMap = copyHFilesToStagingDir();
136+
Map<String, Path> tableToSinkStagingDir = copySourceHFilesToSinkStagingDir();
135137

136138
int maxRetries = conf.getInt(HConstants.BULKLOAD_MAX_RETRIES_NUMBER, 10);
137139

138-
for (Entry<String, Path> tableStagingDir : tableStagingDirsMap.entrySet()) {
139-
String tableNameString = tableStagingDir.getKey();
140-
Path stagingDir = tableStagingDir.getValue();
141-
TableName tableName = TableName.valueOf(tableNameString);
140+
for (Entry<String, Path> tableStagingDir : tableToSinkStagingDir.entrySet()) {
141+
String tableNameStr = tableStagingDir.getKey();
142+
TableName tableName = TableName.valueOf(tableNameStr);
143+
TableName sinkTableName = translator.getSinkTableName(tableName);
144+
Path sinkStagingDir = tableStagingDir.getValue();
142145

143146
// Prepare collection of queue of hfiles to be loaded(replicated)
144147
Deque<LoadQueueItem> queue = new LinkedList<>();
145-
BulkLoadHFilesTool.prepareHFileQueue(conf, connection, tableName, stagingDir, queue, false,
146-
false);
148+
BulkLoadHFilesTool.prepareHFileQueue(conf, connection, sinkTableName, sinkStagingDir, queue,
149+
false, false);
147150

148151
if (queue.isEmpty()) {
149-
LOG.warn("Did not find any files to replicate in directory {}", stagingDir.toUri());
152+
LOG.warn("Did not find any files to replicate in directory {}", sinkStagingDir.toUri());
150153
return null;
151154
}
152155
fsDelegationToken.acquireDelegationToken(sinkFs);
153156
try {
154-
doBulkLoad(conf, tableName, stagingDir, queue, maxRetries);
157+
doBulkLoad(conf, sinkTableName, sinkStagingDir, queue, maxRetries);
155158
} finally {
156-
cleanup(stagingDir);
159+
cleanup(sinkStagingDir);
157160
}
158161
}
159162
return null;
@@ -194,12 +197,12 @@ private void cleanup(Path stagingDir) {
194197
// Do not close the file system
195198
}
196199

197-
private Map<String, Path> copyHFilesToStagingDir() throws IOException {
200+
private Map<String, Path> copySourceHFilesToSinkStagingDir() throws IOException {
198201
Map<String, Path> mapOfCopiedHFiles = new HashMap<>();
199202
Pair<byte[], List<String>> familyHFilePathsPair;
200203
List<String> hfilePaths;
201204
byte[] family;
202-
Path familyStagingDir;
205+
Path sinkFamilyStagingDir;
203206
int familyHFilePathsPairsListSize;
204207
int totalNoOfHFiles;
205208
List<Pair<byte[], List<String>>> familyHFilePathsPairsList;
@@ -224,32 +227,33 @@ private Map<String, Path> copyHFilesToStagingDir() throws IOException {
224227
// For each table name in the map
225228
for (Entry<String, List<Pair<byte[], List<String>>>> tableEntry : bulkLoadHFileMap
226229
.entrySet()) {
227-
String tableName = tableEntry.getKey();
230+
String tableNameStr = tableEntry.getKey();
231+
TableName tableName = TableName.valueOf(tableNameStr);
228232

229233
// Create staging directory for each table
230-
Path stagingDir = createStagingDir(hbaseStagingDir, user, TableName.valueOf(tableName));
234+
Path sinkStagingDir = createSinkStagingDir(hbaseStagingDir, user, tableName);
231235

232236
familyHFilePathsPairsList = tableEntry.getValue();
233237
familyHFilePathsPairsListSize = familyHFilePathsPairsList.size();
234238

235-
// For each list of family hfile paths pair in the table
239+
// For each (family, hfile paths) pair in the table
236240
for (int i = 0; i < familyHFilePathsPairsListSize; i++) {
237241
familyHFilePathsPair = familyHFilePathsPairsList.get(i);
238242

239243
family = familyHFilePathsPair.getFirst();
240244
hfilePaths = familyHFilePathsPair.getSecond();
241245

242-
familyStagingDir = new Path(stagingDir, Bytes.toString(family));
246+
sinkFamilyStagingDir = getSinkFamilyStagingDir(sinkStagingDir, tableName, family);
243247
totalNoOfHFiles = hfilePaths.size();
244248

245-
// For each list of hfile paths for the family
249+
// For each hfile path in the family
246250
List<Future<Void>> futures = new ArrayList<>();
247251
Callable<Void> c;
248252
Future<Void> future;
249253
int currentCopied = 0;
250-
// Copy the hfiles parallely
254+
// Copy the hfiles in parallel
251255
while (totalNoOfHFiles > currentCopied + this.copiesPerThread) {
252-
c = new Copier(sourceFs, familyStagingDir,
256+
c = new Copier(sourceFs, sinkFamilyStagingDir,
253257
hfilePaths.subList(currentCopied, currentCopied + this.copiesPerThread));
254258
future = exec.submit(c);
255259
futures.add(future);
@@ -258,7 +262,7 @@ private Map<String, Path> copyHFilesToStagingDir() throws IOException {
258262

259263
int remaining = totalNoOfHFiles - currentCopied;
260264
if (remaining > 0) {
261-
c = new Copier(sourceFs, familyStagingDir,
265+
c = new Copier(sourceFs, sinkFamilyStagingDir,
262266
hfilePaths.subList(currentCopied, currentCopied + remaining));
263267
future = exec.submit(c);
264268
futures.add(future);
@@ -281,7 +285,7 @@ private Map<String, Path> copyHFilesToStagingDir() throws IOException {
281285
}
282286
// Add the staging directory to this table. Staging directory contains all the hfiles
283287
// belonging to this table
284-
mapOfCopiedHFiles.put(tableName, stagingDir);
288+
mapOfCopiedHFiles.put(tableNameStr, sinkStagingDir);
285289
}
286290
return mapOfCopiedHFiles;
287291
} finally {
@@ -294,12 +298,14 @@ private Map<String, Path> copyHFilesToStagingDir() throws IOException {
294298
}
295299
}
296300

297-
private Path createStagingDir(Path baseDir, User user, TableName tableName) throws IOException {
298-
String tblName = tableName.getNameAsString().replace(":", UNDERSCORE);
301+
private Path createSinkStagingDir(Path baseDir, User user, TableName tableName)
302+
throws IOException {
303+
TableName sinkTableName = translator.getSinkTableName(tableName);
304+
String sinkTableNameStr = sinkTableName.getNameAsString().replace(":", UNDERSCORE);
299305
int RANDOM_WIDTH = 320;
300306
int RANDOM_RADIX = 32;
301307
String doubleUnderScore = UNDERSCORE + UNDERSCORE;
302-
String randomDir = user.getShortName() + doubleUnderScore + tblName + doubleUnderScore
308+
String randomDir = user.getShortName() + doubleUnderScore + sinkTableNameStr + doubleUnderScore
303309
+ (new BigInteger(RANDOM_WIDTH, ThreadLocalRandom.current()).toString(RANDOM_RADIX));
304310
return createStagingDir(baseDir, user, randomDir);
305311
}
@@ -311,50 +317,55 @@ private Path createStagingDir(Path baseDir, User user, String randomDir) throws
311317
return p;
312318
}
313319

320+
private Path getSinkFamilyStagingDir(Path baseDir, TableName tableName, byte[] family) {
321+
byte[] sinkFamily = translator.getSinkFamily(tableName, family);
322+
return new Path(baseDir, Bytes.toString(sinkFamily));
323+
}
324+
314325
/**
315326
* This class will copy the given hfiles from the given source file system to the given local file
316327
* system staging directory.
317328
*/
318329
private class Copier implements Callable<Void> {
319330
private FileSystem sourceFs;
320-
private Path stagingDir;
321-
private List<String> hfiles;
331+
private Path sinkStagingDir;
332+
private List<String> hfilePaths;
322333

323-
public Copier(FileSystem sourceFs, final Path stagingDir, final List<String> hfiles)
334+
public Copier(FileSystem sourceFs, final Path sinkStagingDir, final List<String> hfilePaths)
324335
throws IOException {
325336
this.sourceFs = sourceFs;
326-
this.stagingDir = stagingDir;
327-
this.hfiles = hfiles;
337+
this.sinkStagingDir = sinkStagingDir;
338+
this.hfilePaths = hfilePaths;
328339
}
329340

330341
@Override
331342
public Void call() throws IOException {
332343
Path sourceHFilePath;
333-
Path localHFilePath;
334-
int totalHFiles = hfiles.size();
344+
Path sinkHFilePath;
345+
int totalHFiles = hfilePaths.size();
335346
for (int i = 0; i < totalHFiles; i++) {
336-
sourceHFilePath = new Path(sourceBaseNamespaceDirPath, hfiles.get(i));
337-
localHFilePath = new Path(stagingDir, sourceHFilePath.getName());
347+
sourceHFilePath = new Path(sourceBaseNamespaceDirPath, hfilePaths.get(i));
348+
sinkHFilePath = new Path(sinkStagingDir, sourceHFilePath.getName());
338349
try {
339-
FileUtil.copy(sourceFs, sourceHFilePath, sinkFs, localHFilePath, false, conf);
350+
FileUtil.copy(sourceFs, sourceHFilePath, sinkFs, sinkHFilePath, false, conf);
340351
// If any other exception other than FNFE then we will fail the replication requests and
341352
// source will retry to replicate these data.
342353
} catch (FileNotFoundException e) {
343-
LOG.info("Failed to copy hfile from " + sourceHFilePath + " to " + localHFilePath
354+
LOG.info("Failed to copy hfile from " + sourceHFilePath + " to " + sinkHFilePath
344355
+ ". Trying to copy from hfile archive directory.", e);
345-
sourceHFilePath = new Path(sourceHFileArchiveDirPath, hfiles.get(i));
356+
sourceHFilePath = new Path(sourceHFileArchiveDirPath, hfilePaths.get(i));
346357

347358
try {
348-
FileUtil.copy(sourceFs, sourceHFilePath, sinkFs, localHFilePath, false, conf);
359+
FileUtil.copy(sourceFs, sourceHFilePath, sinkFs, sinkHFilePath, false, conf);
349360
} catch (FileNotFoundException e1) {
350361
// This will mean that the hfile does not exists any where in source cluster FS. So we
351362
// cannot do anything here just log and continue.
352-
LOG.debug("Failed to copy hfile from " + sourceHFilePath + " to " + localHFilePath
363+
LOG.debug("Failed to copy hfile from " + sourceHFilePath + " to " + sinkHFilePath
353364
+ ". Hence ignoring this hfile from replication..", e1);
354365
continue;
355366
}
356367
}
357-
sinkFs.setPermission(localHFilePath, PERM_ALL_ACCESS);
368+
sinkFs.setPermission(sinkHFilePath, PERM_ALL_ACCESS);
358369
}
359370
return null;
360371
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.hadoop.hbase.replication.regionserver;
19+
20+
import org.apache.hadoop.hbase.ExtendedCell;
21+
import org.apache.hadoop.hbase.TableName;
22+
import org.apache.yetus.audience.InterfaceAudience;
23+
24+
@InterfaceAudience.Public
25+
public class IdentityReplicationSinkTranslator implements ReplicationSinkTranslator {
26+
@Override
27+
public TableName getSinkTableName(TableName tableName) {
28+
return tableName;
29+
}
30+
31+
@Override
32+
public byte[] getSinkRowKey(TableName tableName, byte[] rowKey) {
33+
return rowKey;
34+
}
35+
36+
@Override
37+
public byte[] getSinkFamily(TableName tableName, byte[] family) {
38+
return family;
39+
}
40+
41+
@Override
42+
public byte[] getSinkQualifier(TableName tableName, byte[] family, byte[] qualifier) {
43+
return qualifier;
44+
}
45+
46+
@Override
47+
public ExtendedCell getSinkExtendedCell(TableName tableName, ExtendedCell cell) {
48+
return cell;
49+
}
50+
}

0 commit comments

Comments
 (0)