Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test-ipc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
matrix:
config:
- {label: default-build, cmake_args: "-DNANOARROW_BUILD_APPS=ON -DNANOARROW_IPC_WITH_ZSTD=ON -DNANOARROW_IPC_WITH_LZ4=ON"}
- {label: default-noatomics, cmake_args: "-DCMAKE_C_FLAGS='-DNANOARROW_IPC_USE_STDATOMIC=0'"}
- {label: default-noatomics, cmake_args: "-DCMAKE_C_FLAGS='-DNANOARROW_USE_STDATOMIC=0'"}
- {label: shared-test-linkage, cmake_args: "-DNANOARROW_TEST_LINKAGE_SHARED=ON"}
- {label: namespaced-build, cmake_args: "-DNANOARROW_NAMESPACE=SomeUserNamespace"}
- {label: bundled-build, cmake_args: "-DNANOARROW_BUNDLE=ON"}
Expand Down
7 changes: 3 additions & 4 deletions r/src/altrep.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,17 +168,16 @@ SEXP nanoarrow_c_make_altrep_chr(SEXP array_xptr) {
// Ensure the array that we're attaching to this ALTREP object does not keep its
// parent struct alive unnecessarily (i.e., a user can select only a few columns
// and the memory for the unused columns will be released).
SEXP array_xptr_independent = PROTECT(array_xptr_ensure_independent(array_xptr));
array_xptr_ensure_independent(array_xptr);

if (nanoarrow_converter_set_array(converter_xptr, array_xptr_independent) !=
NANOARROW_OK) {
if (nanoarrow_converter_set_array(converter_xptr, array_xptr) != NANOARROW_OK) {
nanoarrow_converter_stop(converter_xptr);
}

Rf_setAttrib(converter_xptr, R_ClassSymbol, nanoarrow_cls_altrep_chr);
SEXP out = PROTECT(R_new_altrep(nanoarrow_altrep_chr_cls, converter_xptr, R_NilValue));
MARK_NOT_MUTABLE(out);
UNPROTECT(3);
UNPROTECT(2);
return out;
}

Expand Down
158 changes: 157 additions & 1 deletion src/nanoarrow/common/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static void ArrowArrayReleaseInternal(struct ArrowArray* array) {
array->release = NULL;
}

static int ArrowArrayIsInternal(struct ArrowArray* array) {
int ArrowArrayIsInternal(struct ArrowArray* array) {
return array->release == &ArrowArrayReleaseInternal;
}

Expand Down Expand Up @@ -568,6 +568,162 @@ ArrowErrorCode ArrowArrayFinishBuildingDefault(struct ArrowArray* array,
return ArrowArrayFinishBuilding(array, NANOARROW_VALIDATION_LEVEL_DEFAULT, error);
}

static int ArrowArrayIsShared(struct ArrowArray* array) {
if (!ArrowArrayIsInternal(array)) {
return 0;
}

for (int64_t i = 0; i < array->n_buffers; i++) {
struct ArrowBuffer* buffer = ArrowArrayBuffer(array, i);
if (buffer->data != NULL && !ArrowIsSharedBuffer(buffer)) {
return 0;
}
}

for (int64_t i = 0; i < array->n_children; i++) {
if (!ArrowArrayIsShared(array->children[i])) {
return 0;
}
}

if (array->dictionary != NULL && !ArrowArrayIsShared(array->dictionary)) {
return 0;
}

return 1;
}

static ArrowErrorCode ArrowArrayMoveSharedInternal(struct ArrowArray* src,
struct ArrowArray* dst) {
if (ArrowArrayIsShared(src)) {
ArrowArrayMove(src, dst);
return NANOARROW_OK;
}

NANOARROW_RETURN_NOT_OK(ArrowArrayInitFromType(dst, NANOARROW_TYPE_UNINITIALIZED));

// Allocate children and move source children to dst children
NANOARROW_RETURN_NOT_OK(ArrowArrayAllocateChildren(dst, src->n_children));
for (int64_t i = 0; i < src->n_children; i++) {
NANOARROW_RETURN_NOT_OK(
ArrowArrayMoveSharedInternal(src->children[i], dst->children[i]));
}

// Allocate dictionary if needed and move source dictionary to dst dictionary
if (src->dictionary != NULL) {
NANOARROW_RETURN_NOT_OK(ArrowArrayAllocateDictionary(dst));
NANOARROW_RETURN_NOT_OK(
ArrowArrayMoveSharedInternal(src->dictionary, dst->dictionary));
}

// We might need some more buffers if we are shallowly copying a string/binary view
if (src->n_buffers > 3) {
if (src->n_buffers > INT_MAX) {
return EINVAL;
}

NANOARROW_RETURN_NOT_OK(
ArrowArrayAddVariadicBuffers(dst, (int32_t)src->n_buffers - 3));
}

// Move src into a shared array and set dst's buffers using the ref-counted version
struct ArrowSharedArray shared_array;
NANOARROW_RETURN_NOT_OK(ArrowSharedArrayInit(&shared_array, src));

for (int64_t i = 0; i < src->n_buffers; i++) {
struct ArrowBuffer* dst_buffer = ArrowArrayBuffer(dst, i);
ArrowErrorCode result = ArrowSharedArrayBuffer(&shared_array, i, dst_buffer);
if (result != NANOARROW_OK) {
ArrowSharedArrayRelease(&shared_array);
return result;
}
}

ArrowSharedArrayRelease(&shared_array);

dst->n_buffers = src->n_buffers;
dst->length = src->length;
dst->null_count = src->null_count;
dst->offset = src->offset;

// Flush internal buffer pointers to array->buffers
NANOARROW_RETURN_NOT_OK(ArrowArrayFlushInternalPointers(dst));

return NANOARROW_OK;
}

static ArrowErrorCode ArrowArrayCloneSharedInternal(struct ArrowArray* src,
struct ArrowArray* dst) {
NANOARROW_RETURN_NOT_OK(ArrowArrayInitFromType(dst, NANOARROW_TYPE_UNINITIALIZED));

// Allocate children and clone source children to dst children
NANOARROW_RETURN_NOT_OK(ArrowArrayAllocateChildren(dst, src->n_children));
for (int64_t i = 0; i < src->n_children; i++) {
NANOARROW_RETURN_NOT_OK(
ArrowArrayCloneSharedInternal(src->children[i], dst->children[i]));
}

// Allocate dictionary if needed and clone source dictionary to dst dictionary
if (src->dictionary != NULL) {
NANOARROW_RETURN_NOT_OK(ArrowArrayAllocateDictionary(dst));
NANOARROW_RETURN_NOT_OK(
ArrowArrayCloneSharedInternal(src->dictionary, dst->dictionary));
}

// We might need some more buffers if we are shallowly copying a string/binary view
if (src->n_buffers > 3) {
if (src->n_buffers > INT_MAX) {
return EINVAL;
}

NANOARROW_RETURN_NOT_OK(
ArrowArrayAddVariadicBuffers(dst, (int32_t)src->n_buffers - 3));
}

for (int64_t i = 0; i < src->n_buffers; i++) {
struct ArrowBuffer* src_buffer = ArrowArrayBuffer(src, i);
struct ArrowBuffer* dst_buffer = ArrowArrayBuffer(dst, i);
NANOARROW_RETURN_NOT_OK(ArrowSharedBufferClone(src_buffer, dst_buffer));
}

dst->n_buffers = src->n_buffers;
dst->length = src->length;
dst->null_count = src->null_count;
dst->offset = src->offset;

// Flush internal buffer pointers to array->buffers
NANOARROW_RETURN_NOT_OK(ArrowArrayFlushInternalPointers(dst));

return NANOARROW_OK;
}

ArrowErrorCode ArrowArrayMoveShared(struct ArrowArray* array, struct ArrowArray* shared) {
struct ArrowArray tmp;
tmp.release = NULL;
ArrowErrorCode result = ArrowArrayMoveSharedInternal(array, shared);
if (result != NANOARROW_OK && tmp.release != NULL) {
ArrowArrayRelease(&tmp);
}

return result;
}

ArrowErrorCode ArrowArrayCloneShared(struct ArrowArray* shared,
struct ArrowArray* array) {
if (!ArrowArrayIsShared(shared)) {
return EINVAL;
}

struct ArrowArray tmp;
tmp.release = NULL;
ArrowErrorCode result = ArrowArrayCloneSharedInternal(shared, array);
if (result != NANOARROW_OK && tmp.release != NULL) {
ArrowArrayRelease(&tmp);
}

return result;
}

void ArrowArrayViewInitFromType(struct ArrowArrayView* array_view,
enum ArrowType storage_type) {
memset(array_view, 0, sizeof(struct ArrowArrayView));
Expand Down
Loading
Loading