[Bf-blender-cvs] [016ad539d72] undo-write: Initial step towards detecting/finding proper memchunk for a given ID.

Bastien Montagne noreply at git.blender.org
Thu May 28 23:06:20 CEST 2020


Commit: 016ad539d72539a6b9c2a782ade1a0714c14266d
Author: Bastien Montagne
Date:   Thu May 28 23:04:32 2020 +0200
Branches: undo-write
https://developer.blender.org/rB016ad539d72539a6b9c2a782ade1a0714c14266d

Initial step towards detecting/finding proper memchunk for a given ID.

WIP.

igeneral idea is to use session_uuid as reference.

===================================================================

M	source/blender/blenloader/BLO_undofile.h
M	source/blender/blenloader/intern/undofile.c
M	source/blender/blenloader/intern/writefile.c

===================================================================

diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h
index f280b8f3b9c..210c1d25fae 100644
--- a/source/blender/blenloader/BLO_undofile.h
+++ b/source/blender/blenloader/BLO_undofile.h
@@ -26,6 +26,7 @@
  */
 
 struct Scene;
+struct GHash;
 
 typedef struct {
   void *next, *prev;
@@ -38,6 +39,9 @@ typedef struct {
    * detect unchanged IDs).
    * Defined when writing the next step (i.e. last undo step has those always false). */
   bool is_identical_future;
+  /** Session uuid of the ID being curently written (MAIN_ID_SESSION_UUID_UNSET when not writing
+   * ID-related data). Used to find matching chunks in previous memundo step. */
+  uint session_uuid;
 } MemFileChunk;
 
 typedef struct MemFile {
@@ -45,6 +49,15 @@ typedef struct MemFile {
   size_t size;
 } MemFile;
 
+typedef struct MemFileWriteData {
+  MemFile *written_memfile;
+  MemFile *reference_memfile;
+  MemFileChunk *reference_current_chunk;
+
+  /** Maps an ID session uuid to its first reference MemFileChunk, if existing. */
+  struct GHash *id_session_uuid_mapping;
+} MemFileWriteData;
+
 typedef struct MemFileUndoData {
   char filename[1024]; /* FILE_MAX */
   MemFile memfile;
@@ -52,10 +65,13 @@ typedef struct MemFileUndoData {
 } MemFileUndoData;
 
 /* actually only used writefile.c */
-extern void memfile_chunk_add(MemFile *memfile,
-                              const char *buf,
-                              unsigned int size,
-                              MemFileChunk **compchunk_step);
+
+extern void BLO_memfile_write_init(MemFileWriteData *mem_data,
+                                   MemFile *written_memfile,
+                                   MemFile *reference_memfile);
+extern void BLO_memfile_write_finalize(MemFileWriteData *mem_data);
+
+extern void BLO_memfile_chunk_add(MemFileWriteData *mem_data, const char *buf, unsigned int size);
 
 /* exports */
 extern void BLO_memfile_free(MemFile *memfile);
diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c
index c7057883f88..64f50b1835e 100644
--- a/source/blender/blenloader/intern/undofile.c
+++ b/source/blender/blenloader/intern/undofile.c
@@ -41,10 +41,12 @@
 #include "DNA_listBase.h"
 
 #include "BLI_blenlib.h"
+#include "BLI_ghash.h"
 
 #include "BLO_readfile.h"
 #include "BLO_undofile.h"
 
+#include "BKE_lib_id.h"
 #include "BKE_main.h"
 
 /* keep last */
@@ -100,8 +102,47 @@ void BLO_memfile_clear_future(MemFile *memfile)
   }
 }
 
