001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.backup.util;
019
020import java.io.IOException;
021import java.util.ArrayList;
022import java.util.List;
023import org.apache.hadoop.fs.Path;
024import org.apache.hadoop.hbase.Cell;
025import org.apache.hadoop.hbase.CellUtil;
026import org.apache.hadoop.hbase.TableName;
027import org.apache.hadoop.hbase.wal.WAL;
028import org.apache.hadoop.hbase.wal.WALEdit;
029import org.apache.hadoop.hbase.wal.WALKey;
030import org.apache.yetus.audience.InterfaceAudience;
031
032import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos;
033
034/**
035 * Processes bulk load files from Write-Ahead Log (WAL) entries.
036 * <p>
037 * Used by backup/restore and replication flows to discover HFiles referenced by bulk-load WALEdits.
038 * Returned {@link Path}s are constructed from the namespace/table/region/family/file components.
039 * </p>
040 */
041@InterfaceAudience.Private
042public final class BulkLoadProcessor {
043  private BulkLoadProcessor() {
044  }
045
046  /**
047   * Extract bulk-load file {@link Path}s from a list of {@link WAL.Entry}.
048   * @param walEntries list of WAL entries.
049   * @return list of Paths in discovery order; empty list if none
050   * @throws IOException if descriptor parsing fails
051   */
052  public static List<Path> processBulkLoadFiles(List<WAL.Entry> walEntries) throws IOException {
053    List<Path> bulkLoadFilePaths = new ArrayList<>();
054
055    for (WAL.Entry entry : walEntries) {
056      bulkLoadFilePaths.addAll(processBulkLoadFiles(entry.getKey(), entry.getEdit()));
057    }
058    return bulkLoadFilePaths;
059  }
060
061  /**
062   * Extract bulk-load file {@link Path}s from a single WAL entry.
063   * @param key  WALKey containing table information; if null returns empty list
064   * @param edit WALEdit to scan; if null returns empty list
065   * @return list of Paths referenced by bulk-load descriptor(s) in this edit; may be empty or
066   *         contain duplicates
067   * @throws IOException if descriptor parsing fails
068   */
069  public static List<Path> processBulkLoadFiles(WALKey key, WALEdit edit) throws IOException {
070    List<Path> bulkLoadFilePaths = new ArrayList<>();
071
072    for (Cell cell : edit.getCells()) {
073      if (CellUtil.matchingQualifier(cell, WALEdit.BULK_LOAD)) {
074        TableName tableName = key.getTableName();
075        String namespace = tableName.getNamespaceAsString();
076        String table = tableName.getQualifierAsString();
077        bulkLoadFilePaths.addAll(processBulkLoadDescriptor(cell, namespace, table));
078      }
079    }
080
081    return bulkLoadFilePaths;
082  }
083
084  private static List<Path> processBulkLoadDescriptor(Cell cell, String namespace, String table)
085    throws IOException {
086    List<Path> bulkLoadFilePaths = new ArrayList<>();
087    WALProtos.BulkLoadDescriptor bld = WALEdit.getBulkLoadDescriptor(cell);
088
089    if (bld == null || !bld.getReplicate() || bld.getEncodedRegionName() == null) {
090      return bulkLoadFilePaths; // Skip if not replicable
091    }
092
093    String regionName = bld.getEncodedRegionName().toStringUtf8();
094    for (WALProtos.StoreDescriptor storeDescriptor : bld.getStoresList()) {
095      bulkLoadFilePaths
096        .addAll(processStoreDescriptor(storeDescriptor, namespace, table, regionName));
097    }
098
099    return bulkLoadFilePaths;
100  }
101
102  private static List<Path> processStoreDescriptor(WALProtos.StoreDescriptor storeDescriptor,
103    String namespace, String table, String regionName) {
104    List<Path> paths = new ArrayList<>();
105    String columnFamily = storeDescriptor.getFamilyName().toStringUtf8();
106
107    for (String storeFile : storeDescriptor.getStoreFileList()) {
108      paths.add(new Path(namespace,
109        new Path(table, new Path(regionName, new Path(columnFamily, storeFile)))));
110    }
111
112    return paths;
113  }
114}