ARROW-2389: [C++] Add CapacityError

This error signals an attempt to exceed capacity of a buffer or container.
This commit is contained in:
Antoine Pitrou committed 2018-05-07 12:53:04 +02:00
1 parent 2f453a0777
commit afc037dfd9
9 files changed
+63 -41

No files matched your search

+4 -3
View File
@@ -1307,7 +1307,7 @@ Status ListBuilder::AppendNextOffset() {
std::stringstream ss;
ss << "ListArray cannot contain more then INT32_MAX - 1 child elements,"
<< " have " << num_values;
return Status::Invalid(ss.str());
return Status::CapacityError(ss.str());
}
return offsets_builder_.Append(static_cast<int32_t>(num_values));
}
@@ -1386,7 +1386,8 @@ Status BinaryBuilder::Resize(int64_t capacity) {
Status BinaryBuilder::ReserveData(int64_t elements) {
if (value_data_length() + elements > value_data_capacity()) {
if (value_data_length() + elements > kBinaryMemoryLimit) {
return Status::Invalid("Cannot reserve capacity larger than 2^31 - 1 for binary");
return Status::CapacityError(
"Cannot reserve capacity larger than 2^31 - 1 for binary");
}
RETURN_NOT_OK(value_data_builder_.Reserve(elements));
}
@@ -1399,7 +1400,7 @@ Status BinaryBuilder::AppendNextOffset() {
std::stringstream ss;
ss << "BinaryArray cannot contain more than " << kBinaryMemoryLimit << " bytes, have "
<< num_bytes;
return Status::Invalid(ss.str());
return Status::CapacityError(ss.str());
}
return offsets_builder_.Append(static_cast<int32_t>(num_bytes));
}
+1 -1
View File
@@ -115,7 +115,7 @@ class RecordBatchSerializer : public ArrayVisitor {
}
if (!allow_64bit_ && arr.length() > std::numeric_limits<int32_t>::max()) {
return Status::Invalid("Cannot write arrays larger than 2^31 - 1 in length");
return Status::CapacityError("Cannot write arrays larger than 2^31 - 1 in length");
}
// push back all common elements
+28 -29
View File
@@ -83,41 +83,40 @@ PyBuffer::~PyBuffer() {
// ----------------------------------------------------------------------
// Python exception -> Status
Status CheckPyError(StatusCode code) {
if (PyErr_Occurred()) {
PyObject* exc_type = nullptr;
PyObject* exc_value = nullptr;
PyObject* traceback = nullptr;
Status ConvertPyError(StatusCode code) {
PyObject* exc_type = nullptr;
PyObject* exc_value = nullptr;
PyObject* traceback = nullptr;
PyErr_Fetch(&exc_type, &exc_value, &traceback);
PyErr_NormalizeException(&exc_type, &exc_value, &traceback);
PyErr_Fetch(&exc_type, &exc_value, &traceback);
PyErr_NormalizeException(&exc_type, &exc_value, &traceback);
OwnedRef exc_type_ref(exc_type);
OwnedRef exc_value_ref(exc_value);
OwnedRef traceback_ref(traceback);
DCHECK_NE(exc_type, nullptr);
std::string message;
RETURN_NOT_OK(internal::PyObject_StdStringStr(exc_value, &message));
OwnedRef exc_type_ref(exc_type);
OwnedRef exc_value_ref(exc_value);
OwnedRef traceback_ref(traceback);
if (code == StatusCode::UnknownError) {
// Try to match the Python exception type with an appropriate Status code
if (PyErr_GivenExceptionMatches(exc_type, PyExc_MemoryError)) {
code = StatusCode::OutOfMemory;
} else if (PyErr_GivenExceptionMatches(exc_type, PyExc_KeyError)) {
code = StatusCode::KeyError;
} else if (PyErr_GivenExceptionMatches(exc_type, PyExc_TypeError)) {
code = StatusCode::TypeError;
} else if (PyErr_GivenExceptionMatches(exc_type, PyExc_ValueError)) {
code = StatusCode::Invalid;
} else if (PyErr_GivenExceptionMatches(exc_type, PyExc_EnvironmentError)) {
code = StatusCode::IOError;
} else if (PyErr_GivenExceptionMatches(exc_type, PyExc_NotImplementedError)) {
code = StatusCode::NotImplemented;
}
std::string message;
RETURN_NOT_OK(internal::PyObject_StdStringStr(exc_value, &message));
if (code == StatusCode::UnknownError) {
// Try to match the Python exception type with an appropriate Status code
if (PyErr_GivenExceptionMatches(exc_type, PyExc_MemoryError)) {
code = StatusCode::OutOfMemory;
} else if (PyErr_GivenExceptionMatches(exc_type, PyExc_KeyError)) {
code = StatusCode::KeyError;
} else if (PyErr_GivenExceptionMatches(exc_type, PyExc_TypeError)) {
code = StatusCode::TypeError;
} else if (PyErr_GivenExceptionMatches(exc_type, PyExc_ValueError)) {
code = StatusCode::Invalid;
} else if (PyErr_GivenExceptionMatches(exc_type, PyExc_EnvironmentError)) {
code = StatusCode::IOError;
} else if (PyErr_GivenExceptionMatches(exc_type, PyExc_NotImplementedError)) {
code = StatusCode::NotImplemented;
}
return Status(code, message);
}
return Status::OK();
return Status(code, message);
}
Status PassPyError() {
+11 -2
View File
@@ -35,8 +35,17 @@ class MemoryPool;
namespace py {
// TODO: inline the successful case
ARROW_EXPORT Status CheckPyError(StatusCode code = StatusCode::UnknownError);
ARROW_EXPORT Status ConvertPyError(StatusCode code = StatusCode::UnknownError);
// Catch a pending Python exception and return the corresponding Status.
// If no exception is pending, Status::OK() is returned.
inline Status CheckPyError(StatusCode code = StatusCode::UnknownError) {
if (ARROW_PREDICT_TRUE(!PyErr_Occurred())) {
return Status::OK();
} else {
return ConvertPyError(code);
}
}
ARROW_EXPORT Status PassPyError();
+3 -3
View File
@@ -165,7 +165,7 @@ Status BuilderAppend(BinaryBuilder* builder, PyObject* obj, bool* is_full) {
*is_full = true;
return Status::OK();
} else {
return Status::Invalid("Maximum array size reached (2GB)");
return Status::CapacityError("Maximum array size reached (2GB)");
}
}
RETURN_NOT_OK(builder->Append(view.bytes, length));
@@ -194,7 +194,7 @@ Status BuilderAppend(FixedSizeBinaryBuilder* builder, PyObject* obj, bool* is_fu
*is_full = true;
return Status::OK();
} else {
return Status::Invalid("Maximum array size reached (2GB)");
return Status::CapacityError("Maximum array size reached (2GB)");
}
}
RETURN_NOT_OK(builder->Append(view.bytes));
@@ -216,7 +216,7 @@ Status BuilderAppend(StringBuilder* builder, PyObject* obj, bool check_valid,
*is_full = true;
return Status::OK();
} else {
return Status::Invalid("Maximum array size reached (2GB)");
return Status::CapacityError("Maximum array size reached (2GB)");
}
}
RETURN_NOT_OK(builder->Append(view.bytes, length));
+3 -3
View File
@@ -1310,7 +1310,7 @@ inline Status NumPyConverter::ConvertTypedLists<NPY_OBJECT, BinaryType>(
RETURN_NOT_OK(
AppendObjectBinaries(numpy_array, nullptr, 0, value_builder, &offset));
if (offset < PyArray_SIZE(numpy_array)) {
return Status::Invalid("Array cell value exceeded 2GB");
return Status::CapacityError("Array cell value exceeded 2GB");
}
return Status::OK();
} else if (PyList_Check(object)) {
@@ -1367,7 +1367,7 @@ inline Status NumPyConverter::ConvertTypedLists<NPY_OBJECT, StringType>(
RETURN_NOT_OK(AppendObjectStrings(numpy_array, nullptr, 0, check_valid,
value_builder, &offset, &have_bytes));
if (offset < PyArray_SIZE(numpy_array)) {
return Status::Invalid("Array cell value exceeded 2GB");
return Status::CapacityError("Array cell value exceeded 2GB");
}
return Status::OK();
} else if (PyList_Check(object)) {
@@ -1514,7 +1514,7 @@ Status AppendUTF32(const char* data, int itemsize, int byteorder,
const int32_t length = static_cast<int32_t>(PyBytes_GET_SIZE(utf8_obj.obj()));
if (builder->value_data_length() + length > kBinaryMemoryLimit) {
return Status::Invalid("Encoded string length exceeds maximum size (2GB)");
return Status::CapacityError("Encoded string length exceeds maximum size (2GB)");
}
return builder->Append(PyBytes_AS_STRING(utf8_obj.obj()), length);
}
+6
View File
@@ -74,6 +74,7 @@ enum class StatusCode : char {
TypeError = 3,
Invalid = 4,
IOError = 5,
CapacityError = 6,
UnknownError = 9,
NotImplemented = 10,
SerializationError = 11,
@@ -129,6 +130,10 @@ class ARROW_EXPORT Status {
return Status(StatusCode::Invalid, msg);
}
static Status CapacityError(const std::string& msg) {
return Status(StatusCode::CapacityError, msg);
}
static Status IOError(const std::string& msg) {
return Status(StatusCode::IOError, msg);
}
@@ -160,6 +165,7 @@ class ARROW_EXPORT Status {
bool IsKeyError() const { return code() == StatusCode::KeyError; }
bool IsInvalid() const { return code() == StatusCode::Invalid; }
bool IsIOError() const { return code() == StatusCode::IOError; }
bool IsCapacityError() const { return code() == StatusCode::CapacityError; }
bool IsTypeError() const { return code() == StatusCode::TypeError; }
bool IsUnknownError() const { return code() == StatusCode::UnknownError; }
bool IsNotImplemented() const { return code() == StatusCode::NotImplemented; }
+6
View File
@@ -48,6 +48,10 @@ class ArrowNotImplementedError(NotImplementedError, ArrowException):
pass
class ArrowCapacityError(ArrowException):
pass
class PlasmaObjectExists(ArrowException):
pass
@@ -85,6 +89,8 @@ cdef int check_status(const CStatus& status) nogil except -1:
raise ArrowNotImplementedError(message)
elif status.IsTypeError():
raise ArrowTypeError(message)
elif status.IsCapacityError():
raise ArrowCapacityError(message)
elif status.IsPlasmaObjectExists():
raise PlasmaObjectExists(message)
elif status.IsPlasmaObjectNonexistent():
+1
View File
@@ -56,6 +56,7 @@ cdef extern from "arrow/api.h" namespace "arrow" nogil:
c_bool IsKeyError()
c_bool IsNotImplemented()
c_bool IsTypeError()
c_bool IsCapacityError()
c_bool IsSerializationError()
c_bool IsPythonError()
c_bool IsPlasmaObjectExists()