-void memfile_chunk_add(MemFile *memfile, const char *buf, uint size, MemFileChunk **compchunk_step)
+void BLO_memfile_write_init(MemFileWriteData *mem_data,
+                            MemFile *written_memfile,
+                            MemFile *reference_memfile)
 {
+  mem_data->written_memfile = written_memfile;
+  mem_data->reference_memfile = reference_memfile;
+  mem_data->reference_current_chunk = reference_memfile ? reference_memfile->chunks.first : NULL;
+
+  if (reference_memfile != NULL) {
+    mem_data->id_session_uuid_mapping = BLI_ghash_new(
+        BLI_ghashutil_inthash_p_simple, BLI_ghashutil_intcmp, __func__);
+    uint current_session_uuid = MAIN_ID_SESSION_UUID_UNSET;
+    LISTBASE_FOREACH (MemFileChunk *, mem_chunk, &reference_memfile->chunks) {
+      if (!ELEM(mem_chunk->session_uuid, MAIN_ID_SESSION_UUID_UNSET, current_session_uuid)) {
+        current_session_uuid = mem_chunk->session_uuid;
+        void **entry;
+        if (!BLI_ghash_ensure_p(mem_data->id_session_uuid_mapping,
+                                POINTER_FROM_UINT(current_session_uuid),
+                                &entry)) {
+          *entry = mem_chunk;
+        }
+        else {
+          BLI_assert(0);
+        }
+      }
+    }
+  }
+}
+
+void BLO_memfile_write_finalize(MemFileWriteData *mem_data)
+{
+  if (mem_data->id_session_uuid_mapping != NULL) {
+    BLI_ghash_free(mem_data->id_session_uuid_mapping, NULL, NULL);
+  }
+}
+
+void BLO_memfile_chunk_add(MemFileWriteData *mem_data, const char *buf, uint size)
+{
+  MemFile *memfile = mem_data->written_memfile;
+  MemFileChunk **compchunk_step = &mem_data->reference_current_chunk;
+
   MemFileChunk *curchunk = MEM_mallocN(sizeof(MemFileChunk), "MemFileChunk");
   curchunk->size = size;
   curchunk->buf = NULL;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 33467317090..358a481bb68 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -331,7 +331,8 @@ typedef struct {
     MemFile *compare;
     /** Use to de-duplicate chunks when writing. */
     MemFileChunk *compare_chunk;
-  } mem;
+  } mem_old;
+  MemFileWriteData mem;
   /** When true, write to #WriteData.current, could also call 'is_undo'. */
   bool use_memfile;
 
@@ -370,7 +371,7 @@ static void writedata_do_write(WriteData *wd, const void *mem, int memlen)
 
   /* memory based save */
   if (wd->use_memfile) {
-    memfile_chunk_add(wd->mem.current, mem, memlen, &wd->mem.compare_chunk);
+    BLO_memfile_chunk_add(&wd->mem, mem, memlen);
   }
   else {
     if (wd->ww->write(wd->ww, mem, memlen) != memlen) {
@@ -471,9 +472,7 @@ static WriteData *mywrite_begin(WriteWrap *ww, MemFile *compare, MemFile *curren
   WriteData *wd = writedata_new(ww);
 
   if (current != NULL) {
-    wd->mem.current = current;
-    wd->mem.compare = compare;
-    wd->mem.compare_chunk = compare ? compare->chunks.first : NULL;
+    BLO_memfile_write_init(&wd->mem, current, compare);
     wd->use_memfile = true;
   }
 
@@ -493,12 +492,57 @@ static bool mywrite_end(WriteData *wd)
     wd->buf_used_len = 0;
   }
 
+  if (wd->use_memfile) {
+    BLO_memfile_write_finalize(&wd->mem);
+  }
+
   const bool err = wd->error;
   writedata_free(wd);
 
   return err;
 }
 
+/**
+ * Start writing of data related to a single ID.
+ *
+ * Only does something when storing an undo step.
+ */
+static void mywrite_id_start(WriteData *wd, ID *id)
+{
+  if (wd->use_memfile) {
+    printf("START writing id %s\n", id->name);
+    if (wd->mem.id_session_uuid_mapping != NULL &&
+        (wd->mem.reference_current_chunk == NULL ||
+         wd->mem.reference_current_chunk->session_uuid != id->session_uuid)) {
+      void *ref = BLI_ghash_lookup(wd->mem.id_session_uuid_mapping,
+                                   POINTER_FROM_UINT(id->session_uuid));
+      if (ref != NULL) {
+        printf("\tFound existing memchunk, had to search\n");
+        wd->mem.reference_current_chunk = ref;
+      }
+    }
+    if (wd->mem.reference_current_chunk != NULL &&
+        wd->mem.reference_current_chunk->session_uuid == id->session_uuid) {
+      printf("\tFound existing memchunk, was next in list\n");
+    }
+  }
+}
+
+/**
+ * Start writing of data related to a single ID.
+ *
+ * Only does something when storing an undo step.
+ */
+static void mywrite_id_end(WriteData *wd, ID *id)
+{
+  if (wd->use_memfile) {
+    /* Very important to do it after every ID write now, otherwise we cannot know whether a
+     * specific ID changed or not. */
+    mywrite_flush(wd);
+    printf("END writing id %s\n", id->name);
+  }
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -4138,6 +4182,8 @@ static bool write_file_handle(Main *mainvar,
           }
         }
 
+        mywrite_id_start(wd, id);
+
         memcpy(id_buffer, id, idtype_struct_size);
 
         ((ID *)id_buffer)->tag = 0;
@@ -4274,11 +4320,7 @@ static bool write_file_handle(Main *mainvar,
           BKE_lib_override_library_operations_store_end(override_storage, id);
         }
 
-        if (wd->use_memfile) {
-          /* Very important to do it after every ID write now, otherwise we cannot know whether a
-           * specific ID changed or not. */
-          mywrite_flush(wd);
-        }
+        mywrite_id_end(wd, id);
       }
 
       if (id_buffer != id_buffer_static) {



More information about the Bf-blender-cvs mailing list