blob: 20482a6c54ddde22f8767c21f1c2ffe6d84eaa74 [file]
// 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.
#pragma once
#include <jni.h>
#include "arrow/array.h"
#include "arrow/io/api.h"
#include "arrow/ipc/api.h"
#include "arrow/memory_pool.h"
#include "arrow/result.h"
#include "arrow/type.h"
namespace arrow {
namespace dataset {
namespace jni {
JNIEnv* GetEnvOrAttach(JavaVM* vm);
Status CheckException(JNIEnv* env);
jclass CreateGlobalClassReference(JNIEnv* env, const char* class_name);
arrow::Result<jmethodID> GetMethodID(JNIEnv* env, jclass this_class, const char* name,
const char* sig);
arrow::Result<jmethodID> GetStaticMethodID(JNIEnv* env, jclass this_class,
const char* name, const char* sig);
std::string JStringToCString(JNIEnv* env, jstring string);
std::vector<std::string> ToStringVector(JNIEnv* env, jobjectArray& str_array);
arrow::Result<jbyteArray> ToSchemaByteArray(JNIEnv* env,
std::shared_ptr<arrow::Schema> schema);
arrow::Result<std::shared_ptr<arrow::Schema>> FromSchemaByteArray(JNIEnv* env,
jbyteArray schemaBytes);
/// \brief Export arrow::RecordBatch for Java (or other JVM languages) use.
/// The exported batch is subject to C data interface specification and can be
/// imported from Java side using provided JNI utilities.
arrow::Status ExportRecordBatch(JNIEnv* env, const std::shared_ptr<RecordBatch>& batch,
jlong struct_array);
/// \brief Import arrow::RecordBatch from JVM language side. The input data should
/// ideally be exported from specific JNI utilities from JVM language side and should
/// conform to C data interface specification.
arrow::Result<std::shared_ptr<RecordBatch>> ImportRecordBatch(
JNIEnv* env, const std::shared_ptr<Schema>& schema, jlong struct_array);
/// \brief Create a new shared_ptr on heap from shared_ptr t to prevent
/// the managed object from being garbage-collected.
///
/// \return address of the newly created shared pointer
template <typename T>
jlong CreateNativeRef(std::shared_ptr<T> t) {
std::shared_ptr<T>* retained_ptr = new std::shared_ptr<T>(t);
return reinterpret_cast<jlong>(retained_ptr);
}
/// \brief Get the shared_ptr that was derived via function CreateNativeRef.
///
/// \param[in] ref address of the shared_ptr
/// \return the shared_ptr object
template <typename T>
std::shared_ptr<T> RetrieveNativeInstance(jlong ref) {
std::shared_ptr<T>* retrieved_ptr = reinterpret_cast<std::shared_ptr<T>*>(ref);
return *retrieved_ptr;
}
/// \brief Destroy a shared_ptr using its memory address.
///
/// \param[in] ref address of the shared_ptr
template <typename T>
void ReleaseNativeRef(jlong ref) {
std::shared_ptr<T>* retrieved_ptr = reinterpret_cast<std::shared_ptr<T>*>(ref);
delete retrieved_ptr;
}
// Indicate an exception thrown during calling Java method via JNI.
// Not thread safe.
class JavaErrorDetail : public StatusDetail {
public:
JavaErrorDetail(JavaVM* vm, jthrowable cause);
virtual ~JavaErrorDetail();
const char* type_id() const override;
std::string ToString() const override;
jthrowable GetCause() const;
private:
JavaVM* vm_;
jthrowable cause_;
};
/// Listener to act on reservations/unreservations from ReservationListenableMemoryPool.
///
/// Note the memory pool will call this listener only on block-level memory
/// reservation/unreservation is granted. So the invocation parameter "size" is always
/// multiple of block size (by default, 512k) specified in memory pool.
class ReservationListener {
public:
virtual ~ReservationListener() = default;
virtual arrow::Status OnReservation(int64_t size) = 0;
virtual arrow::Status OnRelease(int64_t size) = 0;
protected:
ReservationListener() = default;
};
/// A memory pool implementation for pre-reserving memory blocks from a
/// customizable listener. This will typically be used when memory allocations
/// have to be subject to another "virtual" resource manager, which just tracks or
/// limits number of bytes of application's overall memory usage. The underlying
/// memory pool will still be responsible for actual malloc/free operations.
class ReservationListenableMemoryPool : public arrow::MemoryPool {
public:
/// \brief Constructor.
///
/// \param[in] pool the underlying memory pool
/// \param[in] listener a listener for block-level reservations/releases.
/// \param[in] block_size size of each block to reserve from the listener
explicit ReservationListenableMemoryPool(MemoryPool* pool,
std::shared_ptr<ReservationListener> listener,
int64_t block_size = 512 * 1024);
~ReservationListenableMemoryPool();
using MemoryPool::Allocate;
using MemoryPool::Free;
using MemoryPool::Reallocate;
arrow::Status Allocate(int64_t size, int64_t alignment, uint8_t** out) override;
arrow::Status Reallocate(int64_t old_size, int64_t new_size, int64_t alignment,
uint8_t** ptr) override;
void Free(uint8_t* buffer, int64_t size, int64_t alignment) override;
int64_t bytes_allocated() const override;
int64_t max_memory() const override;
int64_t total_bytes_allocated() const override;
int64_t num_allocations() const override;
std::string backend_name() const override;
std::shared_ptr<ReservationListener> get_listener();
private:
class Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace jni
} // namespace dataset
} // namespace arrow