blob: 3279feb8618482799ad5b051a988325b7d340890 [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.
*/
#include "platform.h"
#include "Exception.h"
#include "ExceptionInternal.h"
#include "Thread.h"
#include <cassert>
#include <cstring>
#include <sstream>
namespace hdfs {
function<bool(void)> ChecnOperationCanceledCallback;
namespace internal {
bool CheckOperationCanceled() {
if (ChecnOperationCanceledCallback && ChecnOperationCanceledCallback()) {
THROW(HdfsCanceled, "Operation has been canceled by the user.");
}
return false;
}
const char *GetSystemErrorInfo(int eno) {
static THREAD_LOCAL char message[64];
char buffer[64], *pbuffer;
pbuffer = buffer;
#ifdef STRERROR_R_RETURN_INT
strerror_r(eno, buffer, sizeof(buffer));
#else
pbuffer = strerror_r(eno, buffer, sizeof(buffer));
#endif
snprintf(message, sizeof(message), "(errno: %d) %s", eno, pbuffer);
return message;
}
static THREAD_LOCAL std::string *MessageBuffer = NULL;
static void InitMessageBuffer() {
if (!MessageBuffer) {
MessageBuffer = new std::string;
}
}
static void GetExceptionDetailInternal(const hdfs::HdfsException &e,
std::stringstream &ss, bool topLevel);
static void GetExceptionDetailInternal(const std::exception &e,
std::stringstream &ss, bool topLevel) {
try {
if (!topLevel) {
ss << "Caused by\n";
}
ss << e.what();
} catch (const std::bad_alloc &e) {
return;
}
try {
hdfs::rethrow_if_nested(e);
} catch (const hdfs::HdfsException &nested) {
GetExceptionDetailInternal(nested, ss, false);
} catch (const std::exception &nested) {
GetExceptionDetailInternal(nested, ss, false);
}
}
static void GetExceptionDetailInternal(const hdfs::HdfsException &e,
std::stringstream &ss, bool topLevel) {
try {
if (!topLevel) {
ss << "Caused by\n";
}
ss << e.msg();
} catch (const std::bad_alloc &e) {
return;
}
try {
hdfs::rethrow_if_nested(e);
} catch (const hdfs::HdfsException &nested) {
GetExceptionDetailInternal(nested, ss, false);
} catch (const std::exception &nested) {
GetExceptionDetailInternal(nested, ss, false);
}
}
const char *GetExceptionDetail(const hdfs::HdfsException &e) {
std::stringstream ss;
GetExceptionDetailInternal(e, ss, true);
try {
InitMessageBuffer();
*MessageBuffer = ss.str();
} catch (const std::bad_alloc &e) {
return "Out of memory";
}
return MessageBuffer->c_str();
}
const char *GetExceptionDetail(const exception_ptr e) {
std::stringstream ss;
try {
InitMessageBuffer();
hdfs::rethrow_exception(e);
} catch (const hdfs::HdfsException &nested) {
GetExceptionDetailInternal(nested, ss, true);
} catch (const std::exception &nested) {
GetExceptionDetailInternal(nested, ss, true);
}
try {
*MessageBuffer = ss.str();
} catch (const std::bad_alloc &e) {
return "Out of memory";
}
return MessageBuffer->c_str();
}
static void GetExceptionMessage(const std::exception &e,
std::stringstream &ss, int recursive) {
try {
for (int i = 0; i < recursive; ++i) {
ss << '\t';
}
if (recursive > 0) {
ss << "Caused by: ";
}
ss << e.what();
} catch (const std::bad_alloc &e) {
return;
}
try {
hdfs::rethrow_if_nested(e);
} catch (const std::exception &nested) {
GetExceptionMessage(nested, ss, recursive + 1);
}
}
const char *GetExceptionMessage(const exception_ptr e, std::string &buffer) {
std::stringstream ss;
try {
hdfs::rethrow_exception(e);
} catch (const std::bad_alloc &e) {
return "Out of memory";
} catch (const std::exception &e) {
GetExceptionMessage(e, ss, 0);
}
try {
buffer = ss.str();
} catch (const std::bad_alloc &e) {
return "Out of memory";
}
return buffer.c_str();
}
}
}