Support for the usercache in Microsoft's WinCache extension (1.1+ only). Based on the APC class, but altered to use the old locking method due to #588820: Creating severe load on system by logging thousands of unlink errors in DB log.

From the Zend issue in the queue it sounds like inclusion of new caching engines will be postponed until 2.x so I'm just including the file to be placed in the engines directory for now. When 2.x is available this can be rolled as a patch.

Comments

Canadaka’s picture

Category: feature » bug
Priority: Normal » Minor

I am testing this out, I have it working on a development site I soon hope to make live.
I am having one minor problem possibly, I'm getting a lot of errors in my PHP log about line 208.

[02-Apr-2010 13:44:10] PHP Fatal error: Maximum execution time of 240 seconds exceeded in #### on line 208

Is this anything to be concerned about?

I am running:
Windows 2008 IIS7 x86
PHP 5.2.13
Wincache 1.1 Beta
Drupal 6.16
Cacherouter 6.x-1.x-dev

tauno’s picture

Category: bug » feature
Priority: Minor » Normal

Need a little more info to know if this is related to cacherouter/wincache. What's the #### file?

andypost’s picture

Status: Needs review » Needs work
Issue tags: +Needs documentation

a piece of docs for readme file is needed mostly about pointing to help pages

Canadaka’s picture

sorry i should have specified, I assumed people would think I was talking about the wincache.php file attached to this thread.

Canadaka’s picture

I am also getting this error from time to time. and Twice have had this error fill up the page with hundreds of repeats.

warning: wincache_ucache_add() [function.wincache-ucache-add]: function called with a key which already exists in \sites\all\modules\contrib\cacherouter\engines\wincache.php on line 205.

Both this and the previous error are related to the function lock()

My site will run fine for awhile then grind to a halt, when this happens and i manage to get a pageload in, I see hundreds and hundresds of the above error. I've attached 2 screenshots of the "database logging" and a detail. Something odd to note, I clicked on the details for about 10 entries randomly, they all have "?fbc_channel=1" in the location

http://i355.photobucket.com/albums/r469/canadaka_bucket/wincache_ucache_...
http://i355.photobucket.com/albums/r469/canadaka_bucket/wincache_fbconne...

So could it be some incompatability with the fbconnect module? if so why does it run fine for a period then die.

andypost’s picture

There was idea to implement native locking functyionality in wincache because php under windows does not heve support for semaphores and shm

EDIT: as ugly solution I recommend to use @wincache_add() to suppess errors

tauno’s picture

I don't think the duplicate key error is specifically due to the fbconnect module. I've seen the errors pop up once on my site in the few weeks I've been running this code. As andypost mentioned it has to with the locking method and you can suppress the errors for now. It sounds like that max execution time error you ran into might also be related, although the while loop that continues to try to get a lock should give up after 3 seconds (not 240 like your error message!).

I'll look into this some more and see if I can get the lock method used in HEAD for APC to work. This may be the native locking functionality andypost referred to. I had trouble with it initially (and it looks like many others have had trouble with it too).

Canadaka’s picture

I added PHP @ to supress the errors and increased the user cache memory in PHP.ini to "wincache.ucachesize=64" and i've been running the wincache engine all day with no errors so far.

tauno’s picture

StatusFileSize
new7.86 KB

The attached patch includes the new wincache.php engine file (with the @ to suppress the error messages) and a minor update to the readme to mention wincache as a supported engine.

andypost, you mentioned pointing to help pages in the readme. I'm not sure what help pages we would point to. The generic http://php.net/wincache site?

It sounds like the locking mechanism could still use some work, but it also doesn't sound any worse off than APC at the moment.

donraman’s picture

Now that we have wincache_loc and wincache_unlock functionality, we should use that. Details aabout these functions are available at http://us3.php.net/manual/en/function.wincache-lock.php. The build which has these changes can be downloaded from http://sourceforge.net/projects/wincache/files/. Look under development folder.

One thing which we need to be careful about is the fact that lock name should comprise of chatracters which is allowed in file name. I have observed that currently we use things like C:\Windows\Temp\ as a lock. This will not work as name cannot have characters like \ and :. A modified code can be like:

function lock() {
// Lock once by trying to add lock file, if we can't get the lock, we will loop
// for 3 seconds attempting to get lock. If we still can't get it at that point,
// then we give up and return FALSE.
$key = $this->lock;
$key = strrchr($this->lock, '/');
$key = substr($key, 1);
if (wincache_lock($key) == FALSE) {
$time = time();
while (wincache_lock($key) == FALSE) {
if (time() - $time >= 3) {
return FALSE;
}
}
}
return TRUE;
}

