Blender  V3.3
lib_id_delete.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include "CLG_log.h"
10 
11 #include "MEM_guardedalloc.h"
12 
13 /* all types are needed here, in order to do memory operations */
14 #include "DNA_ID.h"
15 #include "DNA_key_types.h"
16 
17 #include "BLI_utildefines.h"
18 
19 #include "BLI_listbase.h"
20 
21 #include "BKE_anim_data.h"
22 #include "BKE_asset.h"
23 #include "BKE_idprop.h"
24 #include "BKE_idtype.h"
25 #include "BKE_key.h"
26 #include "BKE_layer.h"
27 #include "BKE_lib_id.h"
28 #include "BKE_lib_override.h"
29 #include "BKE_lib_remap.h"
30 #include "BKE_library.h"
31 #include "BKE_main.h"
32 #include "BKE_main_namemap.h"
33 
34 #include "lib_intern.h"
35 
36 #include "DEG_depsgraph.h"
37 
38 #ifdef WITH_PYTHON
39 # include "BPY_extern.h"
40 #endif
41 
42 static CLG_LogRef LOG = {.identifier = "bke.lib_id_delete"};
43 
44 void BKE_libblock_free_data(ID *id, const bool do_id_user)
45 {
46  if (id->properties) {
49  id->properties = NULL;
50  }
51 
52  if (id->override_library) {
54  id->override_library = NULL;
55  }
56 
57  if (id->asset_data) {
59  }
60 
61  if (id->library_weak_reference != NULL) {
63  }
64 
65  BKE_animdata_free(id, do_id_user);
66 }
67 
68 void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
69 {
70  const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id);
71 
72  if (idtype_info != NULL) {
73  if (idtype_info->free_data != NULL) {
74  idtype_info->free_data(id);
75  }
76  return;
77  }
78 
79  BLI_assert_msg(0, "IDType Missing IDTypeInfo");
80 }
81 
82 void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_idtag)
83 {
84  ID *id = idv;
85 
86  if (use_flag_from_idtag) {
87  if ((id->tag & LIB_TAG_NO_MAIN) != 0) {
89  }
90  else {
91  flag &= ~LIB_ID_FREE_NO_MAIN;
92  }
93 
94  if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0) {
96  }
97  else {
99  }
100 
101  if ((id->tag & LIB_TAG_NOT_ALLOCATED) != 0) {
103  }
104  else {
105  flag &= ~LIB_ID_FREE_NOT_ALLOCATED;
106  }
107  }
108 
109  BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || bmain != NULL);
110  BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NOT_ALLOCATED) == 0);
111  BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0);
112 
113  const short type = GS(id->name);
114 
115  if (bmain && (flag & LIB_ID_FREE_NO_DEG_TAG) == 0) {
116  BLI_assert(bmain->is_locked_for_linking == false);
117 
118  DEG_id_type_tag(bmain, type);
119  }
120 
122 
123  Key *key = ((flag & LIB_ID_FREE_NO_MAIN) == 0) ? BKE_key_from_id(id) : NULL;
124 
125  if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) {
127  }
128 
129  if ((flag & LIB_ID_FREE_NO_MAIN) == 0 && key != NULL) {
130  BKE_id_free_ex(bmain, &key->id, flag, use_flag_from_idtag);
131  }
132 
133  BKE_libblock_free_datablock(id, flag);
134 
135  /* avoid notifying on removed data */
136  if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
137  BKE_main_lock(bmain);
138  }
139 
140  if ((flag & LIB_ID_FREE_NO_UI_USER) == 0) {
143  }
144 
146  struct IDRemapper *remapper = BKE_id_remapper_create();
147  BKE_id_remapper_add(remapper, id, NULL);
149  BKE_id_remapper_free(remapper);
150  }
151  }
152 
153  if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
154  ListBase *lb = which_libbase(bmain, type);
155  BLI_remlink(lb, id);
156  if ((flag & LIB_ID_FREE_NO_NAMEMAP_REMOVE) == 0) {
157  BKE_main_namemap_remove_name(bmain, id, id->name + 2);
158  }
159  }
160 
162 
163  if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
164  BKE_main_unlock(bmain);
165  }
166 
167  if ((flag & LIB_ID_FREE_NOT_ALLOCATED) == 0) {
168  MEM_freeN(id);
169  }
170 }
171 
172 void BKE_id_free(Main *bmain, void *idv)
173 {
174  BKE_id_free_ex(bmain, idv, 0, true);
175 }
176 
177 void BKE_id_free_us(Main *bmain, void *idv) /* test users */
178 {
179  ID *id = idv;
180 
181  id_us_min(id);
182 
183  /* XXX This is a temp (2.77) hack so that we keep same behavior as in 2.76 regarding collections
184  * when deleting an object. Since only 'user_one' usage of objects is collections,
185  * and only 'real user' usage of objects is scenes, removing that 'user_one' tag when there
186  * is no more real (scene) users of an object ensures it gets fully unlinked.
187  * But only for local objects, not linked ones!
188  * Otherwise, there is no real way to get rid of an object anymore -
189  * better handling of this is TODO.
190  */
191  if ((GS(id->name) == ID_OB) && (id->us == 1) && !ID_IS_LINKED(id)) {
192  id_us_clear_real(id);
193  }
194 
195  if (id->us == 0) {
196  BKE_libblock_unlink(bmain, id, false, false);
197 
198  BKE_id_free(bmain, id);
199  }
200 }
201 
202 static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
203 {
204  const int tag = LIB_TAG_DOIT;
205  ListBase *lbarray[INDEX_ID_MAX];
206  Link dummy_link = {0};
207  int base_count, i;
208 
209  /* Used by batch tagged deletion, when we call BKE_id_free then, id is no more in Main database,
210  * and has already properly unlinked its other IDs usages.
211  * UI users are always cleared in BKE_libblock_remap_locked() call, so we can always skip it. */
212  const int free_flag = LIB_ID_FREE_NO_UI_USER |
213  (do_tagged_deletion ? LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_USER_REFCOUNT :
214  0);
215  ListBase tagged_deleted_ids = {NULL};
216 
217  base_count = set_listbasepointers(bmain, lbarray);
218 
219  BKE_main_lock(bmain);
220  if (do_tagged_deletion) {
222  /* Main idea of batch deletion is to remove all IDs to be deleted from Main database.
223  * This means that we won't have to loop over all deleted IDs to remove usages
224  * of other deleted IDs.
225  * This gives tremendous speed-up when deleting a large amount of IDs from a Main
226  * containing thousands of those.
227  * This also means that we have to be very careful here, as we by-pass many 'common'
228  * processing, hence risking to 'corrupt' at least user counts, if not IDs themselves. */
229  bool keep_looping = true;
230  while (keep_looping) {
231  ID *id, *id_next;
232  ID *last_remapped_id = tagged_deleted_ids.last;
233  keep_looping = false;
234 
235  /* First tag and remove from Main all datablocks directly from target lib.
236  * Note that we go forward here, since we want to check dependencies before users
237  * (e.g. meshes before objects). Avoids to have to loop twice. */
238  for (i = 0; i < base_count; i++) {
239  ListBase *lb = lbarray[i];
240 
241  for (id = lb->first; id; id = id_next) {
242  id_next = id->next;
243  /* NOTE: in case we delete a library, we also delete all its datablocks! */
244  if ((id->tag & tag) || (ID_IS_LINKED(id) && (id->lib->id.tag & tag))) {
245  BLI_remlink(lb, id);
246  BKE_main_namemap_remove_name(bmain, id, id->name + 2);
247  BLI_addtail(&tagged_deleted_ids, id);
248  /* Do not tag as no_main now, we want to unlink it first (lower-level ID management
249  * code has some specific handling of 'no main' IDs that would be a problem in that
250  * case). */
251  id->tag |= tag;
252  keep_looping = true;
253  }
254  }
255  }
256  if (last_remapped_id == NULL) {
257  dummy_link.next = tagged_deleted_ids.first;
258  last_remapped_id = (ID *)(&dummy_link);
259  }
260  for (id = last_remapped_id->next; id; id = id->next) {
261  /* Will tag 'never NULL' users of this ID too.
262  *
263  * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
264  * links, this can lead to nasty crashing here in second, actual deleting loop.
265  * Also, this will also flag users of deleted data that cannot be unlinked
266  * (object using deleted obdata, etc.), so that they also get deleted. */
268  id,
269  NULL,
273  /* Since we removed ID from Main,
274  * we also need to unlink its own other IDs usages ourself. */
276  bmain,
277  id,
278  NULL,
279  NULL,
281  }
282  }
283 
286 
287  /* Now we can safely mark that ID as not being in Main database anymore. */
288  /* NOTE: This needs to be done in a separate loop than above, otherwise some usercounts of
289  * deleted IDs may not be properly decreased by the remappings (since `NO_MAIN` ID usercounts
290  * is never affected). */
291  for (ID *id = tagged_deleted_ids.first; id; id = id->next) {
292  id->tag |= LIB_TAG_NO_MAIN;
293  }
294  }
295  else {
296  /* First tag all datablocks directly from target lib.
297  * Note that we go forward here, since we want to check dependencies before users
298  * (e.g. meshes before objects).
299  * Avoids to have to loop twice. */
300  struct IDRemapper *remapper = BKE_id_remapper_create();
301  for (i = 0; i < base_count; i++) {
302  ListBase *lb = lbarray[i];
303  ID *id, *id_next;
304  BKE_id_remapper_clear(remapper);
305 
306  for (id = lb->first; id; id = id_next) {
307  id_next = id->next;
308  /* NOTE: in case we delete a library, we also delete all its datablocks! */
309  if ((id->tag & tag) || (ID_IS_LINKED(id) && (id->lib->id.tag & tag))) {
310  id->tag |= tag;
311  BKE_id_remapper_add(remapper, id, NULL);
312  }
313  }
314 
315  if (BKE_id_remapper_is_empty(remapper)) {
316  continue;
317  }
318 
319  /* Will tag 'never NULL' users of this ID too.
320  *
321  * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
322  * links, this can lead to nasty crashing here in second, actual deleting loop.
323  * Also, this will also flag users of deleted data that cannot be unlinked
324  * (object using deleted obdata, etc.), so that they also get deleted. */
326  remapper,
330  }
331  BKE_id_remapper_free(remapper);
332  }
333 
334  BKE_main_unlock(bmain);
335 
336  /* In usual reversed order, such that all usage of a given ID, even 'never NULL' ones,
337  * have been already cleared when we reach it
338  * (e.g. Objects being processed before meshes, they'll have already released their 'reference'
339  * over meshes when we come to freeing obdata). */
340  size_t num_datablocks_deleted = 0;
341  for (i = do_tagged_deletion ? 1 : base_count; i--;) {
342  ListBase *lb = lbarray[i];
343  ID *id, *id_next;
344 
345  for (id = do_tagged_deletion ? tagged_deleted_ids.first : lb->first; id; id = id_next) {
346  id_next = id->next;
347  if (id->tag & tag) {
348  if (((id->tag & LIB_TAG_EXTRAUSER_SET) == 0 && ID_REAL_USERS(id) != 0) ||
349  ((id->tag & LIB_TAG_EXTRAUSER_SET) != 0 && ID_REAL_USERS(id) != 1)) {
350  CLOG_ERROR(&LOG,
351  "Deleting %s which still has %d users (including %d 'extra' shallow users)\n",
352  id->name,
353  ID_REAL_USERS(id),
354  (id->tag & LIB_TAG_EXTRAUSER_SET) != 0 ? 1 : 0);
355  }
356  BKE_id_free_ex(bmain, id, free_flag, !do_tagged_deletion);
357  ++num_datablocks_deleted;
358  }
359  }
360  }
361 
362  bmain->is_memfile_undo_written = false;
363  return num_datablocks_deleted;
364 }
365 
366 void BKE_id_delete(Main *bmain, void *idv)
367 {
368  BLI_assert_msg((((ID *)idv)->tag & LIB_TAG_NO_MAIN) == 0,
369  "Cannot be used with IDs outside of Main");
370 
371  BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
372  ((ID *)idv)->tag |= LIB_TAG_DOIT;
373 
374  id_delete(bmain, false);
375 }
376 
378 {
379  return id_delete(bmain, true);
380 }
381 
382 /* -------------------------------------------------------------------- */
387 {
388 #ifdef WITH_PYTHON
389 # ifdef WITH_PYTHON_SAFETY
390  BPY_id_release(id);
391 # endif
392  if (id->py_instance) {
394  }
395 #else
396  UNUSED_VARS(id);
397 #endif
398 }
399 
void BKE_animdata_free(struct ID *id, bool do_id_user)
Definition: anim_data.c:197
void BKE_asset_metadata_free(struct AssetMetaData **asset_data)
Definition: asset.cc:35
void IDP_FreePropertyContent_ex(struct IDProperty *prop, bool do_id_user)
Definition: idprop.c:1055
const struct IDTypeInfo * BKE_idtype_get_info_from_id(const struct ID *id)
struct Key * BKE_key_from_id(struct ID *id)
Definition: key.c:1783
void BKE_layer_collection_resync_allow(void)
Definition: layer.c:766
void BKE_layer_collection_resync_forbid(void)
Definition: layer.c:761
void BKE_main_collection_sync_remap(const struct Main *bmain)
void BKE_main_id_tag_all(struct Main *mainvar, int tag, bool value)
Definition: lib_id.c:930
void id_us_min(struct ID *id)
Definition: lib_id.c:313
@ LIB_ID_FREE_NO_UI_USER
Definition: BKE_lib_id.h:256
@ LIB_ID_FREE_NOT_ALLOCATED
Definition: BKE_lib_id.h:251
@ LIB_ID_FREE_NO_DEG_TAG
Definition: BKE_lib_id.h:254
@ LIB_ID_FREE_NO_USER_REFCOUNT
Definition: BKE_lib_id.h:245
@ LIB_ID_FREE_NO_MAIN
Definition: BKE_lib_id.h:240
@ LIB_ID_FREE_NO_NAMEMAP_REMOVE
Definition: BKE_lib_id.h:258
void id_us_clear_real(struct ID *id)
Definition: lib_id.c:278
void BKE_lib_override_library_free(struct IDOverrideLibrary **override, bool do_id_user)
@ ID_REMAP_SKIP_USER_CLEAR
Definition: BKE_lib_remap.h:63
@ ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS
Definition: BKE_lib_remap.h:70
@ ID_REMAP_FLAG_NEVER_NULL_USAGE
Definition: BKE_lib_remap.h:50
@ ID_REMAP_FORCE_NEVER_NULL_USAGE
Definition: BKE_lib_remap.h:57
void BKE_libblock_remap_multiple_locked(struct Main *bmain, struct IDRemapper *mappings, short remap_flags)
Definition: lib_remap.c:614
void BKE_id_remapper_add(struct IDRemapper *id_remapper, struct ID *old_id, struct ID *new_id)
void BKE_id_remapper_clear(struct IDRemapper *id_remapper)
void void void BKE_libblock_unlink(struct Main *bmain, void *idv, bool do_flag_never_null, bool do_skip_indirect) ATTR_NONNULL()
Definition: lib_remap.c:670
void BKE_libblock_remap_locked(struct Main *bmain, void *old_idv, void *new_idv, short remap_flags) ATTR_NONNULL(1
void BKE_libblock_relink_ex(struct Main *bmain, void *idv, void *old_idv, void *new_idv, short remap_flags) ATTR_NONNULL(1
bool BKE_id_remapper_is_empty(const struct IDRemapper *id_remapper)
struct IDRemapper * BKE_id_remapper_create(void)
void BKE_id_remapper_free(struct IDRemapper *id_remapper)
int set_listbasepointers(struct Main *main, struct ListBase *lb[])
Definition: main.c:654
void BKE_main_unlock(struct Main *bmain)
Definition: main.c:219
void BKE_main_lock(struct Main *bmain)
Definition: main.c:214
struct ListBase * which_libbase(struct Main *bmain, short type)
Definition: main.c:567
void BKE_main_namemap_remove_name(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL()
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
#define UNUSED_VARS(...)
#define UNUSED(x)
void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr)
void BPY_id_release(struct ID *id)
Definition: bpy_rna.c:287
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
void DEG_id_type_tag(struct Main *bmain, short id_type)
ID and Library types, which are fundamental for sdna.
@ INDEX_ID_MAX
Definition: DNA_ID.h:1058
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
@ LIB_TAG_EXTRAUSER_SET
Definition: DNA_ID.h:700
@ LIB_TAG_NO_USER_REFCOUNT
Definition: DNA_ID.h:745
@ LIB_TAG_NOT_ALLOCATED
Definition: DNA_ID.h:748
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
@ LIB_TAG_NO_MAIN
Definition: DNA_ID.h:744
#define ID_REAL_USERS(id)
Definition: DNA_ID.h:553
@ ID_OB
Definition: DNA_ID_enums.h:47
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
#define GS(x)
Definition: iris.c:225
static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
Definition: lib_id_delete.c:68
size_t BKE_id_multi_tagged_delete(Main *bmain)
void BKE_libblock_free_data_py(ID *id)
void BKE_id_free(Main *bmain, void *idv)
void BKE_libblock_free_data(ID *id, const bool do_id_user)
Definition: lib_id_delete.c:44
void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_idtag)
Definition: lib_id_delete.c:82
void BKE_id_free_us(Main *bmain, void *idv)
static CLG_LogRef LOG
Definition: lib_id_delete.c:42
void BKE_id_delete(Main *bmain, void *idv)
BKE_library_remap_editor_id_reference_cb remap_editor_id_reference_cb
Definition: lib_remap.c:46
BKE_library_free_notifier_reference_cb free_notifier_reference_cb
Definition: lib_remap.c:39
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
const char * identifier
Definition: CLG_log.h:105
IDTypeFreeDataFunction free_data
Definition: BKE_idtype.h:162
Definition: DNA_ID.h:368
void * py_instance
Definition: DNA_ID.h:435
int tag
Definition: DNA_ID.h:387
struct AssetMetaData * asset_data
Definition: DNA_ID.h:375
struct Library * lib
Definition: DNA_ID.h:372
int us
Definition: DNA_ID.h:388
IDProperty * properties
Definition: DNA_ID.h:409
IDOverrideLibrary * override_library
Definition: DNA_ID.h:412
void * next
Definition: DNA_ID.h:369
char name[66]
Definition: DNA_ID.h:378
struct LibraryWeakReference * library_weak_reference
Definition: DNA_ID.h:443
ID id
Definition: DNA_key_types.h:63
ID id
Definition: DNA_ID.h:458
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
char is_locked_for_linking
Definition: BKE_main.h:156
char is_memfile_undo_written
Definition: BKE_main.h:140