44#include " ccf/app_interface.h"
55#include " ccf/common_auth_policies.h"
66#include " ccf/http_status.h"
7+ #include " ccf/kv/compacted_version_conflict.h"
78#include " ccf/kv/map.h"
89#include " ccf/odata_error.h"
910#include " ccf/rust_ffi.h"
1011
1112#include < memory>
13+ #include < optional>
1214#include < string>
1315#include < unordered_map>
1416#include < utility>
@@ -92,6 +94,20 @@ namespace
9294 return value.data != nullptr || value.len == 0 ;
9395 }
9496
97+ bool is_known_http_status (uint16_t status)
98+ {
99+ switch (status)
100+ {
101+ #define XX (code, name, string ) \
102+ case code: \
103+ return true ;
104+ HTTP_STATUS_MAP (XX )
105+ #undef XX
106+ default :
107+ return false ;
108+ }
109+ }
110+
95111 std::string to_string (const ccf_rust_slice& value)
96112 {
97113 if (value.len == 0 )
@@ -156,6 +172,8 @@ struct ccf_rust_endpoint_context
156172 std::unordered_map<std::string, RawMap::ReadOnlyHandle*> read_handles;
157173 std::unordered_map<std::string, RawMap::Handle*> write_handles;
158174 RawMap::Handle::ValueType scratch;
175+ std::optional<ccf::kv::CompactedVersionConflict> compacted_version_conflict =
176+ std::nullopt ;
159177
160178 RawMap::ReadOnlyHandle* read_handle (const std::string& map_name)
161179 {
@@ -188,6 +206,14 @@ struct ccf_rust_endpoint_context
188206 read_handles[map_name] = handle;
189207 return handle;
190208 }
209+
210+ void rethrow_compacted_version_conflict ()
211+ {
212+ if (compacted_version_conflict.has_value ())
213+ {
214+ throw std::move (compacted_version_conflict.value ());
215+ }
216+ }
191217};
192218
193219namespace
@@ -235,14 +261,20 @@ namespace
235261 ctx.rpc_ctx , &ctx.tx , nullptr , {}, {}, {}};
236262 try
237263 {
238- if (state->callback (state->user_data , &rust_ctx) != CCF_RUST_OK )
264+ const auto result = state->callback (state->user_data , &rust_ctx);
265+ rust_ctx.rethrow_compacted_version_conflict ();
266+ if (result != CCF_RUST_OK )
239267 {
240268 ctx.rpc_ctx ->set_error (
241269 HTTP_STATUS_INTERNAL_SERVER_ERROR ,
242270 ccf::errors::InternalError,
243271 " Rust endpoint execution failed" );
244272 }
245273 }
274+ catch (const ccf::kv::CompactedVersionConflict&)
275+ {
276+ throw ;
277+ }
246278 catch (const std::exception& e)
247279 {
248280 ctx.rpc_ctx ->set_error (
@@ -271,14 +303,20 @@ namespace
271303 ctx.rpc_ctx , &ctx.tx , &ctx.tx , {}, {}, {}};
272304 try
273305 {
274- if (state->callback (state->user_data , &rust_ctx) != CCF_RUST_OK )
306+ const auto result = state->callback (state->user_data , &rust_ctx);
307+ rust_ctx.rethrow_compacted_version_conflict ();
308+ if (result != CCF_RUST_OK )
275309 {
276310 ctx.rpc_ctx ->set_error (
277311 HTTP_STATUS_INTERNAL_SERVER_ERROR ,
278312 ccf::errors::InternalError,
279313 " Rust endpoint execution failed" );
280314 }
281315 }
316+ catch (const ccf::kv::CompactedVersionConflict&)
317+ {
318+ throw ;
319+ }
282320 catch (const std::exception& e)
283321 {
284322 ctx.rpc_ctx ->set_error (
@@ -436,7 +474,7 @@ extern "C"
436474
437475 int ccf_rust_response_status (ccf_rust_endpoint_context* ctx, uint16_t status)
438476 {
439- if (ctx == nullptr || status < 100 || status > 599 )
477+ if (ctx == nullptr || ! is_known_http_status ( status) )
440478 {
441479 return CCF_RUST_INVALID_ARGUMENT ;
442480 }
@@ -496,8 +534,8 @@ extern "C"
496534 ccf_rust_slice message)
497535 {
498536 if (
499- ctx == nullptr || status < 400 || status > 599 || ! is_valid_utf8 (code ) ||
500- code.len == 0 || !is_valid_utf8 (message))
537+ ctx == nullptr || status < 400 || ! is_known_http_status (status ) ||
538+ ! is_valid_utf8 (code) || code.len == 0 || !is_valid_utf8 (message))
501539 {
502540 return CCF_RUST_INVALID_ARGUMENT ;
503541 }
@@ -539,6 +577,11 @@ extern "C"
539577 set_slice (value, ctx->scratch );
540578 return CCF_RUST_OK ;
541579 }
580+ catch (const ccf::kv::CompactedVersionConflict& e)
581+ {
582+ ctx->compacted_version_conflict = e;
583+ return CCF_RUST_INTERNAL_ERROR ;
584+ }
542585 catch (...)
543586 {
544587 return CCF_RUST_INTERNAL_ERROR ;
@@ -563,6 +606,11 @@ extern "C"
563606 ctx->read_handle (to_string (map_name))->has (to_bytes (key)) ? 1 : 0 ;
564607 return CCF_RUST_OK ;
565608 }
609+ catch (const ccf::kv::CompactedVersionConflict& e)
610+ {
611+ ctx->compacted_version_conflict = e;
612+ return CCF_RUST_INTERNAL_ERROR ;
613+ }
566614 catch (...)
567615 {
568616 return CCF_RUST_INTERNAL_ERROR ;
@@ -591,6 +639,11 @@ extern "C"
591639 handle->put (to_bytes (key), to_bytes (value));
592640 return CCF_RUST_OK ;
593641 }
642+ catch (const ccf::kv::CompactedVersionConflict& e)
643+ {
644+ ctx->compacted_version_conflict = e;
645+ return CCF_RUST_INTERNAL_ERROR ;
646+ }
594647 catch (...)
595648 {
596649 return CCF_RUST_INTERNAL_ERROR ;
@@ -616,6 +669,11 @@ extern "C"
616669 handle->remove (to_bytes (key));
617670 return CCF_RUST_OK ;
618671 }
672+ catch (const ccf::kv::CompactedVersionConflict& e)
673+ {
674+ ctx->compacted_version_conflict = e;
675+ return CCF_RUST_INTERNAL_ERROR ;
676+ }
619677 catch (...)
620678 {
621679 return CCF_RUST_INTERNAL_ERROR ;
0 commit comments