@@ -645,6 +645,7 @@ pub mod raw {
645645 pub fn get_jwt ( connection_id_ptr : * const u8 , bytes_source_id : * mut BytesSource ) -> u16 ;
646646 }
647647
648+ #[ cfg( feature = "unstable" ) ]
648649 #[ link( wasm_import_module = "spacetime_10.3" ) ]
649650 extern "C" {
650651 /// Suspends execution of this WASM instance until approximately `wake_at_micros_since_unix_epoch`.
@@ -661,8 +662,76 @@ pub mod raw {
661662 /// - The calling WASM instance is holding open a transaction.
662663 /// - The calling WASM instance is not executing a procedure.
663664 // TODO(procedure-sleep-until): remove this
664- #[ cfg( feature = "unstable" ) ]
665665 pub fn procedure_sleep_until ( wake_at_micros_since_unix_epoch : i64 ) -> i64 ;
666+
667+ /// Starts a mutable transaction,
668+ /// suspending execution of this WASM instance until
669+ /// a mutable transaction lock is aquired.
670+ ///
671+ /// Upon resuming, returns `0` on success,
672+ /// enabling further calls that require a pending transaction,
673+ /// or an error code otherwise.
674+ ///
675+ /// # Traps
676+ ///
677+ /// Traps if:
678+ /// - `out` is NULL or `out[..size_of::<i64>()]` is not in bounds of WASM memory.
679+ ///
680+ /// # Errors
681+ ///
682+ /// Returns an error:
683+ ///
684+ /// - `WOULD_BLOCK_TRANSACTION`, if there's already an ongoing transaction.
685+ pub fn procedure_start_mut_tx ( out : * mut i64 ) -> u16 ;
686+
687+ /// Commits a mutable transaction,
688+ /// suspending execution of this WASM instance until
689+ /// the transaction has been committed
690+ /// and subscription queries have been run and broadcast.
691+ ///
692+ /// Upon resuming, returns `0` on success, or an error code otherwise.
693+ ///
694+ /// # Traps
695+ ///
696+ /// This function does not trap.
697+ ///
698+ /// # Errors
699+ ///
700+ /// Returns an error:
701+ ///
702+ /// - `TRANSACTION_NOT_ANONYMOUS`,
703+ /// if the transaction was not started in [`procedure_start_mut_tx`].
704+ /// This can happen if this syscall is erroneously called by a reducer.
705+ /// The code `NOT_IN_TRANSACTION` does not happen,
706+ /// as it is subsumed by `TRANSACTION_NOT_ANONYMOUS`.
707+ /// - `TRANSACTION_IS_READ_ONLY`, if the pending transaction is read-only.
708+ /// This currently does not happen as anonymous read transactions
709+ /// are not exposed to modules.
710+ pub fn procedure_commit_mut_tx ( ) -> u16 ;
711+
712+ /// Aborts a mutable transaction,
713+ /// suspending execution of this WASM instance until
714+ /// the transaction has been rolled back.
715+ ///
716+ /// Upon resuming, returns `0` on success, or an error code otherwise.
717+ ///
718+ /// # Traps
719+ ///
720+ /// This function does not trap.
721+ ///
722+ /// # Errors
723+ ///
724+ /// Returns an error:
725+ ///
726+ /// - `TRANSACTION_NOT_ANONYMOUS`,
727+ /// if the transaction was not started in [`procedure_start_mut_tx`].
728+ /// This can happen if this syscall is erroneously called by a reducer.
729+ /// The code `NOT_IN_TRANSACTION` does not happen,
730+ /// as it is subsumed by `TRANSACTION_NOT_ANONYMOUS`.
731+ /// - `TRANSACTION_IS_READ_ONLY`, if the pending transaction is read-only.
732+ /// This currently does not happen as anonymous read transactions
733+ /// are not exposed to modules.
734+ pub fn procedure_abort_mut_tx ( ) -> u16 ;
666735 }
667736
668737 /// What strategy does the database index use?
@@ -819,7 +888,7 @@ impl fmt::Display for Errno {
819888
820889/// Convert the status value `x` into a result.
821890/// When `x = 0`, we have a success status.
822- fn cvt ( x : u16 ) -> Result < ( ) , Errno > {
891+ fn cvt ( x : u16 ) -> Result < ( ) > {
823892 match Errno :: from_code ( x) {
824893 None => Ok ( ( ) ) ,
825894 Some ( err) => Err ( err) ,
@@ -838,13 +907,25 @@ fn cvt(x: u16) -> Result<(), Errno> {
838907/// - The function `f` never reads a safe and valid `T` from the `out` pointer
839908/// before writing a safe and valid `T` to it.
840909#[ inline]
841- unsafe fn call < T : Copy > ( f : impl FnOnce ( * mut T ) -> u16 ) -> Result < T , Errno > {
910+ unsafe fn call < T : Copy > ( f : impl FnOnce ( * mut T ) -> u16 ) -> Result < T > {
842911 let mut out = MaybeUninit :: uninit ( ) ;
843912 let f_code = f ( out. as_mut_ptr ( ) ) ;
844913 cvt ( f_code) ?;
845914 Ok ( out. assume_init ( ) )
846915}
847916
917+ /// Runs the given function `f`.
918+ ///
919+ /// Assuming the call to `f` returns 0, `Ok(())` is returned,
920+ /// and otherwise `Err(err)` is returned.
921+ #[ inline]
922+ #[ cfg( feature = "unstable" ) ]
923+ fn call_no_ret ( f : impl FnOnce ( ) -> u16 ) -> Result < ( ) > {
924+ let f_code = f ( ) ;
925+ cvt ( f_code) ?;
926+ Ok ( ( ) )
927+ }
928+
848929/// Queries the `table_id` associated with the given (table) `name`.
849930///
850931/// The table id is returned.
@@ -856,7 +937,7 @@ unsafe fn call<T: Copy>(f: impl FnOnce(*mut T) -> u16) -> Result<T, Errno> {
856937/// - `NOT_IN_TRANSACTION`, when called outside of a transaction.
857938/// - `NO_SUCH_TABLE`, when `name` is not the name of a table.
858939#[ inline]
859- pub fn table_id_from_name ( name : & str ) -> Result < TableId , Errno > {
940+ pub fn table_id_from_name ( name : & str ) -> Result < TableId > {
860941 unsafe { call ( |out| raw:: table_id_from_name ( name. as_ptr ( ) , name. len ( ) , out) ) }
861942}
862943
@@ -871,7 +952,7 @@ pub fn table_id_from_name(name: &str) -> Result<TableId, Errno> {
871952/// - `NOT_IN_TRANSACTION`, when called outside of a transaction.
872953/// - `NO_SUCH_INDEX`, when `name` is not the name of an index.
873954#[ inline]
874- pub fn index_id_from_name ( name : & str ) -> Result < IndexId , Errno > {
955+ pub fn index_id_from_name ( name : & str ) -> Result < IndexId > {
875956 unsafe { call ( |out| raw:: index_id_from_name ( name. as_ptr ( ) , name. len ( ) , out) ) }
876957}
877958
@@ -884,7 +965,7 @@ pub fn index_id_from_name(name: &str) -> Result<IndexId, Errno> {
884965/// - `NOT_IN_TRANSACTION`, when called outside of a transaction.
885966/// - `NO_SUCH_TABLE`, when `table_id` is not a known ID of a table.
886967#[ inline]
887- pub fn datastore_table_row_count ( table_id : TableId ) -> Result < u64 , Errno > {
968+ pub fn datastore_table_row_count ( table_id : TableId ) -> Result < u64 > {
888969 unsafe { call ( |out| raw:: datastore_table_row_count ( table_id, out) ) }
889970}
890971
@@ -901,7 +982,7 @@ pub fn datastore_table_row_count(table_id: TableId) -> Result<u64, Errno> {
901982/// - `row` doesn't decode from BSATN to a `ProductValue`
902983/// according to the `ProductType` that the table's schema specifies.
903984#[ inline]
904- pub fn datastore_insert_bsatn ( table_id : TableId , row : & mut [ u8 ] ) -> Result < & [ u8 ] , Errno > {
985+ pub fn datastore_insert_bsatn ( table_id : TableId , row : & mut [ u8 ] ) -> Result < & [ u8 ] > {
905986 let row_ptr = row. as_mut_ptr ( ) ;
906987 let row_len = & mut row. len ( ) ;
907988 cvt ( unsafe { raw:: datastore_insert_bsatn ( table_id, row_ptr, row_len) } ) . map ( |( ) | & row[ ..* row_len] )
@@ -927,7 +1008,7 @@ pub fn datastore_insert_bsatn(table_id: TableId, row: &mut [u8]) -> Result<&[u8]
9271008/// or if `row` cannot project to the index's type.
9281009/// - the row was not found
9291010#[ inline]
930- pub fn datastore_update_bsatn ( table_id : TableId , index_id : IndexId , row : & mut [ u8 ] ) -> Result < & [ u8 ] , Errno > {
1011+ pub fn datastore_update_bsatn ( table_id : TableId , index_id : IndexId , row : & mut [ u8 ] ) -> Result < & [ u8 ] > {
9311012 let row_ptr = row. as_mut_ptr ( ) ;
9321013 let row_len = & mut row. len ( ) ;
9331014 cvt ( unsafe { raw:: datastore_update_bsatn ( table_id, index_id, row_ptr, row_len) } ) . map ( |( ) | & row[ ..* row_len] )
@@ -954,7 +1035,7 @@ pub fn datastore_update_bsatn(table_id: TableId, index_id: IndexId, row: &mut [u
9541035/// - `BSATN_DECODE_ERROR`, when `rel` cannot be decoded to `Vec<ProductValue>`
9551036/// where each `ProductValue` is typed at the `ProductType` the table's schema specifies.
9561037#[ inline]
957- pub fn datastore_delete_all_by_eq_bsatn ( table_id : TableId , relation : & [ u8 ] ) -> Result < u32 , Errno > {
1038+ pub fn datastore_delete_all_by_eq_bsatn ( table_id : TableId , relation : & [ u8 ] ) -> Result < u32 > {
9581039 unsafe { call ( |out| raw:: datastore_delete_all_by_eq_bsatn ( table_id, relation. as_ptr ( ) , relation. len ( ) , out) ) }
9591040}
9601041
@@ -968,7 +1049,7 @@ pub fn datastore_delete_all_by_eq_bsatn(table_id: TableId, relation: &[u8]) -> R
9681049///
9691050/// - `NOT_IN_TRANSACTION`, when called outside of a transaction.
9701051/// - `NO_SUCH_TABLE`, when `table_id` is not a known ID of a table.
971- pub fn datastore_table_scan_bsatn ( table_id : TableId ) -> Result < RowIter , Errno > {
1052+ pub fn datastore_table_scan_bsatn ( table_id : TableId ) -> Result < RowIter > {
9721053 let raw = unsafe { call ( |out| raw:: datastore_table_scan_bsatn ( table_id, out) ) ? } ;
9731054 Ok ( RowIter { raw } )
9741055}
@@ -1028,7 +1109,7 @@ pub fn datastore_index_scan_range_bsatn(
10281109 prefix_elems : ColId ,
10291110 rstart : & [ u8 ] ,
10301111 rend : & [ u8 ] ,
1031- ) -> Result < RowIter , Errno > {
1112+ ) -> Result < RowIter > {
10321113 let raw = unsafe {
10331114 call ( |out| {
10341115 raw:: datastore_index_scan_range_bsatn (
@@ -1076,7 +1157,7 @@ pub fn datastore_delete_by_index_scan_range_bsatn(
10761157 prefix_elems : ColId ,
10771158 rstart : & [ u8 ] ,
10781159 rend : & [ u8 ] ,
1079- ) -> Result < u32 , Errno > {
1160+ ) -> Result < u32 > {
10801161 unsafe {
10811162 call ( |out| {
10821163 raw:: datastore_delete_by_index_scan_range_bsatn (
@@ -1239,13 +1320,81 @@ impl Drop for RowIter {
12391320 }
12401321}
12411322
1323+ #[ cfg( feature = "unstable" ) ]
12421324pub mod procedure {
12431325 //! Side-effecting or asynchronous operations which only procedures are allowed to perform.
1326+
1327+ use super :: { call, call_no_ret, raw, Result } ;
1328+
12441329 #[ inline]
1245- #[ cfg( feature = "unstable" ) ]
12461330 pub fn sleep_until ( wake_at_timestamp : i64 ) -> i64 {
12471331 // Safety: Just calling an `extern "C"` function.
12481332 // Nothing weird happening here.
1249- unsafe { super :: raw:: procedure_sleep_until ( wake_at_timestamp) }
1333+ unsafe { raw:: procedure_sleep_until ( wake_at_timestamp) }
1334+ }
1335+
1336+ /// Starts a mutable transaction,
1337+ /// suspending execution of this WASM instance until
1338+ /// a mutable transaction lock is aquired.
1339+ ///
1340+ /// Upon resuming, returns `Ok(timestamp)` on success,
1341+ /// enabling further calls that require a pending transaction,
1342+ /// or [`Errno`] otherwise.
1343+ ///
1344+ /// # Errors
1345+ ///
1346+ /// Returns an error:
1347+ ///
1348+ /// - `WOULD_BLOCK_TRANSACTION`, if there's already an ongoing transaction.
1349+ #[ inline]
1350+ pub fn procedure_start_mut_tx ( ) -> Result < i64 > {
1351+ unsafe { call ( |out| raw:: procedure_start_mut_tx ( out) ) }
1352+ }
1353+
1354+ /// Commits a mutable transaction,
1355+ /// suspending execution of this WASM instance until
1356+ /// the transaction has been committed
1357+ /// and subscription queries have been run and broadcast.
1358+ ///
1359+ /// Upon resuming, returns `Ok(()` on success, or an [`Errno`] otherwise.
1360+ ///
1361+ /// # Errors
1362+ ///
1363+ /// Returns an error:
1364+ ///
1365+ /// - `TRANSACTION_NOT_ANONYMOUS`,
1366+ /// if the transaction was not started in [`procedure_start_mut_tx`].
1367+ /// This can happen if this syscall is erroneously called by a reducer.
1368+ /// The code `NOT_IN_TRANSACTION` does not happen,
1369+ /// as it is subsumed by `TRANSACTION_NOT_ANONYMOUS`.
1370+ /// - `TRANSACTION_IS_READ_ONLY`, if the pending transaction is read-only.
1371+ /// This currently does not happen as anonymous read transactions
1372+ /// are not exposed to modules.
1373+ #[ inline]
1374+ pub fn procedure_commit_mut_tx ( ) -> Result < ( ) > {
1375+ call_no_ret ( || unsafe { raw:: procedure_commit_mut_tx ( ) } )
1376+ }
1377+
1378+ /// Aborts a mutable transaction,
1379+ /// suspending execution of this WASM instance until
1380+ /// the transaction has been rolled back.
1381+ ///
1382+ /// Upon resuming, returns `Ok(())` on success, or an [`Errno`] otherwise.
1383+ ///
1384+ /// # Errors
1385+ ///
1386+ /// Returns an error:
1387+ ///
1388+ /// - `TRANSACTION_NOT_ANONYMOUS`,
1389+ /// if the transaction was not started in [`procedure_start_mut_tx`].
1390+ /// This can happen if this syscall is erroneously called by a reducer.
1391+ /// The code `NOT_IN_TRANSACTION` does not happen,
1392+ /// as it is subsumed by `TRANSACTION_NOT_ANONYMOUS`.
1393+ /// - `TRANSACTION_IS_READ_ONLY`, if the pending transaction is read-only.
1394+ /// This currently does not happen as anonymous read transactions
1395+ /// are not exposed to modules.
1396+ #[ inline]
1397+ pub fn procedure_abort_mut_tx ( ) -> Result < ( ) > {
1398+ call_no_ret ( || unsafe { raw:: procedure_abort_mut_tx ( ) } )
12501399 }
12511400}
0 commit comments