HDFS-10465: libhdfs++: Implement GetBlockLocations. Contributed by Bob Hansen
This commit is contained in:
parent
f1f0b8f0f8
commit
18f4d2f42e
|
@ -0,0 +1,168 @@
|
||||||
|
/**
|
||||||
|
* 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 HDFSPP_BLOCK_LOCATION_H
|
||||||
|
#define HDFSPP_BLOCK_LOCATION_H
|
||||||
|
|
||||||
|
namespace hdfs {
|
||||||
|
|
||||||
|
class DNInfo {
|
||||||
|
public:
|
||||||
|
DNInfo() : xfer_port(-1), info_port(-1), IPC_port(-1), info_secure_port(-1) {}
|
||||||
|
|
||||||
|
std::string getHostname() const {
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHostname(const std::string & hostname) {
|
||||||
|
this->hostname = hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getIPAddr() const {
|
||||||
|
return ip_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setIPAddr(const std::string & ip_addr) {
|
||||||
|
this->ip_addr = ip_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getXferPort() const {
|
||||||
|
return xfer_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setXferPort(int xfer_port) {
|
||||||
|
this->xfer_port = xfer_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getInfoPort() const {
|
||||||
|
return info_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setInfoPort(int info_port) {
|
||||||
|
this->info_port = info_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getIPCPort() const {
|
||||||
|
return IPC_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setIPCPort(int IPC_port) {
|
||||||
|
this->IPC_port = IPC_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getInfoSecurePort() const {
|
||||||
|
return info_secure_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setInfoSecurePort(int info_secure_port) {
|
||||||
|
this->info_secure_port = info_secure_port;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::string hostname;
|
||||||
|
std::string ip_addr;
|
||||||
|
int xfer_port;
|
||||||
|
int info_port;
|
||||||
|
int IPC_port;
|
||||||
|
int info_secure_port;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BlockLocation {
|
||||||
|
public:
|
||||||
|
bool isCorrupt() const {
|
||||||
|
return corrupt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCorrupt(bool corrupt) {
|
||||||
|
this->corrupt = corrupt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t getLength() const {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLength(int64_t length) {
|
||||||
|
this->length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t getOffset() const {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOffset(int64_t offset) {
|
||||||
|
this->offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<DNInfo> & getDataNodes() const {
|
||||||
|
return dn_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDataNodes(const std::vector<DNInfo> & dn_info) {
|
||||||
|
this->dn_info = dn_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool corrupt;
|
||||||
|
int64_t length;
|
||||||
|
int64_t offset; // Offset of the block in the file
|
||||||
|
std::vector<DNInfo> dn_info; // Info about who stores each block
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileBlockLocation {
|
||||||
|
public:
|
||||||
|
uint64_t getFileLength() {
|
||||||
|
return fileLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFileLength(uint64_t fileLength) {
|
||||||
|
this->fileLength = fileLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLastBlockComplete() const {
|
||||||
|
return this->lastBlockComplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLastBlockComplete(bool lastBlockComplete) {
|
||||||
|
this->lastBlockComplete = lastBlockComplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isUnderConstruction() const {
|
||||||
|
return underConstruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUnderConstruction(bool underConstruction) {
|
||||||
|
this->underConstruction = underConstruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<BlockLocation> & getBlockLocations() const {
|
||||||
|
return blockLocations;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBlockLocations(const std::vector<BlockLocation> & blockLocations) {
|
||||||
|
this->blockLocations = blockLocations;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
uint64_t fileLength;
|
||||||
|
bool lastBlockComplete;
|
||||||
|
bool underConstruction;
|
||||||
|
std::vector<BlockLocation> blockLocations;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace hdfs
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HDFSPP_BLOCK_LOCATION_H */
|
|
@ -115,6 +115,63 @@ LIBHDFS_EXTERNAL
|
||||||
int hdfsBuilderConfGetInt(struct hdfsBuilder *bld, const char *key, int32_t *val);
|
int hdfsBuilderConfGetInt(struct hdfsBuilder *bld, const char *key, int32_t *val);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the block information and data nodes associated with a particular file.
|
||||||
|
*
|
||||||
|
* The hdfsBlockLocations structure will have zero or more hdfsBlockInfo elements,
|
||||||
|
* which will have zero or more ip_addr elements indicating which datanodes have
|
||||||
|
* each block.
|
||||||
|
*
|
||||||
|
* @param fs A connected hdfs instance
|
||||||
|
* @param path Path of the file to query
|
||||||
|
* @param locations The address of an output pointer to contain the block information.
|
||||||
|
* On success, this pointer must be later freed with hdfsFreeBlockLocations.
|
||||||
|
*
|
||||||
|
* @return 0 on success; nonzero error code otherwise.
|
||||||
|
* If the file does not exist, an error will be returned.
|
||||||
|
*/
|
||||||
|
struct hdfsDNInfo {
|
||||||
|
const char * ip_address;
|
||||||
|
const char * hostname;
|
||||||
|
int xfer_port;
|
||||||
|
int info_port;
|
||||||
|
int IPC_port;
|
||||||
|
int info_secure_port;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hdfsBlockInfo {
|
||||||
|
uint64_t start_offset;
|
||||||
|
uint64_t num_bytes;
|
||||||
|
|
||||||
|
size_t num_locations;
|
||||||
|
struct hdfsDNInfo * locations;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hdfsBlockLocations
|
||||||
|
{
|
||||||
|
uint64_t fileLength;
|
||||||
|
int isLastBlockComplete;
|
||||||
|
int isUnderConstruction;
|
||||||
|
|
||||||
|
size_t num_blocks;
|
||||||
|
struct hdfsBlockInfo * blocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
LIBHDFS_EXTERNAL
|
||||||
|
int hdfsGetBlockLocations(hdfsFS fs, const char *path, struct hdfsBlockLocations ** locations);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees up an hdfsBlockLocations pointer allocated by hdfsGetBlockLocations.
|
||||||
|
*
|
||||||
|
* @param locations The previously-populated pointer allocated by hdfsGetBlockLocations
|
||||||
|
* @return 0 on success, nonzero on error
|
||||||
|
*/
|
||||||
|
LIBHDFS_EXTERNAL
|
||||||
|
int hdfsFreeBlockLocations(struct hdfsBlockLocations * locations);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client can supply a C style function pointer to be invoked any time something
|
* Client can supply a C style function pointer to be invoked any time something
|
||||||
* is logged. Unlike the C++ logger this will not filter by level or component,
|
* is logged. Unlike the C++ logger this will not filter by level or component,
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "hdfspp/options.h"
|
#include "hdfspp/options.h"
|
||||||
#include "hdfspp/status.h"
|
#include "hdfspp/status.h"
|
||||||
#include "hdfspp/events.h"
|
#include "hdfspp/events.h"
|
||||||
|
#include "hdfspp/block_location.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -168,6 +169,16 @@ class FileSystem {
|
||||||
const std::function<void(const Status &, FileHandle *)> &handler) = 0;
|
const std::function<void(const Status &, FileHandle *)> &handler) = 0;
|
||||||
virtual Status Open(const std::string &path, FileHandle **handle) = 0;
|
virtual Status Open(const std::string &path, FileHandle **handle) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the locations of all known blocks for the indicated file, or an error
|
||||||
|
* if the information clould not be found
|
||||||
|
*/
|
||||||
|
virtual void GetBlockLocations(const std::string & path,
|
||||||
|
const std::function<void(const Status &, std::shared_ptr<FileBlockLocation> locations)> ) = 0;
|
||||||
|
virtual Status GetBlockLocations(const std::string & path,
|
||||||
|
std::shared_ptr<FileBlockLocation> * locations) = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that it is an error to destroy the filesystem from within a filesystem
|
* Note that it is an error to destroy the filesystem from within a filesystem
|
||||||
* callback. It will lead to a deadlock and the termination of the process.
|
* callback. It will lead to a deadlock and the termination of the process.
|
||||||
|
|
|
@ -167,12 +167,20 @@ static int ReportCaughtNonException()
|
||||||
return Error(Status::Exception("Uncaught value not derived from std::exception", ""));
|
return Error(Status::Exception("Uncaught value not derived from std::exception", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return false on failure */
|
bool CheckSystem(hdfsFS fs) {
|
||||||
bool CheckSystemAndHandle(hdfsFS fs, hdfsFile file) {
|
|
||||||
if (!fs) {
|
if (!fs) {
|
||||||
ReportError(ENODEV, "Cannot perform FS operations with null FS handle.");
|
ReportError(ENODEV, "Cannot perform FS operations with null FS handle.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return false on failure */
|
||||||
|
bool CheckSystemAndHandle(hdfsFS fs, hdfsFile file) {
|
||||||
|
if (!CheckSystem(fs))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!file) {
|
if (!file) {
|
||||||
ReportError(EBADF, "Cannot perform FS operations with null File handle.");
|
ReportError(EBADF, "Cannot perform FS operations with null File handle.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -410,6 +418,92 @@ int hdfsCancel(hdfsFS fs, hdfsFile file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hdfsGetBlockLocations(hdfsFS fs, const char *path, struct hdfsBlockLocations ** locations_out)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!CheckSystem(fs)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (locations_out == nullptr) {
|
||||||
|
ReportError(EINVAL, "Null pointer passed to hdfsGetBlockLocations");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<FileBlockLocation> ppLocations;
|
||||||
|
Status stat = fs->get_impl()->GetBlockLocations(path, &ppLocations);
|
||||||
|
if (!stat.ok()) {
|
||||||
|
return Error(stat);
|
||||||
|
}
|
||||||
|
|
||||||
|
hdfsBlockLocations *locations = new struct hdfsBlockLocations();
|
||||||
|
(*locations_out) = locations;
|
||||||
|
|
||||||
|
bzero(locations, sizeof(*locations));
|
||||||
|
locations->fileLength = ppLocations->getFileLength();
|
||||||
|
locations->isLastBlockComplete = ppLocations->isLastBlockComplete();
|
||||||
|
locations->isUnderConstruction = ppLocations->isUnderConstruction();
|
||||||
|
|
||||||
|
const std::vector<BlockLocation> & ppBlockLocations = ppLocations->getBlockLocations();
|
||||||
|
locations->num_blocks = ppBlockLocations.size();
|
||||||
|
locations->blocks = new struct hdfsBlockInfo[locations->num_blocks];
|
||||||
|
for (size_t i=0; i < ppBlockLocations.size(); i++) {
|
||||||
|
auto ppBlockLocation = ppBlockLocations[i];
|
||||||
|
auto block = &locations->blocks[i];
|
||||||
|
|
||||||
|
block->num_bytes = ppBlockLocation.getLength();
|
||||||
|
block->start_offset = ppBlockLocation.getOffset();
|
||||||
|
|
||||||
|
const std::vector<DNInfo> & ppDNInfos = ppBlockLocation.getDataNodes();
|
||||||
|
block->num_locations = ppDNInfos.size();
|
||||||
|
block->locations = new hdfsDNInfo[block->num_locations];
|
||||||
|
for (size_t j=0; j < block->num_locations; j++) {
|
||||||
|
auto ppDNInfo = ppDNInfos[j];
|
||||||
|
auto dn_info = &block->locations[j];
|
||||||
|
|
||||||
|
dn_info->xfer_port = ppDNInfo.getXferPort();
|
||||||
|
dn_info->info_port = ppDNInfo.getInfoPort();
|
||||||
|
dn_info->IPC_port = ppDNInfo.getIPCPort();
|
||||||
|
dn_info->info_secure_port = ppDNInfo.getInfoSecurePort();
|
||||||
|
|
||||||
|
char * buf;
|
||||||
|
buf = new char[ppDNInfo.getHostname().size() + 1];
|
||||||
|
strncpy(buf, ppDNInfo.getHostname().c_str(), ppDNInfo.getHostname().size());
|
||||||
|
dn_info->hostname = buf;
|
||||||
|
|
||||||
|
buf = new char[ppDNInfo.getIPAddr().size() + 1];
|
||||||
|
strncpy(buf, ppDNInfo.getIPAddr().c_str(), ppDNInfo.getIPAddr().size());
|
||||||
|
dn_info->ip_address = buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} catch (const std::exception & e) {
|
||||||
|
return ReportException(e);
|
||||||
|
} catch (...) {
|
||||||
|
return ReportCaughtNonException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int hdfsFreeBlockLocations(struct hdfsBlockLocations * blockLocations) {
|
||||||
|
if (blockLocations == nullptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (size_t i=0; i < blockLocations->num_blocks; i++) {
|
||||||
|
auto block = &blockLocations->blocks[i];
|
||||||
|
for (size_t j=0; j < block->num_locations; j++) {
|
||||||
|
auto location = &block->locations[j];
|
||||||
|
delete[] location->hostname;
|
||||||
|
delete[] location->ip_address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] blockLocations->blocks;
|
||||||
|
delete blockLocations;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* EVENT CALLBACKS
|
* EVENT CALLBACKS
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
|
|
@ -97,12 +97,15 @@ void NameNodeOperations::GetBlockLocations(const std::string & path,
|
||||||
auto locations = s.resp->locations();
|
auto locations = s.resp->locations();
|
||||||
|
|
||||||
file_info->file_length_ = locations.filelength();
|
file_info->file_length_ = locations.filelength();
|
||||||
|
file_info->last_block_complete_ = locations.islastblockcomplete();
|
||||||
|
file_info->under_construction_ = locations.underconstruction();
|
||||||
|
|
||||||
for (const auto &block : locations.blocks()) {
|
for (const auto &block : locations.blocks()) {
|
||||||
file_info->blocks_.push_back(block);
|
file_info->blocks_.push_back(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locations.has_lastblock() && locations.lastblock().b().numbytes()) {
|
if (!locations.islastblockcomplete() &&
|
||||||
|
locations.has_lastblock() && locations.lastblock().b().numbytes()) {
|
||||||
file_info->blocks_.push_back(locations.lastblock());
|
file_info->blocks_.push_back(locations.lastblock());
|
||||||
file_info->file_length_ += locations.lastblock().b().numbytes();
|
file_info->file_length_ += locations.lastblock().b().numbytes();
|
||||||
}
|
}
|
||||||
|
@ -336,6 +339,102 @@ Status FileSystemImpl::Open(const std::string &path,
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BlockLocation LocatedBlockToBlockLocation(const hadoop::hdfs::LocatedBlockProto & locatedBlock)
|
||||||
|
{
|
||||||
|
BlockLocation result;
|
||||||
|
|
||||||
|
result.setCorrupt(locatedBlock.corrupt());
|
||||||
|
result.setOffset(locatedBlock.offset());
|
||||||
|
|
||||||
|
std::vector<DNInfo> dn_info;
|
||||||
|
dn_info.reserve(locatedBlock.locs_size());
|
||||||
|
for (const hadoop::hdfs::DatanodeInfoProto & datanode_info: locatedBlock.locs()) {
|
||||||
|
const hadoop::hdfs::DatanodeIDProto &id = datanode_info.id();
|
||||||
|
DNInfo newInfo;
|
||||||
|
if (id.has_ipaddr())
|
||||||
|
newInfo.setIPAddr(id.ipaddr());
|
||||||
|
if (id.has_hostname())
|
||||||
|
newInfo.setHostname(id.hostname());
|
||||||
|
if (id.has_xferport())
|
||||||
|
newInfo.setXferPort(id.xferport());
|
||||||
|
if (id.has_infoport())
|
||||||
|
newInfo.setInfoPort(id.infoport());
|
||||||
|
if (id.has_ipcport())
|
||||||
|
newInfo.setIPCPort(id.ipcport());
|
||||||
|
if (id.has_infosecureport())
|
||||||
|
newInfo.setInfoSecurePort(id.infosecureport());
|
||||||
|
dn_info.push_back(newInfo);
|
||||||
|
}
|
||||||
|
result.setDataNodes(dn_info);
|
||||||
|
|
||||||
|
if (locatedBlock.has_b()) {
|
||||||
|
const hadoop::hdfs::ExtendedBlockProto & b=locatedBlock.b();
|
||||||
|
result.setLength(b.numbytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystemImpl::GetBlockLocations(const std::string & path,
|
||||||
|
const std::function<void(const Status &, std::shared_ptr<FileBlockLocation> locations)> handler)
|
||||||
|
{
|
||||||
|
auto conversion = [handler](const Status & status, std::shared_ptr<const struct FileInfo> fileInfo) {
|
||||||
|
if (status.ok()) {
|
||||||
|
auto result = std::make_shared<FileBlockLocation>();
|
||||||
|
|
||||||
|
result->setFileLength(fileInfo->file_length_);
|
||||||
|
result->setLastBlockComplete(fileInfo->last_block_complete_);
|
||||||
|
result->setUnderConstruction(fileInfo->under_construction_);
|
||||||
|
|
||||||
|
std::vector<BlockLocation> blocks;
|
||||||
|
for (const hadoop::hdfs::LocatedBlockProto & locatedBlock: fileInfo->blocks_) {
|
||||||
|
auto newLocation = LocatedBlockToBlockLocation(locatedBlock);
|
||||||
|
blocks.push_back(newLocation);
|
||||||
|
}
|
||||||
|
result->setBlockLocations(blocks);
|
||||||
|
|
||||||
|
handler(status, result);
|
||||||
|
} else {
|
||||||
|
handler(status, std::shared_ptr<FileBlockLocation>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
nn_.GetBlockLocations(path, conversion);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status FileSystemImpl::GetBlockLocations(const std::string & path,
|
||||||
|
std::shared_ptr<FileBlockLocation> * fileBlockLocations)
|
||||||
|
{
|
||||||
|
if (!fileBlockLocations)
|
||||||
|
return Status::InvalidArgument("Null pointer passed to GetBlockLocations");
|
||||||
|
|
||||||
|
auto callstate = std::make_shared<std::promise<std::tuple<Status, std::shared_ptr<FileBlockLocation>>>>();
|
||||||
|
std::future<std::tuple<Status, std::shared_ptr<FileBlockLocation>>> future(callstate->get_future());
|
||||||
|
|
||||||
|
/* wrap async call with promise/future to make it blocking */
|
||||||
|
auto callback = [callstate](const Status &s, std::shared_ptr<FileBlockLocation> blockInfo) {
|
||||||
|
callstate->set_value(std::make_tuple(s,blockInfo));
|
||||||
|
};
|
||||||
|
|
||||||
|
GetBlockLocations(path, callback);
|
||||||
|
|
||||||
|
/* wait for async to finish */
|
||||||
|
auto returnstate = future.get();
|
||||||
|
auto stat = std::get<0>(returnstate);
|
||||||
|
|
||||||
|
if (!stat.ok()) {
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
*fileBlockLocations = std::get<1>(returnstate);
|
||||||
|
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FileSystemImpl::WorkerDeleter::operator()(std::thread *t) {
|
void FileSystemImpl::WorkerDeleter::operator()(std::thread *t) {
|
||||||
// It is far too easy to destroy the filesystem (and thus the threadpool)
|
// It is far too easy to destroy the filesystem (and thus the threadpool)
|
||||||
// from within one of the worker threads, leading to a deadlock. Let's
|
// from within one of the worker threads, leading to a deadlock. Let's
|
||||||
|
|
|
@ -106,6 +106,12 @@ public:
|
||||||
Status Open(const std::string &path, FileHandle **handle) override;
|
Status Open(const std::string &path, FileHandle **handle) override;
|
||||||
|
|
||||||
|
|
||||||
|
virtual void GetBlockLocations(const std::string & path,
|
||||||
|
const std::function<void(const Status &, std::shared_ptr<FileBlockLocation> locations)> ) override;
|
||||||
|
virtual Status GetBlockLocations(const std::string & path,
|
||||||
|
std::shared_ptr<FileBlockLocation> * locations) override;
|
||||||
|
|
||||||
|
|
||||||
void SetFsEventCallback(fs_event_callback callback) override;
|
void SetFsEventCallback(fs_event_callback callback) override;
|
||||||
|
|
||||||
/* add a new thread to handle asio requests, return number of threads in pool
|
/* add a new thread to handle asio requests, return number of threads in pool
|
||||||
|
|
|
@ -28,6 +28,8 @@ namespace hdfs {
|
||||||
*/
|
*/
|
||||||
struct FileInfo {
|
struct FileInfo {
|
||||||
unsigned long long file_length_;
|
unsigned long long file_length_;
|
||||||
|
bool under_construction_;
|
||||||
|
bool last_block_complete_;
|
||||||
std::vector<::hadoop::hdfs::LocatedBlockProto> blocks_;
|
std::vector<::hadoop::hdfs::LocatedBlockProto> blocks_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ set (LIBHDFSPP_LIB_DIR ${LIBHDFSPP_SRC_DIR}/lib)
|
||||||
set (LIBHDFSPP_BINDING_C ${LIBHDFSPP_LIB_DIR}/bindings/c)
|
set (LIBHDFSPP_BINDING_C ${LIBHDFSPP_LIB_DIR}/bindings/c)
|
||||||
include_directories(
|
include_directories(
|
||||||
${GENERATED_JAVAH}
|
${GENERATED_JAVAH}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
${CMAKE_BINARY_DIR}
|
${CMAKE_BINARY_DIR}
|
||||||
${JNI_INCLUDE_DIRS}
|
${JNI_INCLUDE_DIRS}
|
||||||
${LIBHDFS_SRC_DIR}/include
|
${LIBHDFS_SRC_DIR}/include
|
||||||
|
@ -54,6 +54,11 @@ function(add_memcheck_test name binary)
|
||||||
endif()
|
endif()
|
||||||
endfunction(add_memcheck_test)
|
endfunction(add_memcheck_test)
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# UNIT TESTS - TEST SELECTED PARTS OF THE LIBRARY
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
add_executable(uri_test uri_test.cc)
|
add_executable(uri_test uri_test.cc)
|
||||||
target_link_libraries(uri_test common gmock_main ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(uri_test common gmock_main ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
@ -96,16 +101,6 @@ add_executable(hdfspp_errors_test hdfspp_errors.cc)
|
||||||
target_link_libraries(hdfspp_errors_test common gmock_main bindings_c fs rpc proto common reader connection ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} ${SASL_LIBRARIES} gmock_main ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(hdfspp_errors_test common gmock_main bindings_c fs rpc proto common reader connection ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} ${SASL_LIBRARIES} gmock_main ${CMAKE_THREAD_LIBS_INIT})
|
||||||
add_memcheck_test(hdfspp_errors hdfspp_errors_test)
|
add_memcheck_test(hdfspp_errors hdfspp_errors_test)
|
||||||
|
|
||||||
#This test requires a great deal of Hadoop Java infrastructure to run.
|
|
||||||
if(HADOOP_BUILD)
|
|
||||||
add_library(hdfspp_test_shim_static STATIC hdfs_shim.c libhdfs_wrapper.c libhdfspp_wrapper.cc ${LIBHDFSPP_BINDING_C}/hdfs.cc)
|
|
||||||
|
|
||||||
build_libhdfs_test(libhdfs_threaded hdfspp_test_shim_static expect.c test_libhdfs_threaded.c ${OS_DIR}/thread.c)
|
|
||||||
link_libhdfs_test(libhdfs_threaded hdfspp_test_shim_static fs reader rpc proto common connection ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} ${SASL_LIBRARIES} native_mini_dfs ${JAVA_JVM_LIBRARY})
|
|
||||||
add_libhdfs_test(libhdfs_threaded hdfspp_test_shim_static)
|
|
||||||
|
|
||||||
endif(HADOOP_BUILD)
|
|
||||||
|
|
||||||
add_executable(hdfs_builder_test hdfs_builder_test.cc)
|
add_executable(hdfs_builder_test hdfs_builder_test.cc)
|
||||||
target_link_libraries(hdfs_builder_test test_common gmock_main bindings_c fs rpc proto common reader connection ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} ${SASL_LIBRARIES} gmock_main ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(hdfs_builder_test test_common gmock_main bindings_c fs rpc proto common reader connection ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} ${SASL_LIBRARIES} gmock_main ${CMAKE_THREAD_LIBS_INIT})
|
||||||
add_memcheck_test(hdfs_builder_test hdfs_builder_test)
|
add_memcheck_test(hdfs_builder_test hdfs_builder_test)
|
||||||
|
@ -113,3 +108,38 @@ add_memcheck_test(hdfs_builder_test hdfs_builder_test)
|
||||||
add_executable(logging_test logging_test.cc)
|
add_executable(logging_test logging_test.cc)
|
||||||
target_link_libraries(logging_test common gmock_main bindings_c fs rpc proto common reader connection ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} ${SASL_LIBRARIES} gmock_main ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(logging_test common gmock_main bindings_c fs rpc proto common reader connection ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} ${SASL_LIBRARIES} gmock_main ${CMAKE_THREAD_LIBS_INIT})
|
||||||
add_memcheck_test(logging_test logging_test)
|
add_memcheck_test(logging_test logging_test)
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# INTEGRATION TESTS - TESTS THE FULL LIBRARY AGAINST ACTUAL SERVERS
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# This test requires a great deal of Hadoop Java infrastructure to run.
|
||||||
|
#
|
||||||
|
if(HADOOP_BUILD)
|
||||||
|
|
||||||
|
include_directories (
|
||||||
|
#TODO: Put this in a variable up top and pull it out here
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../../libhdfs-tests/
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(hdfspp_test_shim_static STATIC hdfs_shim.c libhdfs_wrapper.c libhdfspp_wrapper.cc ${LIBHDFSPP_BINDING_C}/hdfs.cc)
|
||||||
|
|
||||||
|
# TODO: get all of the mini dfs library bits here in one plase
|
||||||
|
# add_library(hdfspp_mini_cluster native_mini_dfs ${JAVA_JVM_LIBRARY} )
|
||||||
|
|
||||||
|
#TODO: Link against full library rather than just parts
|
||||||
|
|
||||||
|
build_libhdfs_test(libhdfs_threaded hdfspp_test_shim_static expect.c test_libhdfs_threaded.c ${OS_DIR}/thread.c)
|
||||||
|
link_libhdfs_test(libhdfs_threaded hdfspp_test_shim_static fs reader rpc proto common connection ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} native_mini_dfs ${JAVA_JVM_LIBRARY} ${SASL_LIBRARIES} )
|
||||||
|
add_libhdfs_test (libhdfs_threaded hdfspp_test_shim_static)
|
||||||
|
|
||||||
|
build_libhdfs_test(hdfspp_mini_dfs_smoke hdfspp_test_shim_static ${CMAKE_CURRENT_LIST_DIR}/hdfspp_mini_dfs_smoke.cc)
|
||||||
|
link_libhdfs_test (hdfspp_mini_dfs_smoke hdfspp_test_shim_static fs reader rpc proto common connection gmock_main ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} native_mini_dfs ${JAVA_JVM_LIBRARY} ${SASL_LIBRARIES})
|
||||||
|
add_libhdfs_test (hdfspp_mini_dfs_smoke hdfspp_test_shim_static)
|
||||||
|
|
||||||
|
build_libhdfs_test(hdfs_ext hdfspp_test_shim_static ${CMAKE_CURRENT_LIST_DIR}/hdfs_ext_test.cc)
|
||||||
|
link_libhdfs_test (hdfs_ext hdfspp_test_shim_static hdfspp_static gmock_main native_mini_dfs ${JAVA_JVM_LIBRARY} ${SASL_LIBRARIES})
|
||||||
|
add_libhdfs_test (hdfs_ext hdfspp_test_shim_static)
|
||||||
|
|
||||||
|
endif(HADOOP_BUILD)
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include "expect.h"
|
||||||
|
|
||||||
|
#include "hdfspp_mini_dfs.h"
|
||||||
|
#include "hdfspp/hdfs_ext.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace hdfs {
|
||||||
|
|
||||||
|
class HdfsExtTest: public ::testing::Test {
|
||||||
|
public:
|
||||||
|
MiniCluster cluster;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make sure we can set up a mini-cluster and connect to it
|
||||||
|
TEST_F(HdfsExtTest, TestGetBlockLocations) {
|
||||||
|
HdfsHandle connection = cluster.connect_c();
|
||||||
|
EXPECT_NE(nullptr, connection.handle());
|
||||||
|
|
||||||
|
hdfsBlockLocations * blocks = nullptr;
|
||||||
|
|
||||||
|
// Free a null pointer
|
||||||
|
int result = hdfsFreeBlockLocations(blocks);
|
||||||
|
EXPECT_EQ(0, result);
|
||||||
|
|
||||||
|
// Test non-extant files
|
||||||
|
result = hdfsGetBlockLocations(connection, "non_extant_file", &blocks);
|
||||||
|
EXPECT_NE(0, result); // Should be an error
|
||||||
|
|
||||||
|
// Test an extant file
|
||||||
|
std::string filename = connection.newFile(1024);
|
||||||
|
result = hdfsGetBlockLocations(connection, filename.c_str(), &blocks);
|
||||||
|
EXPECT_EQ(0, result);
|
||||||
|
|
||||||
|
EXPECT_EQ(1024, blocks->fileLength);
|
||||||
|
EXPECT_EQ(1, blocks->num_blocks);
|
||||||
|
EXPECT_EQ(0, blocks->isUnderConstruction);
|
||||||
|
EXPECT_NE(0, blocks->isLastBlockComplete);
|
||||||
|
EXPECT_EQ(1024, blocks->blocks->num_bytes);
|
||||||
|
EXPECT_EQ(0, blocks->blocks->start_offset);
|
||||||
|
EXPECT_EQ(1, blocks->blocks->num_locations);
|
||||||
|
EXPECT_NE(nullptr, blocks->blocks->locations->hostname);
|
||||||
|
EXPECT_NE(nullptr, blocks->blocks->locations->ip_address);
|
||||||
|
EXPECT_NE(0, blocks->blocks->locations->xfer_port);
|
||||||
|
|
||||||
|
result = hdfsFreeBlockLocations(blocks);
|
||||||
|
EXPECT_EQ(0, result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
// The following line must be executed to initialize Google Mock
|
||||||
|
// (and Google Test) before running the tests.
|
||||||
|
::testing::InitGoogleMock(&argc, argv);
|
||||||
|
int exit_code = RUN_ALL_TESTS();
|
||||||
|
google::protobuf::ShutdownProtobufLibrary();
|
||||||
|
|
||||||
|
return exit_code;
|
||||||
|
}
|
|
@ -311,7 +311,7 @@ int hdfsFileIsEncrypted(hdfsFileInfo *hdfsFileInfo) {
|
||||||
((libhdfs_hdfsFileInfo *) hdfsFileInfo);
|
((libhdfs_hdfsFileInfo *) hdfsFileInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
char*** hdfsGetHosts(hdfsFS fs, const char* path,
|
char*** hdfsGetHosts(hdfsFS fs, const char* path,
|
||||||
tOffset start, tOffset length) {
|
tOffset start, tOffset length) {
|
||||||
return libhdfs_hdfsGetHosts(fs->libhdfsRep, path, start, length);
|
return libhdfs_hdfsGetHosts(fs->libhdfsRep, path, start, length);
|
||||||
}
|
}
|
||||||
|
@ -383,3 +383,25 @@ const void *hadoopRzBufferGet(const struct hadoopRzBuffer *buffer) {
|
||||||
void hadoopRzBufferFree(hdfsFile file, struct hadoopRzBuffer *buffer) {
|
void hadoopRzBufferFree(hdfsFile file, struct hadoopRzBuffer *buffer) {
|
||||||
return libhdfs_hadoopRzBufferFree(file->libhdfsRep, buffer);
|
return libhdfs_hadoopRzBufferFree(file->libhdfsRep, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************
|
||||||
|
* hdfs_ext functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
void hdfsGetLastError(char *buf, int len) {
|
||||||
|
return libhdfspp_hdfsGetLastError(buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hdfsCancel(hdfsFS fs, hdfsFile file) {
|
||||||
|
return libhdfspp_hdfsCancel(fs->libhdfsppRep, file->libhdfsppRep);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hdfsGetBlockLocations(hdfsFS fs, const char *path, struct hdfsBlockLocations ** locations) {
|
||||||
|
return libhdfspp_hdfsGetBlockLocations(fs->libhdfsppRep, path, locations);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hdfsFreeBlockLocations(struct hdfsBlockLocations * locations) {
|
||||||
|
return libhdfspp_hdfsFreeBlockLocations(locations);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hdfs/hdfs.h"
|
||||||
|
#include "hdfspp/hdfspp.h"
|
||||||
|
#include <native_mini_dfs.h>
|
||||||
|
|
||||||
|
#include <google/protobuf/io/coded_stream.h>
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#define TO_STR_HELPER(X) #X
|
||||||
|
#define TO_STR(X) TO_STR_HELPER(X)
|
||||||
|
|
||||||
|
#define TEST_BLOCK_SIZE 134217728
|
||||||
|
|
||||||
|
namespace hdfs {
|
||||||
|
|
||||||
|
|
||||||
|
static std::atomic<int> dirnum;
|
||||||
|
static std::atomic<int> filenum;
|
||||||
|
|
||||||
|
|
||||||
|
class FSHandle {
|
||||||
|
public:
|
||||||
|
FSHandle() : fs(nullptr) {}
|
||||||
|
FSHandle(FileSystem * fs_in) : fs(fs_in) {}
|
||||||
|
|
||||||
|
|
||||||
|
FileSystem * handle() { return fs.get(); }
|
||||||
|
operator FileSystem *() { return fs.get(); }
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<FileSystem> fs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For tests going through the C API to libhdfs++
|
||||||
|
*/
|
||||||
|
|
||||||
|
class HdfsHandle {
|
||||||
|
public:
|
||||||
|
HdfsHandle() : fs(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
HdfsHandle(hdfsFS fs_in) : fs(fs_in) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~HdfsHandle () {
|
||||||
|
if (fs) {
|
||||||
|
EXPECT_EQ(0, hdfsDisconnect(fs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string newDir(const std::string & parent_dir = "/") {
|
||||||
|
int newDirNum = dirnum++;
|
||||||
|
|
||||||
|
std::string path = parent_dir;
|
||||||
|
if (path.back() != '/')
|
||||||
|
path += "/";
|
||||||
|
path += "dir" + std::to_string(newDirNum) + "/";
|
||||||
|
|
||||||
|
EXPECT_EQ(0, hdfsCreateDirectory(*this, path.c_str()));
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string newFile(const std::string & dir = "/", size_t size = 1024) {
|
||||||
|
int newFileNum = filenum++;
|
||||||
|
|
||||||
|
std::string path = dir;
|
||||||
|
if (path.back() != '/')
|
||||||
|
path += "/";
|
||||||
|
path += "file" + std::to_string(newFileNum);
|
||||||
|
|
||||||
|
hdfsFile file = hdfsOpenFile(*this, path.c_str(), O_WRONLY, 0, 0, 0);
|
||||||
|
EXPECT_NE(nullptr, file);
|
||||||
|
void * buf = malloc(size);
|
||||||
|
bzero(buf, size);
|
||||||
|
EXPECT_EQ(1024, hdfsWrite(*this, file, buf, size));
|
||||||
|
EXPECT_EQ(0, hdfsCloseFile(*this, file));
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string newFile(size_t size) {
|
||||||
|
return newFile("/", size);
|
||||||
|
}
|
||||||
|
|
||||||
|
hdfsFS handle() { return fs; }
|
||||||
|
operator hdfsFS() { return fs; }
|
||||||
|
private:
|
||||||
|
hdfsFS fs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MiniCluster {
|
||||||
|
public:
|
||||||
|
MiniCluster() : io_service(IoService::New()) {
|
||||||
|
struct NativeMiniDfsConf conf = {
|
||||||
|
1, /* doFormat */
|
||||||
|
0, /* webhdfs */
|
||||||
|
-1, /* webhdfs port */
|
||||||
|
1 /* shortcircuit */
|
||||||
|
};
|
||||||
|
clusterInfo = nmdCreate(&conf);
|
||||||
|
EXPECT_NE(nullptr, clusterInfo);
|
||||||
|
EXPECT_EQ(0, nmdWaitClusterUp(clusterInfo));
|
||||||
|
|
||||||
|
//TODO: Write some files for tests to read/check
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~MiniCluster() {
|
||||||
|
if (clusterInfo) {
|
||||||
|
EXPECT_EQ(0, nmdShutdown(clusterInfo));
|
||||||
|
}
|
||||||
|
nmdFree(clusterInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect via the C++ API
|
||||||
|
FSHandle connect(const std::string username) {
|
||||||
|
Options options;
|
||||||
|
FileSystem * fs = FileSystem::New(io_service, username, options);
|
||||||
|
EXPECT_NE(nullptr, fs);
|
||||||
|
FSHandle result(fs);
|
||||||
|
|
||||||
|
tPort port = (tPort)nmdGetNameNodePort(clusterInfo);
|
||||||
|
EXPECT_NE(0, port);
|
||||||
|
Status status = fs->Connect("localhost", std::to_string(port));
|
||||||
|
EXPECT_EQ(true, status.ok());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSHandle connect() {
|
||||||
|
return connect("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect via the C API
|
||||||
|
HdfsHandle connect_c(const std::string & username) {
|
||||||
|
tPort port;
|
||||||
|
hdfsFS hdfs;
|
||||||
|
struct hdfsBuilder *bld;
|
||||||
|
|
||||||
|
port = (tPort)nmdGetNameNodePort(clusterInfo);
|
||||||
|
bld = hdfsNewBuilder();
|
||||||
|
EXPECT_NE(nullptr, bld);
|
||||||
|
hdfsBuilderSetForceNewInstance(bld);
|
||||||
|
hdfsBuilderSetNameNode(bld, "localhost");
|
||||||
|
hdfsBuilderSetNameNodePort(bld, port);
|
||||||
|
hdfsBuilderConfSetStr(bld, "dfs.block.size",
|
||||||
|
TO_STR(TEST_BLOCK_SIZE));
|
||||||
|
hdfsBuilderConfSetStr(bld, "dfs.blocksize",
|
||||||
|
TO_STR(TEST_BLOCK_SIZE));
|
||||||
|
if (!username.empty()) {
|
||||||
|
hdfsBuilderSetUserName(bld, username.c_str());
|
||||||
|
}
|
||||||
|
hdfs = hdfsBuilderConnect(bld);
|
||||||
|
EXPECT_NE(nullptr, hdfs);
|
||||||
|
|
||||||
|
return HdfsHandle(hdfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect via the C API
|
||||||
|
HdfsHandle connect_c() {
|
||||||
|
return connect_c("");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct NativeMiniDfsCluster* clusterInfo;
|
||||||
|
IoService * io_service;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hdfspp_mini_dfs.h"
|
||||||
|
|
||||||
|
namespace hdfs {
|
||||||
|
|
||||||
|
class HdfsMiniDfsSmokeTest: public ::testing::Test {
|
||||||
|
public:
|
||||||
|
MiniCluster cluster;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make sure we can set up a mini-cluster and connect to it
|
||||||
|
TEST_F(HdfsMiniDfsSmokeTest, SmokeTest) {
|
||||||
|
FSHandle handle = cluster.connect();
|
||||||
|
EXPECT_NE(nullptr, handle.handle());
|
||||||
|
|
||||||
|
HdfsHandle connection = cluster.connect_c();
|
||||||
|
EXPECT_NE(nullptr, connection.handle());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
// The following line must be executed to initialize Google Mock
|
||||||
|
// (and Google Test) before running the tests.
|
||||||
|
::testing::InitGoogleMock(&argc, argv);
|
||||||
|
int exit_code = RUN_ALL_TESTS();
|
||||||
|
google::protobuf::ShutdownProtobufLibrary();
|
||||||
|
|
||||||
|
return exit_code;
|
||||||
|
}
|
|
@ -90,3 +90,7 @@
|
||||||
#undef kObjectKindDirectory
|
#undef kObjectKindDirectory
|
||||||
#undef hdfsReadStatistics
|
#undef hdfsReadStatistics
|
||||||
#undef hdfsFileInfo
|
#undef hdfsFileInfo
|
||||||
|
#undef hdfsGetLastError
|
||||||
|
#undef hdfsCancel
|
||||||
|
#undef hdfsGetBlockLocations
|
||||||
|
#undef hdfsFreeBlockLocations
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
/* Rename libhdfspp structs and functions */
|
/* Rename libhdfspp structs and functions */
|
||||||
#include "libhdfspp_wrapper_defines.h"
|
#include "libhdfspp_wrapper_defines.h"
|
||||||
#include "hdfs/hdfs.h"
|
#include "hdfs/hdfs.h"
|
||||||
|
#include "hdfspp/hdfs_ext.h"
|
||||||
#include "libhdfs_wrapper_undefs.h"
|
#include "libhdfs_wrapper_undefs.h"
|
||||||
|
|
||||||
/* "Original" symbols can be included elsewhere. */
|
/* "Original" symbols can be included elsewhere. */
|
||||||
|
|
|
@ -90,3 +90,7 @@
|
||||||
#define kObjectKindDirectory libhdfspp_kObjectKindDirectory
|
#define kObjectKindDirectory libhdfspp_kObjectKindDirectory
|
||||||
#define hdfsReadStatistics libhdfspp_hdfsReadStatistics
|
#define hdfsReadStatistics libhdfspp_hdfsReadStatistics
|
||||||
#define hdfsFileInfo libhdfspp_hdfsFileInfo
|
#define hdfsFileInfo libhdfspp_hdfsFileInfo
|
||||||
|
#define hdfsGetLastError libhdfspp_hdfsGetLastError
|
||||||
|
#define hdfsCancel libhdfspp_hdfsCancel
|
||||||
|
#define hdfsGetBlockLocations libhdfspp_hdfsGetBlockLocations
|
||||||
|
#define hdfsFreeBlockLocations libhdfspp_hdfsFreeBlockLocations
|
||||||
|
|
Loading…
Reference in New Issue