Андрей (andy) wrote in changelog,
Андрей
andy
changelog

[livejournal] r21343: LJSUP-11496 (optimize get_daycounts for ...

Committer: ailyin
LJSUP-11496 (optimize get_daycounts for ONTD)
U   trunk/cgi-bin/LJ/DelayedEntry.pm
U   trunk/cgi-bin/LJ/Entry.pm
U   trunk/cgi-bin/LJ/User.pm
U   trunk/cgi-bin/ljprotocol.pl
Modified: trunk/cgi-bin/LJ/DelayedEntry.pm
===================================================================
--- trunk/cgi-bin/LJ/DelayedEntry.pm	2012-03-11 14:35:54 UTC (rev 21342)
+++ trunk/cgi-bin/LJ/DelayedEntry.pm	2012-03-11 15:03:24 UTC (rev 21343)
@@ -1053,20 +1053,6 @@
     return \@tags_array;
 }
 
-sub __kill_dayct2_cache {
-    my ($u) = @_;
-    my $uid = LJ::want_userid($u) or return undef;
-
-    my $memkey = [$uid, "dayct2:$uid:p"];
-    LJ::MemCache::delete($memkey);
-
-    $memkey = [$uid, "dayct2:$uid:a"];
-    LJ::MemCache::delete($memkey);
-
-    $memkey = [$uid, "dayct2:$uid:g"];
-    LJ::MemCache::delete($memkey);
-}
-
 sub __statistics_absorber {
     my ($journal, $poster) = @_;
 

Modified: trunk/cgi-bin/LJ/Entry.pm
===================================================================
--- trunk/cgi-bin/LJ/Entry.pm	2012-03-11 14:35:54 UTC (rev 21342)
+++ trunk/cgi-bin/LJ/Entry.pm	2012-03-11 15:03:24 UTC (rev 21343)
@@ -2503,7 +2503,6 @@
     my $dc = $u->log2_do(undef, "DELETE FROM log2 WHERE journalid=$jid AND jitemid=$jitemid $and");
     LJ::MemCache::delete([$jid, "log2:$jid:$jitemid"]);
     LJ::MemCache::decr([$jid, "log2ct:$jid"]) if $dc > 0;
-    LJ::memcache_kill($jid, "dayct2");
 
     if ( $jitemid == $u->get_sticky_entry_id() ){
         $u->remove_sticky_entry_id();

Modified: trunk/cgi-bin/LJ/User.pm
===================================================================
--- trunk/cgi-bin/LJ/User.pm	2012-03-11 14:35:54 UTC (rev 21342)
+++ trunk/cgi-bin/LJ/User.pm	2012-03-11 15:03:24 UTC (rev 21343)
@@ -6607,7 +6607,7 @@
     my $u = shift;
     my $userid = LJ::want_userid($u);
     foreach my $key ("userid","bio","talk2ct","log2ct",
-                     "log2lt","memkwid","dayct2","s1overr","s1uc","fgrp",
+                     "log2lt","memkwid","s1overr","s1uc","fgrp",
                      "friends","friendofs","tu","upicinf","upiccom",
                      "upicurl", "intids", "memct", "lastcomm")
     {
@@ -8184,41 +8184,41 @@
 # non-zero count.  examples:
 #  [ [ 2003, 6, 5, 3 ], [ 2003, 6, 8, 4 ], ... ]
 #
-sub get_daycounts
-{
-    my ($u, $remote) = @_;
-    my $uid = LJ::want_userid($u) or return undef;
+sub get_daycounts {
+    my ( $u, $remote ) = @_;
 
-    my $memkind = 'p'; # public only, changed below
-    my $secwhere = "AND security='public'";
-    my $viewall = 0;
+    # ['public'], ['all'], or [ 'gmask', $gmask ]
+    my $kind;
     if ($remote) {
-        # do they have the viewall priv?
-        my %getargs = eval { LJ::Request->args } || (); # eval for check web context
-        if (defined $getargs{'viewall'} and $getargs{'viewall'} eq '1' and LJ::check_priv($remote, 'canview', '*')) {
+        my $viewall = 0;
+        if ( LJ::is_web_context() && LJ::Request->get_param('viewall') &&
+            LJ::check_priv( $remote, 'canview', '*' ) )
+        {
             $viewall = 1;
             LJ::statushistory_add($u->{'userid'}, $remote->{'userid'},
                 "viewall", "calendar");
         }
 
-        if ($remote->{'userid'} == $uid || $viewall) {
-            $secwhere = "";   # see everything
-            $memkind = 'a'; # all
-        } elsif ($remote->{'journaltype'} eq 'P') {
-            my $gmask = LJ::get_groupmask($u, $remote);
-            if ($gmask) {
-                $secwhere = "AND (security='public' OR (security='usemask' AND allowmask & $gmask))";
-                $memkind = 'g' . $gmask; # friends case: allowmask == gmask == 1
+        if ( LJ::u_equals( $u, $remote ) ) {
+            $kind = ['all'];
+        } else {
+            if ( my $gmask = LJ::get_groupmask($u, $remote) ) {
+                # friends case: allowmask == gmask == 1
+                $kind = [ 'gmask', $gmask ];
+            } else {
+                $kind = ['public'];
             }
         }
+    } else {
+        $kind = ['public'];
     }
 
     ##
-    ## the first element of array, that is stored in memcache, 
-    ## is the time of the creation of the list. The memcache is 
+    ## the first element of the array stored in memcache
+    ## is the time of the creation of the list. The memcache is
     ## invalid if there are new entries in journal since that time.
     ##
-    my $memkey = [$uid, "dayct2:$uid:$memkind"];
+    my $memkey = [ $u->userid, join( ':', 'dayct3', $u->userid, @$kind ) ];
     my $list = LJ::MemCache::get($memkey);
     if ($list) {
         my $list_create_time = shift @$list;
@@ -8229,7 +8229,9 @@
     
     ## get lock to prevent multiple apache processes to execute the sql below.
     ## one process runs, the other wait for results 
-    my $release_lock = sub { $dbcr->selectrow_array("SELECT RELEASE_LOCK('$memkey')"); };
+    my $release_lock = sub {
+        $dbcr->selectrow_array("SELECT RELEASE_LOCK('$memkey')");
+    };
     my $locked = $dbcr->selectrow_array("SELECT GET_LOCK('$memkey',10)");
     return unless $locked; ## 10 seconds expired
 
@@ -8243,22 +8245,128 @@
         }
     }
 
+    if ( LJ::is_enabled( 'dayct_month', $u ) ) {
+        $release_lock->();
+        my ( $min_year, $max_year ) = $dbcr->selectrow_array(
+            'SELECT MIN(year), MAX(year) FROM log2 WHERE journalid=?',
+            undef, $u->userid );
+
+        my $days = [];
+
+        foreach my $year ( $min_year .. $max_year ) {
+            foreach my $month ( 1 .. 12 ) {
+                my $month_daycounts =
+                    get_month_daycounts( $u, $kind, $year, $month );
+                push @$days, @$month_daycounts;
+            }
+        }
+
+        LJ::MemCache::set( $memkey, [ time, @$days ] );
+        return $days;
+    }
+
+    my ( $selecttype, $gmask ) = @$kind;
+    my $secwhere;
+    if ( $selecttype eq 'all' ) {
+        $secwhere = '';
+    } elsif ( $selecttype eq 'public' ) {
+        $secwhere = 'AND security="public"';
+    } elsif ( $selecttype eq 'gmask' ) {
+        $secwhere = "AND ( security='public' OR " .
+            "(security='usemask' AND allowmask & $gmask) )";
+    }
+
     my $sth = $dbcr->prepare("SELECT year, month, day, COUNT(*) ".
-                             "FROM log2 WHERE journalid=? $secwhere GROUP BY 1, 2, 3");
-    $sth->execute($uid);
-    my @days;
-    while (my ($y, $m, $d, $c) = $sth->fetchrow_array) {
+                             "FROM log2 WHERE journalid=? $secwhere " .
+                             "GROUP BY year, month, day");
+    $sth->execute( $u->userid );
+    my $days = [];
+    while ( my ( $y, $m, $d, $c ) = $sth->fetchrow_array ) {
         # we force each number from string scalars (from DBI) to int scalars,
         # so they store smaller in memcache
-        push @days, [ int($y), int($m), int($d), int($c) ];
+        push @$days, [ int($y), int($m), int($d), int($c) ];
     }
 
-    LJ::MemCache::set($memkey, [time, @days]);
+    LJ::MemCache::set( $memkey, [time, @$days] );
 
     $release_lock->();
-    return \@days;
+    return $days;
 }
 
+sub get_month_daycounts {
+    my ( $u, $kind, $year, $month ) = @_;
+
+    my $memkind = join( ':', @$kind );
+
+    ##
+    ## the first element of the array stored in memcache
+    ## is the time of the creation of the list. The memcache is
+    ## invalid if there are new entries in journal since that time.
+    ##
+    my $memkey = [ $u->userid,
+        join( ':', 'dayct3', 'month', $year, $month, $u->userid, @$kind ) ];
+
+    my $list = LJ::MemCache::get($memkey);
+    if ($list) {
+        my $list_create_time = shift @$list;
+
+        my $timeupdate       = $u->timeupdate;
+        my $timeupdate_year  = ( gmtime $timeupdate )[5] + 1900;
+        my $timeupdate_month = ( gmtime $timeupdate )[4] + 1;
+
+        return $list if $timeupdate_year != $year ||
+            $timeupdate_month != $month ||
+            $u->timeupdate <= $list_create_time;
+    }
+
+    my $dbcr = LJ::get_cluster_def_reader($u) or return;
+    
+    ## get lock to prevent multiple apache processes to execute the sql below.
+    ## one process runs, the other wait for results 
+    my $release_lock = sub {
+        $dbcr->selectrow_array("SELECT RELEASE_LOCK('$memkey')");
+    };
+    my $locked = $dbcr->selectrow_array("SELECT GET_LOCK('$memkey',10)");
+    return unless $locked; ## 10 seconds expired
+
+    $list = LJ::MemCache::get($memkey);
+    if ($list) {
+        ## other process may have filled the data while we waited for the lock
+        my $list_create_time = shift @$list;
+        $release_lock->();
+        return $list;
+    }
+
+    my ( $selecttype, $gmask ) = @$kind;
+    my $secwhere;
+    if ( $selecttype eq 'all' ) {
+        $secwhere = '';
+    } elsif ( $selecttype eq 'public' ) {
+        $secwhere = 'AND security="public"';
+    } elsif ( $selecttype eq 'gmask' ) {
+        $secwhere = "AND ( security='public' OR " .
+            "(security='usemask' AND allowmask & $gmask) )";
+    }
+
+    my $sth = $dbcr->prepare("SELECT day, COUNT(*) ".
+                             "FROM log2 WHERE journalid=? $secwhere AND " .
+                             "year=? AND month=? " .
+                             "GROUP BY day");
+    $sth->execute( $u->userid, $year, $month );
+    my $days = [];
+    while ( my ( $d, $c ) = $sth->fetchrow_array ) {
+        # we force each number from string scalars (from DBI) to int scalars,
+        # so they store smaller in memcache
+        push @$days, [ int($year), int($month), int($d), int($c) ];
+    }
+
+    my $exptime = 3600 + int( rand(3600) );
+    LJ::MemCache::set( $memkey, [time, @$days], $exptime );
+
+    $release_lock->();
+    return $days;
+}
+
 ## input: $u, $remote, $year, $month
 ## output: hashref with data for rendering calendar for given month,
 ##      days:       arrayref [ count of entries for each day]

Modified: trunk/cgi-bin/ljprotocol.pl
===================================================================
--- trunk/cgi-bin/ljprotocol.pl	2012-03-11 14:35:54 UTC (rev 21342)
+++ trunk/cgi-bin/ljprotocol.pl	2012-03-11 15:03:24 UTC (rev 21343)
@@ -2598,7 +2598,6 @@
     }
 
     LJ::MemCache::incr([$ownerid, "log2ct:$ownerid"]);
-    LJ::memcache_kill($ownerid, "dayct2");
 
     # set userprops.
     {
@@ -3316,8 +3315,6 @@
     }
     return fail($err,501,$dbcm->errstr) if $dbcm->err;
 
-    LJ::memcache_kill($ownerid, "dayct2");
-
     if (defined $oldevent->{'anum'}) {
         $res->{'anum'} = $oldevent->{'anum'};
         $res->{'url'} = LJ::item_link($uowner, $itemid, $oldevent->{'anum'});

Tags: ailyin, andy, livejournal, pl, pm
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments