Howdy,

Found a small bug in Admin/Polls.pm that kept polls from showing up on 
the main page when used with memcached.  See Polls.diff for the fix.

I've also attached a few other minor mods I made:

Cache.diff changes the cache key that memcached uses.  It adds the 
site_id to the key and uses an md5 hash instead of the original resource 
key.  Just after I added the site_id, I discovered that newer versions 
of Cache::Memcached actually have a way to set up unique namespace when 
you initialize the class.  However, this patch will ensure a unique 
namespace and a consistent keylength regardless of the library version.

Static.diff forces Scoop to use static pages if memcached is turned on 
regardless of any var.  Instead of using the filesystem to store the 
HTML, scoop will use memcached instead.  Be forewarned that this patch 
removes all the filesystem code and forces a site into using static pages.

PS:  While all three patches are against the latest revisions of their 
respective files, they are not against a cvs checkout.

Enjoy!

--
Cory R. King
-------------- next part --------------
--- lib/Scoop/Admin/Polls.orig	2006-10-06 08:58:35.837581054 -0700
+++ lib/Scoop/Admin/Polls.pm	2006-10-06 09:07:43.132089631 -0700
@@ -232,6 +232,7 @@
 						SET		=> "value=''",
 						WHERE	=> "name='current_poll'",
 					});
+		$S->cache->remove('vars');
 		$S->cache->stamp('vars');
 		my $question = $S->get_poll_hash($editqid)->{'question'};
 
@@ -266,6 +267,7 @@
 						SET		=> "value=''",
 						WHERE	=> "name='current_poll'",
 					});
+				$S->cache->remove('vars');
 				$S->cache->stamp('vars');
 			}
 		}
@@ -542,7 +544,7 @@
 		$sth->finish;
 		
 		# And reload the vars cache
-		$S->cache->clear({resource => 'vars', element => 'VARS'});
+		$S->cache->remove('vars');
 		$S->cache->stamp('vars');
 		$S->_set_vars();
 		$S->_set_blocks();
@@ -748,6 +750,7 @@
 
 		my $question = $S->get_poll_hash($qid)->{'question'};
 		$message = qq| Set poll "$question" to display on main page |;
+		$S->cache->remove('vars');
 		$S->cache->stamp('vars');
 	}
 
-------------- next part --------------
--- lib/Scoop/Cache.orig	2006-09-19 12:04:12.000000000 -0700
+++ lib/Scoop/Cache.pm	2006-10-06 09:18:22.691276378 -0700
@@ -15,6 +15,7 @@
 package Scoop::Cache;
 use strict;
 use vars qw( $Cache );
+use Digest::MD5 qw(md5_base64);
 
 my $DEBUG = 0;
 
@@ -101,13 +102,19 @@
 
 	# if we're using memcached, short circuit the rest of the function
 	if($self->{scoop}->{MEMCACHED} && $resource ne 'boxes'){
-		warn "fetching $resource with memcached...\n" if $DEBUG;
+		my $key = $self->_make_resource_key($resource);
+		warn "fetching $resource ($key) with memcached...\n" if $DEBUG;
+
 		my $S = $self->{scoop}; # and a flip
 		# one nice thing, at least, is that the memcached server
 		# seems to handle a lot of the stuff that we'd ordinarily
 		# need to worry about ourselves, so this is, at least, a lot
 		# simpler.
-		my $data = $S->memcached->get($resource);
+		#
+		# just note that we are using a different key
+		# in memcache... we dont expose this to the outside world
+		my $data = $S->memcached->get($key);
+		warn "hit!" if $data && $DEBUG;
 		return $data->{value};
 		}
 	# first, check to see if the resource exists in the cache
