Rebuild Permissions process not completing correctly

LynnS - May 23, 2009 - 18:55
Project:Drupal
Version:6.14
Component:base system
Category:bug report
Priority:normal
Assigned:Unassigned
Status:needs review
Description

On trying to use any kind of node permissions module (the main case: forum_access), when I went to rebuild node permissions from the accepted ~/admin/content/node-settings/rebuild the status bar would complete to 100% and I would get the following error message:

The content access permissions could not be rebuilt.
The content access permissions need to be rebuilt.

That was on two of three sites in a multisite installation. The third would get to 97% and stall.

The only solution, after much consultation with Marco at Advomatic, was to put this in a node and click "Preview":

<?php
set_time_limit
(0);
db_query("DELETE FROM {node_access}");
node_access_rebuild();
?>

That makes the error go away. Marco suspects an issue with the batch function.

#1

DamienMcKenna - November 8, 2009 - 20:49
Title:Batch failing on node permissions update» Rebuild Permissions process not completing correctly
Version:6.12» 6.14
Status:active» needs review

I ran into this using og_access.module on a site migrated from D5 that has ~90,000 nodes. For completeness sake, here are the steps I've performed so far:

  • Disable all contrib modules.
  • Backed up the database.
  • Switch to D6 branch in working copy.
  • Move all modules out of sites/all/modules.
  • Update.php - 62 updates.
  • Backed up the database.
  • Moved back cck & enable all modules. Ran all updates.
  • Moved back filefield & enabled it. No applicable updates.
  • Moved back imagefield & enabled it. Ran all updates.
  • Moved back link & enabled it. Ran all updates.
  • Moved back date & enabled it. Ran all updates. Had to run updates again to catch them all.
  • Moved back token & enabled it. No applicable updates.
  • Moved back imageapi & enabled it. No applicable updates.
  • Moved back imagecache & enabled it. Ran all updates.
  • Moved back javascript_aggregator & enabled it. Ran all updates.
  • Moved back og & enabled it. Ran all updates.
  • Rebuilt permissions. After completing it said "The content access permissions have not been properly rebuilt.".
  • Disabled OG. Rebuilt permissions.
  • Enabled OG. Rebuilt permissions

Each time I perform the Rebuild Permissions step it fails with the above error. I did a dump of the corresponding {batch} table record when it got to the 'finished' callback and it said the following:

Array
(
    [sets] => Array
        (
            [0] => Array
                (
                    [sandbox] => Array
                        (
                            [progress] => 96600
                            [current_node] => 4605
                            [max] => 96553
                        )
                    [results] => Array
                        (
                        )
                    [success] =>
                    [title] => Rebuilding content access permissions
                    [operations] => Array
                        (
                            [0] => Array
                                (
                                    [0] => _node_access_rebuild_batch_operation
                                    [1] => Array
                                        (
                                        )
                                )
                        )
                    [finished] => _node_access_rebuild_batch_finished
                    [init_message] => Initializing.
                    [progress_message] => Remaining @remaining of @total.
                    [error_message] => An error has occurred.
                    [total] => 1
                )
        )
// and more with the form details..

Tracing through the code I found that _node_access_rebuild_batch_operation() was doing all of the work of managing the batch process, which contains the following:

<?php
  $result
= db_query_range("SELECT nid FROM {node} WHERE nid > %d ORDER BY nid ASC", $context['sandbox']['current_node'], 0, $limit);
  while (
$row = db_fetch_array($result)) {
   
$loaded_node = node_load($row['nid'], NULL, TRUE);
   
// To preserve database integrity, only aquire grants if the node
    // loads successfully.
   
if (!empty($loaded_node)) {
     
node_access_acquire_grants($loaded_node);
    }
   
$context['sandbox']['progress']++;
   
$context['sandbox']['current_node'] = $loaded_node->nid;
  }
?>

The part that seemed confusing to me was the following line:

<?php
    $context
['sandbox']['current_node'] = $loaded_node->nid;
?>

I figured that there could be circumstances when the $loaded_node would fail on the last node load of a particular loop thus storing an empty value in $current_node for the next loop. On the next loop the database abstraction layer takes this NULL value and the query above, performs a type casting on the NULL to make it an integer, resulting in the following query:

SELECT nid FROM {node} WHERE nid > 0 ORDER BY nid ASC

This could then cause the whole batch process to start over.

In my case it always ran to completion and returned the error above.

What I did to fix it was changed the current_node assignment to just use the nid value from the row itself, i.e.:

<?php
    $context
['sandbox']['current_node'] = $row['nid'];
?>

That allowed it to successfully complete the task.

AttachmentSizeStatusTest resultOperations
drupal-n471080.patch1.17 KBIgnoredNoneNone
 
 

Drupal is a registered trademark of Dries Buytaert.