[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