View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.regionserver.wal;
21  
22  import java.io.IOException;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.hbase.HRegionInfo;
27  import org.apache.hadoop.hbase.HTableDescriptor;
28  import org.apache.hadoop.hbase.classification.InterfaceAudience;
29  import org.apache.hadoop.hbase.protobuf.generated.WALProtos;
30  import org.apache.hadoop.hbase.protobuf.generated.WALProtos.CompactionDescriptor;
31  import org.apache.hadoop.hbase.protobuf.generated.WALProtos.FlushDescriptor;
32  import org.apache.hadoop.hbase.protobuf.generated.WALProtos.RegionEventDescriptor;
33  import org.apache.hadoop.hbase.regionserver.MultiVersionConcurrencyControl;
34  import org.apache.hadoop.hbase.wal.WAL;
35  import org.apache.hadoop.hbase.wal.WALKey;
36  
37  import com.google.protobuf.TextFormat;
38  
39  /**
40   * Helper methods to ease Region Server integration with the write ahead log.
41   * Note that methods in this class specifically should not require access to anything
42   * other than the API found in {@link WAL}.
43   */
44  @InterfaceAudience.Private
45  public class WALUtil {
46    private static final Log LOG = LogFactory.getLog(WALUtil.class);
47  
48    private WALUtil() {
49      // Shut down construction of this class.
50    }
51  
52    /**
53     * Write the marker that a compaction has succeeded and is about to be committed.
54     * This provides info to the HMaster to allow it to recover the compaction if
55     * this regionserver dies in the middle (This part is not yet implemented). It also prevents
56     * the compaction from finishing if this regionserver has already lost its lease on the log.
57     * @param mvcc Used by WAL to get sequence Id for the waledit.
58     */
59    public static long writeCompactionMarker(WAL wal, HTableDescriptor htd, HRegionInfo hri,
60        final CompactionDescriptor c, MultiVersionConcurrencyControl mvcc)
61    throws IOException {
62      long trx = writeMarker(wal, htd, hri, WALEdit.createCompaction(hri, c), mvcc, true);
63      if (LOG.isTraceEnabled()) {
64        LOG.trace("Appended compaction marker " + TextFormat.shortDebugString(c));
65      }
66      return trx;
67    }
68  
69    /**
70     * Write a flush marker indicating a start / abort or a complete of a region flush
71     */
72    public static long writeFlushMarker(WAL wal, HTableDescriptor htd, HRegionInfo hri,
73        final FlushDescriptor f, boolean sync, MultiVersionConcurrencyControl mvcc)
74    throws IOException {
75      long trx = writeMarker(wal, htd, hri, WALEdit.createFlushWALEdit(hri, f), mvcc, sync);
76      if (LOG.isTraceEnabled()) {
77        LOG.trace("Appended flush marker " + TextFormat.shortDebugString(f));
78      }
79      return trx;
80    }
81  
82    /**
83     * Write a region open marker indicating that the region is opened
84     */
85    public static long writeRegionEventMarker(WAL wal, HTableDescriptor htd, HRegionInfo hri,
86        final RegionEventDescriptor r, final MultiVersionConcurrencyControl mvcc)
87    throws IOException {
88      long trx = writeMarker(wal, htd, hri, WALEdit.createRegionEventWALEdit(hri, r), mvcc, true);
89      if (LOG.isTraceEnabled()) {
90        LOG.trace("Appended region event marker " + TextFormat.shortDebugString(r));
91      }
92      return trx;
93    }
94  
95    /**
96     * Write a log marker that a bulk load has succeeded and is about to be committed.
97     *
98     * @param wal        The log to write into.
99     * @param htd        A description of the table that we are bulk loading into.
100    * @param hri       A description of the region in the table that we are bulk loading into.
101    * @param desc A protocol buffers based description of the client's bulk loading request
102    * @return txid of this transaction or if nothing to do, the last txid
103    * @throws IOException We will throw an IOException if we can not append to the HLog.
104    */
105   public static long writeBulkLoadMarkerAndSync(final WAL wal, final HTableDescriptor htd,
106       final HRegionInfo hri, final WALProtos.BulkLoadDescriptor desc,
107       final MultiVersionConcurrencyControl mvcc)
108   throws IOException {
109     long trx = writeMarker(wal, htd, hri, WALEdit.createBulkLoadEvent(hri, desc), mvcc, true);
110     if (LOG.isTraceEnabled()) {
111       LOG.trace("Appended Bulk Load marker " + TextFormat.shortDebugString(desc));
112     }
113     return trx;
114   }
115 
116   private static long writeMarker(final WAL wal, final HTableDescriptor htd, final HRegionInfo hri,
117       final WALEdit edit, final MultiVersionConcurrencyControl mvcc, final boolean sync)
118   throws IOException {
119     // TODO: Pass in current time to use?
120     WALKey key =
121       new HLogKey(hri.getEncodedNameAsBytes(), hri.getTable(), System.currentTimeMillis(), mvcc);
122     // Add it to the log but the false specifies that we don't need to add it to the memstore
123     long trx = MultiVersionConcurrencyControl.NONE;
124     try {
125       trx = wal.append(htd, hri, key, edit, false);
126       if (sync) wal.sync(trx);
127     } finally {
128       // If you get hung here, is it a real WAL or a mocked WAL? If the latter, you need to
129       // trip the latch that is inside in getWriteEntry up in your mock. See down in the append
130       // called from onEvent in FSHLog.
131       MultiVersionConcurrencyControl.WriteEntry we = key.getWriteEntry();
132       if (mvcc != null && we != null) mvcc.complete(we);
133     }
134     return trx;
135   }
136 }