forked from lance-format/lance
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsession.rs
More file actions
149 lines (130 loc) · 4.7 KB
/
session.rs
File metadata and controls
149 lines (130 loc) · 4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright The Lance Authors
use std::sync::Arc;
use jni::JNIEnv;
use jni::objects::JObject;
use jni::sys::jlong;
use lance::dataset::{DEFAULT_INDEX_CACHE_SIZE, DEFAULT_METADATA_CACHE_SIZE};
use lance::session::Session as LanceSession;
use lance_io::object_store::ObjectStoreRegistry;
use crate::error::{Error, Result};
/// Creates a new Session and returns a handle to it.
///
/// The handle is a raw pointer to a Box<Arc<LanceSession>>, which allows
/// the session to be shared between multiple datasets.
#[unsafe(no_mangle)]
pub extern "system" fn Java_org_lance_Session_createNative(
mut env: JNIEnv,
_obj: JObject,
index_cache_size_bytes: jlong,
metadata_cache_size_bytes: jlong,
) -> jlong {
ok_or_throw_with_return!(
env,
create_session(index_cache_size_bytes, metadata_cache_size_bytes),
0
)
}
fn create_session(
index_cache_size_bytes: jlong,
metadata_cache_size_bytes: jlong,
) -> Result<jlong> {
let index_cache_size = if index_cache_size_bytes >= 0 {
index_cache_size_bytes as usize
} else {
DEFAULT_INDEX_CACHE_SIZE
};
let metadata_cache_size = if metadata_cache_size_bytes >= 0 {
metadata_cache_size_bytes as usize
} else {
DEFAULT_METADATA_CACHE_SIZE
};
let session = LanceSession::new(
index_cache_size,
metadata_cache_size,
Arc::new(ObjectStoreRegistry::default()),
);
// Wrap in Arc and Box, then convert to raw pointer
let boxed: Box<Arc<LanceSession>> = Box::new(Arc::new(session));
let handle = Box::into_raw(boxed) as jlong;
Ok(handle)
}
/// Returns the current size of the session in bytes.
#[unsafe(no_mangle)]
pub extern "system" fn Java_org_lance_Session_sizeBytesNative(
mut env: JNIEnv,
obj: JObject,
) -> jlong {
ok_or_throw_with_return!(env, size_bytes_native(&mut env, obj), 0)
}
fn size_bytes_native(env: &mut JNIEnv, obj: JObject) -> Result<jlong> {
let handle = get_session_handle(env, &obj)?;
if handle == 0 {
return Err(Error::input_error("Session is closed".to_string()));
}
// Safety: We trust that the handle is valid and was created by createNative
let session_arc = unsafe { &*(handle as *const Arc<LanceSession>) };
Ok(session_arc.size_bytes() as jlong)
}
/// Releases the native session handle.
#[unsafe(no_mangle)]
pub extern "system" fn Java_org_lance_Session_releaseNative(
_env: JNIEnv,
_obj: JObject,
handle: jlong,
) {
if handle != 0 {
// Safety: We trust that the handle is valid and was created by createNative
let _ = unsafe { Box::from_raw(handle as *mut Arc<LanceSession>) };
// The Box is dropped here, which decrements the Arc reference count
}
}
/// Helper function to get the session handle from a Session object
fn get_session_handle(env: &mut JNIEnv, obj: &JObject) -> Result<jlong> {
let handle = env.get_field(obj, "nativeSessionHandle", "J")?;
Ok(handle.j()?)
}
/// Creates an Arc<LanceSession> from a raw handle.
/// This is used when passing a session to dataset operations.
///
/// # Safety
/// The handle must be a valid pointer created by `create_session`.
pub fn session_from_handle(handle: jlong) -> Option<Arc<LanceSession>> {
if handle == 0 {
return None;
}
// Safety: We trust that the handle is valid and was created by createNative
let session_arc = unsafe { &*(handle as *const Arc<LanceSession>) };
Some(session_arc.clone())
}
/// Creates a raw handle from an Arc<LanceSession>.
/// This is used when returning a session handle from a dataset.
///
/// Note: This creates a new Box, so the caller is responsible for
/// managing its lifetime or converting it back to a Java Session object.
pub fn handle_from_session(session: Arc<LanceSession>) -> jlong {
let boxed: Box<Arc<LanceSession>> = Box::new(session);
Box::into_raw(boxed) as jlong
}
/// Compares two session handles to see if they point to the same underlying session.
/// This is needed because each call to handle_from_session creates a new Box,
/// resulting in different pointer addresses even for the same session.
#[unsafe(no_mangle)]
pub extern "system" fn Java_org_lance_Session_isSameAsNative(
_env: JNIEnv,
_obj: JObject,
handle1: jlong,
handle2: jlong,
) -> jni::sys::jboolean {
if handle1 == 0 || handle2 == 0 {
return 0; // false
}
// Safety: We trust that the handles are valid and were created by createNative
let session1 = unsafe { &*(handle1 as *const Arc<LanceSession>) };
let session2 = unsafe { &*(handle2 as *const Arc<LanceSession>) };
if Arc::ptr_eq(session1, session2) {
1 // true
} else {
0 // false
}
}