66//! Writes go through an in-flight queue of at most [`WRITE_CHANNEL_CAPACITY`] pending
77//! batches on the same thread that drives the current-thread runtime.
88
9+ use std:: path:: PathBuf ;
910use std:: sync:: Arc ;
1011
1112use arrow_array:: RecordBatch ;
1213use arrow_array:: StructArray ;
1314use arrow_array:: ffi:: FFI_ArrowArray ;
1415use arrow_array:: ffi:: FFI_ArrowSchema ;
16+ use async_fs:: File ;
1517use futures:: SinkExt ;
1618use futures:: channel:: mpsc;
1719use jni:: EnvUnowned ;
@@ -22,7 +24,8 @@ use jni::sys::JNI_FALSE;
2224use jni:: sys:: JNI_TRUE ;
2325use jni:: sys:: jboolean;
2426use jni:: sys:: jlong;
25- use object_store:: path:: Path ;
27+ use object_store:: ObjectStore ;
28+ use object_store:: path:: Path as ObjectStorePath ;
2629use url:: Url ;
2730use vortex:: array:: ArrayRef ;
2831use vortex:: array:: arrow:: FromArrowArray ;
@@ -52,6 +55,40 @@ use crate::session::session_ref;
5255/// the writer is felt on the Java thread producing batches.
5356const WRITE_CHANNEL_CAPACITY : usize = 4 ;
5457
58+ enum WriteTarget {
59+ Local ( PathBuf ) ,
60+ ObjectStore {
61+ store : Arc < dyn ObjectStore > ,
62+ path : ObjectStorePath ,
63+ } ,
64+ }
65+
66+ fn resolve_write_target (
67+ uri : & str ,
68+ properties : & HashMap < String , String > ,
69+ ) -> VortexResult < WriteTarget > {
70+ match Url :: parse ( uri) {
71+ Ok ( url) if url. scheme ( ) == "file" => {
72+ let path = url
73+ . to_file_path ( )
74+ . map_err ( |_| vortex_err ! ( "invalid file URL: {uri}" ) ) ?;
75+ return Ok ( WriteTarget :: Local ( path) ) ;
76+ }
77+ Ok ( url) if uri. contains ( "://" ) => {
78+ let path = ObjectStorePath :: from_url_path ( url. path ( ) )
79+ . map_err ( |_| vortex_err ! ( "invalid object_store path: {}" , url. path( ) ) ) ?;
80+ let store = make_object_store ( & url, properties) ?;
81+ return Ok ( WriteTarget :: ObjectStore { store, path } ) ;
82+ }
83+ Err ( err) if uri. contains ( "://" ) => {
84+ return Err ( vortex_err ! ( "invalid URL {uri}: {err}" ) ) ;
85+ }
86+ _ => { }
87+ }
88+
89+ Ok ( WriteTarget :: Local ( PathBuf :: from ( uri) ) )
90+ }
91+
5592/// Native writer holding a write-task handle and a sender that Java pushes batches into.
5693pub struct NativeWriter {
5794 handle : Option < Task < VortexResult < WriteSummary > > > ,
@@ -136,21 +173,27 @@ pub extern "system" fn Java_dev_vortex_jni_NativeWriter_create(
136173 let write_schema = import_dtype_from_arrow ( arrow_schema_addr) ?;
137174
138175 let file_path: String = uri. try_to_string ( env) ?;
139- let url = Url :: parse ( & file_path)
140- . map_err ( |e| JNIError :: Vortex ( vortex_err ! ( "invalid URL {file_path}: {e}" ) ) ) ?;
141176 let properties: HashMap < String , String > = extract_properties ( env, & options) ?;
142- let path = Path :: from_url_path ( url. path ( ) )
143- . map_err ( |_| vortex_err ! ( "invalid object_store path: {}" , url. path( ) ) ) ?;
144-
145- let store = make_object_store ( & url, & properties) ?;
177+ let target = resolve_write_target ( & file_path, & properties) ?;
146178 let ( tx, rx) = mpsc:: channel ( WRITE_CHANNEL_CAPACITY ) ;
147179 let stream = ArrayStreamAdapter :: new ( write_schema. clone ( ) , rx) ;
148180
149181 let handle = session. handle ( ) . spawn ( async move {
150- let mut write = ObjectStoreWrite :: new ( Arc :: new ( Compat :: new ( store) ) , & path) . await ?;
151- let summary = session. write_options ( ) . write ( & mut write, stream) . await ?;
152- write. shutdown ( ) . await ?;
153- Ok ( summary)
182+ match target {
183+ WriteTarget :: Local ( path) => {
184+ let mut file = File :: create ( path) . await ?;
185+ let summary = session. write_options ( ) . write ( & mut file, stream) . await ?;
186+ file. shutdown ( ) . await ?;
187+ Ok ( summary)
188+ }
189+ WriteTarget :: ObjectStore { store, path } => {
190+ let mut write =
191+ ObjectStoreWrite :: new ( Arc :: new ( Compat :: new ( store) ) , & path) . await ?;
192+ let summary = session. write_options ( ) . write ( & mut write, stream) . await ?;
193+ write. shutdown ( ) . await ?;
194+ Ok ( summary)
195+ }
196+ }
154197 } ) ;
155198
156199 Ok ( Box :: new ( NativeWriter :: new ( write_schema, handle, tx) ) . into_raw ( ) )
0 commit comments