Wednesday 30 May 2012

Get 4 position bound a position


Get 4 position bound a position
/**
     * @author phuc.duong
     * @todo G
     */
   public function getFourPosition($long, $lat, $distance) {
        $earthRadius = 6371;
        //latitude in radians
        $lat = ($lat * pi()) / 180;

        //longitude in radians
        $lon = ($long * pi()) / 180;

        //angular distance covered on earth's surface
        $d = floatval($distance) / $earthRadius;
        $arrTemp = array();
        $bearing = array(0, 90, 180, 270);
        foreach ($bearing as $key => $value) {
            $bearing = $value * pi() / 180; //rad
            $arrTemp[$key]['Lat'] = asin(sin($lat) * cos($d) + cos($lat) * sin($d) * cos($bearing));
            $arrTemp[$key]['Long'] = (($lon + atan2(sin($bearing) * sin($d) * cos($lat), cos($d) - sin($lat) * sin($arrTemp[$key]['Lat']))) * 180) / pi();
            $arrTemp[$key]['Lat'] = ($arrTemp[$key]['Lat'] * 180) / pi();
        }
        return $arrTemp;
    }

Saturday 26 May 2012

Monday 21 May 2012

Create Virtual Host on Ubuntu

Install
1. cd /etc/apache2/sites-available
2. sudo vim yourdomain.com.conf and enter your VirtualHost directive. Below I've put
the most basic example, see Apache docs for details and additional features:
3. <VirtualHost *>
4. ServerName yourdomain.com
5. DocumentRoot /home/youruser/public_html
6. </VirtualHost>
7. Save & exit.
8. sudo vim /etc/hosts and add your new domain to the 127.0.0.1 localhost line so it looks
like this:
9. 127.0.0.1 localhost yourdomain.com
10. Save & exit.
11. Enable your new virtualhost:
12. sudo a2ensite yourdomain.com.conf
13. Reload the Apache configuration:
14. sudo /etc/init.d/apache2 reload

Remove

Code:
sudo a2dissite sitename
Restart apache2
Code:
sudo /etc/init.d/apache2 reload
Again to remove (delete)it completely from the system,
Code:
sudo rm /etc/apache2/sites-available/sitename
I would also disable it first before deleting the file.

Backup script + User in mysql

backup script
***************************
su d=$(date +%Y_%m_%d_%H_%M)
project="project_data"
path="/backup/databases/$project-$d.gz"
mysqldump --opt --routines --single-transaction -uroot -ppassword $project | gzip > $path
**************************************

restore
****************************************
gunzip < project_data.gz | mysql -uroot -p -h192.168.1.1
project_data
****************************************

User
#####Create user
create user 'developer'@'localhost' identified by 'password';

######grant user
grant all on *.* to 'developer'@'localhost';
FLUSH PRIVILEGES;
#
######revoke user
REVOKE INSERT ON *.* FROM 'jeffrey'@'localhost';
FLUSH PRIVILEGES;
#
######Drop user
DROP USER 'jeffrey'@'localhost';

######Update user password
update user set password=PASSWORD("123456") where user='root' and
host='localhost';
flush privileges;

######Show grant of user
SHOW GRANTS FOR 'developer'@'%';

MySQL Replication

MySQL Replication

Two years ago, I had to learn MySQL replication because we had to transfer our databases to a new server with minimal downtime. If it's performed correctly, the downtime could be under 60 seconds. In my case, the downtime was about 5 minutes because of my carelessness. Nonetheless, MySQL replication can be used for many purposes including:
  1. Scalability - if most of your queries are read.
  2. Data security
  3. Analytics - there are cases when you have complex queries and you do not want to put the stress on the production server.
  4. Long-distance data distribution
Whatever your reason for coming here. Let's cut it short and start configuring.

Configuring the master server
  1. Master server must have binary log enabled
  2. Unique server-id must be configured
Edit my.cnf, for
  • Red Hat based server: /etc/my.cnf
  • Debian based server: /etc/mysql/my.cnf
