コード例 #1
0
ファイル: Session.php プロジェクト: guohuadeng/stampApp
 public function getLifeTime()
 {
     $stores = Mage::app()->getStores();
     if (empty($stores)) {
         return self::SEESION_MAX_COOKIE_LIFETIME;
     } else {
         return parent::getLifeTime();
     }
 }
コード例 #2
0
   * Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
   * The name of Colin Mollenhour may not be used to endorse or promote products
     derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
require 'app/Mage.php';
Mage::app();
if (empty($argv[1])) {
    die('Must specify session id.');
}
$sessionId = $argv[1];
$redisSession = new Cm_RedisSession_Model_Session();
$sessionData = $redisSession->_inspectSession($sessionId);
$data = $sessionData['data'];
unset($sessionData['data']);
var_dump($sessionData);
echo "DATA:\n{$data}\n";
コード例 #3
0
ファイル: Session.php プロジェクト: phpdave11/Cm_RedisSession
 /**
  * Fetch session data
  *
  * @param string $sessionId
  * @return string
  */
 public function read($sessionId)
 {
     if (!$this->_useRedis) {
         return parent::read($sessionId);
     }
     Varien_Profiler::start(__METHOD__);
     // Get lock on session. Increment the "lock" field and if the new value is 1, we have the lock.
     $sessionId = self::SESSION_PREFIX . $sessionId;
     $tries = $waiting = $lock = 0;
     $lockPid = $oldLockPid = NULL;
     // Restart waiting for lock when current lock holder changes
     $detectZombies = FALSE;
     if ($this->_logLevel >= Zend_Log::WARN) {
         $timeStart = microtime(true);
     }
     if ($this->_logLevel >= Zend_Log::DEBUG) {
         $this->_log(sprintf("Attempting to take lock on ID %s", $sessionId));
     }
     $this->_redis->select($this->_dbNum);
     while ($this->_useLocking) {
         // Increment lock value for this session and retrieve the new value
         $oldLock = $lock;
         $lock = $this->_redis->hIncrBy($sessionId, 'lock', 1);
         // Get the pid of the process that has the lock
         if ($lock != 1 && $tries + 1 >= $this->_getBreakAfter()) {
             $lockPid = $this->_redis->hGet($sessionId, 'pid');
         }
         // If we got the lock, update with our pid and reset lock and expiration
         if ($lock == 1 || $tries >= $this->_getBreakAfter() && $oldLockPid == $lockPid) {
             $this->_hasLock = TRUE;
             break;
         } else {
             if (!$waiting) {
                 $i = 0;
                 do {
                     $waiting = $this->_redis->hIncrBy($sessionId, 'wait', 1);
                 } while (++$i < $this->_maxConcurrency && $waiting < 1);
             } else {
                 // Detect broken sessions (e.g. caused by fatal errors)
                 if ($detectZombies) {
                     $detectZombies = FALSE;
                     if ($lock > $oldLock && $lock + 1 < $oldLock + $waiting) {
                         // Reset session to fresh state
                         if ($this->_logLevel >= Zend_Log::INFO) {
                             $this->_log(sprintf("Detected zombie waiter after %.5f seconds for ID %s (%d waiting)\n  %s (%s - %s)", microtime(true) - $timeStart, $sessionId, $waiting, Mage::app()->getRequest()->getRequestUri(), Mage::app()->getRequest()->getClientIp(), Mage::app()->getRequest()->getHeader('User-Agent')), Zend_Log::INFO);
                         }
                         $waiting = $this->_redis->hIncrBy($sessionId, 'wait', -1);
                         continue;
                     }
                 }
                 // Limit concurrent lock waiters to prevent server resource hogging
                 if ($waiting >= $this->_maxConcurrency) {
                     // Overloaded sessions get 503 errors
                     $this->_redis->hIncrBy($sessionId, 'wait', -1);
                     $this->_sessionWritten = TRUE;
                     // Prevent session from getting written
                     $writes = $this->_redis->hGet($sessionId, 'writes');
                     if ($this->_logLevel >= Zend_Log::WARN) {
                         $this->_log(sprintf("Session concurrency exceeded for ID %s; displaying HTTP 503 (%s waiting, %s total requests)\n  %s (%s - %s)", $sessionId, $waiting, $writes, Mage::app()->getRequest()->getRequestUri(), Mage::app()->getRequest()->getClientIp(), Mage::app()->getRequest()->getHeader('User-Agent')), Zend_Log::WARN);
                     }
                     $this->_logLevel = -1;
                     // Disable further logging
                     require_once Mage::getBaseDir() . DS . 'errors' . DS . '503.php';
                     exit;
                 }
             }
         }
         $tries++;
         $oldLockPid = $lockPid;
         $sleepTime = self::SLEEP_TIME;
         // Detect dead lock waiters
         if ($tries % self::DETECT_ZOMBIES == 1) {
             $detectZombies = TRUE;
             $sleepTime += 10000;
             // sleep + 0.01 seconds
         }
         // Detect dead lock holder every 10 seconds (only works on same node as lock holder)
         if ($tries % self::DETECT_ZOMBIES == 0) {
             Varien_Profiler::start(__METHOD__ . '-detect-zombies');
             if ($this->_logLevel >= Zend_Log::DEBUG) {
                 $this->_log(sprintf("Checking for zombies after %.5f seconds of waiting...", microtime(true) - $timeStart));
             }
             $pid = $this->_redis->hGet($sessionId, 'pid');
             if ($pid && !$this->_pidExists($pid)) {
                 // Allow a live process to get the lock
                 $this->_redis->hSet($sessionId, 'lock', 0);
                 if ($this->_logLevel >= Zend_Log::INFO) {
                     $this->_log(sprintf("Detected zombie process (%s) for %s (%s waiting)\n  %s (%s - %s)", $pid, $sessionId, $waiting, Mage::app()->getRequest()->getRequestUri(), Mage::app()->getRequest()->getClientIp(), Mage::app()->getRequest()->getHeader('User-Agent')), Zend_Log::INFO);
                 }
                 Varien_Profiler::stop(__METHOD__ . '-detect-zombies');
                 continue;
             }
             Varien_Profiler::stop(__METHOD__ . '-detect-zombies');
         }
         // Timeout
         if ($tries >= $this->_getBreakAfter() + $this->_failAfter) {
             $this->_hasLock = FALSE;
             if ($this->_logLevel >= Zend_Log::NOTICE) {
                 $this->_log(sprintf("Giving up on read lock for ID %s after %.5f seconds (%d attempts)", $sessionId, microtime(true) - $timeStart, $tries), Zend_Log::NOTICE);
             }
             break;
         } else {
             if ($this->_logLevel >= Zend_Log::DEBUG) {
                 $this->_log(sprintf("Waiting %.2f seconds for lock on ID %s (%d tries, lock pid is %s, %.5f seconds elapsed)", $sleepTime / 1000000, $sessionId, $tries, $lockPid, microtime(true) - $timeStart));
             }
             Varien_Profiler::start(__METHOD__ . '-wait');
             usleep($sleepTime);
             Varien_Profiler::stop(__METHOD__ . '-wait');
         }
     }
     self::$failedLockAttempts = $tries;
     // Session can be read even if it was not locked by this pid!
     if ($this->_logLevel >= Zend_Log::DEBUG) {
         $timeStart = microtime(true);
     }
     list($sessionData, $sessionWrites) = $this->_redis->hMGet($sessionId, array('data', 'writes'));
     Varien_Profiler::stop(__METHOD__);
     if ($this->_logLevel >= Zend_Log::DEBUG) {
         $this->_log(sprintf("Data read for ID %s in %.5f seconds", $sessionId, microtime(true) - $timeStart));
     }
     $this->_sessionWrites = (int) $sessionWrites;
     // This process is no longer waiting for a lock
     if ($tries > 0) {
         $this->_redis->hIncrBy($sessionId, 'wait', -1);
     }
     // This process has the lock, save the pid
     if ($this->_hasLock) {
         $setData = array('pid' => $this->_getPid(), 'lock' => 1);
         // Save request data in session so if a lock is broken we can know which page it was for debugging
         if ($this->_logLevel >= Zend_Log::INFO) {
             if (empty($_SERVER['REQUEST_METHOD'])) {
                 $setData['req'] = $_SERVER['SCRIPT_NAME'];
             } else {
                 $setData['req'] = "{$_SERVER['REQUEST_METHOD']} {$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}";
             }
             if ($lock != 1) {
                 $this->_log(sprintf("Successfully broke lock for ID %s after %.5f seconds (%d attempts). Lock: %d\nLast request of broken lock: %s", $sessionId, microtime(true) - $timeStart, $tries, $lock, $this->_redis->hGet($sessionId, 'req')), Zend_Log::INFO);
             }
         }
     }
     // Set session data and expiration
     $this->_redis->pipeline();
     if (!empty($setData)) {
         $this->_redis->hMSet($sessionId, $setData);
     }
     $this->_redis->expire($sessionId, min($this->getLifeTime(), $this->_maxLifetime));
     $this->_redis->exec();
     // Reset flag in case of multiple session read/write operations
     $this->_sessionWritten = FALSE;
     return $sessionData ? $this->_decodeData($sessionData) : '';
 }
