Esempio n. 1
0
 public function shutdown()
 {
     if ($this->mainLB) {
         $this->chronProt->shutdownLB($this->mainLB);
     }
     foreach ($this->extLBs as $extLB) {
         $this->chronProt->shutdownLB($extLB);
     }
     $this->chronProt->shutdown();
     $this->commitMasterChanges();
 }
Esempio n. 2
0
 /**
  * @param ChronologyProtector $cp
  */
 protected function shutdownChronologyProtector(ChronologyProtector $cp)
 {
     // Get all the master positions needed
     $this->forEachLB(function (LoadBalancer $lb) use($cp) {
         $cp->shutdownLB($lb);
     });
     // Write them to the stash
     $unsavedPositions = $cp->shutdown();
     // If the positions failed to write to the stash, at least wait on local datacenter
     // slaves to catch up before responding. Even if there are several DCs, this increases
     // the chance that the user will see their own changes immediately afterwards. As long
     // as the sticky DC cookie applies (same domain), this is not even an issue.
     $this->forEachLB(function (LoadBalancer $lb) use($unsavedPositions) {
         $masterName = $lb->getServerName($lb->getWriterIndex());
         if (isset($unsavedPositions[$masterName])) {
             $lb->waitForAll($unsavedPositions[$masterName]);
         }
     });
 }
Esempio n. 3
0
 /**
  * Get and record all of the staged DB positions into persistent memory storage
  *
  * @param ChronologyProtector $cp
  * @param callable|null $workCallback Work to do instead of waiting on syncing positions
  * @param string $mode One of (sync, async); whether to wait on remote datacenters
  */
 protected function shutdownChronologyProtector(ChronologyProtector $cp, $workCallback, $mode)
 {
     // Record all the master positions needed
     $this->forEachLB(function (ILoadBalancer $lb) use($cp) {
         $cp->shutdownLB($lb);
     });
     // Write them to the persistent stash. Try to do something useful by running $work
     // while ChronologyProtector waits for the stash write to replicate to all DCs.
     $unsavedPositions = $cp->shutdown($workCallback, $mode);
     if ($unsavedPositions && $workCallback) {
         // Invoke callback in case it did not cache the result yet
         $workCallback();
         // work now to block for less time in waitForAll()
     }
     // If the positions failed to write to the stash, at least wait on local datacenter
     // replica DBs to catch up before responding. Even if there are several DCs, this increases
     // the chance that the user will see their own changes immediately afterwards. As long
     // as the sticky DC cookie applies (same domain), this is not even an issue.
     $this->forEachLB(function (ILoadBalancer $lb) use($unsavedPositions) {
         $masterName = $lb->getServerName($lb->getWriterIndex());
         if (isset($unsavedPositions[$masterName])) {
             $lb->waitForAll($unsavedPositions[$masterName]);
         }
     });
 }
Esempio n. 4
0
 public function testChronologyProtector()
 {
     // (a) First HTTP request
     $mPos = new MySQLMasterPos('db1034-bin.000976', '843431247');
     $mockDB = $this->getMockBuilder('DatabaseMysql')->disableOriginalConstructor()->getMock();
     $mockDB->expects($this->any())->method('doneWrites')->will($this->returnValue(true));
     $mockDB->expects($this->any())->method('getMasterPos')->will($this->returnValue($mPos));
     $lb = $this->getMockBuilder('LoadBalancer')->disableOriginalConstructor()->getMock();
     $lb->expects($this->any())->method('getConnection')->will($this->returnValue($mockDB));
     $lb->expects($this->any())->method('getServerCount')->will($this->returnValue(2));
     $lb->expects($this->any())->method('parentInfo')->will($this->returnValue(array('id' => "main-DEFAULT")));
     $lb->expects($this->any())->method('getAnyOpenConnection')->will($this->returnValue($mockDB));
     $bag = new HashBagOStuff();
     $cp = new ChronologyProtector($bag, array('ip' => '127.0.0.1', 'agent' => "Totally-Not-FireFox"));
     $mockDB->expects($this->exactly(2))->method('doneWrites');
     // Nothing to wait for
     $cp->initLB($lb);
     // Record in stash
     $cp->shutdownLB($lb);
     $cp->shutdown();
     // (b) Second HTTP request
     $cp = new ChronologyProtector($bag, array('ip' => '127.0.0.1', 'agent' => "Totally-Not-FireFox"));
     $lb->expects($this->once())->method('waitFor')->with($this->equalTo($mPos));
     // Wait
     $cp->initLB($lb);
     // Record in stash
     $cp->shutdownLB($lb);
     $cp->shutdown();
 }
Esempio n. 5
0
 public function testChronologyProtector()
 {
     // (a) First HTTP request
     $mPos = new MySQLMasterPos('db1034-bin.000976', '843431247');
     $now = microtime(true);
     $mockDB = $this->getMockBuilder('DatabaseMysql')->disableOriginalConstructor()->getMock();
     $mockDB->method('writesOrCallbacksPending')->willReturn(true);
     $mockDB->method('lastDoneWrites')->willReturn($now);
     $mockDB->method('getMasterPos')->willReturn($mPos);
     $lb = $this->getMockBuilder('LoadBalancer')->disableOriginalConstructor()->getMock();
     $lb->method('getConnection')->willReturn($mockDB);
     $lb->method('getServerCount')->willReturn(2);
     $lb->method('parentInfo')->willReturn(['id' => "main-DEFAULT"]);
     $lb->method('getAnyOpenConnection')->willReturn($mockDB);
     $lb->method('hasOrMadeRecentMasterChanges')->will($this->returnCallback(function () use($mockDB) {
         $p = 0;
         $p |= call_user_func([$mockDB, 'writesOrCallbacksPending']);
         $p |= call_user_func([$mockDB, 'lastDoneWrites']);
         return (bool) $p;
     }));
     $lb->method('getMasterPos')->willReturn($mPos);
     $bag = new HashBagOStuff();
     $cp = new ChronologyProtector($bag, ['ip' => '127.0.0.1', 'agent' => "Totally-Not-FireFox"]);
     $mockDB->expects($this->exactly(2))->method('writesOrCallbacksPending');
     $mockDB->expects($this->exactly(2))->method('lastDoneWrites');
     // Nothing to wait for
     $cp->initLB($lb);
     // Record in stash
     $cp->shutdownLB($lb);
     $cp->shutdown();
     // (b) Second HTTP request
     $cp = new ChronologyProtector($bag, ['ip' => '127.0.0.1', 'agent' => "Totally-Not-FireFox"]);
     $lb->expects($this->once())->method('waitFor')->with($this->equalTo($mPos));
     // Wait
     $cp->initLB($lb);
     // Record in stash
     $cp->shutdownLB($lb);
     $cp->shutdown();
 }