Insert the following lines under [mysqld]:
[mysqld]
log-bin   = mysql-bin
server-id = 1
Make sure the following lines must be commented out. Otherwise, slave servers won't be able to access the master:
#skip-networking
#bind-address    = 127.0.0.1
Now, restart MySQL service:
Debian based:  service mysql restart
Red Hat based: /etc/init.d/mysqld restart
Create replication user on master server
  1. Log into MySQL server as root
    mysql -uroot -p
  2. Now, on MySQL shell create the replication user
    mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'%' IDENTIFIED BY 'password';
    mysql> FLUSH PRIVILEGES;
Configuring the slave server
  1. Unique server-id must be configured. Remember, none of the slave/master servers can have the same server-id. Server-id enabled communication between the master and slave servers.
  2. Enabling binary log is not compulsory but it recommended for data backup and crash recovery. There might be a case when you want this slave server to be the master server for other slaves.
  3. The following configurations can be set/changed whilst MySQL service is running:
    • master-host: master IP address or hostname.
    • master-user: MySQL user account with replication privilege.
    • master-password: replication user password.
    • master-connect-retry: seconds to retry to connect after network failure.
Edit my.cnf and insert the following lines under [mysqld]:
[mysqld]
log-bin               = mysql-bin
server-id             = 2
master-host           = 192.168.0.1
master-user           = slave_user
master-password       = password
master-connect-retry  = 60
Now, restart MySQL service.

Preparing to replicate
Most of the cases, we have our master database running long before the slave. Hence, the master database should have a lot of data. We must import data from master to slave before replicating. There are two ways:
  1. LOAD DATA FROM MASTER:
    use this if you are willing to have the master server being locked during the importing operation.
    1. Log into MySQL server as root:
      mysql -uroot -p
    2. Now, importing and replicating from MySQL shell:
      mysql> LOAD DATA FROM MASTER;
    Done! Life cannot be simpler than this!

  2. Common procedure:

    Tasks on master server

    1. Enabling READ LOCK from master server for mysqldump later. We want to make sure that data will not be changed while we dumping the databases:
      mysql> FLUSH TABLES WITH READ LOCK;
    2. Now, get the log sequence number:
      mysql> SHOW MASTER STATUS;
      If we see something like this, then we are on the right track:
      +------------------+----------+--------------+------------------+
      | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
      +------------------+----------+--------------+------------------+
      | mysql-bin.000001 |      106 |              |                  |
      +------------------+----------+--------------+------------------+
      1 row in set (0.00 sec)
      Please take note of the position (106)! This is the log position where we start backing up the data.
    3. Backup up the database from Linux shell:
      mysqldump --routines --triggers --single-transaction --quick -uroot -p --all-databases > all-dbs.sql
    4. Unlock the master database so data can be written:
      mysql> UNLOCK TABLES;
    5. Now, transfer SQL file (all-dbs.sql) to slave server.

    Tasks on slave server

    1. Import data to slave server:
      mysql -uroot -ppassword mysql < /path/to/all-dbs.sql
      Note: -ppassword: no space between -p & password
    2. Stop slave from replicating:
      mysql> SLAVE STOP;
    3. Now, we have to manually set the log sequence position:
      mysql> CHANGE MASTER TO
      MASTER_HOST='192.168.0.1',
      MASTER_USER='slave_user',
      MASTER_PASSWORD='password',
      MASTER_LOG_FILE='mysql-bin.001',
      MASTER_LOG_POS=106;
    4. Finally, start replicating:
      mysql> SLAVE START;
By now, our slave server should be replicating from the master server.

Zend Framework Cache Backend Memcached + Session Cache

Storing Sessions in Memcached with Zend Framework

Zend Framework has an excellent API for sessions in order to build out your own session save handler. By taking this approach I can still leverage the cache manager and share the same connection to memcached for other things in my application. If you need to expire contents during a deployment this can still handle it utilizing the “clone” keyword.
On to the code! See the link above for the Libmemcached implementation if you do not have the latest RC release. Next we need to build out the session save handler. We will name this Zend_Session_SaveHandler_Cache as it will support any cache that you would like to throw at it. The benefit of this really comes down to the lower environments and the ability to simply store sessions in APC for a time or even going to a simple file based for development / testing.

Zend_Session_SaveHandler_Cache

You will want to store this file in library/Zend/Session/SaveHandler/Cache.php. This handles the main setup for doing the Cache save handler.
 
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-webat this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Session
 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id$
 */
 
/**
 * @see Zend_Session
 */
require_once 'Zend/Session.php';
 
