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.namequeues;
21  
22  import com.lmax.disruptor.EventHandler;
23  import com.lmax.disruptor.RingBuffer;
24  import java.lang.reflect.InvocationTargetException;
25  import java.util.HashMap;
26  import java.util.Map;
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.classification.InterfaceAudience;
29  import org.apache.hadoop.hbase.namequeues.request.NamedQueueGetRequest;
30  import org.apache.hadoop.hbase.namequeues.response.NamedQueueGetResponse;
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  
34  /**
35   * Event Handler run by disruptor ringbuffer consumer.
36   * Although this is generic implementation for namedQueue, it can have individual queue specific
37   * logic.
38   */
39  @InterfaceAudience.Private
40  class LogEventHandler implements EventHandler<RingBufferEnvelope> {
41  
42    private static final Logger LOG = LoggerFactory.getLogger(LogEventHandler.class);
43  
44    // Map that binds namedQueues to corresponding queue service implementation.
45    // If NamedQueue of specific type is enabled, corresponding service will be used to
46    // insert and retrieve records.
47    // Individual queue sizes should be determined based on their individual configs within
48    // each service.
49    private final Map<NamedQueuePayload.NamedQueueEvent, NamedQueueService> namedQueueServices =
50      new HashMap<>();
51  
52    private static final String NAMED_QUEUE_PROVIDER_CLASSES = "hbase.namedqueue.provider.classes";
53  
54    LogEventHandler(final Configuration conf) {
55      for (String implName : conf.getStringCollection(NAMED_QUEUE_PROVIDER_CLASSES)) {
56        Class<?> clz;
57        try {
58          clz = Class.forName(implName);
59        } catch (ClassNotFoundException e) {
60          LOG.warn("Failed to find NamedQueueService implementor class {}", implName, e);
61          continue;
62        }
63  
64        if (!NamedQueueService.class.isAssignableFrom(clz)) {
65          LOG.warn("Class {} is not implementor of NamedQueueService.", clz);
66          continue;
67        }
68  
69        // add all service mappings here
70        try {
71          NamedQueueService namedQueueService =
72            (NamedQueueService) clz.getConstructor(Configuration.class).newInstance(conf);
73          namedQueueServices.put(namedQueueService.getEvent(), namedQueueService);
74        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException
75            | InvocationTargetException e) {
76          LOG.warn("Unable to instantiate/add NamedQueueService implementor {} to service map.",
77            clz);
78        }
79      }
80    }
81  
82    /**
83     * Called when a publisher has published an event to the {@link RingBuffer}.
84     * This is generic consumer of disruptor ringbuffer and for each new namedQueue that we
85     * add, we should also provide specific consumer logic here.
86     *
87     * @param event published to the {@link RingBuffer}
88     * @param sequence of the event being processed
89     * @param endOfBatch flag to indicate if this is the last event in a batch from
90     *   the {@link RingBuffer}
91     */
92    @Override
93    public void onEvent(RingBufferEnvelope event, long sequence, boolean endOfBatch) {
94      final NamedQueuePayload namedQueuePayload = event.getPayload();
95      // consume ringbuffer payload based on event type
96      namedQueueServices.get(namedQueuePayload.getNamedQueueEvent())
97        .consumeEventFromDisruptor(namedQueuePayload);
98    }
99  
100   /**
101    * Cleans up queues maintained by services.
102    *
103    * @param namedQueueEvent type of queue to clear
104    * @return true if queue is cleaned up, false otherwise
105    */
106   boolean clearNamedQueue(NamedQueuePayload.NamedQueueEvent namedQueueEvent) {
107     return namedQueueServices.get(namedQueueEvent).clearNamedQueue();
108   }
109 
110   /**
111    * Add all in memory queue records to system table. The implementors can use system table
112    * or direct HDFS file or ZK as persistence system.
113    */
114   void persistAll(NamedQueuePayload.NamedQueueEvent namedQueueEvent) {
115     namedQueueServices.get(namedQueueEvent).persistAll();
116   }
117 
118   /**
119    * Retrieve in memory queue records from ringbuffer
120    *
121    * @param request namedQueue request with event type
122    * @return queue records from ringbuffer after filter (if applied)
123    */
124   NamedQueueGetResponse getNamedQueueRecords(NamedQueueGetRequest request) {
125     return namedQueueServices.get(request.getNamedQueueEvent()).getNamedQueueRecords(request);
126   }
127 
128 }