If a node has revisions associated with it, and is deleted, the file reference (in the file_usage table) will remain, even after the node is deleted.

Since the record in the file_usage table still exists, any module that uses hooks from the file module (or filefield module - see https://www.drupal.org/node/1191438), such as the media module (see https://www.drupal.org/node/911830) will be unable to delete files, per the lock on those files in the file_usage table.

I believe that the is an issue with the revisions system, which seams to be working as designed, but has at least one bug and functions, in some ways, counter-intuitively even when working correctly.

IF a node has revisions, any files associated with it will be locked, even if the file changes in future revisions - this is, I believe, the intended behavior. However, If that node is deletion, the file_usage table is only updated with the current revisions, and old revisions, which no longer exist, as the node was deleted, still keep the file locked.

The solution is to add the removal of the file_usage directly in node.module itself - lots of people are trying to get around this and making it much more complicated than it should be, when all that is necessary is the following (in /modules/node.module, in the function node_delete_multiple()):

db_delete('file_usage')
       ->condition('id', $nids, 'IN')
       ->execute();

The following is SQL code that cleans up orphaned references in the file_usage table (Remove all records associated with nodes that no longer exist):

DELETE from file_usage WHERE fid IN (select fid from (select fu.fid as fid from file_usage fu LEFT JOIN node n ON n.nid = fu.id WHERE n.nid IS NULL) as tt);
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

joshua.albert’s picture

Status: Needs review » Closed (duplicate)
Related issues: +#2310893: file_usage not cleared when deleting node!
joshua.albert’s picture

Status: Closed (duplicate) » Needs work

The last submitted patch, add_file_usage_deletion_to_node_deletion.patch, failed testing.

joshua.albert’s picture

Manually removed directory in patch.

cilefen’s picture

Version: 7.34 » 7.x-dev
Status: Needs work » Needs review

There is a patch, so it "needs review".

jastraat’s picture

Note that the SQL you provided should be modified - otherwise you'll also be deleting all entries for files not associated with nodes. (Like IMCE). You want to add a condition where fu.type = 'node'.

David_Rothstein’s picture

Title: File usage records not removed on node deletion » File usage records for files referenced in older node revisions are not removed on node deletion
Status: Needs review » Postponed
Parent issue: » #1239558: Deleting an entity with revisions and file/image field does not release file usage of non-default revisions, causing files to linger

Adding the Drupal 8 issue as a parent issue and marking this postponed on that.

azinck’s picture

Status: Postponed » Needs review
FileSize
1.1 KB

I would like to propose we un-postpone this. The D8 patch appears to be taking the approach of actually properly deleting all the individual revisions. I am not sure why D7 was not architected in that way, but it wasn't. Revision field and other data is deleted directly from the db, outside the revision deletion API, and I don't think we should change that at this point in the D7 project lifecycle.

For D7, I'm taking the approach here of doing this in file_field_delete() and limiting our cleanup to file_usage records from the file module. If there are other modules recording file_usage for entities I think they need to implement delete hooks of their own and manage their own file usage.

Putting this code in file_field_delete() ensures that the file_usage cleanup happens for *any* revisionable entities, not merely nodes.

An alternative would be to say that any file_usage record with entity and ID values matching the entity being deleted should get cleaned up (a solution like that suggested by the OP here) but I'm not sure we should take that much liberty. Perhaps there are other modules using the file_usage table in unexpected ways and I don't want to trample on their behavior. Let's just make sure the file module handles this correctly for its own file_usage records.

Lastly: should we write an update hook that cleans up file_usage records that belong to now-deleted entities? I'm leaning towards yes, but I'm also wary of anything that might cause files to be deleted "unexpectedly" for folks, no matter that those files *should* have already been cleaned up long ago.