@@ -174,7 +181,8 @@
 	my $now = time();
 	if($self->{scoop}->{MEMCACHED}){
 		my $S = $self->{scoop};
-		warn "Storing $resource with value $value with memcached\n" if $DEBUG;
+		my $key = $self->_make_resource_key($resource);
+		warn "Storing $resource ($key) with value $value with memcached\n" if $DEBUG;
 		# do we need to fiddle with expires?
 		# might as well
 		if($expires){
@@ -195,7 +203,7 @@
 		$data->{value} = $value;
 		$data->{last_update} = $data->{last_access} = $now;
 		$self->stamp($resource) unless $self->refresh_one($resource);
-		$S->memcached->set($resource, $data, $expires);
+		$S->memcached->set($key, $data, $expires);
 		return 1;
 		}
 
@@ -252,9 +260,13 @@
 
 	# once again...
 	if($self->{scoop}->{MEMCACHED}){
+		my $key = $self->_make_resource_key($resource);
 		warn "Removing $resource from memcached...\n" if $DEBUG;
 		# this is really here for completeness
-		$self->{scoop}->{MEMCACHED}->delete($resource);
+
+		# note that the only place we expose our unique key is to memcache
+		# the rest uses the "real" resource name
+		$self->{scoop}->{MEMCACHED}->delete($key);
 		delete $self->{refresh}->{$resource}; # for completeness -							      # might even be used
 		return 1;
 		}
@@ -359,6 +371,16 @@
 	return $size;
 }
 