コード例 #4
0
*/
require 'app/Mage.php';
Mage::app();
if (empty($argv[1])) {
    die('Must specify session glob pattern. E.g. sess_*');
}
$sessionPattern = $argv[1];
if (empty($argv[2])) {
    die('Must specify group-by key. E.g. http_user_agent, remote_addr, http_secure, http_host, request_uri, is_new_visitor');
}
$groupBy = $argv[2];
if (empty($argv[3])) {
    die('Must specify sort-by parameter. writes or count');
}
$sortBy = $argv[3];
$redisSession = new Cm_RedisSession_Model_Session();
$cursor = 0;
$getSessionData = function ($data, $key) use($groupBy) {
    switch ($groupBy) {
        case 'is_new_visitor':
            if (preg_match("/\"{$key}\";b:([01])/", $data, $matches)) {
                return $matches[1];
            }
            break;
        default:
            // remote_addr, http_secure, http_host, http_user_agent, request_uri, is_new_visitor
            if (preg_match("/\"{$key}\";s:\\d+:\"([^\"]+)\"/", $data, $matches)) {
                return $matches[1];
            }
            break;
    }
コード例 #5
0
 /**
  * Fetch session data
  *
  * @param string $sessionId
  * @return string
  */
 public function read($sessionId)
 {
     if (!$this->_useRedis) {
         return parent::read($sessionId);
     }
     // Get lock on session. Increment the "lock" field and if the new value is 1, we have the lock.
     // If the new value is a multiple of BREAK_MODULO then we are breaking the lock.
     $sessionId = self::SESSION_PREFIX . $sessionId;
     $tries = $waiting = $lock = 0;
     $detectZombies = FALSE;
     if ($this->_logLevel >= 7) {
         Mage::log(sprintf("%s: Attempting read lock on ID %s", $this->_getPid(), $sessionId), Zend_Log::DEBUG, self::LOG_FILE);
         // reset timer
         $this->_timeStart = microtime(true);
     }
     if ($this->_dbNum) {
         $this->_redis->select($this->_dbNum);
     }
     while (1) {
         // Increment lock value for this session and retrieve the new value
         $oldLock = $lock;
         $lock = $this->_redis->hIncrBy($sessionId, 'lock', 1);
         // If we got the lock, update with our pid and reset lock and expiration
         if ($lock == 1 || $tries >= $this->_breakAfter && $lock % self::BREAK_MODULO == 0) {
             $setData = array('pid' => $this->_getPid(), 'lock' => 1);
             // Save request data in session so if a lock is broken we can know which page it was for debugging
             if ($this->_logLevel >= 6) {
                 $additionalDetails = sprintf("(%s attempts)", $tries);
                 if ($this->_logLevel >= 7) {
                     $additionalDetails = sprintf("after %.5f seconds ", microtime(true) - $this->_timeStart, $tries) . $additionalDetails;
                 }
                 if (empty($_SERVER['REQUEST_METHOD'])) {
                     $setData['req'] = $_SERVER['SCRIPT_NAME'];
                 } else {
                     $setData['req'] = "{$_SERVER['REQUEST_METHOD']} {$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}";
                 }
                 if ($lock != 1) {
                     Mage::log(sprintf("%s: Successfully broke lock for ID %s %s. Lock: %s, BREAK_MODULO: %s\nLast request of broken lock: %s", $this->_getPid(), $sessionId, $additionalDetails, $lock, self::BREAK_MODULO, $this->_redis->hGet($sessionId, 'req')), Zend_Log::INFO, self::LOG_FILE);
                 }
             }
             $this->_redis->pipeline()->hMSet($sessionId, $setData)->expire($sessionId, min($this->getLifeTime(), self::MAX_LIFETIME))->exec();
             $this->_hasLock = TRUE;
             break;
         } else {
             if (!$waiting) {
                 $i = 0;
                 do {
                     $waiting = $this->_redis->hIncrBy($sessionId, 'wait', 1);
                     if ($this->_logLevel >= 7) {
                         Mage::log(sprintf("%s: Waiting for lock on ID %s (%s tries, %s waiting, %.5f seconds elapsed)", $this->_getPid(), $sessionId, $tries, $waiting, microtime(true) - $this->_timeStart), Zend_Log::DEBUG, self::LOG_FILE);
                     }
                 } while (++$i < $this->_maxConcurrency && $waiting < 1);
             } else {
                 // Detect broken sessions (e.g. caused by fatal errors)
                 if ($detectZombies) {
                     $detectZombies = FALSE;
                     if ($lock > $oldLock && $lock + 1 < $oldLock + $waiting) {
                         // Reset session to fresh state
                         if ($this->_logLevel >= 6) {
                             Mage::log(sprintf("%s: Detected zombie waiter after %.5f seconds for ID %s (%s waiting)\n  %s (%s - %s)", $this->_getPid(), microtime(true) - $this->_timeStart, $sessionId, $waiting, Mage::app()->getRequest()->getRequestUri(), Mage::app()->getRequest()->getClientIp(), Mage::app()->getRequest()->getHeader('User-Agent')), Zend_Log::INFO, self::LOG_FILE);
                         }
                         $waiting = $this->_redis->hIncrBy($sessionId, 'wait', -1);
                         continue;
                     }
                 }
                 // Limit concurrent lock waiters to prevent server resource hogging
                 if ($waiting >= $this->_maxConcurrency) {
                     // Overloaded sessions get 503 errors
                     $this->_redis->hIncrBy($sessionId, 'wait', -1);
                     $this->_sessionWritten = TRUE;
                     // Prevent session from getting written
                     $writes = $this->_redis->hGet($sessionId, 'writes');
                     if ($this->_logLevel >= 4) {
                         Mage::log(sprintf("%s: Session concurrency exceeded for ID %s; displaying HTTP 503 (%s waiting, %s total requests)\n  %s (%s - %s)", $this->_getPid(), $sessionId, $waiting, $writes, Mage::app()->getRequest()->getRequestUri(), Mage::app()->getRequest()->getClientIp(), Mage::app()->getRequest()->getHeader('User-Agent')), Zend_Log::WARN, self::LOG_FILE);
                     }
                     require_once Mage::getBaseDir() . DS . 'errors' . DS . '503.php';
                     exit;
                 }
             }
         }
         $tries++;
         // Detect dead waiters
         if ($tries == 1) {
             $detectZombies = TRUE;
             // TODO: allow configuration of sleep period?
             usleep(1500000);
             // 1.5 seconds
         }
         // Detect dead processes every 10 seconds
         if ($tries % self::DETECT_ZOMBIES == 0) {
             if ($this->_logLevel >= 7) {
                 Mage::log(sprintf("%s: Checking for zombies after %.5f seconds of waiting...", $this->_getPid(), microtime(true) - $this->_timeStart), Zend_Log::DEBUG, self::LOG_FILE);
             }
             $pid = $this->_redis->hGet($sessionId, 'pid');
             if ($pid && !$this->_pidExists($pid)) {
                 // Allow a live process to get the lock
                 $this->_redis->hSet($sessionId, 'lock', 0);
                 if ($this->_logLevel >= 6) {
                     Mage::log(sprintf("%s: Detected zombie process (%s) for %s (%s waiting)\n  %s (%s - %s)", $this->_getPid(), $pid, $sessionId, $waiting, Mage::app()->getRequest()->getRequestUri(), Mage::app()->getRequest()->getClientIp(), Mage::app()->getRequest()->getHeader('User-Agent')), Zend_Log::INFO, self::LOG_FILE);
                 }
                 continue;
             }
         }
         // Timeout
         if ($tries >= $this->_breakAfter + self::FAIL_AFTER) {
             $this->_hasLock = FALSE;
             if ($this->_logLevel >= 5) {
                 $additionalDetails = sprintf("(%s attempts)", $tries);
                 if ($this->_logLevel >= 7) {
                     $additionalDetails = sprintf("after %.5f seconds ", microtime(true) - $this->_timeStart, $tries) . $additionalDetails;
                 }
                 Mage::log(sprintf("%s: Giving up on read lock for ID %s %s", $this->_getPid(), $sessionId, $additionalDetails), Zend_Log::NOTICE, self::LOG_FILE);
             }
             break;
         } else {
             // TODO: configurable wait period?
             sleep(1);
         }
     }
     self::$failedLockAttempts = $tries;
     // This process is no longer waiting for a lock
     if ($tries > 0) {
         $this->_redis->hIncrBy($sessionId, 'wait', -1);
     }
     // Session can be read even if it was not locked by this pid!
     $sessionData = $this->_redis->hGet($sessionId, 'data');
     if ($this->_logLevel >= 7) {
         Mage::log(sprintf("%s: Data read for ID %s after %.5f seconds", $this->_getPid(), $sessionId, microtime(true) - $this->_timeStart), Zend_Log::DEBUG, self::LOG_FILE);
     }
     return $sessionData ? $this->_decodeData($sessionData) : '';
 }
コード例 #6
0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
require 'app/Mage.php';
Mage::app();
$test = in_array('--test', $argv);
$coreSession = new Mage_Core_Model_Session_Abstract();
$redisSession = new Cm_RedisSession_Model_Session();
$sessionPath = $coreSession->getSessionSavePath();
if (!is_readable($sessionPath) || !($dir = opendir($sessionPath))) {
    die("The session save path is not readable: {$sessionPath}\n");
}
if (!$redisSession->hasConnection()) {
    die("Could not connect to redis server, please check your configuration.\n");
}
$sessionLifetime = max(Mage::getStoreConfig('admin/security/session_cookie_lifetime'), Mage::getStoreConfig('web/cookie/cookie_lifetime'), 3600);
if (!in_array('-y', $argv)) {
    $redisConfig = Mage::getConfig()->getNode('global/redis_session');
    $redisConnection = $redisConfig->descend('host') . ':' . $redisConfig->descend('port') . '/' . $redisConfig->descend('db');
    $input = readline("Migrate sessions from {$sessionPath} to {$redisConnection} with {$sessionLifetime} second lifetime? (y|n) ");
    if ($input != 'y') {
        die("Aborted.\n");
    }