From b63c834614345c7d2cbc2b7da384ab92728e87b5 Mon Sep 17 00:00:00 2001 From: Prem Chaitanya Prathi Date: Tue, 30 Apr 2024 14:09:11 +0530 Subject: [PATCH] feat: wrapper API's using subranges --- cpp/example/test.c | 50 ++++++++---- cpp/negentropy_wrapper.c | 161 +++++++++++++++++++++++++++++++++++---- cpp/negentropy_wrapper.h | 12 +++ 3 files changed, 191 insertions(+), 32 deletions(-) diff --git a/cpp/example/test.c b/cpp/example/test.c index 1d85951..c4efd44 100644 --- a/cpp/example/test.c +++ b/cpp/example/test.c @@ -35,19 +35,13 @@ int main(){ if(st1 == NULL){ perror("failed to create storage"); } - void* ngn_inst1 = negentropy_new(st1, 153600); - if(ngn_inst1 == NULL){ - perror("failed to create negentropy instance"); - } + void* st2 = storage_new("",""); if(st2 == NULL){ perror("failed to create storage"); } - void* ngn_inst2 = negentropy_new(st2, 153600); - if(ngn_inst2 == NULL){ - perror("failed to create negentropy instance"); - } + unsigned char m1[] = {0x6a, 0xdf, 0xaa, 0xe0, 0x31, 0xeb, 0x61, 0xa8, \ 0x3c, 0xff, 0x9c, 0xfd, 0xd2, 0xae, 0xf6, 0xed, \ @@ -85,8 +79,32 @@ int main(){ b4.data = (unsigned char*)malloc(37*sizeof(unsigned char)); printf("storage size of st2 is %d \n",storage_size(st2)); + + void* subrange = subrange_new(st2, 0 , UINT64_MAX); + if (subrange == NULL){ + perror("failed to init subrange"); + } + printf("subrange init successful"); + + void* subrange1 = subrange_new(st1, 0 , UINT64_MAX); + if (subrange == NULL){ + perror("failed to init subrange"); + } + printf("subrange init successful"); + + void* ngn_inst1 = negentropy_new(subrange1, 153600); + if(ngn_inst1 == NULL){ + perror("failed to create negentropy instance"); + } + + void* ngn_inst2 = negentropy_new(subrange, 153600); + if(ngn_inst2 == NULL){ + perror("failed to create negentropy instance"); + } + + result res; - int ret1 = negentropy_initiate(ngn_inst1, &res); + int ret1 = negentropy_subrange_initiate(ngn_inst1, &res); if(ret1 < 0){ perror("failed to initiate negentropy instance"); } @@ -99,7 +117,7 @@ int main(){ b3.len = 0; b3.data = (unsigned char*)malloc(69*sizeof(unsigned char)); - ret1 = reconcile(ngn_inst2, &b4, &res); + ret1 = reconcile_subrange(ngn_inst2, &b4, &res); if(ret1 < 0){ perror("error from reconcile"); } @@ -113,7 +131,7 @@ int main(){ //outSize = reconcile_with_ids(ngn_inst1, &b3, &rec_callback); result res1; - reconcile_with_ids_no_cbk(ngn_inst1, &b3, &res1); + reconcile_with_ids_subrange_no_cbk(ngn_inst1, &b3, &res1); printf("needIds count:%llu , haveIds count: %llu \n",res1.need_ids_len, res1.have_ids_len); for (int i=0; i < res1.need_ids_len ; i++) { @@ -130,9 +148,9 @@ int main(){ free(b4.data); free_result(&res1); - void* subrange = subrange_new(st1, 0 , UINT64_MAX); - if (subrange == NULL){ - perror("failed to init subrange"); - } - printf("subrange init successful"); + subrange_delete(subrange); + subrange_delete(subrange1); + + printf("storage after subrange deletion, st1 size: %d, st2 size: %d.", storage_size(st1), storage_size(st2)); + } diff --git a/cpp/negentropy_wrapper.c b/cpp/negentropy_wrapper.c index 9f927ac..409751f 100644 --- a/cpp/negentropy_wrapper.c +++ b/cpp/negentropy_wrapper.c @@ -45,22 +45,6 @@ int storage_size(void* storage){ return lmdbStorage->size(); } -void* subrange_new(void* storage, uint64_t startTimeStamp, uint64_t endTimeStamp){ - negentropy::storage::BTreeMem* st = reinterpret_cast(storage); - negentropy::storage::SubRange* subRange = NULL; - try { - subRange = new negentropy::storage::SubRange(*st, negentropy::Bound(startTimeStamp), negentropy::Bound(endTimeStamp)); - } catch (negentropy::err e){ - return NULL; - } - return subRange; -} - -void subrange_delete(void* range){ - negentropy::storage::SubRange* subRange = reinterpret_cast(range); - delete subRange; -} - void negentropy_delete(void* negentropy){ Negentropy* ngn_inst = reinterpret_cast*>(negentropy); delete ngn_inst; @@ -298,3 +282,148 @@ void free_result(result* r){ free((void *)r->error); } } + +/*SubRange specific functions +TODO: These and above methods need to be optimized to reduce code duplication*/ + +void* subrange_new(void* storage, uint64_t startTimeStamp, uint64_t endTimeStamp){ + negentropy::storage::BTreeMem* st = reinterpret_cast(storage); + negentropy::storage::SubRange* subRange = NULL; + try { + subRange = new negentropy::storage::SubRange(*st, negentropy::Bound(startTimeStamp), negentropy::Bound(endTimeStamp)); + } catch (negentropy::err e){ + return NULL; + } + return subRange; +} + +void subrange_delete(void* range){ + negentropy::storage::SubRange* subRange = reinterpret_cast(range); + delete subRange; +} + +void negentropy_subrange_delete(void* negentropy){ + Negentropy* ngn_inst = reinterpret_cast*>(negentropy); + delete ngn_inst; +} + +void* negentropy_subrange_new(void* subrange, uint64_t frameSizeLimit){ + //TODO: Make these typecasts into macros?? + negentropy::storage::SubRange* sub_range; + //TODO: reinterpret cast is risky, need to use more safe type conversion. + sub_range = reinterpret_cast(subrange); + + Negentropy* ne; + try{ + ne = new Negentropy(*sub_range, frameSizeLimit); + }catch(negentropy::err e){ + return NULL; + } + return ne; +} + +// Returns -1 if already initiated. +int negentropy_subrange_initiate(void* negentropy, result* result){ + Negentropy* ngn_inst; + ngn_inst = reinterpret_cast*>(negentropy); + + std::string* output = new std::string(); + try { + *output = ngn_inst->initiate(); +/* std::cout << "output of initiate is, len:" << output->size() << ", output:"; + printHexString(std::string_view(*output)); */ + } catch(negentropy::err e){ + //std::cout << "Exception raised in initiate " << e.what() << std::endl; + return -1; + } + if (output->size() > 0 ){ + result->output.len = output->size(); + result->output.data = (unsigned char*)calloc(output->size(), sizeof(unsigned char)); + memcpy(result->output.data, (unsigned char*)output->c_str(),result->output.len) ; + }else { + result->output.len = 0; + result->output.data = NULL; + } + delete output; + return 0; +} + +void negentropy_subrange_setinitiator(void* negentropy){ + Negentropy *ngn_inst; + ngn_inst = reinterpret_cast*>(negentropy); + + ngn_inst->setInitiator(); + +} + +int reconcile_subrange(void* negentropy, buffer* query, result* result){ + Negentropy *ngn_inst; + ngn_inst = reinterpret_cast*>(negentropy); + std::string* out = new std::string(); + try { + *out = ngn_inst->reconcile(std::string_view(reinterpret_cast< char const* >(query->data), query->len)); +/* std::cout << "reconcile output of reconcile is, len:" << out->size() << ", output:"; + printHexString(std::string_view(*out)); */ + } catch(negentropy::err e){ + //All errors returned are non-recoverable errors. + //So passing on the error message upwards + //std::cout << "Exception raised in reconcile " << e.what() << std::endl; + result->error = (char*)calloc(strlen(e.what()), sizeof(char)); + strcpy(result->error,e.what()); + return -1; + } + if (out->size() > 0 ){ + result->output.len = out->size(); + result->output.data = (unsigned char*)calloc(out->size(), sizeof(unsigned char)); + memcpy(result->output.data, (unsigned char*)out->c_str(),result->output.len) ; + }else { + result->output.len = 0; + result->output.data = NULL; + } + return 0; +} + +int reconcile_with_ids_subrange_no_cbk(void* negentropy, buffer* query, result* result){ + Negentropy *ngn_inst; + ngn_inst = reinterpret_cast*>(negentropy); + + std::optional out; + std::vector haveIds, needIds; + try { + out = ngn_inst->reconcile(std::string_view(reinterpret_cast< char const* >(query->data), query->len), haveIds, needIds); + result->have_ids_len = haveIds.size(); + result->need_ids_len = needIds.size(); + if (haveIds.size() > 0){ + result->have_ids = (buffer*)calloc(result->have_ids_len, sizeof(buffer)); + transform_with_alloc(haveIds, result->have_ids); + } + + if (needIds.size() > 0) { + result->need_ids = (buffer*)calloc(result->need_ids_len, sizeof(buffer)); + transform_with_alloc(needIds, result->need_ids); + } + + // std::cout << "have_ids_len:" << result->have_ids_len << "need_ids_len:" << result->need_ids_len << std::endl; + + + } catch(negentropy::err e){ + std::cout << "caught error "<< e.what() << std::endl; + result->error = (char*)calloc(strlen(e.what()), sizeof(char)); + strcpy(result->error,e.what()); + return -1; + } + buffer output = {0,NULL}; + if (out) { + result->output.len = out.value().size(); + result->output.data = (unsigned char*)calloc(out.value().size(), sizeof(unsigned char)); + memcpy(result->output.data, (unsigned char*)out.value().c_str(),result->output.len) ; +/* std::cout << "reconcile_with_ids output of reconcile is, len:" << out.value().size() << ", output:"; + printHexString(std::string_view(out.value())); */ + }else { + //std::cout << "reconcile_with_ids_no_cbk output is empty " << std::endl; + result->output.len = 0; + result->output.data = NULL; + } + return 0; +} + diff --git a/cpp/negentropy_wrapper.h b/cpp/negentropy_wrapper.h index 7e07241..32c9ba6 100644 --- a/cpp/negentropy_wrapper.h +++ b/cpp/negentropy_wrapper.h @@ -31,10 +31,22 @@ EXTERNC void storage_delete(void* storage); EXTERNC int storage_size(void* storage); +//SubRange methods EXTERNC void* subrange_new(void* storage, uint64_t startTimeStamp, uint64_t endTimeStamp); EXTERNC void subrange_delete(void* range); +EXTERNC void* negentropy_subrange_new(void* subrange, uint64_t frameSizeLimit); + +EXTERNC void negentropy_subrange_delete(void* negentropy); + +EXTERNC int negentropy_subrange_initiate(void* negentropy, result* result); + +EXTERNC int reconcile_subrange(void* negentropy, buffer* query, result* result); + +EXTERNC int reconcile_with_ids_subrange_no_cbk(void* negentropy, buffer* query, result* result); + +//End of SubRange methods EXTERNC void* negentropy_new(void* storage, uint64_t frameSizeLimit); EXTERNC void negentropy_delete(void* negentropy);