From a9a10e6d13c3848e7f2feb67f0eab2872512b0c8 Mon Sep 17 00:00:00 2001
From: "Dmitriy A. Gerasimov" <dmitriy.gerasimov@demlabs.net>
Date: Mon, 9 Nov 2020 00:54:37 +0700
Subject: [PATCH] [*] Chunks treshold now sorted with bubble

---
 modules/type/blocks/dap_chain_block_chunk.c   | 109 +++++++++++++++---
 .../blocks/include/dap_chain_block_chunk.h    |  26 ++++-
 2 files changed, 114 insertions(+), 21 deletions(-)

diff --git a/modules/type/blocks/dap_chain_block_chunk.c b/modules/type/blocks/dap_chain_block_chunk.c
index 97ecedb452..5e40fe835e 100644
--- a/modules/type/blocks/dap_chain_block_chunk.c
+++ b/modules/type/blocks/dap_chain_block_chunk.c
@@ -56,7 +56,7 @@ dap_chain_block_chunks_t * dap_chain_block_chunks_create(dap_chain_cs_blocks_t *
  */
 void dap_chain_block_chunks_delete(dap_chain_block_chunks_t * a_chunks)
 {
-    dap_chain_block_chunk_t * l_chunk = a_chunks->chunks_first;
+    dap_chain_block_chunk_t * l_chunk = a_chunks->chunks_last;
 
     while(l_chunk){
         dap_chain_block_cache_hash_t* l_block_cache_hash = NULL, *l_tmp = NULL;
@@ -98,40 +98,111 @@ dap_chain_block_cache_t * dap_chain_block_chunks_add(dap_chain_block_chunks_t *
     // Save to GDB
     dap_chain_global_db_gr_set(dap_strdup(l_block_cache->block_hash_str),a_block,a_block_size, a_chunks->gdb_group);
 
-    // Init cache-hash object
-    l_chunk_cache_hash = DAP_NEW_Z(dap_chain_block_cache_hash_t);
-    l_chunk_cache_hash->block_cache=l_block_cache;
-    l_chunk_cache_hash->ts_created = time(NULL);
-    memcpy(&l_chunk_cache_hash->block_hash, &l_block_cache->block_hash,sizeof (l_block_cache->block_hash));
 
 
     // And here we select chunk for the new block cache
-    for (dap_chain_block_chunk_t * l_chunk = a_chunks->chunks_first; l_chunk; l_chunk = l_chunk->prev ){
-        if(dap_hash_fast_compare(&l_chunk->block_cache_first->block_hash, &l_block_cache->prev_hash ) ){
+    bool l_is_chunk_found = false;
+    for (dap_chain_block_chunk_t * l_chunk = a_chunks->chunks_last; l_chunk; l_chunk = l_chunk->prev ){
+        if(dap_hash_fast_compare(&l_chunk->block_cache_top->block_hash, &l_block_cache->prev_hash ) ){
+            // Init cache-hash object
+            l_chunk_cache_hash = DAP_NEW_Z(dap_chain_block_cache_hash_t);
+            l_chunk_cache_hash->block_cache=l_block_cache;
+            l_chunk_cache_hash->ts_created = time(NULL);
+            memcpy(&l_chunk_cache_hash->block_hash, &l_block_cache->block_hash,sizeof (l_block_cache->block_hash));
             l_chunk_cache_hash->chunk = l_chunk;
-            break;
+
+            // Update first block cache from the head
+            l_chunk->block_cache_top = l_block_cache;
+            // Add to selected chunk its hash object
+            HASH_ADD(hh,l_chunk->block_cache_hash , block_hash, sizeof (l_chunk_cache_hash->block_hash), l_chunk_cache_hash);
+
+            // Update chunk id to make it unique
+            dap_chain_hash_fast_t l_hash_new_data[2]={l_block_cache->block_hash,l_chunk->chunk_id };
+            dap_hash_fast(l_hash_new_data,sizeof (l_hash_new_data),&l_chunk->chunk_id);
+            l_is_chunk_found = true;
         }
     }
 
-    if ( ! l_chunk_cache_hash->chunk) { // Don't found anything suitable - if so we create our own chunk
+    if ( ! l_is_chunk_found ) { // Don't found anything suitable - if so we create our own chunk
         dap_chain_block_chunk_t * l_chunk = DAP_NEW_Z(dap_chain_block_chunk_t);
-        l_chunk->block_cache_first = l_block_cache;
         // Add in tail
-        l_chunk->prev = a_chunks->chunks_last;
-        if (a_chunks->chunks_last){
-            l_chunk->next = a_chunks->chunks_last->next;
+        l_chunk->prev = a_chunks->chunks_first;
+        if (a_chunks->chunks_first){
+            l_chunk->next = a_chunks->chunks_first->next;
             if (! l_chunk->next)
-                a_chunks->chunks_first = l_chunk;
+                a_chunks->chunks_last = l_chunk;
             else
                 l_chunk->next->prev = l_chunk;
         }else
-            a_chunks->chunks_first = l_chunk;
-        a_chunks->chunks_last = l_chunk;
+            a_chunks->chunks_last = l_chunk;
+        a_chunks->chunks_first = l_chunk;
+
+        // Init cache-hash object
+        l_chunk_cache_hash = DAP_NEW_Z(dap_chain_block_cache_hash_t);
+        l_chunk_cache_hash->block_cache=l_block_cache;
+        l_chunk_cache_hash->ts_created = time(NULL);
+        memcpy(&l_chunk_cache_hash->block_hash, &l_block_cache->block_hash,sizeof (l_block_cache->block_hash));
+        l_chunk_cache_hash->chunk = l_chunk;
+
+        // Update first block cache from the head
+        l_chunk->block_cache_top = l_block_cache;
+        // Add to selected chunk its hash object
+        HASH_ADD(hh,l_chunk->block_cache_hash , block_hash, sizeof (l_chunk_cache_hash->block_hash), l_chunk_cache_hash);
+
+        // Update chunk id to make it unique
+        dap_chain_hash_fast_t l_hash_new_data[2]={l_block_cache->block_hash,l_chunk->chunk_id };
+        dap_hash_fast(l_hash_new_data,sizeof (l_hash_new_data),&l_chunk->chunk_id);
     }
-    // Add to selected chunk its hash object
-    HASH_ADD(hh,l_chunk_cache_hash->chunk->block_cache_hash , block_hash, sizeof (l_chunk_cache_hash->block_hash), l_chunk_cache_hash);
+
+
     // Add object itself to all-chunks cache
     HASH_ADD(hh,a_chunks->cache ,block_hash ,sizeof (l_block_cache->block_hash), l_block_cache);
 
+    // Sort chunk list beginning from the new one and bubble up the longest one on the top
+    size_t l_chunk_length_max=0;
+    //dap_chain_block_chunk_t * l_chunk_max = NULL;
+    for (dap_chain_block_chunk_t * l_chunk = a_chunks->chunks_first ; l_chunk; l_chunk = l_chunk->next ){
+        size_t l_chunk_length = HASH_COUNT(l_chunk->block_cache_hash);
+        if (! l_chunk_length){
+            log_it(L_WARNING,"Chunk can't be empty, it must be deleted from chunks treshold");
+        }
+        if (l_chunk_length > l_chunk_length_max ){
+            //l_chunk_max = l_chunk;
+            l_chunk_length_max = l_chunk_length;
+        }else if (l_chunk_length == l_chunk_length_max ){
+            continue;
+        }else{
+            // Prev store
+            dap_chain_block_chunk_t * l_chunk_prev = l_chunk->prev;
+
+            // Link next with prev
+            if (l_chunk->next )
+                l_chunk->next->prev = l_chunk->prev;
+
+            dap_chain_block_chunk_t * l_chunk_prev_prev = NULL;
+
+            if (l_chunk_prev){
+                // Link prev with next
+                l_chunk_prev->next = l_chunk->next;
+                l_chunk_prev_prev = l_chunk_prev->prev;
+                // Link prev with current
+                l_chunk_prev->prev = l_chunk;
+                // Update first chunks
+                if ( ! l_chunk_prev_prev)
+                    a_chunks->chunks_first = l_chunk;
+            }
+
+            // Link current with prev
+            l_chunk->next = l_chunk->prev ;
+            l_chunk->prev = l_chunk_prev_prev;
+
+            // Replace previous with current
+            l_chunk = l_chunk_prev;
+
+            // Its the last chunk
+            if ( ! l_chunk->next)
+                a_chunks->chunks_last = l_chunk;
+        }
+    }
     return l_block_cache;
 }
diff --git a/modules/type/blocks/include/dap_chain_block_chunk.h b/modules/type/blocks/include/dap_chain_block_chunk.h
index 18a9e8e9ee..cd7a90ecda 100644
--- a/modules/type/blocks/include/dap_chain_block_chunk.h
+++ b/modules/type/blocks/include/dap_chain_block_chunk.h
@@ -35,8 +35,9 @@ typedef struct dap_chain_block_cache_hash{
 
 
 typedef struct dap_chain_block_chunk{
+    dap_chain_hash_fast_t chunk_id;
     dap_chain_block_cache_hash_t *block_cache_hash;
-    dap_chain_block_cache_t *block_cache_first;
+    dap_chain_block_cache_t *block_cache_top;
     struct dap_chain_block_chunk * prev;
     struct dap_chain_block_chunk * next;
 } dap_chain_block_chunk_t;
@@ -47,8 +48,8 @@ typedef struct dap_chain_block_chunks{
 
     dap_chain_block_cache_t *cache;
 
-    dap_chain_block_chunk_t * chunks_first;
     dap_chain_block_chunk_t * chunks_last;
+    dap_chain_block_chunk_t * chunks_first;
     char * gdb_group;
 } dap_chain_block_chunks_t;
 
@@ -56,3 +57,24 @@ dap_chain_block_chunks_t * dap_chain_block_chunks_create(dap_chain_cs_blocks_t *
 void dap_chain_block_chunks_delete(dap_chain_block_chunks_t * a_chunks);
 
 dap_chain_block_cache_t * dap_chain_block_chunks_add(dap_chain_block_chunks_t * a_chunks, dap_chain_block_t *a_block ,size_t a_block_size);
+
+/**
+ * @brief dap_chain_block_chunks_get_longest_count
+ * @param a_chunks
+ */
+static inline size_t dap_chain_block_chunks_get_longest_count(dap_chain_block_chunks_t * a_chunks)
+{
+    assert(a_chunks);
+    return a_chunks->chunks_last? HASH_COUNT(a_chunks->chunks_last->block_cache_hash):0;
+}
+
+/**
+ * @brief dap_chain_block_chunks_get_longest_top
+ * @param a_chunks
+ * @return
+ */
+static inline dap_chain_block_cache_t* dap_chain_block_chunks_get_longest_top(dap_chain_block_chunks_t * a_chunks)
+{
+    assert(a_chunks);
+    return a_chunks->chunks_last?a_chunks->chunks_last->block_cache_top:NULL;
+}
-- 
GitLab