blob: 4b00165b615f499280ac8c86c799082c90e5a4ed [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#ifndef IMPALA_EXEC_HDFS_PLUGIN_TEXT_SCANNER_H
#define IMPALA_EXEC_HDFS_PLUGIN_TEXT_SCANNER_H
#include <boost/thread/shared_mutex.hpp>
#include "common/status.h"
#include "exec/scan-node.h"
#include "exec/hdfs-scanner.h"
#include "exec/hdfs-scan-node-base.h"
namespace impala {
/// This is a wrapper for calling external implementations of text scanners for
/// compression formats that Impala does not have builtin support for.
/// The plugin scanners are implemented in dynamically linked libraries.
///
/// The two entry points are:
/// IssueInitialRanges -- issue calls to the I/O manager to read the file headers
/// GetHdfsPluginTextScanner -- returns a pointer to the Scanner object.
///
/// Plugin names should all be upper case. If the plugin name is FOO, then the plugin
/// library must be called "libimpalafoo.so" and it must contain the following exported
/// functions:
/// const char* GetImpalaBuildVersion();
///
/// void FooIssueInitialRangesImpl(HdfsScanNodeBase*,
/// const std::vector<HdfsFileDesc*>&);
///
/// HdfsScanner* CreateFooTextScanner(HdfsScanNodeBase*, RuntimeState*);
///
class HdfsPluginTextScanner {
public:
static HdfsScanner* GetHdfsPluginTextScanner(HdfsScanNodeBase* scan_node,
RuntimeState* state, const std::string& plugin_name);
static Status IssueInitialRanges(HdfsScanNodeBase* scan_node,
const std::vector<HdfsFileDesc*>& files, const std::string& plugin_name);
private:
// Typedefs for functions loaded from plugin shared objects.
typedef const char* (*GetPluginImpalaBuildVersionFn)();
typedef HdfsScanner* (*CreateScannerFn)
(HdfsScanNodeBase* scan_node, RuntimeState* state);
typedef Status (*IssueInitialRangesFn)(
HdfsScanNodeBase* scan_node, const std::vector<HdfsFileDesc*>& files);
struct LoadedPlugin {
/// If non-OK, then we have tried and failed to load this plugin.
Status library_load_status;
/// Dynamically linked function to create the Scanner Object.
CreateScannerFn create_scanner_fn = nullptr;
/// Dynamically linked function to issue the initial scan ranges.
IssueInitialRangesFn issue_initial_ranges_fn = nullptr;
};
/// Lock to protect loading of libraries and 'loaded_plugins_'. We only allow loading a
/// single library at a time. Must be held in shared mode when accessing
/// 'loaded_plugins_' and exclusive mode when loading a library.
static boost::shared_mutex library_load_lock_;
/// Map from upper case plugin name to the loaded plugin.
/// Protected by 'library_load_lock_. Entries are never removed once loaded.
static std::unordered_map<std::string, LoadedPlugin> loaded_plugins_;
/// Return an error if the specified plugin isn't enabled.
static Status CheckPluginEnabled(const std::string& plugin_name);
/// Dynamically loads the required functions for the plugin identified by 'plugin_name'
/// and populates 'create_scanner_fn' and 'issue_initial_ranges_fn' in 'plugin'.
/// Returns an error if an error is encountered with loading the library or the
/// functions. 'library_load_lock_' must be held by the caller in exclusive mode.
static Status LoadPluginLibrary(const std::string& plugin_name, LoadedPlugin* plugin);
};
}
#endif