function unlock() {
$key = $this->lock;
$key = strrchr($this->lock, '/');
$key = substr($key, 1);
return wincache_unlock($key);
}

Or something similar. I am not 100% sure but we need to either strip C:\WIndows\Temp or replace : and / with something which is acceptable as part of Windows file name.

andypost’s picture

@donraman your code is wrong take a look at eacc.php

  /**
   * lock()
   *   lock the cache from other writes.
   *
   * @param none
   * @return string
   *   Returns TRUE on success, FALSE on failure
   */
  function lock() {
    return eaccelerator_lock($this->lock);
  }

  /**
   * unlock()
   *   unlock the cache from other writes.
   *
   * @param none
   * @return bool
   *   Returns TRUE on success, FALSE on failure
   */
  function unlock() {
    return  eaccelerator_unlock($this->lock);
  }

The same should be done here

No need to loop through because
The execution of the current script will be blocked until the lock can be obtained.

tauno’s picture

StatusFileSize
new7.42 KB

Untested patch that uses wincache_lock and _unlock. Requires the latest dev version of wincache.

If no one else beats me to it, I'll be testing this next week when I have easy access to my dev servers again.

andypost’s picture

Status: Needs work » Needs review

Patch seems good to go! Need some reviews!

donraman’s picture

@andypost Thanks for clarifying it. Yes the lock will wait and hence there is no need to loop. I didn't realize it as the previous code was doing the loop. Good catch.

@tauno/@andypost Doing it eaacelerator way will not work as I already explained. The name of the object cannot contain backslash. And in your code if you print the name of the lock name ($this->lock) it prints something like C:\Windows\Temp/lock_file_name. The reason why backslash is not allowed is because we are using CreateMutex call as described at http://msdn.microsoft.com/en-us/library/ms682411(VS.85).aspx. So code should be something like:

  /**
   * lock()
   *   lock the cache from other writes.
   *
   * @param none
   * @return string
   *   Returns TRUE on success, FALSE on failure
   */
  function lock() {
    return wincache_lock(basename($this->lock));
  }

  /**
   * unlock()
   *   unlock the cache from other writes.
   *
   * @param none
   * @return bool
   *   Returns TRUE on success, FALSE on failure
   */
  function unlock() {
    return  wincache_unlock(basename($this->lock));
  }

