CakeFest 2024: The Official CakePHP Conference

Memcached::cas

(PECL memcached >= 0.1.0)

Memcached::casCompare et échange un élément

Description

public Memcached::cas(
    string|int|float $cas_token,
    string $key,
    mixed $value,
    int $expiration = 0
): bool

Memcached::cas() effectue une opération de "check and set" (littéralement, vérifie et assigne), de manière que l'élément ne soit stocké que si aucune autre client ne l'a mise à jour depuis qu'il a été lu par le client courant. La vérification est faîte via le paramètre cas_token qui est une valeur 64 bits unique, assignée à l'élément par memcached. Voir la documentation de Memcached::get*() pour savoir comment obtenir cette valeur. Notez que cette valeur est représentée par un nombre flottant, à cause de limitations dans l'espace des entiers de PHP.

Liste de paramètres

cas_token

Valeur unique associée à un élément existant. Généré par memcached.

key

La clé avec laquelle stocker la valeur.

value

La valeur à stocker.

expiration

Le délai d'expiration, par défaut à zéro. Voyez délais d'expiration pour plus d'informations.

Valeurs de retour

Cette fonction retourne true en cas de succès ou false si une erreur survient. La méthode Memcached::getResultCode() va retourner la constante Memcached::RES_DATA_EXISTS si l'élément que vous essayez de stocker a été modifié depuis votre dernière lecture.

Exemples

Exemple #1 Exemple avec Memcached::cas()

<?php
$m
= new Memcached();
$m->addServer('localhost', 11211);

do {
/* Lit une IP et son CAS */
$ips = $m->get('ip_block', null, $cas);
/* Si l'IP n'existe pas encore, on la crèe et on fait un
ajout atomique qui va échouer si l'IP a déjà été ajoutée */
if ($m->getResultCode() == Memcached::RES_NOTFOUND) {
$ips = array($_SERVER['REMOTE_ADDR']);
$m->add('ip_block', $ips);
/* Sinon, on ajoute l'IP à la liste, et on la stocke avec l'opération
compare-and-swap et le token, qui va échouer si la liste a été mise à jour */
} else {
$ips[] = $_SERVER['REMOTE_ADDR'];
$m->cas($cas, 'ip_block', $ips);
}
} while (
$m->getResultCode() != Memcached::RES_SUCCESS);

?>

Voir aussi

add a note

User Contributed Notes 4 notes

up
2
abodera at gmail dot com
13 years ago
Watch out!

When using binary protocol, the expected result after cas() is 21 (Memcached::RES_END).

For example, to make the above example #1 work with binary protocol, use the following:
<?php
$m
= new Memcached();
$m->addServer('localhost', 11211);
$m->setOption(Memcached::OPT_BINARY_PROTOCOL,true)

// [...]

} else {
$ips[] = $_SERVER['REMOTE_ADDR'];
$m->cas($cas, 'ip_block', $ips);
}
} while (
$m->getResultCode() != Memcached::RES_END);
?>
up
2
sparcbr at gmail dot com
7 years ago
Do not check command success in a while loop with something like


$memCached->getResultCode() != Memcached::RES_SUCCESS

Memcached::RES_SERVER_ERROR or anything like this and your script will loop forev
up
1
Haravikk
6 years ago
I'm not sure whether this remains true in the newer versions of the Memcached module (v3.0 onwards) but in the version shipped with PHP 5.6 the return value and result code when using this method with OPT_BINARY_PROTOCOL enabled are entirely useless.

Setting a value successful may return true, with a result code of RES_END, but it may also return true with a result code of RES_SUCCESS.

However, *unsuccessfully* setting a value likewise seems to return true and RES_SUCCESS, effectively rendering this function's return value useless with the binary protocol enabled as it is impossible to distinguish success from failure.

If you need to rely on the return value of this method then I strongly recommend disabling the binary protocol under PHP 5.6, as in its current state the common memcached module is too broken otherwise for CAS usage.

Hopefully someone else can weigh in on whether this is still broken in newer versions or not.
up
1
php at sergentet dot fr
6 years ago
To prevent a perpetual loop on any Memcached error, you can add a simple counter :

$security_count = 0;

do {
//[]....
$security_loop++
if ($security_loop > 10) {
break; //( or return "your return value" on a function )
}
} while ($m->getResultCode() != Memcached::RES_SUCCESS);
To Top