View Javadoc

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  
19  package org.apache.hadoop.hbase.snapshot;
20  
21  import com.google.protobuf.InvalidProtocolBufferException;
22  import java.io.IOException;
23  import java.io.InterruptedIOException;
24  import java.util.ArrayList;
25  import java.util.List;
26  import java.util.concurrent.Callable;
27  import java.util.concurrent.Executor;
28  import java.util.concurrent.ExecutionException;
29  import java.util.concurrent.ExecutorCompletionService;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.hadoop.hbase.classification.InterfaceAudience;
34  import org.apache.hadoop.conf.Configuration;
35  import org.apache.hadoop.fs.FSDataInputStream;
36  import org.apache.hadoop.fs.FSDataOutputStream;
37  import org.apache.hadoop.fs.FileStatus;
38  import org.apache.hadoop.fs.FileSystem;
39  import org.apache.hadoop.fs.Path;
40  import org.apache.hadoop.fs.PathFilter;
41  import org.apache.hadoop.hbase.HRegionInfo;
42  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
43  import org.apache.hadoop.hbase.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;
44  import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
45  import org.apache.hadoop.hbase.util.ByteStringer;
46  import org.apache.hadoop.hbase.util.FSUtils;
47  
48  /**
49   * DO NOT USE DIRECTLY. USE {@link SnapshotManifest}.
50   *
51   * Snapshot v2 layout format
52   *  - Single Manifest file containing all the information of regions
53   *  - In the online-snapshot case each region will write a "region manifest"
54   *      /snapshotName/manifest.regionName
55   */
56  @InterfaceAudience.Private
57  public final class SnapshotManifestV2 {
58    private static final Log LOG = LogFactory.getLog(SnapshotManifestV2.class);
59  
60    public static final int DESCRIPTOR_VERSION = 2;
61  
62    public static final String SNAPSHOT_MANIFEST_PREFIX = "region-manifest.";
63  
64    private SnapshotManifestV2() {}
65  
66    static class ManifestBuilder implements SnapshotManifest.RegionVisitor<
67                      SnapshotRegionManifest.Builder, SnapshotRegionManifest.FamilyFiles.Builder> {
68      private final Configuration conf;
69      private final Path snapshotDir;
70      private final FileSystem fs;
71  
72      public ManifestBuilder(final Configuration conf, final FileSystem fs, final Path snapshotDir) {
73        this.snapshotDir = snapshotDir;
74        this.conf = conf;
75        this.fs = fs;
76      }
77  
78      public SnapshotRegionManifest.Builder regionOpen(final HRegionInfo regionInfo) {
79        SnapshotRegionManifest.Builder manifest = SnapshotRegionManifest.newBuilder();
80        manifest.setRegionInfo(HRegionInfo.convert(regionInfo));
81        return manifest;
82      }
83  
84      public void regionClose(final SnapshotRegionManifest.Builder region) throws IOException {
85        // we should ensure the snapshot dir exist, maybe it has been deleted by master
86        // see HBASE-16464
87        if (fs.exists(snapshotDir)) {
88          SnapshotRegionManifest manifest = region.build();
89          FSDataOutputStream stream = fs.create(getRegionManifestPath(snapshotDir, manifest));
90          try {
91            manifest.writeTo(stream);
92          } finally {
93            stream.close();
94          }
95        } else {
96          LOG.warn("can't write manifest without parent dir, maybe it has been deleted by master?");
97        }
98      }
99  
100     public SnapshotRegionManifest.FamilyFiles.Builder familyOpen(
101         final SnapshotRegionManifest.Builder region, final byte[] familyName) {
102       SnapshotRegionManifest.FamilyFiles.Builder family =
103           SnapshotRegionManifest.FamilyFiles.newBuilder();
104       family.setFamilyName(ByteStringer.wrap(familyName));
105       return family;
106     }
107 
108     public void familyClose(final SnapshotRegionManifest.Builder region,
109         final SnapshotRegionManifest.FamilyFiles.Builder family) {
110       region.addFamilyFiles(family.build());
111     }
112 
113     public void storeFile(final SnapshotRegionManifest.Builder region,
114         final SnapshotRegionManifest.FamilyFiles.Builder family, final StoreFileInfo storeFile)
115         throws IOException {
116       SnapshotRegionManifest.StoreFile.Builder sfManifest =
117             SnapshotRegionManifest.StoreFile.newBuilder();
118       sfManifest.setName(storeFile.getPath().getName());
119       if (storeFile.isReference()) {
120         sfManifest.setReference(storeFile.getReference().convert());
121       }
122       sfManifest.setFileSize(storeFile.getReferencedFileStatus(fs).getLen());
123       family.addStoreFiles(sfManifest.build());
124     }
125   }
126 
127   static List<SnapshotRegionManifest> loadRegionManifests(final Configuration conf,
128       final Executor executor,final FileSystem fs, final Path snapshotDir,
129       final SnapshotDescription desc) throws IOException {
130     FileStatus[] manifestFiles = FSUtils.listStatus(fs, snapshotDir, new PathFilter() {
131       @Override
132       public boolean accept(Path path) {
133         return path.getName().startsWith(SNAPSHOT_MANIFEST_PREFIX);
134       }
135     });
136 
137     if (manifestFiles == null || manifestFiles.length == 0) return null;
138 
139     final ExecutorCompletionService<SnapshotRegionManifest> completionService =
140       new ExecutorCompletionService<SnapshotRegionManifest>(executor);
141     for (final FileStatus st: manifestFiles) {
142       completionService.submit(new Callable<SnapshotRegionManifest>() {
143         @Override
144         public SnapshotRegionManifest call() throws IOException {
145           FSDataInputStream stream = fs.open(st.getPath());
146           try {
147             return SnapshotRegionManifest.parseFrom(stream);
148           } finally {
149             stream.close();
150           }
151         }
152       });
153     }
154 
155     ArrayList<SnapshotRegionManifest> regionsManifest =
156         new ArrayList<SnapshotRegionManifest>(manifestFiles.length);
157     try {
158       for (int i = 0; i < manifestFiles.length; ++i) {
159         regionsManifest.add(completionService.take().get());
160       }
161     } catch (InterruptedException e) {
162       throw new InterruptedIOException(e.getMessage());
163     } catch (ExecutionException e) {
164       Throwable t = e.getCause();
165 
166       if(t instanceof InvalidProtocolBufferException) {
167         throw (InvalidProtocolBufferException)t;
168       } else {
169         IOException ex = new IOException("ExecutionException");
170         ex.initCause(e.getCause());
171         throw ex;
172       }
173     }
174     return regionsManifest;
175   }
176 
177   static void deleteRegionManifest(final FileSystem fs, final Path snapshotDir,
178       final SnapshotRegionManifest manifest) throws IOException {
179     fs.delete(getRegionManifestPath(snapshotDir, manifest), true);
180   }
181 
182   private static Path getRegionManifestPath(final Path snapshotDir,
183       final SnapshotRegionManifest manifest) {
184     String regionName = SnapshotManifest.getRegionNameFromManifest(manifest);
185     return new Path(snapshotDir, SNAPSHOT_MANIFEST_PREFIX + regionName);
186   }
187 }