Or something similar. You guys are the best judge for it. My point is all backslash ('\') should be stripped somehow, otherwise lock will fail.

Thanks,
Don

donraman’s picture

One additional information, I did test the new wincache.php with the above code and it works. This is just an information from my side.

Thanks,
Don.

andypost’s picture

@donraman thanx for explanation of implementation, there's no need to strip backslash form lock name because it's name is {prefix}_{cache_table}_lock
I think we could drop a line into readme about prefix that should not contain backslash

PS: I think you are using WaitForSingleObject() to wait for mutex get released so why not add a $timeout to wincache_lock() to make API more common for synchronization? Also it could prevent a deadlocks.

Patch looks fine for me, so I'm going to make some local tests and commit it.

Also I'm waiting more reviews.

donraman’s picture

@andypost thanks for the enhancement request. I have filed a change request at http://pecl.php.net/bugs/bug.php?id=17287. We will triage it appropriately and see when this can be considered.

tauno’s picture

@andypost did you get my latest patch working?

Now that I'm trying to test this on my windows dev server, it's not using the user cache as it should be. I'm not sure yet if it's my server config or an issue with how locking is implemented in the latest patch. I noticed quite a few differences between the APC and eaccelerator engines in cacherouter. Any thoughts about which is the better implementation to base wincache support on?

Canadaka’s picture

where is the newest wincache.php code? I tried the code in psot #12 and it doens't work, the usercache is not populated. I'm trying to test out the new Wincache 1.1 Beta2

tauno’s picture

Status: Needs review » Needs work

@canadaka - I think the patch still needs work. It's on my list for later today or tomorrow to try to figure out.

tauno’s picture

Assigned: Unassigned » tauno
Status: Needs work » Needs review
StatusFileSize
new7.42 KB

@donraman had it right for the current 6.x branch of cacherouter. Cache.php includes the file based locking that is not present in the 7.x branch.

Line 62 of Cache.php:

    $this->lock = $this->lock_dir . '/' . $this->prefix . $this->name . '_lock';

and that's why basename() is needed...Updated patch is attached.

tauno’s picture

Wincache 1.1 has been released now and I've been running this patch for a couple months on the 1.1 betas with only one issue that doesn't seem to be wincache specific (#867702: Page cache lifetime setting is resulting in negative TTL).

andypost’s picture

Sounds good, so I glad to commit this when I get a time

tauno’s picture

StatusFileSize
new7.59 KB

Minor update to handle the negative TTL issue linked to in #22.

hyates’s picture

Not sure what the problem was, but this patch caused some pretty unpredictable behavior on my machine. It would fill the fastcgi queue and lock up my server. Disabled this patch and it never happended again. Sorry I could not provide more debugging info.

hyates’s picture

Double post. My bad

tauno’s picture

Interesting. I've been running it for several months with no problems.

What are the details of your server (IIS, PHP, wincache versions)?
How quickly did the fastcgi processes get created?

hyates’s picture

StatusFileSize
new6.39 KB

I heavily suspect it had to do with the locking issue. So i might not have the right wincache.php file. had a bunch of error in my logs:

[14-Oct-2010 15:37:07] PHP Warning: wincache_ucache_add() [<a href='function.wincache-ucache-add'>function.wincache-ucache-add</a>]: function called with a key which already exists in <snip>\sites\all\modules\cacherouter\engines\wincache.php on line 207

I was using the attached wincache.php which probably needs a couple of the patches in this post applied to it. Anyone mind posting their working wincache.php?

Thanks.

iis: 7.5
php: 5.2.14
wincache: 1.1.0630.0

NOTE: Do no use the wincache.php attached to this post.

tauno’s picture

StatusFileSize
new6.06 KB

Yep, you're using an outdated version of the wincache engine that doesn't use the wincache locking. Try the patch in #24 above or this complete version.

hyates’s picture

Yup. I used the patch in #24 and its been working fine ever since. #29 is identical with what I am using.

Thank you very much for your help tauno and everyone else in this thread!

tauno’s picture

Status: Needs review » Reviewed & tested by the community

Seems like it's been working for those of us using it.

math-hew’s picture

I've had CacheRouter/WinCache installed and running great for about two months now, but recently we noticed an issue - when we go to update a module, some files/folders won't delete, and for a short while (15 minutes to an hour) we lose all access to those files/folders in Windows. Then, mysteriously, the folders will either a) disappear or b) give us our access back so we can delete them.

Disabling CacheRouter and WinCache fixes the problem. Anyone else experiencing something similar?

Canadaka’s picture

Version: 6.x-1.x-dev » 7.x-1.x-dev

Now that Drupal 7 is released is there anyway to utilize wincache's usercache with it? Seems cacherouter is not making a version for 7, so will there be a seperate wincache project?

tauno’s picture

For D7 we should be able to write a cache engine implementation for the core caching system. I haven't had a chance yet to look at what that would require. That same engine might also work for the D6 backport of the new caching system.

It's on my list, but someone else might get to it before I can.

Akaoni’s picture

I've started a WinCache implementation of DrupalCacheInterface here:
http://drupal.org/sandbox/Akaoni/1154744

It seems to be working fine, but it hasn't had any proper testing yet.

Canadaka’s picture

Seems no one has moved forward in creating a wincache module for Drupal 7. Your work is all I've seen.
I'm not sure how you utilize it? Once your module is enabled then what? Is there some lines that need to be added to settings.php?

aron novak’s picture

$conf['cache_backends'] = array('sites/all/modules/wincache/wincache.module');
$conf['cache_class_cache'] = 'WinCacheDrupal';
$conf['cache_class_cache_bootstrap'] = 'WinCacheDrupal';

And executing variable_set('cache_class_cache', 'WinCacheDrupal'); via devel/php did the trick, now the site uses the wincache, everything seems to be fine so far

jrsinclair’s picture

It seems that Microsoft have taken on this task over at http://drupal.org/sandbox/microsoft/1441326.

If you're at all interested in seeing this module happen, please help out by giving them a code review over at http://drupal.org/node/1473540

david_garcia’s picture

Version: 7.x-1.x-dev » 6.x-1.x-dev
Issue summary: View changes

Changed version to 6.x-1-x dev, cacherouter module is not being ported to Drupal 7 or 8, and thus being deprecated.

I am not sure, but I think the issue should be closed.

For a Drupal 7 version of the Wincache Module visit:

https://www.drupal.org/project/wincachedrupal