+# makes a unique key for memcache
+#  - basically the site_id + the resource name
+sub _make_resource_key {
+	my $self=shift;
+	my $resource = shift;
+	$resource = md5_base64($resource);
+
+	return $self->{id}."_".$resource;
+}
+
 sub _calculate_size_array {
 	my $self = shift;
 	my $data = shift;
@@ -375,6 +397,7 @@
 	my $self = shift;
 	my $resource = shift || return;
 
+
 	# refresh timestamps are cached in the object for the duration of the
 	# request, so check to see if the requested one is in the cache
 	return $self->{refresh}->{$resource} if $self->{refresh}->{$resource};
-------------- next part --------------
--- lib/Scoop/Static.orig	2006-09-19 16:10:06.000000000 -0700
+++ lib/Scoop/Static.pm	2006-09-19 17:27:50.000000000 -0700
@@ -5,8 +5,9 @@
 sub check_do_static {
 	my $S = shift;
 	
-	return 0 unless ($S->{UI}->{VARS}->{use_static_pages} && 
-	                 $S->{UI}->{VARS}->{page_path} &&
+	# if you have memcache turned on, I'm gonna cache this page no matter
+	# what you say....
+	return 0 unless ( ($S->{UI}->{VARS}->{use_static_pages} || $S->{MEMCACHED} ) &&
 					 $S->{GID} eq 'Anonymous');
 	
 	return 0 unless ($S->cgi()->param('op') eq 'displaystory');
@@ -31,9 +32,8 @@
 	my $S = shift;
 	my $page_mod = shift;
 	
-	my $base_path = $S->{UI}->{VARS}->{page_path};
 	my $sid = $S->cgi->param('sid');
-	my $path = $base_path.'/'.$sid.'_'.$page_mod;
+	my $path = 'static_'.$sid.'_'.$page_mod;
 	warn "Full static page path is <$path>\n" if $DEBUG;
 	return $path;
 }
@@ -51,20 +51,18 @@
 	return undef if ($S->_check_story_mode($sid) < 0);
 	
 	my $full_path = $S->make_static_path($page_mod);
+	my $stat_hash = $S->cache->fetch($full_path);
+
+	my $stat_time = $$stat_hash{time};
+	my $stat_page = $$stat_hash{page};
+
+	return undef unless $stat_time;
 	
-	unless (-e $full_path && -r $full_path) { 
-		warn "Static file <$full_path> does not exist, or isn't readable.\n" if $DEBUG;
-		return undef;
-	}
-	
-	open STATIC, "<$full_path" || {warn "Can't open $full_path: $!\n" and return undef};
-	my @file_info = stat STATIC;
-	
-	warn "Block time is ".$S->cache->refresh_one('blocks').", Var time is ".$S->cache->refresh_one('vars').", File time is $file_info[9]\n" if $DEBUG;
+	warn "Block time is ".$S->cache->refresh_one('blocks').", Var time is ".$S->cache->refresh_one('vars').", File time is $stat_time, $S->{CONFIG}->{site_id}\n" if $DEBUG;
 
 	# Check cache time for blocks and vars
-	unless (($S->cache->refresh_one('blocks') <= $file_info[9]) &&
-	        ($S->cache->refresh_one('vars')   <= $file_info[9])) {
+	unless (($S->cache->refresh_one('blocks') <= $stat_time) &&
+	        ($S->cache->refresh_one('vars')   <= $stat_time)) {
 		warn "Block or Var stamps invalid.\n" if $DEBUG;
 		return undef;
 	}
@@ -74,36 +72,26 @@
 	# Check cache time for story
 	my $resource = $sid.'_mod';
 	
-	unless ($S->cache->refresh_one($resource) <= $file_info[9]) {
-		warn "$resource time is ".$S->cache->refresh_one($resource).", file time is $file_info[9]\n" if $DEBUG;
+	unless ($S->cache->refresh_one($resource) <= $stat_time) {
+		warn "$resource time is ".$S->cache->refresh_one($resource).", file time is $stat_time\n" if $DEBUG;
 		return undef;
 	}
 	
 	warn "Static page is good. Returning.\n" if $DEBUG;
 	# Ok, so the page is valid. Pull it in, and return it
-	my $stat_file;
-	{ local $/; $stat_file = <STATIC> }
-	close STATIC;
-	
+
 	# If we're a regular user, need to mark the comments
-	$stat_file = $S->mark_new_comments($stat_file, $sid) unless ($S->{UID} == -1);
+	$stat_page = $S->mark_new_comments($stat_page, $sid) unless ($S->{UID} == -1);
 	
         # Set the page's subtitle properly
-	my $q_sid = $S->dbh->quote($sid);
-        my ($rv, $sth) = $S->db_select({
-                ARCHIVE => $S->_check_archivestatus($sid),
-                WHAT => 'title',
-                FROM => 'stories',
-                WHERE => qq|sid = $q_sid|
-        });
-        $S->{UI}->{BLOCKS}->{subtitle} .= $sth->fetchrow;
-        $sth->finish;
+
+        $S->{UI}->{BLOCKS}->{subtitle} .= $$stat_hash{subtitle};
         $S->{UI}->{BLOCKS}->{subtitle} =~ s/</&lt;/g;
         $S->{UI}->{BLOCKS}->{subtitle} =~ s/>/&gt;/g;
 
 	# And the ratings! Put something here.
 	
-	return $stat_file;
+	return $stat_page;
 }
 
 
@@ -147,25 +135,30 @@
 			($S->{GID} ne 'Anonymous')) {
 	
 		my $full_path = $S->make_static_path($page_mod);
+		my $time = time();
+
+		warn "Writing new cache file $full_path - $time\n" if $DEBUG;
+
 
 		my $page = $S->{UI}->{BLOCKS}->{$S->{CURRENT_TEMPLATE}};
 		$page =~ s/%%STORY%%/$S->{UI}->{BLOCKS}->{STORY}/g;
 		$page =~ s/%%COMMENTS%%/$S->{UI}->{BLOCKS}->{COMMENTS}/g;
 		$page =~ s/%%CONTENT%%/$S->{UI}->{BLOCKS}->{CONTENT}/g;
-		$S->make_cache_dir_path($full_path);
 
-		open STAT, ">$full_path" || {warn "Can't open $full_path: $!\n" and return undef};
-		print STAT $page || warn "Can't print to $full_path: $!\n";
-		close STAT;
+		my %stat_hash = (
+			page=>$page,
+			time=>$time,
+			subtitle=>$S->{UI}->{BLOCKS}->{subtitle}
+		);
 
-		warn "Wrote new cache file $full_path\n" if $DEBUG;
+		$S->cache->store($full_path, \%stat_hash);
 
-		# Make sure the story has a time stamp
+		warn "Wrote new cache file $full_path - $time\n" if $DEBUG;
 
+		# Make sure the story has a time stamp
 		my $resource = $sid.'_mod';
 
 		unless ($S->cache->refresh_one($resource)) {
-			my $time = time();
 			warn "Stamping $resource at $time\n" if $DEBUG;
 			$S->cache->stamp_cache($resource, $time, 1);
 		}