/**
 * @see Zend_Config
 */
require_once 'Zend/Config.php';
 
/**
 * @see Zend_Cache
 */
require_once 'Zend/Cache.php';
 
/**
 * Zend_Session_SaveHandler_Cache
 *
 
 * @category   Zend
 * @package    Zend_Session
 * @subpackage SaveHandler
 * @copyright  Copyright (c) 2010 CaringBridge. (http://www.caringbridge.org)
 */
class Zend_Session_SaveHandler_Cache
    implements Zend_Session_SaveHandler_Interface
{
 
    /**
     * Zend Cache
     * @var Zend_Cache
     */
    protected $_cache;
 
    /**
     * Destructor
     *
     * @return void
     */
    public function __destruct()
    {
        Zend_Session::writeClose();
    }
 
    /**
     * Set Cache
     *
     * @param Zend_Cache_Core $cache
     * @return Zend_Session_SaveHandler_Cache
     */
    public function setCache(Zend_Cache_Core $cache)
    {
        $this->_cache = $cache;
    }
 
    /**
     * Get Cache
     *-
     * @return Zend_Cache_Core
     */
    public function getCache()
    {
        return $this->_cache;
    }
 
    /**
     * Open Session
     *
     * @param string $save_path
     * @param string $name
     * @return boolean
     */
    public function open($save_path, $name)
    {
        $this->_sessionSavePath = $save_path;
        $this->_sessionName     = $name;
 
        return true;
    }
 
    /**
     * Close session
     *
     * @return boolean
     */
    public function close()
    {
        return true;
    }
 
    /**
     * Read session data
     *
     * @param string $id
     * @return string
     */
    public function read($id)
    {
        if (!$data = $this->_cache->load($id)) {
            return null;
        }
        return $data;
    }
 
    /**
     * Write session data
     *
     * @param string $id
     * @param string $data
     * @return boolean
     */
    public function write($id, $data)
    {
        return $this->_cache->save(
            $data,
            $id,
            array(),
            Zend_Session::getOptions('gc_maxlifetime')
        );
    }
 
    /**
     * Destroy session
     *
     * @param string $id
     * @return boolean
     */
    public function destroy($id)
    {
        return $this->_cache->remove($id);
    }
 
    /**
     * Garbage Collection
     *
     * @param int $maxlifetime
     * @return true
     */
    public function gc($maxlifetime)
    {
        return true;
    } 
 
   // add by phuc*************************************************
    /**
     * Set whether or not the lifetime of an existing session should be overridden
     *
     * @param boolean $overrideLifetime
     * @return Zend_Session_SaveHandler_DbTable
     */
    public function setOverrideLifetime($overrideLifetime)
    {
        $this->_overrideLifetime = (boolean) $overrideLifetime;

        return $this;
    }

    /**
     * Retrieve whether or not the lifetime of an existing session should be overridden
     *
     * @return boolean
     */
    public function getOverrideLifetime()
    {
        return $this->_overrideLifetime;
    }
    
    /**
     * Set session lifetime and optional whether or not the lifetime of an existing session should be overridden
     *
     * $lifetime === false resets lifetime to session.gc_maxlifetime
     *
     * @param int $lifetime
     * @param boolean $overrideLifetime (optional)
     * @return Zend_Session_SaveHandler_DbTable
     */
    public function setLifetime($lifetime, $overrideLifetime = null)
    {
        if ($lifetime < 0) {
            /**
             * @see Zend_Session_SaveHandler_Exception
             */
            require_once 'Zend/Session/SaveHandler/Exception.php';
            throw new Zend_Session_SaveHandler_Exception();
        } else if (empty($lifetime)) {
            $this->_lifetime = (int) ini_get('session.gc_maxlifetime');
        } else {
            $this->_lifetime = (int) $lifetime;
        }

        if ($overrideLifetime != null) {
            $this->setOverrideLifetime($overrideLifetime);
        }

        return $this;
    }  
}

Setting up the Application

To set up the application to work correctly, you will need to modify the application.ini file if you are using Zend_Application as well as modifying the bootstrap process to set the cache.

Application Configuration

