mrkskwsnck
mrkskwsnck

Reputation: 357

APCu: Cannot call key() on invalid iterator

I'm working on an older version of ILIAS 5.4 in an DDEV (Docker) development environment. It is a Learning Management System written in PHP. The runtime environment consists of:

Currently I stumbled over an error regarding the APCUIterator which I don't know how to handle. Regarding the while-clause, where the key()-method is being called on the iterator

    /**
     * @param bool $complete
     *
     * @return bool
     */
    public function flush($complete = false)
    {
        if ($complete) {
            return apcu_clear_cache();
        }

        $key_prefix = $this->returnKey('');
        $apcu_iterator = new APCUIterator();
        $apcu_iterator->rewind();
        while ($current_key = $apcu_iterator->key()) {
            // "begins with"
            if (substr($current_key, 0, strlen($key_prefix)) === $key_prefix) {
                $this->delete($current_key);
            }
            $apcu_iterator->next();
        }
        return true;
    }

the error message says: Cannot call key() on invalid iterator—Inside the container I can reproduce the error with the following extracted snippet

<?php
$iterator = new APCUIterator();
$iterator->key();
# Nothing else matters

and the resulting error renders like the following screenshot in the browser

enter image description here

My best guess is that there is something missing inside the container. Either a dependency or a configuration. Any suggestions?

EDIT: Here follows the APC configuration related ddev php -i | grep -i apc output.

/etc/php/7.3/cli/conf.d/20-apcu.ini,
/etc/php/7.3/cli/conf.d/25-apcu_bc.ini,
/etc/php/7.3/cli/conf.d/enableapcu.ini,
apc
APC Compatibility => 1.0.5
apcu
APCu Support => Enabled
APCu Debugging => Disabled
apc.coredump_unmap => Off => Off
apc.enable_cli => On => On
apc.enabled => On => On
apc.entries_hint => 4096 => 4096
apc.gc_ttl => 3600 => 3600
apc.mmap_file_mask => no value => no value
apc.preload_path => no value => no value
apc.serializer => php => php
apc.shm_segments => 1 => 1
apc.shm_size => 32M => 32M
apc.slam_defense => Off => Off
apc.smart => 0 => 0
apc.ttl => 0 => 0
apc.use_request_time => Off => Off
igbinary APCu serializer ABI => 0

EDIT 2: Here follows the APC configuration related php -i | grep -i apc output from the native staging system (not Docker) based on Debian with Apache web server.

/etc/php/7.3/cli/conf.d/20-apcu.ini,
apcu
APCu Support => Disabled
APCu Debugging => Disabled
apc.coredump_unmap => Off => Off
apc.enable_cli => Off => Off
apc.enabled => On => On
apc.entries_hint => 4096 => 4096
apc.gc_ttl => 3600 => 3600
apc.mmap_file_mask => no value => no value
apc.preload_path => no value => no value
apc.serializer => php => php
apc.shm_segments => 1 => 1
apc.shm_size => 32M => 32M
apc.slam_defense => Off => Off
apc.smart => 0 => 0
apc.ttl => 0 => 0
apc.use_request_time => On => On

Upvotes: 1

Views: 225

Answers (1)

Yvan
Yvan

Reputation: 2699

Hit the same issue on $apcu->current().

One way to avoid this is to try $apcu->valid(), which should return true:

$apcu_iterator = new APCUIterator();
if ($apcu_iterator->valid()) {
 // do stuff on iterator
}

It seems that when the iterator didn't found any valid key (either there's nothing stored, or you filtered it and no key matches), it returns an invalid iterator:

$apc = new APCUIterator();
var_dump($apc->getTotalCount());
var_dump($apc->valid());

With keys:

int(5)
bool(true)

Without valid keys:

int(0)
bool(false)

So you can use either ->valid() or check ->getTotalCount() before using the iterator.

Upvotes: 0

Related Questions