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  package org.apache.hadoop.hbase.wal;
19  
20  import java.io.IOException;
21  import java.util.ArrayList;
22  import java.util.List;
23  import java.util.Set;
24  import java.util.concurrent.CopyOnWriteArrayList;
25  import java.util.concurrent.atomic.AtomicBoolean;
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.hadoop.conf.Configuration;
29  import org.apache.hadoop.fs.Path;
30  import org.apache.hadoop.hbase.Cell;
31  import org.apache.hadoop.hbase.CellUtil;
32  import org.apache.hadoop.hbase.HConstants;
33  import org.apache.hadoop.hbase.HRegionInfo;
34  import org.apache.hadoop.hbase.HTableDescriptor;
35  import org.apache.hadoop.hbase.classification.InterfaceAudience;
36  // imports for things that haven't moved from regionserver.wal yet.
37  import org.apache.hadoop.hbase.regionserver.MultiVersionConcurrencyControl.WriteEntry;
38  import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
39  import org.apache.hadoop.hbase.regionserver.wal.WALCoprocessorHost;
40  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
41  import org.apache.hadoop.hbase.util.FSUtils;
42  
43  /**
44   * No-op implementation of {@link WALProvider} used when the WAL is disabled.
45   *
46   * Should only be used when severe data loss is acceptable.
47   *
48   */
49  @InterfaceAudience.Private
50  class DisabledWALProvider implements WALProvider {
51  
52    private static final Log LOG = LogFactory.getLog(DisabledWALProvider.class);
53  
54    WAL disabled;
55  
56    @Override
57    public void init(final WALFactory factory, final Configuration conf,
58        final List<WALActionsListener> listeners, String providerId) throws IOException {
59      if (null != disabled) {
60        throw new IllegalStateException("WALProvider.init should only be called once.");
61      }
62      if (null == providerId) {
63        providerId = "defaultDisabled";
64      }
65      disabled = new DisabledWAL(new Path(FSUtils.getWALRootDir(conf), providerId), conf, null);
66    }
67  
68    @Override
69    public List<WAL> getWALs() throws IOException {
70      List<WAL> wals = new ArrayList<WAL>();
71      wals.add(disabled);
72      return wals;
73    }
74  
75    @Override
76    public WAL getWAL(final byte[] identifier, byte[] namespace) throws IOException {
77      return disabled;
78    }
79  
80    @Override
81    public void close() throws IOException {
82      disabled.close();
83    }
84  
85    @Override
86    public void shutdown() throws IOException {
87      disabled.shutdown();
88    }
89  
90    private static class DisabledWAL implements WAL {
91      protected final List<WALActionsListener> listeners =
92          new CopyOnWriteArrayList<WALActionsListener>();
93      protected final Path path;
94      protected final WALCoprocessorHost coprocessorHost;
95      protected final AtomicBoolean closed = new AtomicBoolean(false);
96  
97      public DisabledWAL(final Path path, final Configuration conf,
98          final List<WALActionsListener> listeners) {
99        this.coprocessorHost = new WALCoprocessorHost(this, conf);
100       this.path = path;
101       if (null != listeners) {
102         for(WALActionsListener listener : listeners) {
103           registerWALActionsListener(listener);
104         }
105       }
106     }
107 
108     @Override
109     public void registerWALActionsListener(final WALActionsListener listener) {
110       listeners.add(listener);
111     }
112     
113     @Override
114     public boolean unregisterWALActionsListener(final WALActionsListener listener) {
115       return listeners.remove(listener);
116     }
117 
118     @Override
119     public byte[][] rollWriter() {
120       if (!listeners.isEmpty()) {
121         for (WALActionsListener listener : listeners) {
122           listener.logRollRequested(WALActionsListener.RollRequestReason.ERROR);
123         }
124         for (WALActionsListener listener : listeners) {
125           try {
126             listener.preLogRoll(path, path);
127           } catch (IOException exception) {
128             LOG.debug("Ignoring exception from listener.", exception);
129           }
130         }
131         for (WALActionsListener listener : listeners) {
132           try {
133             listener.postLogRoll(path, path);
134           } catch (IOException exception) {
135             LOG.debug("Ignoring exception from listener.", exception);
136           }
137         }
138       }
139       return null;
140     }
141 
142     @Override
143     public byte[][] rollWriter(boolean force) {
144       return rollWriter();
145     }
146 
147     @Override
148     public void shutdown() {
149       if(closed.compareAndSet(false, true)) {
150         if (!this.listeners.isEmpty()) {
151           for (WALActionsListener listener : this.listeners) {
152             listener.logCloseRequested();
153           }
154         }
155       }
156     }
157 
158     @Override
159     public void close() {
160       shutdown();
161     }
162 
163     @Override
164     public long append(HTableDescriptor htd, HRegionInfo info, WALKey key, WALEdit edits,
165         boolean inMemstore) throws IOException {
166       WriteEntry writeEntry = key.getMvcc().begin();
167       if (!edits.isReplay()) {
168         for (Cell cell : edits.getCells()) {
169           CellUtil.setSequenceId(cell, writeEntry.getWriteNumber());
170         }
171       }
172       key.setWriteEntry(writeEntry);
173       if (!this.listeners.isEmpty()) {
174         final long start = System.nanoTime();
175         long len = 0;
176         for (Cell cell : edits.getCells()) {
177           len += CellUtil.estimatedSerializedSizeOf(cell);
178         }
179         final long elapsed = (System.nanoTime() - start)/1000000l;
180         for (WALActionsListener listener : this.listeners) {
181           listener.postAppend(len, elapsed, key, edits);
182         }
183       }
184       return -1;
185     }
186 
187     @Override
188     public void sync() {
189       if (!this.listeners.isEmpty()) {
190         for (WALActionsListener listener : this.listeners) {
191           listener.postSync(0l, 0);
192         }
193       }
194     }
195 
196     @Override
197     public void sync(long txid) {
198       sync();
199     }
200 
201     @Override
202     public void sync(boolean forceSync) throws IOException {
203       sync();
204     }
205 
206     @Override
207     public void sync(long txid, boolean forceSync) throws IOException {
208       sync(txid);
209     }
210 
211     @Override
212     public Long startCacheFlush(final byte[] encodedRegionName, Set<byte[]> flushedFamilyNames) {
213       if (closed.get()) return null;
214       return HConstants.NO_SEQNUM;
215     }
216 
217     @Override
218     public void completeCacheFlush(final byte[] encodedRegionName) {
219     }
220 
221     @Override
222     public void abortCacheFlush(byte[] encodedRegionName) {
223     }
224 
225     @Override
226     public WALCoprocessorHost getCoprocessorHost() {
227       return coprocessorHost;
228     }
229 
230     @Override
231     public long getEarliestMemstoreSeqNum(byte[] encodedRegionName) {
232       return HConstants.NO_SEQNUM;
233     }
234 
235     @Override
236     public long getEarliestMemstoreSeqNum(byte[] encodedRegionName, byte[] familyName) {
237       return HConstants.NO_SEQNUM;
238     }
239 
240     @Override
241     public String toString() {
242       return "WAL disabled.";
243     }
244   }
245 
246   @Override
247   public long getNumLogFiles() {
248     return 0;
249   }
250 
251   @Override
252   public long getLogFileSize() {
253     return 0;
254   }
255 }