This file is located at application/configs/application.ini
; setup the cache
resources.cachemanager.memcached.frontend.name                            = Core
resources.cachemanager.memcached.frontend.options.automatic_serialization = On
resources.cachemanager.memcached.backend.name                             = Libmemcached
resources.cachemanager.memcached.backend.options.servers.one.host         = localhost
resources.cachemanager.memcached.backend.options.servers.one.port         = 11211
resources.cachemanager.memcached.backend.options.servers.one.persistent   = On
; session savehandler class
resources.session.name = phpsessionname
resources.session.saveHandler.class        = Zend_Session_SaveHandler_Cache
resources.session.gc_maxlifetime           = 7200

Setting up the Bootstrap

This file is located at: application/Bootstrap.php. Since the Zend_Session_SaveHandler_Cache requires a cache to be set, we need to place this in the bootstrap, also you will likely want to ensure no possibility of session hijacking in the bootstrap as well.
    /** 
     * Initialize the Session Id
     * This code initializes the session and then
     * will ensure that we force them into an id to
     * prevent session fixation / hijacking.
     *
     * @return void
     */
    protected function _initSessionId()
    {   
        $this->bootstrap('session');
        $opts = $this->getOptions();
        if ('Zend_Session_SaveHandler_Cache' == $opts['resources']['session']['saveHandler']['class']) {
            $cache = $this->bootstrap('cachemanager')
                          ->getResource('cachemanager')
                          ->getCache('memcached');
            Zend_Session::getSaveHandler()->setCache($cache);
        }
        $defaultNamespace = new Zend_Session_Namespace();
        if (!isset($defaultNamespace->initialized)) {
            Zend_Session::regenerateId();
            $defaultNamespace->initialized = true;
        }
    }

Sharing Libmemcached between Content and Sessions

Say we want to share the cache within our code base but utilize an SVN revision number to keep a prefix for the cache but not the sessions. Here is an implementation to do so in the Bootstrap.php file based on the above configuration.
    /**
     * Initialize the Cache Manager
     * Initializes the memcached cache into
     * the registry and returns the cache manager.
     *
     * @return Zend_Cache_Manager
     */
    protected function _initCachemanager()
    {
        $cachemanager = $this->getPluginResource('cachemanager')
                             ->init();
 
        // fetch the current revision from svn and use it as a prefix
        // why: we do not want to restart memcached, or you will lose sessions.
        if (!$appVersion = apc_fetch('progsite_version')) {
            $dir = getcwd();
            chdir(dirname(__FILE__));
            $appVersion = filter_var(`svn info | grep "Revision"`, FILTER_SANITIZE_NUMBER_INT);
            chdir($dir);
            unset($dir);
            if (!$appVersion) {
                $appVersion = mt_rand(0, 99999); // simply handles an export instead of checkout
            }
            apc_store('progsite_version', $appVersion);
        }
 
        $memcached = $cachemanager->getCache('memcached');
        $memcached->setOption('cache_id_prefix', APPLICATION_ENV . '_' . $appVersion);
 
        return $cachemanager;
    }
 
    /**
     * Initialize the Session Id
     * This code initializes the session and then
     * will ensure that we force them into an id to
     * prevent session fixation / hijacking.
     *
     * @return void
     */
    protected function _initSessionId()
    {
        $this->bootstrap('session');
        $opts = $this->getOptions();
        if ('Zend_Session_SaveHandler_Cache' == $opts['resources']['session']['saveHandler']['class']) {
            $cache = $this->bootstrap('cachemanager')
                          ->getResource('cachemanager')
                          ->getCache('memcached'); 
            $cache = clone $cache;
            $cache->setOption('cache_id_prefix', APPLICATION_ENV);
 
            Zend_Session::getSaveHandler()->setCache($cache);
        }
        $defaultNamespace = new Zend_Session_Namespace();
        if (!isset($defaultNamespace->initialized)) {
            Zend_Session::regenerateId();
            $defaultNamespace->initialized = true;
        }
    }
Note that the above code clones the current memcached adapter. We do this so that we can keep 1 instance that utilizes the cache_id_prefix with a number for the revision number and then sessions do not need that. This allows us to see content changes at deployment when the web server is restarted but we do not need to lose our session states.

Conclusion

Memcached is a handy tool to have, it also works well to integrate into the Zend Framework. I hope someone else also finds the Session_SaveHandler_Cache useful. This has been running out in a production environment for quite a while and has been extremely stable. Why not take it for a run yourself.