I'm actually trying to understand why memcached is not storing data for a give Id.
I'm using Magento EE 1.11.2.0 that is based on Zend Framework 1.11.1.
The interface used to deal with memcached is Zend_Cache_Backend_Memcached
Now there is not such big custom code here, this is my custom container that save the cache:
public function saveCache($blockContent)
{
$lifeTime = 86400 * 30 * 6;
$tags = array(
My_Module_Model_PageCache_Container_Category_Blabla::CACHE_TAG
);
$cacheId = $this->_getCacheId();
if ($cacheId !== false) {
$this->_saveCache($blockContent, $cacheId, $tags, $lifeTime);
}
return $this;
}
I'm just forcing magento to use my custom cache tag and a fixed lifetime ( memcache doens't support custom tag so I guess this is not the problem ) also my lifetime is not used in memcached because I can see that the default one is used.
At the beginning I thought the issue was caused by a to long cache ID but now after reducing it ( <31 char ) this didn't help me:
I can see that the load() method Zend_Cache_Backend_Memcached return always false for my cache ids.
While the save() method return true like if it was cached.
This is my local.xml configuration:
<cache>
<slow_backend_store_data>1</slow_backend_store_data>
<auto_refresh_fast_cache>0</auto_refresh_fast_cache>
<backend>memcached</backend>
<slow_backend>database</slow_backend>
<memcached>
<servers>
<!--<server>-->
<!--<host><![CDATA[127.0.0.1]]></host>-->
<!--<port><![CDATA[11213]]></port>-->
<!--<persistent><![CDATA[1]]></persistent>-->
<!--</server>-->
<server>
<host><![CDATA[unix:///tmp/memcached.sock]]></host>
<port><![CDATA[0]]></port>
<persistent><![CDATA[0]]></persistent>
<weight><![CDATA[2]]></weight>
<timeout><![CDATA[5]]></timeout>
</server>
</servers>
<compression><![CDATA[0]]></compression>
<hashed_directory_level><![CDATA[]]></hashed_directory_level>
<hashed_directory_umask><![CDATA[]]></hashed_directory_umask>
<file_name_prefix><![CDATA[]]></file_name_prefix>
</memcached>
</cache>
<full_page_cache>
<backend>memcached</backend>
<slow_backend>database</slow_backend>
<slow_backend_store_data><![CDATA[1]]></slow_backend_store_data>
<memcached>
<servers>
<server>
<host><![CDATA[unix:///tmp/memcached.sock]]></host>
<port><![CDATA[0]]></port>
<persistent><![CDATA[0]]></persistent>
<weight><![CDATA[2]]></weight>
<timeout><![CDATA[10]]></timeout>
<retry_interval><![CDATA[10]]></retry_interval>
<status><![CDATA[1]]></status>
<stats_update_factor><![CDATA[1]]></stats_update_factor>
</server>
</servers>
</memcached>
</full_page_cache>
I also tried to check the entry of memcached to see if my id was stored or not with this command:
echo 'stats cachedump 35 35' | sudo nc -U /tmp/memcached.sock
Any idea about the reason of this ?
How can I debug it ? ( I cannot go under Zend_Cache_Backend_Memcached with xdebug)
You can restart memcached with -vv and look at the interactions.
BTW, the default port for memcache is 11211. FYI
here the issue is $lifetime and a relative bug in Zend_Cache_Backend_Memcached.
Memcached has a max lifetime of 30 days (2592000) so the limit I was using it was too big and that is why the data was not stored.
Sadly:
Zend_Cache_Backend_Memcached::save()
doesn't check if the limit is correct < 2592000
the set() method on the memcached object return true even if it doesn't store the data
$result = #$this->_memcache->set($id, array($data, time(), $lifetime), $flag, $lifetime);
Related
I've been trying to figure out a way to validate DNS records in PHP (oa1) but have come up short.
I can validate a whole domain with this library, but not the individual records: https://github.com/metaregistrar/php-dnssec-validator
In addition, that library only allows for a very small set of TLDs to be validated.
Is there another library out there that can handle this for me, or perhaps something else I should look into?
I've also found this: http://www.phpclasses.org/package/9031-PHP-Validate-DNSSEC-keys-and-calculate-the-DS-record.html
But I have no idea how to get the keys to use in their validating function.
Help please!
UPDATE
So, I ended up using this...
exec('host -t RRSIG ' . $domain, $output);
Returns the RRSIG, or lack thereof, with minimal hassle.
The PHP engine has a fixed set of DNS record types it supports, all defined by the type parameter to dns_get_record. You can double check this list by looking in the engine code that implements DNS queries.
Unfortunately, none of the DNSSEC records are in that pre-defined list. So, you need to rely on a library or an external tool.
I'd use Net_DNS2, as it supports many DNSSEC RR. Example:
$google = new \Net_DNS2_Resolver(['nameservers' => ['8.8.8.8', '8.8.4.4']]);
$google->dnssec = true;
try {
$result = $google->query('kyhwana.org', 'SSHFP');
} catch(\Net_DNS2_Exception $ex) {
die($ex->getMessage());
}
foreach ($result->answer as $answer) {
if ($answer instanceof \Net_DNS2_RR_SSHFP) {
printf(
'%s %d %s %s %d %d %s' . PHP_EOL,
$answer->name,
$answer->ttl,
$answer->class,
$answer->type,
$answer->algorithm,
$answer->fp_type,
$answer->fingerprint
);
} else if ($answer instanceof \Net_DNS2_RR_RRSIG) {
printf('Signed by %s: %s' . PHP_EOL, $answer->signname, $answer->signature);
}
}
Aside: if your domain uses ECDSA algorithm or the SHA-256 fingerprint (like the example above), then you need the latest Net_DNS2 code which fixes Issue #39.
I haven't implemented the code yet but it looks to me like using php to verify the signatures themselves is a mistake. Use a local recursive resolver like unbound on the local server that enforces DNSSEC.
Then in php with the PEAR module Net_DNS2 look for an RRSIG record for the domain of interest. The result should tell you the zone responsible for that record.
Look for a DNSKEY record in that zone. If present, then look for a DS record.
The DS record will come from the parent zone (e.g. .email for deviant.email) and if present indicates DNSSEC is present for the zone.
If DNSSEC is present for the zone, then all the results for the zone are valid if your local recursive nameserver enforces DNSSEC.
I believe with Net_DNS2 that using
r = new Net_DNS2_Resolver(array('nameservers' => array('127.0.0,1')));
r->dnssec = true;
will also result in Net_DNS2 also validating the results if DNSSEC is active - which is indicated by the DS record that comes from the parent zone. But using a recursive resolver (preferably on the webserver) that enforces DNSSEC is probably safest.
Make sure the recursive resolver isn't listening on public interfaces so it doesn't get used in reflective amplification attacks.
Having the same goal (validate DNSSEC in PHP), i ended up with:
exec("drill -k root.keys -TDQ $domain SOA | grep -v '^;;'", $output);
This is doing a complete topdown DNSSEC validation.
You need root keys you can retrieve with:
unbound-anchor # NB: on FreeBSD, use local-unbound-anchor for "base" version
Or "manually":
dig . dnskey > root.keys
To confirm that the record is fully DNSSEC validated, check the last line of exec output:
[S] self sig OK This is not satisfying, probably zone key has not been populated in parent zone
[B] bogus
[T] trusted This means that everything is OK!
Following is the configuration Code for my DB cache in Yii
'dbcache'=>array(
'class'=>'system.db.CDbConnection',
'connectionString'=>'sqlite:/' . str_replace('\\','/',str_replace('C:\\','',getcwd()).'/protected/data/cache.db'),
),
And the following is my code for getting the record set and setting in the cache:
$recordset = Table1::model ()->cache(0)->find ( "primary_id=:id", array (":id" => $id) );
I have used 0 for the cache duration because I need to make it for infinite period.
Now I need to refresh my Cache. on some condition. How can I refresh the query Cache in Yii if its duration is infinite. Please help :)
First of all, setting the value as 0 doesn't mean that you are setting for Infinite Period. It does mean that you have simply Disabled the cache.
Refer the Code: Class Reference - CActiveRecord
If you want to refresh the Schema Cache, use the code as Yii::app()->schema->refresh()
I'm having a problem with the session variables in my web app.
The thing is that I set it with the following code and check if it exists and only if not then I update it.
The idea is to know if the user is enterprise or not for his session.
I use the following code:
$logo_class = "logo";
if(!Yii::app()->user->isGuest) {
define("ENT_LIM_PROD_COUNT", 10000);
$user_id = Stores::model()->findByPk(Products::model()->getStoreID())->user_id;
if(array_key_exists('is_enterprise', Yii::app()->session)) {
if(Yii::app()->session['is_enterprise'] === true)
$logo_class = "logo_ent";
} else {
$total_prod = LicenseMngr::getFeatureAllocTotal($user_id, LicenseMngr::FEATURE_PRODUCTS);
Yii::app()->session['is_enterprise'] = ($total_prod > ENT_LIM_PROD_COUNT ? true : false);
if(Yii::app()->session['is_enterprise'] === true)
$logo_class = "logo_ent";
}
}
I have tried using different types of sessions in my config file and now it's:
'session'=>array(
'autoStart' => true,
'sessionName' => 'session',
'timeout' => 30758400
),
Now, the problem is that every time I refresh the page the index "is_enterprise" is not in the session array as if it was never set.
I have tried changing the session save directory to /var/tmp.
I'm running:
Darwin niflheim 12.3.0 Darwin Kernel Version 12.3.0: Sun Jan 6 22:37:10 PST 2013; root:xnu-2050.22.13~1/RELEASE_X86_64 x86_64
PHP Version 5.4.15 (web)
The following line does a rest call to a server to get information we need (It's probably the only thing that isn't related to YII here):
$total_prod = LicenseMngr::getFeatureAllocTotal($user_id, LicenseMngr::FEATURE_PRODUCTS);
P.S: This is not the only custom variable that it happens with, I hope that helps.
OK So after a while we were able to solve the problem... Apparently the session variable in YII is not an array but an object and you can access it as an array so array_key_exists didn't work.
Changing it to isset solved the problem.
In Subversion 1.6, there was an .svn directory in every working copy directory. I could use the following code to quickly retrive the current revision number without the need for shell access/execution.
public function getSubversionRevision() {
if(file_exists("../.svn/entries")) {
$svn = File("../.svn/entries");
return (int)$svn[3];
}
return false;
}
Subversion 1.7 breaks this code. There is now only one .svn directory per local repository. There is an entries file in this directory but it no longer has anything useful for me. It looks like everything I need is now in a SQLite database. Specifically wc.db. I suppose I could use PHP's SQLite functions to get the info I need, but this sounds a little too expensive to run on every (or close to every) page load.
Any ideas? Breaking out the exec function and hoping that Subversion binaries are installed (and in the $PATH!) is a last resort. To summarize, I need to find a way to locate the .svn directory at the root of the repository (which could be different depending on your checkout location) and then somehow parse a file in there (probably wc.db) in a cost-effective way.
try using a SVN library SVN as it will give you access to repository information and more functionality over SVN repository.
Take a look at function svn_status you will receive and array of svn repository information
Array (
[0] => Array (
[path] => /home/bob/wc/sandwich.txt
[text_status] => 8 // item was modified
[repos_text_status] => 1 // no information available, use update
[prop_status] => 3 // no changes
[repos_prop_status] => 1 // no information available, use update
[name] => sandwich.txt
[url] => http://www.example.com/svnroot/deli/trunk/sandwich.txt
[repos] => http://www.example.com/svnroot/
[revision] => 123 // <-- Current Revision
//..
)
)
You can write a script to svn update for you every time, and scrap the revision number from the update's output into a file. The following bash script should more or less do it:
#!/bin/bash
svn --non-interactive update ..
svn --non-interactive update .. | perl -p -e "s/.* revision ([\d]*)\./\$1/" > ../version.phtml;
I implemented a clumsy (but relatively thorough) implementation of Subversion 1.7 revision retrieval in TheHostingTool. Check the commit message for an explanation. The function is contained in class_main.php which is one directory after /trunk (/trunk/includes/class_main.php). You'll need to adjust relative paths for your specific needs. This is a slightly modified version of the function found in class_main.php for use elsewhere.
public function getSubversionRevision() {
// This will work for Subverson 1.6 clients and below
if(file_exists("../.svn/entries")) {
$svn = File("../.svn/entries");
return (int)$svn[3];
}
// Check the previous directories recursively looking for wc.db (Subversion 1.7)
$searchDepth = 3; // Max search depth
// Do we have PDO? And do we have the SQLite PDO driver?
if(!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) {
$searchDepth = 0; // Don't even bother...
}
for($i = 1; $i <= $searchDepth; $i++) {
$dotdot .= '../';
if(!file_exists("$dotdot.svn/wc.db")) {
continue;
}
$wcdb = new PDO("sqlite:$dotdot.svn/wc.db");
$result = $wcdb->query('SELECT "revision" FROM "NODES" WHERE "repos_path" = "'.basename(realpath('..')).'"');
return (int)$result->fetchColumn();
}
if($this->canRun('exec')) {
exec('svnversion ' . realpath('..'), $out, $return);
// For this to work, svnversion must be in your PHP's PATH enviroment variable
if($return === 0 && $out[0] != "Unversioned directory") {
return (int)$out[0];
}
}
return false;
}
Instead of .= '../' you may want to use str_repeat if you don't start at 1. Or, you could simply define $dotdot ahead of time to wherever you would like to start.
Or just query:
SELECT "changed_revision" FROM "NODES" ORDER BY changed_revision DESC LIMIT 1;
if you wonder the last revision of the whole repo! :)
Excuse me, but if you want portable and bullet-proof solution, why not call Subversion CLI inside PHP?
You can use svn info inside any directory of WC (capture, parse output and get a set of data) of svnversion if you want to get only global revision
Hey all, here are the version of my current setup
Memcached (1.2.2)
Pecl Memcached Client 1.0.2 (using libmemcached 0.43)
Issue: I cant get a cas token returned during a get request
Here is the code in question!
27 public function action_test() {
28 //phpinfo();
29 $m = Model_Mem::getSingleton();
30 $found = $m->get('navigation');
31 echo (int)count($found).'<br />'; // Returns an array of navigation objects
32
33 $cas = 0;
34 $found = $m->get('navigation', null, &$cas);
35 echo (int)count($found); // Returns nothing!
36
37 exit;
38 }
The output from the first echo is 7, and the second echo is 1. Also, the $cas variable as well as the $found variable from the second group of code are both empty. Im not 100% sure if I am doing this right but the cas token just doesnt seem to be working for me at all. Ive went through the php Memcached documentation with no mention on any kind of CAS enable flag that i could easily spot. Ive also tried to look at the memcached.org site for some info but im lost!
Ive never had any problems with it, its just everytime i try and use the cas functionality on a get request i do something wrong. Thanks for anyone helping me out!
*EDIT
Here is what the Model_Mem::getSingleton() function returns
static function getSingleton() {
if (self::$m)
return self::$m;
self::$m = new Memcached();
$servers = array(
array('127.0.0.1', 11211, 25),
array('127.0.0.1', 11212, 25),
array('127.0.0.1', 11213, 25),
array('127.0.0.1', 11214, 25)
);
// Sets up some options for the memcache server
self::$m->setOption(Memcached::OPT_DISTRIBUTION,Memcached::DISTRIBUTION_CONSISTENT);
self::$m->setOption(Memcached::OPT_PREFIX_KEY, Kohana::config('globals.prefix'));
self::$m->addServers($servers);
return self::$m;
}
Arg, debian's latest [secure] memcached release didn't have this feature yet. Upgraded to the latest by installing the memcached server's source and all is well.
Just FYI, CAS means "compare-and-swap": https://en.wikipedia.org/wiki/Compare-and-swap