From 9e68742946adf889862d5829d5aa9571a0e30638 Mon Sep 17 00:00:00 2001
From: "Constantin P." <papizh.konstantin@demlabs.net>
Date: Sat, 8 Jun 2024 23:56:17 +0700
Subject: [PATCH 1/5] Solution refined

---
 modules/chain/CMakeLists.txt           |   8 -
 modules/chain/dap_chain.c              |   6 +-
 modules/chain/dap_chain_cell.c         | 324 ++++++++++++++-----------
 modules/chain/include/dap_chain_cell.h |   1 -
 modules/net/dap_chain_net.c            |   2 +-
 5 files changed, 193 insertions(+), 148 deletions(-)

diff --git a/modules/chain/CMakeLists.txt b/modules/chain/CMakeLists.txt
index 5e2c10d1c..689e6c69b 100644
--- a/modules/chain/CMakeLists.txt
+++ b/modules/chain/CMakeLists.txt
@@ -4,11 +4,6 @@ project (dap_chain)
 file(GLOB DAP_CHAIN_SRCS *.c)
 file(GLOB DAP_CHAIN_HEADERS include/*.h)
 
-if (WIN32)
-    file (GLOB MMAN_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../../dap-sdk/3rdparty/mman/*)
-    list(APPEND DAP_CHAIN_SRCS ${MMAN_SRCS})
-endif()
-
 add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_SRCS} ${DAP_CHAIN_HEADERS})
 
 if(BUILD_CELLFRAME_SDK_TESTS)
@@ -21,9 +16,6 @@ endif()
 target_link_libraries(${PROJECT_NAME} dap_chain_common dap_global_db dap_notify_srv dap_stream ${GLIB_LDFLAGS})
 target_include_directories(${PROJECT_NAME} INTERFACE . include/ ${GLIB_INCLUDE_DIRS})
 target_include_directories(${PROJECT_NAME} PUBLIC include)
-if (WIN32)
-    target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/../../dap-sdk/3rdparty/mman/)
-endif()
 
 if (INSTALL_SDK)
 set_target_properties(${PROJECT_NAME}  PROPERTIES PUBLIC_HEADER "${DAP_CHAIN_HEADERS}")
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index 2bec84dd2..4bd3de572 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -111,7 +111,7 @@ dap_chain_t *dap_chain_create(const char *a_chain_net_name, const char *a_chain_
             .name       = dap_strdup(a_chain_name),
             .net_name   = dap_strdup(a_chain_net_name),
 #ifdef DAP_OS_WINDOWS // TODO
-            .is_mapped  = false,
+            .is_mapped  = true,
 #else
             .is_mapped  = dap_config_get_item_bool_default(g_config, "ledger", "mapped", true),
 #endif
@@ -610,7 +610,9 @@ int dap_chain_load_all(dap_chain_t *a_chain)
         const char l_suffix[] = ".dchaincell";
         size_t l_suffix_len = strlen(l_suffix);
         if (!strncmp(l_filename + strlen(l_filename) - l_suffix_len, l_suffix, l_suffix_len)) {
-            dap_chain_cell_t *l_cell = dap_chain_cell_create_fill2(a_chain, l_filename);
+            uint64_t l_cell_id_uint64 = 0;
+            sscanf(l_filename, "%"DAP_UINT64_FORMAT_x".dchaincell", &l_cell_id_uint64);
+            dap_chain_cell_t *l_cell = dap_chain_cell_create_fill(a_chain, (dap_chain_cell_id_t){ .uint64 = l_cell_id_uint64 });
             l_ret += dap_chain_cell_load(a_chain, l_cell);
             if (DAP_CHAIN_PVT(a_chain)->need_reorder) {
                 const char *l_filename_backup = dap_strdup_printf("%s.unsorted", l_cell->file_storage_path);
diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c
index 7034d04aa..8e3e2f65a 100644
--- a/modules/chain/dap_chain_cell.c
+++ b/modules/chain/dap_chain_cell.c
@@ -31,7 +31,7 @@
 #include "dap_strfuncs.h"
 #include "dap_file_utils.h"
 #ifdef DAP_OS_WINDOWS
-#include "mman.h"
+#include <winternl.h>
 #else
 #include <sys/mman.h>
 #endif
@@ -55,6 +55,32 @@ typedef struct dap_chain_cell_file_header
     dap_chain_cell_id_t cell_id;
 } DAP_ALIGN_PACKED dap_chain_cell_file_header_t;
 
+#ifdef DAP_OS_WINDOWS
+typedef NTSTATUS (*pfn_NtCreateSection)(
+    OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess,
+    IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,
+    IN OPTIONAL PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection,
+    IN ULONG AllocationAttributes, IN OPTIONAL HANDLE FileHandle);
+static pfn_NtCreateSection pfnNtCreateSection;
+
+typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT;
+typedef NTSTATUS (*pfn_NtMapViewOfSection) (
+    IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress,
+    IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize,
+    IN OUT OPTIONAL PLARGE_INTEGER SectionOffset, IN OUT PSIZE_T ViewSize,
+    IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType,
+    IN ULONG Win32Protect);
+static pfn_NtMapViewOfSection pfnNtMapViewOfSection;
+
+typedef NTSTATUS (*pfn_NtUnmapViewOfSection) (
+        IN HANDLE ProcessHandle, IN PVOID BaseAddress);
+static pfn_NtUnmapViewOfSection pfnNtUnmapViewOfSection;
+
+typedef NTSTATUS (*pfn_NtExtendSection) (
+    IN HANDLE SectionHandle, IN PLARGE_INTEGER NewSectionSize);
+static pfn_NtExtendSection pfnNtExtendSection;
+#endif
+
 static bool s_debug_more = false;
 
 /**
@@ -65,10 +91,91 @@ static bool s_debug_more = false;
 int dap_chain_cell_init(void)
 {
     s_debug_more = dap_config_get_item_bool_default(g_config, "chain", "debug_more", false);
+#ifdef DAP_OS_WINDOWS
+    if ( dap_config_get_item_bool_default(g_config, "ledger", "mapped", true) ) {
+        HMODULE ntdll = GetModuleHandle("ntdll.dll");
+        if ( !ntdll )
+            return log_it(L_CRITICAL, "Ntdll error"), -1;
+        pfnNtCreateSection      = (pfn_NtCreateSection)     GetProcAddress(ntdll, "NtCreateSection");
+        pfnNtMapViewOfSection   = (pfn_NtMapViewOfSection)  GetProcAddress(ntdll, "NtMapViewOfSection");
+        pfnNtExtendSection      = (pfn_NtExtendSection)     GetProcAddress(ntdll, "NtExtendSection");
+        pfnNtUnmapViewOfSection = (pfn_NtUnmapViewOfSection)GetProcAddress(ntdll, "NtUnmapViewOfSection");
+    }
+    
+#endif
     //s_cells_path = dap_config_get_item_str(g_config,"resources","cells_storage");
     return  0;
 }
 
+DAP_STATIC_INLINE int s_cell_file_write_header(dap_chain_cell_t *a_cell)
+{
+    dap_chain_cell_file_header_t l_hdr = {
+        .signature      = DAP_CHAIN_CELL_FILE_SIGNATURE,
+        .version        = DAP_CHAIN_CELL_FILE_VERSION,
+        .type           = DAP_CHAIN_CELL_FILE_TYPE_RAW,
+        .chain_id       = a_cell->chain->id,
+        .chain_net_id   = a_cell->chain->net_id,
+        .cell_id        = a_cell->id
+    };
+    return (int)fwrite(&l_hdr, sizeof(l_hdr), 1, a_cell->file_storage);
+}
+
+DAP_STATIC_INLINE int s_cell_map_new_volume(dap_chain_cell_t *a_cell, size_t a_fpos) {
+    int l_fildes = fileno(a_cell->file_storage);
+#ifdef DAP_OS_WINDOWS
+    HANDLE hSection = NULL;
+    if ( !a_fpos ) {
+        //if (a_cell->map_range_bounds)
+        //    NtClose( (HANDLE)a_cell->map_range_bounds->data );
+        LARGE_INTEGER SectionSize = { 
+            .QuadPart = ( fseek(a_cell->file_storage, 0, SEEK_END), ftell(a_cell->file_storage) ) 
+        };
+        
+        NTSTATUS err = pfnNtCreateSection(&hSection, SECTION_MAP_READ|SECTION_EXTEND_SIZE|SECTION_MAP_WRITE, 
+                                          NULL, &SectionSize, PAGE_READWRITE, SEC_RESERVE,
+                                          (HANDLE)_get_osfhandle(l_fildes));
+        if ( !NT_SUCCESS(err) ) {
+            log_it(L_ERROR, "NtCreateSection() failed, status %lx", err);
+            return -1;
+        }
+        a_cell->map_range_bounds = dap_list_append(a_cell->map_range_bounds, hSection);
+    }
+#endif
+    size_t  l_map_size      = dap_page_roundup(DAP_MAPPED_VOLUME_LIMIT),
+#ifdef DAP_OS_WINDOWS
+            l_volume_start  = a_fpos ? dap_64k_rounddown(a_fpos)    : 0,
+#else               
+            l_volume_start  = a_fpos ? dap_page_rounddown(a_fpos)   : 0,
+#endif                  
+            l_offset        = a_fpos - l_volume_start;
+#ifdef DAP_OS_WINDOWS
+    hSection = (HANDLE)a_cell->map_range_bounds->data;
+    a_cell->map = NULL;
+    int err = 0;
+    if ( !NT_SUCCESS ( err = pfnNtMapViewOfSection(hSection, GetCurrentProcess(), 
+                                                   (HANDLE)&a_cell->map, 0, 0, 
+                                                   &l_volume_start, &l_map_size,
+                                                   ViewUnmap, MEM_RESERVE,
+                                                   PAGE_WRITECOPY) ) )
+    {
+        log_it(L_ERROR, "NtMapViewOfSection() failed, status %lx", err);
+        NtClose(hSection);
+        return -1;
+    }
+#else
+    if ( MAP_FAILED == (a_cell->map = mmap(NULL, l_map_size, PROT_READ|PROT_WRITE,
+                                           MAP_PRIVATE, fileno(a_cell->file_storage), l_volume_start)) ) {
+        log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be mapped, errno %d",
+                        a_cell->file_storage_path, a_cell->id.uint64, errno);
+        return -1;
+    }
+#endif
+    a_cell->map_pos = a_cell->map + l_offset;
+    a_cell->map_range_bounds = dap_list_append(a_cell->map_range_bounds, a_cell->map);
+    a_cell->map_range_bounds = dap_list_append(a_cell->map_range_bounds, a_cell->map_end = a_cell->map + l_map_size);
+    return 0;
+}
+
 /**
  * @brief dap_chain_cell_find_by_id
  * get dap_chain_cell_t object by cell (shard) id
@@ -103,77 +210,53 @@ dap_chain_cell_t * dap_chain_cell_create_fill(dap_chain_t * a_chain, dap_chain_c
         pthread_rwlock_unlock(&a_chain->cell_rwlock);
         return l_cell;
     }
-        char file_storage_path[MAX_PATH];
+#define CLEANUP_AND_RET return ({ fclose(l_file); DAP_DELETE(l_cell); pthread_rwlock_unlock(&a_chain->cell_rwlock); NULL; })
+    char file_storage_path[MAX_PATH];
     snprintf(file_storage_path, MAX_PATH, "%s/%0"DAP_UINT64_FORMAT_x".dchaincell",
              DAP_CHAIN_PVT(a_chain)->file_storage_dir, a_cell_id.uint64);
     
-    char *l_map = NULL;
-    size_t l_size = 0;
-    FILE *l_file = fopen(file_storage_path, "r+b");
-    if ( l_file ) {
-        if ( a_chain->is_mapped ) {
-            fseek(l_file, 0, SEEK_END);
-            l_size = ftell(l_file);
-            fseek(l_file, 0, SEEK_SET);
-            if ( MAP_FAILED == (l_map = mmap(NULL, l_size ? l_size : dap_page_roundup(DAP_MAPPED_VOLUME_LIMIT), PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(l_file), 0)) ) {
-                log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be mapped, errno %d", file_storage_path, a_cell_id.uint64, errno);
-                fclose(l_file);
-                pthread_rwlock_unlock(&a_chain->cell_rwlock);
-                return NULL;
-            }
-        }
-    } else if (errno == ENOENT) {
-        if ( !(l_file = fopen(file_storage_path, "w+b")) ) {
-            log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be opened, error %d",
-                            file_storage_path, a_cell_id.uint64, errno);
-            pthread_rwlock_unlock(&a_chain->cell_rwlock);
-            return NULL;
-        }
-        if ( a_chain->is_mapped && MAP_FAILED == (l_map = mmap(NULL, l_size = dap_page_roundup(DAP_MAPPED_VOLUME_LIMIT), PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(l_file), 0)) ) {
-            log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be mapped, error %d",
-                            file_storage_path, a_cell_id.uint64, errno);
-            fclose(l_file);
-            pthread_rwlock_unlock(&a_chain->cell_rwlock);
-            return NULL;
-        }
+    FILE *l_file = fopen(file_storage_path, "a+b");
+    if ( !l_file ) {
+        log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be opened, error %d",
+                        file_storage_path, a_cell_id.uint64, errno);
+        CLEANUP_AND_RET;
     }
-
-    l_cell = DAP_NEW_Z(dap_chain_cell_t);
+    if ( !(l_cell = DAP_NEW_Z(dap_chain_cell_t)) )
+        CLEANUP_AND_RET;
     *l_cell = (dap_chain_cell_t) {
         .id             = a_cell_id,
-        .map            = l_map,
-        .map_pos        = l_map,
-        .map_end        = l_map ? l_map + l_size : NULL,
-        .file_storage   = l_file,
         .chain          = a_chain,
+        .file_storage   = l_file,
         .storage_rwlock = PTHREAD_RWLOCK_INITIALIZER
     };
-    memcpy(l_cell->file_storage_path, file_storage_path, sizeof(file_storage_path));
-    if (l_map) {
-        l_cell->map_range_bounds = dap_list_append(l_cell->map_range_bounds, l_map);
-        l_cell->map_range_bounds = dap_list_append(l_cell->map_range_bounds, l_cell->map_end);  
+    size_t l_size = ( fseek(l_file, 0, SEEK_END), ftell(l_file) );
+    if ( l_size < sizeof(dap_chain_cell_file_header_t) ) {
+        if (l_size) {
+            log_it(L_INFO, "Possibly corrupt cell storage 0x%016"DAP_UINT64_FORMAT_X" \"%s\", rewriting it",
+                            a_cell_id.uint64, file_storage_path);
+            l_file = freopen(file_storage_path, "w+b", l_file);
+        }
+        if ( !s_cell_file_write_header(l_cell) ) {
+            log_it(L_ERROR, "Can't init file storage for cell 0x%016"DAP_UINT64_FORMAT_X" \"%s\", errno %d",
+                             a_cell_id.uint64, file_storage_path, errno);
+            CLEANUP_AND_RET;
+        }
+        log_it(L_NOTICE, "Initialized file storage for cell 0x%016"DAP_UINT64_FORMAT_X" \"%s\"",
+                          a_cell_id.uint64, file_storage_path);
+        fflush(l_file);
     }
+
+    if ( a_chain->is_mapped && s_cell_map_new_volume(l_cell, 0) ) {
+        CLEANUP_AND_RET;
+    }
+#undef CLEANUP_AND_RET
+    memcpy(l_cell->file_storage_path, file_storage_path, sizeof(file_storage_path));
     debug_if (s_debug_more && a_chain->is_mapped, L_DEBUG, "Mapped volume size is %lu", (size_t)(l_cell->map_end - l_cell->map));
     HASH_ADD(hh, a_chain->cells, id, sizeof(dap_chain_cell_id_t), l_cell);
     pthread_rwlock_unlock(&a_chain->cell_rwlock);
     return l_cell;
 }
 
-/**
- * @brief dap_chain_cell_create_fill2
- * set l_cell->file_storage_path and l_cell->id.uint64 from name of chain. 
- * For example, 0.dchaincell. 0 - chain id, dchaincell - name of file
- * @param a_chain - chain object
- * @param a_filename - chain filename, for example "0.dchaincell"
- * @return dap_chain_cell_t* 
- */
-dap_chain_cell_t * dap_chain_cell_create_fill2(dap_chain_t * a_chain, const char *a_filename)
-{
-    uint64_t l_cell_id_uint64;
-    sscanf(a_filename, "%"DAP_UINT64_FORMAT_x".dchaincell", &l_cell_id_uint64);
-    return dap_chain_cell_create_fill(a_chain, (dap_chain_cell_id_t){ .uint64 = l_cell_id_uint64});
-}
-
 /**
  * @brief
  * close a_cell->file_storage file object
@@ -188,13 +271,24 @@ void dap_chain_cell_close(dap_chain_cell_t *a_cell)
         a_cell->file_storage = NULL;
     }
     if (a_cell->chain->is_mapped) {
-        for (dap_list_t *l_iter = a_cell->map_range_bounds; l_iter; l_iter = l_iter->next) {
+        dap_list_t *l_iter = a_cell->map_range_bounds;
+#ifdef DAP_OS_WINDOWS
+        l_iter = l_iter->next;
+#endif
+        for (; l_iter; l_iter = l_iter->next) {
             if (l_iter->next) {
                 debug_if(s_debug_more, L_DEBUG, "Unmap volume %p (%lu bytes)", l_iter->data, (size_t)(l_iter->next->data - l_iter->data));
+#ifdef DAP_OS_WINDOWS
+                pfnNtUnmapViewOfSection(GetCurrentProcess(), l_iter->data);
+#else
                 munmap(l_iter->data, (size_t)(l_iter->next->data - l_iter->data));
+#endif
                 l_iter = l_iter->next;
             }
         }
+#ifdef DAP_OS_WINDOWS
+        NtClose(a_cell->map_range_bounds->data);
+#endif
         dap_list_free(a_cell->map_range_bounds);
     }
 }
@@ -251,15 +345,12 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
 {
     if (!a_cell)
         return -1;
-    fseek(a_cell->file_storage, 0, SEEK_END);
-    size_t l_size = ftell(a_cell->file_storage);
-    fseek(a_cell->file_storage, 0, SEEK_SET);
-    if ( l_size < sizeof(dap_chain_cell_file_header_t) || (a_chain->is_mapped && !a_cell->map_pos) ) {
+    size_t l_size = ( fseek(a_cell->file_storage, 0, SEEK_END), ftell(a_cell->file_storage) ), l_pos = 0;
+    if ( l_size <= sizeof(dap_chain_cell_file_header_t) ) {
         log_it(L_INFO, "Chain cell \"%s\" is yet empty", a_cell->file_storage_path);
         return -1;
     }
     int l_ret = 0;
-    size_t l_full_size = 0;
     dap_chain_cell_file_header_t *l_hdr = NULL;
     if (a_chain->is_mapped) {
         l_hdr = (dap_chain_cell_file_header_t*)a_cell->map;
@@ -271,7 +362,6 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
             DAP_DELETE(l_hdr);
             return -2;
         }
-        l_full_size += sizeof(dap_chain_cell_file_header_t);
     }
     if (l_hdr->signature != DAP_CHAIN_CELL_FILE_SIGNATURE) {
         log_it(L_ERROR, "Wrong signature in chain \"%s\", possible file corrupt", a_cell->file_storage_path);
@@ -286,16 +376,23 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
         return -4;
     }
 
+    l_pos += sizeof(dap_chain_cell_file_header_t);
     uint64_t q = 0;
     if (a_chain->is_mapped) {
         a_cell->map_pos = a_cell->map + sizeof(dap_chain_cell_file_header_t);
-        for (uint64_t l_el_size = 0; a_cell->map_pos < a_cell->map_end && ( l_el_size = *(uint64_t*)a_cell->map_pos ); ++q, a_cell->map_pos += l_el_size) {
-            dap_hash_fast_t l_atom_hash = {};
+        for ( uint64_t l_el_size = 0; l_pos < l_size; ++q, l_pos += l_el_size + sizeof(uint64_t) ) {
+            size_t space_left = (size_t)( a_cell->map_end - a_cell->map_pos );
+            if ( space_left < sizeof(uint64_t) || (space_left - sizeof(uint64_t)) < *(uint64_t*)a_cell->map_pos )
+                if ( !s_cell_map_new_volume(a_cell, l_pos) )
+                    break;
+            l_el_size = *(uint64_t*)a_cell->map_pos;
+            dap_hash_fast_t l_atom_hash;
             dap_chain_atom_ptr_t l_atom = (dap_chain_atom_ptr_t)(a_cell->map_pos += sizeof(uint64_t));
             dap_hash_fast(l_atom, l_el_size, &l_atom_hash);
             a_chain->callback_atom_add(a_chain, l_atom, l_el_size, &l_atom_hash);
+            a_cell->map_pos += l_el_size;
         }
-        fseek(a_cell->file_storage, a_cell->map_pos - a_cell->map, SEEK_SET);
+        fseek(a_cell->file_storage, l_pos, SEEK_SET);
     } else { 
         DAP_DELETE(l_hdr);
         size_t l_read = 0;
@@ -312,7 +409,7 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
                 l_ret = -5;
                 break;
             }
-            l_full_size += sizeof(uint64_t) + ( l_read = fread((void*)l_element, 1, l_el_size, a_cell->file_storage) );
+            l_pos += sizeof(uint64_t) + ( l_read = fread((void*)l_element, 1, l_el_size, a_cell->file_storage) );
             if (l_read != l_el_size) {
                 log_it(L_ERROR, "Read only %lu of %zu bytes, stop cell loading", l_read, l_el_size);
                 DAP_DELETE(l_element);
@@ -327,75 +424,25 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
             }
             ++q;
         }
-        fseek(a_cell->file_storage, l_full_size, SEEK_SET);
+        fseek(a_cell->file_storage, l_pos, SEEK_SET);
     }
     log_it(L_INFO, "Loaded %lu atoms in cell %s", q, a_cell->file_storage_path);
     return l_ret;
 }
 
-static int s_file_write_header(dap_chain_cell_t *a_cell)
-{
-    if (!a_cell->file_storage) {
-        log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" not opened",
-               a_cell->file_storage_path, a_cell->id.uint64);
-        return -2;
-    } else {
-        fseek(a_cell->file_storage, 0L, SEEK_END);
-        if (ftell(a_cell->file_storage) >= (ssize_t)sizeof(dap_chain_cell_file_header_t)) {
-            log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" is already not empty!",
-                   a_cell->file_storage_path, a_cell->id.uint64);
-            return -3;
-        }
-    }
-    dap_chain_cell_file_header_t l_hdr = {
-        .signature      = DAP_CHAIN_CELL_FILE_SIGNATURE,
-        .version        = DAP_CHAIN_CELL_FILE_VERSION,
-        .type           = DAP_CHAIN_CELL_FILE_TYPE_RAW,
-        .chain_id       = { .uint64 = a_cell->id.uint64 },
-        .chain_net_id   = a_cell->chain->net_id
-    };
-
-    if(fwrite(&l_hdr, sizeof(l_hdr), 1, a_cell->file_storage) == 1) {
-        log_it(L_NOTICE, "Initialized file storage for cell 0x%016"DAP_UINT64_FORMAT_X" ( %s )",
-                a_cell->id.uint64, a_cell->file_storage_path);
-        fflush(a_cell->file_storage);
-        if (a_cell->chain->is_mapped)
-            a_cell->map_pos = a_cell->map + sizeof(l_hdr);
-        return 0;
-    }
-    log_it(L_ERROR, "Can't init file storage for cell 0x%016"DAP_UINT64_FORMAT_X" ( %s )",
-                    a_cell->id.uint64, a_cell->file_storage_path);
-    return -1;
-}
-
-static int s_file_atom_add(dap_chain_cell_t *a_cell, dap_chain_atom_ptr_t a_atom, uint64_t a_atom_size)
+static int s_cell_file_atom_add(dap_chain_cell_t *a_cell, dap_chain_atom_ptr_t a_atom, uint64_t a_atom_size)
 {
     if (!a_atom || !a_atom_size) {
         log_it(L_CRITICAL, "Invalid arguments");
         return -1;
     }
     if (a_cell->chain->is_mapped) {
-        size_t l_pos = ftell(a_cell->file_storage);
+        size_t l_pos = ( fseek(a_cell->file_storage, 0, SEEK_END), ftell(a_cell->file_storage) );
         debug_if (s_debug_more, L_DEBUG, "Before filling volume for atom size %lu, stream pos of %s is %lu, map pos is %lu, space left in map %lu",
                       a_atom_size, a_cell->file_storage_path, l_pos, (size_t)(a_cell->map_pos - a_cell->map), (size_t)(a_cell->map_end - a_cell->map_pos));
-        if ( a_atom_size > (size_t)(a_cell->map_end - a_cell->map_pos) ) {
-            size_t  l_map_size      = dap_page_roundup(DAP_MAPPED_VOLUME_LIMIT),
-                    l_volume_start  = dap_page_rounddown(l_pos),
-                    l_offset        = l_pos - l_volume_start;
-            debug_if (s_debug_more, L_DEBUG, "Need to enlarge map of %s, current stream pos is %lu, map pos is %lu, offset of new map is %lu",
-                a_cell->file_storage_path, ftell(a_cell->file_storage), (size_t)(a_cell->map_end - a_cell->map_pos), l_offset);
-            if ( MAP_FAILED == (a_cell->map = mmap(NULL, l_map_size, PROT_READ|PROT_WRITE, 
-                                                   MAP_PRIVATE, fileno(a_cell->file_storage), l_volume_start)) )
-            {
-                log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X" cannot be mapped, errno %d",
-                                a_cell->file_storage_path, a_cell->id.uint64, errno);
-                fclose(a_cell->file_storage);
+        if ( a_atom_size + sizeof(uint64_t) > (size_t)(a_cell->map_end - a_cell->map_pos) )
+            if ( s_cell_map_new_volume(a_cell, l_pos) )
                 return -2;
-            }
-            a_cell->map_pos = a_cell->map + l_offset;
-            a_cell->map_range_bounds = dap_list_append(a_cell->map_range_bounds, a_cell->map);
-            a_cell->map_range_bounds = dap_list_append(a_cell->map_range_bounds, a_cell->map_end = a_cell->map + l_map_size);
-        }
     }
     
     debug_if (s_debug_more && a_cell->chain->is_mapped, L_DEBUG, "Before writing an atom of size %lu, stream pos of %s is %lu and pos is %lu, space left in map %lu", 
@@ -447,13 +494,12 @@ ssize_t dap_chain_cell_file_append(dap_chain_cell_t *a_cell, const void *a_atom,
     if (!a_atom || !a_atom_size) {
         a_cell->file_storage = freopen(a_cell->file_storage_path, "w+b", a_cell->file_storage);
         debug_if (s_debug_more,L_DEBUG, "Rewinding file %s", a_cell->file_storage_path);
-        if (a_cell->chain->is_mapped && a_cell->map_range_bounds) {
-            a_cell->map = a_cell->map_pos = a_cell->map_range_bounds->data;
-            a_cell->map_end = a_cell->map_range_bounds->next->data;
-        }
-        if ( s_file_write_header(a_cell) ) {
+        bool was_mapped = a_cell->chain->is_mapped;
+        a_cell->chain->is_mapped = false;
+        if ( !s_cell_file_write_header(a_cell) ) {
             log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X": can't fill header",
                             a_cell->file_storage_path, a_cell->id.uint64);
+            a_cell->chain->is_mapped = was_mapped;
             pthread_rwlock_unlock(&a_cell->storage_rwlock);
             return -2;
         }
@@ -465,14 +511,15 @@ ssize_t dap_chain_cell_file_append(dap_chain_cell_t *a_cell, const void *a_atom,
              l_atom && l_atom_size;
              l_atom = a_cell->chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size))
         {
-            if (s_file_atom_add(a_cell, l_atom, l_atom_size)) {
+            if ( s_cell_file_atom_add(a_cell, l_atom, l_atom_size) ) {
                 l_err = true;
                 break;
             } else {
-                l_total_res += l_atom_size + sizeof(uint64_t);
+                l_total_res += sizeof(uint64_t) + l_atom_size;
                 ++l_count;
             }
         }
+        a_cell->chain->is_mapped = was_mapped;
         a_cell->chain->callback_atom_iter_delete(l_atom_iter);
         debug_if (s_debug_more && a_cell->chain->is_mapped,L_DEBUG, "After rewriting file %s, stream pos is %lu and map pos is %lu",
                       a_cell->file_storage_path, ftell(a_cell->file_storage),
@@ -481,13 +528,7 @@ ssize_t dap_chain_cell_file_append(dap_chain_cell_t *a_cell, const void *a_atom,
         debug_if (s_debug_more && a_cell->chain->is_mapped,L_DEBUG, "Before appending an atom of size %lu, stream pos of %s is %lu, map pos is %lu",
                       a_atom_size, a_cell->file_storage_path, ftell(a_cell->file_storage),
                       (size_t)(a_cell->map_pos - a_cell->map));
-        if ( !ftell(a_cell->file_storage) && s_file_write_header(a_cell) ) {
-            log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X": can't fill header",
-                            a_cell->file_storage_path, a_cell->id.uint64);
-            pthread_rwlock_unlock(&a_cell->storage_rwlock);
-            return -3;
-        }
-        if (s_file_atom_add(a_cell, a_atom, a_atom_size)) {
+        if ( s_cell_file_atom_add(a_cell, a_atom, a_atom_size) ) {
             log_it(L_ERROR, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X": can't save atom!",
                    a_cell->file_storage_path, a_cell->id.uint64);
             pthread_rwlock_unlock(&a_cell->storage_rwlock);
@@ -502,6 +543,17 @@ ssize_t dap_chain_cell_file_append(dap_chain_cell_t *a_cell, const void *a_atom,
 
     if (l_total_res) {
         fflush(a_cell->file_storage);
+#ifdef DAP_OS_WINDOWS
+        if (a_cell->chain->is_mapped) {
+            LARGE_INTEGER SectionSize = (LARGE_INTEGER) { .QuadPart = ftell(a_cell->file_storage) };
+            HANDLE hSection = (HANDLE)a_cell->map_range_bounds->data;
+            NTSTATUS err = pfnNtExtendSection(hSection, &SectionSize);
+            if ( !NT_SUCCESS(err) ) {
+                log_it(L_ERROR, "NtExtendSection() failed, status %lx", err);
+                return -4;
+            }
+        }
+#endif
         log_it(L_DEBUG, "Chain cell \"%s\" 0x%016"DAP_UINT64_FORMAT_X": saved %zu atoms (%zu bytes)",
                a_cell->file_storage_path, a_cell->id.uint64, l_count, l_total_res);
         if (l_err) {
diff --git a/modules/chain/include/dap_chain_cell.h b/modules/chain/include/dap_chain_cell.h
index 2c52cce17..5c132c684 100644
--- a/modules/chain/include/dap_chain_cell.h
+++ b/modules/chain/include/dap_chain_cell.h
@@ -74,7 +74,6 @@ typedef struct dap_chain_cell_decl{
 
 int dap_chain_cell_init(void);
 dap_chain_cell_t *dap_chain_cell_create_fill(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id);
-dap_chain_cell_t *dap_chain_cell_create_fill2(dap_chain_t *a_chain, const char *a_filename);
 dap_chain_cell_t *dap_chain_cell_find_by_id(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id);
 void dap_chain_cell_close(dap_chain_cell_t *a_cell);
 void dap_chain_cell_delete(dap_chain_cell_t *a_cell);
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index f5e39df6e..a2046030f 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -2195,7 +2195,7 @@ bool s_net_load(void *a_arg)
                     log_it(L_WARNING, "No purge callback for chain %s, can't reload it with correct order", l_chain->name);
             }
         } else {
-            dap_chain_save_all( l_chain );
+            //dap_chain_save_all( l_chain );
             log_it (L_NOTICE, "Initialized chain files");
         }
         l_chain->atom_num_last = l_chain->callback_count_atom(l_chain);
-- 
GitLab


From 4705ffb032c60c439ac23951cc09fdbae4e120e8 Mon Sep 17 00:00:00 2001
From: "Constantin P." <papizh.konstantin@demlabs.net>
Date: Sat, 8 Jun 2024 23:59:37 +0700
Subject: [PATCH 2/5] Sub up

---
 dap-sdk | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dap-sdk b/dap-sdk
index 063776950..392b1c81f 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit 063776950c5bce0a5179eee970a5def10edffa41
+Subproject commit 392b1c81fa0bd58e2c617ce6a379e403f72b3dd2
-- 
GitLab


From f04d8f55b1d77a722256dc93ec71ca46445a8e85 Mon Sep 17 00:00:00 2001
From: "Constantin P." <papizh.konstantin@demlabs.net>
Date: Mon, 10 Jun 2024 14:24:06 +0700
Subject: [PATCH 3/5] ...

---
 modules/chain/dap_chain.c              |  6 +-----
 modules/chain/dap_chain_cell.c         | 15 +++------------
 modules/chain/include/dap_chain_cell.h |  4 +++-
 modules/net/dap_chain_ledger.c         |  6 +-----
 modules/net/dap_chain_net.c            |  2 +-
 modules/type/dag/dap_chain_cs_dag.c    |  4 ++--
 6 files changed, 11 insertions(+), 26 deletions(-)

diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index 4bd3de572..45e255e3c 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -110,11 +110,7 @@ dap_chain_t *dap_chain_create(const char *a_chain_net_name, const char *a_chain_
             .net_id     = a_chain_net_id,
             .name       = dap_strdup(a_chain_name),
             .net_name   = dap_strdup(a_chain_net_name),
-#ifdef DAP_OS_WINDOWS // TODO
-            .is_mapped  = true,
-#else
             .is_mapped  = dap_config_get_item_bool_default(g_config, "ledger", "mapped", true),
-#endif
             .cell_rwlock    = PTHREAD_RWLOCK_INITIALIZER,
             .atom_notifiers = NULL
     };
@@ -614,7 +610,7 @@ int dap_chain_load_all(dap_chain_t *a_chain)
             sscanf(l_filename, "%"DAP_UINT64_FORMAT_x".dchaincell", &l_cell_id_uint64);
             dap_chain_cell_t *l_cell = dap_chain_cell_create_fill(a_chain, (dap_chain_cell_id_t){ .uint64 = l_cell_id_uint64 });
             l_ret += dap_chain_cell_load(a_chain, l_cell);
-            if (DAP_CHAIN_PVT(a_chain)->need_reorder) {
+            if (!DAP_CHAIN_PVT(a_chain)->need_reorder) {
                 const char *l_filename_backup = dap_strdup_printf("%s.unsorted", l_cell->file_storage_path);
                 if (remove(l_filename_backup) == -1) {
                     log_it(L_ERROR, "File %s doesn't exist", l_filename_backup);
diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c
index 8e3e2f65a..d0afa1263 100644
--- a/modules/chain/dap_chain_cell.c
+++ b/modules/chain/dap_chain_cell.c
@@ -41,7 +41,7 @@
 #define DAP_CHAIN_CELL_FILE_SIGNATURE 0xfa340bef153eba48
 #define DAP_CHAIN_CELL_FILE_TYPE_RAW 0
 #define DAP_CHAIN_CELL_FILE_TYPE_COMPRESSED 1
-#define DAP_MAPPED_VOLUME_LIMIT (1 << 28) // 256 MB for now, may be should be configurable?
+#define DAP_MAPPED_VOLUME_LIMIT (1 << 20) // 256 MB for now, may be should be configurable?
 /**
   * @struct dap_chain_cell_file_header
   */
@@ -355,6 +355,7 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
     if (a_chain->is_mapped) {
         l_hdr = (dap_chain_cell_file_header_t*)a_cell->map;
     } else {
+        fseek(a_cell->file_storage, 0, SEEK_SET);
         l_hdr = DAP_NEW(dap_chain_cell_file_header_t);
         if ( fread(l_hdr, 1, sizeof(*l_hdr), a_cell->file_storage) != sizeof(*l_hdr) ) {
             log_it(L_ERROR,"Can't read chain header \"%s\"", a_cell->file_storage_path);
@@ -383,7 +384,7 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
         for ( uint64_t l_el_size = 0; l_pos < l_size; ++q, l_pos += l_el_size + sizeof(uint64_t) ) {
             size_t space_left = (size_t)( a_cell->map_end - a_cell->map_pos );
             if ( space_left < sizeof(uint64_t) || (space_left - sizeof(uint64_t)) < *(uint64_t*)a_cell->map_pos )
-                if ( !s_cell_map_new_volume(a_cell, l_pos) )
+                if ( s_cell_map_new_volume(a_cell, l_pos) )
                     break;
             l_el_size = *(uint64_t*)a_cell->map_pos;
             dap_hash_fast_t l_atom_hash;
@@ -567,13 +568,3 @@ ssize_t dap_chain_cell_file_append(dap_chain_cell_t *a_cell, const void *a_atom,
     return l_total_res;
 }
 
-/**
- * @brief
- * return dap_chain_cell_file_append(a_cell, NULL, 0);
- * @param a_cell dap_chain_cell_t
- * @return
- */
-ssize_t dap_chain_cell_file_update(dap_chain_cell_t *a_cell)
-{
-    return dap_chain_cell_file_append(a_cell, NULL, 0);
-}
diff --git a/modules/chain/include/dap_chain_cell.h b/modules/chain/include/dap_chain_cell.h
index 5c132c684..afc9d2192 100644
--- a/modules/chain/include/dap_chain_cell.h
+++ b/modules/chain/include/dap_chain_cell.h
@@ -79,5 +79,7 @@ void dap_chain_cell_close(dap_chain_cell_t *a_cell);
 void dap_chain_cell_delete(dap_chain_cell_t *a_cell);
 void dap_chain_cell_delete_all(dap_chain_t *a_chain);
 int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell);
-ssize_t dap_chain_cell_file_update(dap_chain_cell_t *a_cell);
 ssize_t dap_chain_cell_file_append(dap_chain_cell_t *a_cell,const void *a_atom, size_t a_atom_size);
+DAP_STATIC_INLINE ssize_t dap_chain_cell_file_update(dap_chain_cell_t *a_cell) {
+    return dap_chain_cell_file_append(a_cell, NULL, 0);
+}
diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c
index af4225190..320d0e811 100644
--- a/modules/net/dap_chain_ledger.c
+++ b/modules/net/dap_chain_ledger.c
@@ -584,12 +584,8 @@ static dap_ledger_t * dap_ledger_handle_new(void)
     l_ledger_pvt->threshold_txs_free_timer = dap_interval_timer_create(s_threshold_free_timer_tick,
                                                                       (dap_timer_callback_t)s_threshold_txs_free, l_ledger);
     l_ledger_pvt->threshold_emissions_free_timer = dap_interval_timer_create(s_threshold_free_timer_tick,
-                                                                            (dap_timer_callback_t) s_threshold_emission_free, l_ledger);
-#ifdef DAP_OS_WINDOWS
-    l_ledger_pvt->mapped = false;
-#else                                                                            
+                                                                            (dap_timer_callback_t) s_threshold_emission_free, l_ledger);                                                                          
     l_ledger_pvt->mapped = dap_config_get_item_bool_default(g_config, "ledger", "mapped", true);
-#endif
     return l_ledger;
 }
 
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index a2046030f..6b50fce03 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -2177,7 +2177,7 @@ bool s_net_load(void *a_arg)
         l_net->pub.fee_addr = c_dap_chain_addr_blank;
         if (!dap_chain_load_all(l_chain)) {
             log_it (L_NOTICE, "Loaded chain files");
-            if (DAP_CHAIN_PVT(l_chain)->need_reorder) {
+            if (!DAP_CHAIN_PVT(l_chain)->need_reorder) {
                 log_it(L_DAP, "Reordering chain files for chain %s", l_chain->name);
                 if (l_chain->callback_atom_add_from_treshold)
                     while (l_chain->callback_atom_add_from_treshold(l_chain, NULL))
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index 5b047189d..2f3055ca7 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -347,8 +347,8 @@ static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain)
     }
     HASH_ITER(hh, l_dag_pvt->events_lasts_unlinked, l_event_current, l_event_tmp) {
         HASH_DEL(l_dag_pvt->events_lasts_unlinked, l_event_current);
-        if (!a_chain->is_mapped && !l_event_current->mapped_region)
-            DAP_DELETE(l_event_current->event);
+        //if (!a_chain->is_mapped && !l_event_current->mapped_region)
+        //    DAP_DELETE(l_event_current->event);
         DAP_DELETE(l_event_current);
     }
     HASH_ITER(hh, l_dag_pvt->events_treshold, l_event_current, l_event_tmp) {
-- 
GitLab


From 8b8c830510f7fc7540fb2d452ea5b33201a23782 Mon Sep 17 00:00:00 2001
From: "Constantin P." <papizh.konstantin@demlabs.net>
Date: Tue, 11 Jun 2024 13:08:07 +0700
Subject: [PATCH 4/5] ...

---
 modules/chain/dap_chain.c      | 10 +++++++++-
 modules/chain/dap_chain_cell.c | 15 ++++++++++++++-
 modules/net/dap_chain_net.c    |  7 ++++---
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index 45e255e3c..d0171a36e 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -610,7 +610,14 @@ int dap_chain_load_all(dap_chain_t *a_chain)
             sscanf(l_filename, "%"DAP_UINT64_FORMAT_x".dchaincell", &l_cell_id_uint64);
             dap_chain_cell_t *l_cell = dap_chain_cell_create_fill(a_chain, (dap_chain_cell_id_t){ .uint64 = l_cell_id_uint64 });
             l_ret += dap_chain_cell_load(a_chain, l_cell);
-            if (!DAP_CHAIN_PVT(a_chain)->need_reorder) {
+            if ( DAP_CHAIN_PVT(a_chain)->need_reorder ) {
+#ifdef DAP_OS_WINDOWS
+                strcat(l_cell->file_storage_path, ".new");
+                if (remove(l_cell->file_storage_path) == -1) {
+                    log_it(L_ERROR, "File %s doesn't exist", l_cell->file_storage_path);
+                }
+                *(l_cell->file_storage_path + strlen(l_cell->file_storage_path) - 4) = '\0';
+#else
                 const char *l_filename_backup = dap_strdup_printf("%s.unsorted", l_cell->file_storage_path);
                 if (remove(l_filename_backup) == -1) {
                     log_it(L_ERROR, "File %s doesn't exist", l_filename_backup);
@@ -619,6 +626,7 @@ int dap_chain_load_all(dap_chain_t *a_chain)
                     log_it(L_ERROR, "Couldn't rename %s to %s", l_cell->file_storage_path, l_filename_backup);
                 }
                 DAP_DELETE(l_filename_backup);
+#endif
             }
         }
     }
diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c
index d0afa1263..0167d9c88 100644
--- a/modules/chain/dap_chain_cell.c
+++ b/modules/chain/dap_chain_cell.c
@@ -41,7 +41,7 @@
 #define DAP_CHAIN_CELL_FILE_SIGNATURE 0xfa340bef153eba48
 #define DAP_CHAIN_CELL_FILE_TYPE_RAW 0
 #define DAP_CHAIN_CELL_FILE_TYPE_COMPRESSED 1
-#define DAP_MAPPED_VOLUME_LIMIT (1 << 20) // 256 MB for now, may be should be configurable?
+#define DAP_MAPPED_VOLUME_LIMIT ( 1 << 28 ) // 256 MB for now, may be should be configurable?
 /**
   * @struct dap_chain_cell_file_header
   */
@@ -291,6 +291,16 @@ void dap_chain_cell_close(dap_chain_cell_t *a_cell)
 #endif
         dap_list_free(a_cell->map_range_bounds);
     }
+#ifdef DAP_OS_WINDOWS
+    char *l_new = strstr(a_cell->file_storage_path, ".new");
+    if (l_new) {
+        char *l_orig = dap_strdup(a_cell->file_storage_path);
+        *l_new = '\0';
+        remove(a_cell->file_storage_path);
+        rename(l_orig, a_cell->file_storage_path);
+        DAP_DELETE(l_orig);
+    }
+#endif
 }
 
 /**
@@ -493,6 +503,9 @@ ssize_t dap_chain_cell_file_append(dap_chain_cell_t *a_cell, const void *a_atom,
     bool l_err = false;
     pthread_rwlock_wrlock(&a_cell->storage_rwlock);
     if (!a_atom || !a_atom_size) {
+#ifdef DAP_OS_WINDOWS
+        strcat(a_cell->file_storage_path, ".new");
+#endif
         a_cell->file_storage = freopen(a_cell->file_storage_path, "w+b", a_cell->file_storage);
         debug_if (s_debug_more,L_DEBUG, "Rewinding file %s", a_cell->file_storage_path);
         bool was_mapped = a_cell->chain->is_mapped;
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 1ccf77513..4e71dd369 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -2172,19 +2172,20 @@ bool s_net_load(void *a_arg)
         l_net->pub.fee_addr = c_dap_chain_addr_blank;
         if (!dap_chain_load_all(l_chain)) {
             log_it (L_NOTICE, "Loaded chain files");
-            if (!DAP_CHAIN_PVT(l_chain)->need_reorder) {
+            if ( DAP_CHAIN_PVT(l_chain)->need_reorder ) {
                 log_it(L_DAP, "Reordering chain files for chain %s", l_chain->name);
-                if (l_chain->callback_atom_add_from_treshold)
+                if (l_chain->callback_atom_add_from_treshold) {
                     while (l_chain->callback_atom_add_from_treshold(l_chain, NULL))
                         log_it(L_DEBUG, "Added atom from treshold");
+                }
                 dap_chain_save_all(l_chain);
                 DAP_CHAIN_PVT(l_chain)->need_reorder = false;
                 if (l_chain->callback_purge) {
+                    dap_chain_net_decree_purge(l_net);
                     l_chain->callback_purge(l_chain);
                     dap_ledger_purge(l_net->pub.ledger, false);
                     l_net->pub.fee_value = uint256_0;
                     l_net->pub.fee_addr = c_dap_chain_addr_blank;
-                    dap_chain_net_decree_purge(l_net);
                     dap_chain_load_all(l_chain);
                 } else
                     log_it(L_WARNING, "No purge callback for chain %s, can't reload it with correct order", l_chain->name);
-- 
GitLab


From ced69bd2a14b34ffd444de5d06692cfef3baffa1 Mon Sep 17 00:00:00 2001
From: Constantin P <papizh.konstantin@demlabs.net>
Date: Tue, 11 Jun 2024 17:35:57 +0700
Subject: [PATCH 5/5] Pointer arithmetics fixed

---
 modules/chain/dap_chain_cell.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c
index 0167d9c88..31dba0eee 100644
--- a/modules/chain/dap_chain_cell.c
+++ b/modules/chain/dap_chain_cell.c
@@ -356,8 +356,8 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
     if (!a_cell)
         return -1;
     size_t l_size = ( fseek(a_cell->file_storage, 0, SEEK_END), ftell(a_cell->file_storage) ), l_pos = 0;
-    if ( l_size <= sizeof(dap_chain_cell_file_header_t) ) {
-        log_it(L_INFO, "Chain cell \"%s\" is yet empty", a_cell->file_storage_path);
+    if ( l_size < sizeof(dap_chain_cell_file_header_t) ) {
+        log_it(L_ERROR, "Chain cell \"%s\" is corrupt, create new file", a_cell->file_storage_path);
         return -1;
     }
     int l_ret = 0;
@@ -386,8 +386,15 @@ int dap_chain_cell_load(dap_chain_t *a_chain, dap_chain_cell_t *a_cell)
         if (!a_chain->is_mapped) DAP_DELETE(l_hdr);
         return -4;
     }
-
     l_pos += sizeof(dap_chain_cell_file_header_t);
+    if (a_chain->is_mapped)
+        a_cell->map_pos += l_pos;
+    if (l_size == l_pos) {
+        fseek(a_cell->file_storage, l_pos, SEEK_END);
+        return 0;
+    }
+        
+        
     uint64_t q = 0;
     if (a_chain->is_mapped) {
         a_cell->map_pos = a_cell->map + sizeof(dap_chain_cell_file_header_t);
-- 
GitLab