HDFS-9699: libhdfs++: Add appropriate catch blocks for asio operations that throw. Contributed by Bob Hansen
This commit is contained in:
parent
1600e6bba8
commit
6a96f978eb
|
@ -150,6 +150,16 @@ static int Error(const Status &stat) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int ReportException(const std::exception & e)
|
||||
{
|
||||
return Error(Status::Exception("Uncaught exception", e.what()));
|
||||
}
|
||||
|
||||
static int ReportCaughtNonException()
|
||||
{
|
||||
return Error(Status::Exception("Uncaught value not derived from std::exception", ""));
|
||||
}
|
||||
|
||||
/* return false on failure */
|
||||
bool CheckSystemAndHandle(hdfsFS fs, hdfsFile file) {
|
||||
if (!fs) {
|
||||
|
@ -180,6 +190,8 @@ hdfsFS hdfsConnect(const char *nn, tPort port) {
|
|||
}
|
||||
|
||||
hdfsFS hdfsConnectAsUser(const char* nn, tPort port, const char *user) {
|
||||
try
|
||||
{
|
||||
std::string port_as_string = std::to_string(port);
|
||||
IoService * io_service = IoService::New();
|
||||
std::string user_name;
|
||||
|
@ -206,9 +218,18 @@ hdfsFS hdfsConnectAsUser(const char* nn, tPort port, const char *user) {
|
|||
return nullptr;
|
||||
}
|
||||
return new hdfs_internal(fs);
|
||||
} catch (const std::exception & e) {
|
||||
ReportException(e);
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
ReportCaughtNonException();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int hdfsDisconnect(hdfsFS fs) {
|
||||
try
|
||||
{
|
||||
if (!fs) {
|
||||
ReportError(ENODEV, "Cannot disconnect null FS handle.");
|
||||
return -1;
|
||||
|
@ -216,10 +237,17 @@ int hdfsDisconnect(hdfsFS fs) {
|
|||
|
||||
delete fs;
|
||||
return 0;
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
hdfsFile hdfsOpenFile(hdfsFS fs, const char *path, int flags, int bufferSize,
|
||||
short replication, tSize blocksize) {
|
||||
try
|
||||
{
|
||||
(void)flags;
|
||||
(void)bufferSize;
|
||||
(void)replication;
|
||||
|
@ -235,18 +263,34 @@ hdfsFile hdfsOpenFile(hdfsFS fs, const char *path, int flags, int bufferSize,
|
|||
return nullptr;
|
||||
}
|
||||
return new hdfsFile_internal(f);
|
||||
} catch (const std::exception & e) {
|
||||
ReportException(e);
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
ReportCaughtNonException();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int hdfsCloseFile(hdfsFS fs, hdfsFile file) {
|
||||
try
|
||||
{
|
||||
if (!CheckSystemAndHandle(fs, file)) {
|
||||
return -1;
|
||||
}
|
||||
delete file;
|
||||
return 0;
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
tSize hdfsPread(hdfsFS fs, hdfsFile file, tOffset position, void *buffer,
|
||||
tSize length) {
|
||||
try
|
||||
{
|
||||
if (!CheckSystemAndHandle(fs, file)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -257,9 +301,16 @@ tSize hdfsPread(hdfsFS fs, hdfsFile file, tOffset position, void *buffer,
|
|||
return Error(stat);
|
||||
}
|
||||
return (tSize)len;
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
tSize hdfsRead(hdfsFS fs, hdfsFile file, void *buffer, tSize length) {
|
||||
try
|
||||
{
|
||||
if (!CheckSystemAndHandle(fs, file)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -271,10 +322,17 @@ tSize hdfsRead(hdfsFS fs, hdfsFile file, void *buffer, tSize length) {
|
|||
}
|
||||
|
||||
return (tSize)len;
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
/* 0 on success, -1 on error*/
|
||||
int hdfsSeek(hdfsFS fs, hdfsFile file, tOffset desiredPos) {
|
||||
try
|
||||
{
|
||||
if (!CheckSystemAndHandle(fs, file)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -286,9 +344,16 @@ int hdfsSeek(hdfsFS fs, hdfsFile file, tOffset desiredPos) {
|
|||
}
|
||||
|
||||
return 0;
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
tOffset hdfsTell(hdfsFS fs, hdfsFile file) {
|
||||
try
|
||||
{
|
||||
if (!CheckSystemAndHandle(fs, file)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -300,15 +365,27 @@ tOffset hdfsTell(hdfsFS fs, hdfsFile file) {
|
|||
}
|
||||
|
||||
return offset;
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
/* extended API */
|
||||
int hdfsCancel(hdfsFS fs, hdfsFile file) {
|
||||
try
|
||||
{
|
||||
if (!CheckSystemAndHandle(fs, file)) {
|
||||
return -1;
|
||||
}
|
||||
static_cast<FileHandleImpl*>(file->get_impl())->CancelOperations();
|
||||
return 0;
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -341,7 +418,16 @@ hdfsBuilder::hdfsBuilder(const char * directory) :
|
|||
|
||||
struct hdfsBuilder *hdfsNewBuilder(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new struct hdfsBuilder();
|
||||
} catch (const std::exception & e) {
|
||||
ReportException(e);
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
ReportCaughtNonException();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void hdfsBuilderSetNameNode(struct hdfsBuilder *bld, const char *nn)
|
||||
|
@ -366,12 +452,21 @@ void hdfsBuilderSetUserName(struct hdfsBuilder *bld, const char *userName)
|
|||
|
||||
void hdfsFreeBuilder(struct hdfsBuilder *bld)
|
||||
{
|
||||
try
|
||||
{
|
||||
delete bld;
|
||||
} catch (const std::exception & e) {
|
||||
ReportException(e);
|
||||
} catch (...) {
|
||||
ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
int hdfsBuilderConfSetStr(struct hdfsBuilder *bld, const char *key,
|
||||
const char *val)
|
||||
{
|
||||
try
|
||||
{
|
||||
optional<HdfsConfiguration> newConfig = bld->loader.OverlayValue(bld->config, key, val);
|
||||
if (newConfig)
|
||||
{
|
||||
|
@ -383,6 +478,11 @@ int hdfsBuilderConfSetStr(struct hdfsBuilder *bld, const char *key,
|
|||
ReportError(EINVAL, "Could not change Builder value");
|
||||
return 1;
|
||||
}
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
void hdfsConfStrFree(char *val)
|
||||
|
@ -391,7 +491,8 @@ void hdfsConfStrFree(char *val)
|
|||
}
|
||||
|
||||
hdfsFS hdfsBuilderConnect(struct hdfsBuilder *bld) {
|
||||
|
||||
try
|
||||
{
|
||||
if (!bld->overrideHost.empty())
|
||||
{
|
||||
// TODO: pass rest of config once we get that done (HDFS-9556)
|
||||
|
@ -411,18 +512,39 @@ hdfsFS hdfsBuilderConnect(struct hdfsBuilder *bld) {
|
|||
ReportError(EINVAL, "No host provided to builder in hdfsBuilderConnect");
|
||||
return nullptr;
|
||||
}
|
||||
} catch (const std::exception & e) {
|
||||
ReportException(e);
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
ReportCaughtNonException();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int hdfsConfGetStr(const char *key, char **val)
|
||||
{
|
||||
try
|
||||
{
|
||||
hdfsBuilder builder;
|
||||
return hdfsBuilderConfGetStr(&builder, key, val);
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
int hdfsConfGetInt(const char *key, int32_t *val)
|
||||
{
|
||||
try
|
||||
{
|
||||
hdfsBuilder builder;
|
||||
return hdfsBuilderConfGetInt(&builder, key, val);
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -430,12 +552,23 @@ int hdfsConfGetInt(const char *key, int32_t *val)
|
|||
//
|
||||
struct hdfsBuilder *hdfsNewBuilderFromDirectory(const char * configDirectory)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new struct hdfsBuilder(configDirectory);
|
||||
} catch (const std::exception & e) {
|
||||
ReportException(e);
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
ReportCaughtNonException();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int hdfsBuilderConfGetStr(struct hdfsBuilder *bld, const char *key,
|
||||
char **val)
|
||||
{
|
||||
try
|
||||
{
|
||||
optional<std::string> value = bld->config.Get(key);
|
||||
if (value)
|
||||
{
|
||||
|
@ -448,6 +581,11 @@ int hdfsBuilderConfGetStr(struct hdfsBuilder *bld, const char *key,
|
|||
*val = nullptr;
|
||||
}
|
||||
return 0;
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
||||
// If we're running on a 32-bit platform, we might get 64-bit values that
|
||||
|
@ -460,6 +598,8 @@ bool isValidInt(int64_t value)
|
|||
|
||||
int hdfsBuilderConfGetInt(struct hdfsBuilder *bld, const char *key, int32_t *val)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Pull from default configuration
|
||||
optional<int64_t> value = bld->config.GetInt(key);
|
||||
if (value)
|
||||
|
@ -472,4 +612,9 @@ int hdfsBuilderConfGetInt(struct hdfsBuilder *bld, const char *key, int32_t *val
|
|||
// If not found, don't change val
|
||||
ReportError(EINVAL, "Could not get Builder value");
|
||||
return 0;
|
||||
} catch (const std::exception & e) {
|
||||
return ReportException(e);
|
||||
} catch (...) {
|
||||
return ReportCaughtNonException();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,30 @@
|
|||
|
||||
#include "hdfs_public_api.h"
|
||||
|
||||
#include "common/logging.h"
|
||||
|
||||
namespace hdfs {
|
||||
|
||||
IoService::~IoService() {}
|
||||
|
||||
IoService *IoService::New() { return new IoServiceImpl(); }
|
||||
|
||||
void IoServiceImpl::Run() {
|
||||
// As recommended in http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/io_service.html#boost_asio.reference.io_service.effect_of_exceptions_thrown_from_handlers
|
||||
asio::io_service::work work(io_service_);
|
||||
for(;;)
|
||||
{
|
||||
try
|
||||
{
|
||||
io_service_.run();
|
||||
break;
|
||||
} catch (const std::exception & e) {
|
||||
LOG_WARN() << "Unexpected exception in libhdfspp worker thread: " << e.what();
|
||||
} catch (...) {
|
||||
LOG_WARN() << "Unexpected value not derived from std::exception in libhdfspp worker thread";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -27,10 +27,7 @@ namespace hdfs {
|
|||
|
||||
class IoServiceImpl : public IoService {
|
||||
public:
|
||||
virtual void Run() override {
|
||||
asio::io_service::work work(io_service_);
|
||||
io_service_.run();
|
||||
}
|
||||
virtual void Run() override;
|
||||
virtual void Stop() override { io_service_.stop(); }
|
||||
::asio::io_service &io_service() { return io_service_; }
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue