[Bf-blender-cvs] [18dc611b401] master: ID namemap: Add check for consistency.

Bastien Montagne noreply at git.blender.org
Wed Jul 27 11:24:49 CEST 2022


Commit: 18dc611b401690c477a97b7d74f4c666c9b41e42
Author: Bastien Montagne
Date:   Wed Jul 27 11:19:48 2022 +0200
Branches: master
https://developer.blender.org/rB18dc611b401690c477a97b7d74f4c666c9b41e42

ID namemap: Add check for consistency.

Add a util function to check that content of a given Main and the
namemaps in it are consistent.

Add some asserts calling this check after file read, and after some
override operations.

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

M	source/blender/blenkernel/BKE_main_namemap.h
M	source/blender/blenkernel/intern/lib_override.cc
M	source/blender/blenkernel/intern/main_namemap.cc
M	source/blender/windowmanager/intern/wm_files.c

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

diff --git a/source/blender/blenkernel/BKE_main_namemap.h b/source/blender/blenkernel/BKE_main_namemap.h
index d201e45a2c9..c5fce803a03 100644
--- a/source/blender/blenkernel/BKE_main_namemap.h
+++ b/source/blender/blenkernel/BKE_main_namemap.h
@@ -46,6 +46,14 @@ bool BKE_main_namemap_get_name(struct Main *bmain, struct ID *id, char *name) AT
 void BKE_main_namemap_remove_name(struct Main *bmain, struct ID *id, const char *name)
     ATTR_NONNULL();
 
+/**
+ * Check that all ID names in given `bmain` are unique (per ID type and library), and that existing
+ * name maps are consistent with existing relevant IDs.
+ *
+ * This is typically called within an assert, or in tests.
+ */
+bool BKE_main_namemap_validate(struct Main *bmain) ATTR_NONNULL();
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/intern/lib_override.cc b/source/blender/blenkernel/intern/lib_override.cc
index 3130ecca77f..8ca42905042 100644
--- a/source/blender/blenkernel/intern/lib_override.cc
+++ b/source/blender/blenkernel/intern/lib_override.cc
@@ -2670,6 +2670,8 @@ void BKE_lib_override_library_main_resync(Main *bmain,
                 library->filepath);
     }
   }
+
+  BLI_assert(BKE_main_namemap_validate(bmain));
 }
 
 void BKE_lib_override_library_delete(Main *bmain, ID *id_root)
@@ -3746,6 +3748,8 @@ void BKE_lib_override_library_main_update(Main *bmain)
   }
   FOREACH_MAIN_ID_END;
 
+  BLI_assert(BKE_main_namemap_validate(bmain));
+
   G_MAIN = orig_gmain;
 }
 
diff --git a/source/blender/blenkernel/intern/main_namemap.cc b/source/blender/blenkernel/intern/main_namemap.cc
index 00115d2a0be..3a7b325b3d2 100644
--- a/source/blender/blenkernel/intern/main_namemap.cc
+++ b/source/blender/blenkernel/intern/main_namemap.cc
@@ -22,6 +22,10 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "CLG_log.h"
+
+static CLG_LogRef LOG = {"bke.main_namemap"};
+
 //#define DEBUG_PRINT_MEMORY_USAGE
 
 using namespace blender;
@@ -363,3 +367,88 @@ void BKE_main_namemap_remove_name(struct Main *bmain, struct ID *id, const char
   }
   val->mark_unused(number);
 }
+
+struct Uniqueness_Key {
+  char name[MAX_ID_NAME];
+  Library *lib;
+  uint64_t hash() const
+  {
+    return BLI_ghashutil_combine_hash(BLI_ghashutil_strhash_n(name, MAX_ID_NAME),
+                                      BLI_ghashutil_ptrhash(lib));
+  }
+  bool operator==(const Uniqueness_Key &o) const
+  {
+    return lib == o.lib && !BLI_ghashutil_strcmp(name, o.name);
+  }
+};
+
+bool BKE_main_namemap_validate(Main *bmain)
+{
+  Set<Uniqueness_Key> id_names_libs;
+  bool is_valid = true;
+  ID *id_iter;
+  FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
+    Uniqueness_Key key;
+    BLI_strncpy(key.name, id_iter->name, MAX_ID_NAME);
+    key.lib = id_iter->lib;
+    if (!id_names_libs.add(key)) {
+      is_valid = false;
+      CLOG_ERROR(&LOG,
+                 "ID name '%s' (from library '%s') is found more than once",
+                 id_iter->name,
+                 id_iter->lib != nullptr ? id_iter->lib->filepath : "<None>");
+    }
+
+    UniqueName_Map *name_map = get_namemap_for(bmain, id_iter, false);
+    if (name_map == nullptr) {
+      continue;
+    }
+    UniqueName_TypeMap *type_map = name_map->find_by_type(GS(id_iter->name));
+    BLI_assert(type_map != nullptr);
+
+    UniqueName_Key key_namemap;
+    /* Remove full name from the set. */
+    BLI_strncpy(key_namemap.name, id_iter->name + 2, MAX_NAME);
+    if (!type_map->full_names.contains(key_namemap)) {
+      is_valid = false;
+      CLOG_ERROR(&LOG,
+                 "ID name '%s' (from library '%s') exists in current Main, but is not listed in "
+                 "the namemap",
+                 id_iter->name,
+                 id_iter->lib != nullptr ? id_iter->lib->filepath : "<None>");
+    }
+  }
+  FOREACH_MAIN_ID_END;
+
+  Library *lib = nullptr;
+  UniqueName_Map *name_map = bmain->name_map;
+  do {
+    if (name_map != nullptr) {
+      int i = 0;
+      for (short idcode = BKE_idtype_idcode_iter_step(&i); idcode != 0;
+           idcode = BKE_idtype_idcode_iter_step(&i)) {
+        UniqueName_TypeMap *type_map = name_map->find_by_type(idcode);
+        if (type_map != nullptr) {
+          for (const UniqueName_Key &id_name : type_map->full_names) {
+            Uniqueness_Key key;
+            *(reinterpret_cast<short *>(key.name)) = idcode;
+            BLI_strncpy(key.name + 2, id_name.name, MAX_NAME);
+            key.lib = lib;
+            if (!id_names_libs.contains(key)) {
+              is_valid = false;
+              CLOG_ERROR(&LOG,
+                         "ID name '%s' (from library '%s') is listed in the namemap, but does not "
+                         "exists in current Main",
+                         key.name,
+                         lib != nullptr ? lib->filepath : "<None>");
+            }
+          }
+        }
+      }
+    }
+    lib = static_cast<Library *>((lib == nullptr) ? bmain->libraries.first : lib->id.next);
+    name_map = (lib != nullptr) ? lib->runtime.name_map : nullptr;
+  } while (lib != nullptr);
+
+  return is_valid;
+}
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index a4d5bed21da..45e8f8786df 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -71,6 +71,7 @@
 #include "BKE_lib_override.h"
 #include "BKE_lib_remap.h"
 #include "BKE_main.h"
+#include "BKE_main_namemap.h"
 #include "BKE_packedFile.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
@@ -1004,6 +1005,8 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
 
   WM_cursor_wait(false);
 
+  BLI_assert(BKE_main_namemap_validate(CTX_data_main(C)));
+
   return success;
 }



More information about the Bf-blender-cvs mailing list