Memcache In PHP

Written by Tully on October 22, 2010 Categories: Linux, PHP

This week I have been doing a lot of caching with Memcache. Memcache is a great distributed memory caching system. I was running various tests and wanted to see general statistics. To check the stats for memcache, you can telnet into the Memcache ip/port and run the command stats.

Example:
telnet ip port
stats
quit

After doing this I wanted to write a simple class to get the statistics of Memcache in PHP. Below is the Memcache Stats class I wrote to connect to a Memcache server and run a command.

class MemcacheStats {

    private $ip;

    private $data;

    private $errors = array();

    public function __construct($ip)
    {
        $this->ip = $ip;
    }

    public function command($command)
    {
        try {
            $fh = @fsockopen($this->ip, 11211, $errno, $errstr, 30);
            if (!$fh) {
                array_push($this->errors, "$errno: $errstr");
                throw new Exception("Could not connect to memcache server at {$this->ip}");
            } else {
                $out = "$command\r\n";
                $out .= "quit\r\n";
                fwrite($fh, $out);
                while (!feof($fh)) {
                    $this->data .= fgets($fh, 128);
                }
            }
        } catch (Exception $e) {
            $this->errors = $e;
        }
        return $this->data;
    }

    public function isError()
    {
        if (!empty($this->errors)) {
            return $this->errors;
        }
        return false;
    }

    public function getData()
    {
        return $this->data;
    }
}
No Comments

Zend Form Hack

Written by Tully on October 15, 2010 Categories: PHP

Zend_Form_Element_Radio does not allow you to remove the preselected option. You can set it initially to an integer value that is not one of your radio option values. The problem with this is, when you reload the form and it doesn’t pass validation, the integer value you set to hack this gets reset to the first element option. To fix this problem, I wrote a hack you can add just before you give the view script the form object that resets it to an integer value that is not already set. If the user has selected an option that is valid, it will stay populated and not remove this selected option.

//Zend_Form_Radio has a bug where you cannot remove preselected
//values. The element default to the first option. This will
//loop through every radio element and set the value to 3
//if the value is empty. This is a hack which unsets the default value.
foreach ($form->getElements() as $element) {
    if ($element->getType() == 'Zend_Form_Element_Radio') {
        if ($element->getValue() == '') {
            $element->setValue('3');
        }
    }
}
No Comments

PHP gzip test

Written by Tully on October 12, 2010 Categories: Apache, PHP

Today I wrote a quick script to download a web page with both a compressed(gzip) version and a non-compressed version. I wanted something quick that I could run from the command line. The PHP gzip script returns the size of the page in both gzipped and non-gzipped versions. It also calculates the time it took to download each version in seconds. One last feature of the script is that it downloads the page 10 times in both versions, and displays the average of both gzipped and non-gzipped compressed versions.

How to run the script:

tully@hydralisk:/tmp$ php download.php http://example.com

No-Compression:    85047 Time: 0.00 seconds

With-Compression:  11178 Time: 1.00 seconds

Downloading compressed and non-compressed versions 10 times each and then calculating average…

Non-Compressed version: 0.5

Compressed version: 0.35

function download($site, $gzip=0)
{
// Headers
$headers = array('Accept-Encoding: compress, gzip');
$ch = curl_init($site);
if ($gzip==1)
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($ch);
return strlen($content);
}

if ($argc < 2) {
echo "Usage: php $argv[0]\n";
} else {
$start = time();
echo "No-Compression:    ".download($argv[1]);
printf("\tTime: %2.2f seconds \n", number_format(((time() - $start))));
$start = time();
echo "With-Compression:  ".download($argv[1], 1);
printf("\tTime: %2.2f seconds \n", number_format(((time() - $start))));
}

echo "\nDownloading compressed and non-compressed versions\n10 times each and then calculating average... \n";
$times = array();
for($i=0;$i<20;$i++) {
$start = time();
download($argv[1]);
array_push($times, (time() - $start));
}
echo "Non-Compressed version: ".average($times) . "\n";

$times = array();
for($i=0;$i<20;$i++) {
$start = time();
download($argv[1], 1);
array_push($times, (time() - $start));
}
echo "Compressed version: ".average($times) . "\n";

// Helper to get average
function average(Array $a)
{
return array_sum($a) / count($a);
}
No Comments

Jira Memory Error

Written by Tully on October 7, 2010 Categories: Linux

So this week I ran into memory errors with Jira. The exact error message that caused Jira to stop responding to requests was “java.lang.OutOfMemoryError: PermGen space”. After some research, I found out that this memory is not the common object heap space memory. This memory actually deals with the binary code of classes and methods. A good explanation of this error can be found here. After understanding what this error meant, I did some more research for increasing this particular type of memory. The solution I came up with is shown below.

In your favorite text editor(mine is VIM) open up the following file:
atlassian-jira-enterprise-4.1.2-standalone/bin/setenv.sh

Replace the JAVA_OPTS= line with the following:
export JAVA_OPTS=”-Xms768m -Xmx1024m -XX:MaxPermSize=256m”

The above line sets my minimum memory size to 768mb and max size to 1020mb. It also sets the Perm size to 256MB. The default perm size varies. Mine was defaulted to 64mb.

After changing this variable, save the file and restart Jira. Now login as an administrator. From the admin panel click the arrow next to Administrator and select “System Info”. Now scroll down to the section “Java VM Memory Statistics”. From here you can view how much memory you have allocated to JIRA and how much is being used.

1 Comment

Google Weather API

Written by Tully on October 4, 2010 Categories: PHP

Today I needed to display weather results for given cities. After reading reviews and API docs from various sites, I decided to use the Google Weather API. The Google Weather API was very easy to work with. All you need to do is hit the API with your city/zip and Google would return the 4 day forecast in XML. The API also included links to the weather condition images. If you wanted too, you could replace these links easily to use your own custom weather images.

Example of how to get the current condition:

$weatherObj = new GoogleWeather(‘Los Angeles California’);
$weatherResult = $weatherObj->getCurrentCondition ();

Example of how to retrieve 4 day forecast:

$weatherObj = new GoogleWeather(‘Los Angeles California’);
$weatherResult = $weatherObj->getAllDays();

/**
 * Used to return Weather results from Googles Weather API.
 *
 * Requires (PHP Curl,PHP Tidy)
 *
 * @author Tully Rankin
 *
 */
class GoogleWeather {

/**
 * URL of API
 *
 * @param string
 */
protected $url;

/**
 * Search Query
 *
 * @param string
 */
protected $query;

/**
 * Response from API Query
 *
 * @param string
 */
protected $data;

/**
 * DOM Instance
 *
 * @param DOMDocument
 */
protected $dom;

	/**
	 * Initializes GoogleWeather properties and
	 * queries API with search string.
	 *
	 * @param string $query Location to search
	 * @param string $url URL of the Google Weather API
	 */
	public function __construct($query, $url = 'http://www.google.com/ig/api?weather=')
	{
		$query = str_replace(' ', '+', $query);
		$this->query = $query;
		$this->url = $url;
		$this->_retrieveDATA();
		$this->dom = new DomDocument();
		$this->dom->loadXML($this->data);
		if ($this->_isResultEmpty())
			return false;
	}

	/**
	 * Queries GoogleWeather API.
	 * uses PHP Curl extention.
	 */
	protected function _retrieveDATA()
	{
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $this->url . $this->query);
		curl_setopt($ch, CURLOPT_HEADER, 0);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		$data = curl_exec($ch);
		$this->data = $this->_tidyXML($data);
	}

	/**
	 * Cleans up malformed XML Data.
	 *
	 * @param string $xml XML Formatted string
	 * @return string
	 */
	protected function _tidyXML($xml)
	{
		$options = array('input-xml' => true, 'output-xml' => true, 'clean' => true);
		$clean = tidy_parse_string($xml, $options, 'UTF8');
		tidy_clean_repair($clean);
		return $clean;
	}

	/**
	 * Checks if returned DATA has results.
	 *
	 * @return bool
	 */
	protected function _isResultEmpty()
	{
		$error = $this->dom->getElementsByTagName('problem_cause')->item(0);
		return $error;
	}

	/**
	 * Gets the current weather condition.
	 *
	 * @return array
	 */
	public function getCurrentCondition()
	{
		$node = $this->dom->getElementsByTagName('current_conditions')->item(0);
		$current = array();
		foreach ($node->childNodes as $c) {
			$current[$c->nodeName] = $c->getAttribute('data');
		}
		return $current;
	}

	/**
	 * Get weather conditions for all days. As of now
	 * Google currently returns 4 days.
	 *
	 * @return array
	 */
	public function getAllDays()
	{
		$nodes = $this->dom->getElementsByTagName('forecast_conditions');
		$i = 1;
		$weather = array();
		foreach ($nodes as $node) {
			foreach ($node->childNodes as $c) {
				if ($c->hasAttributes())
					$weather[$i][$c->nodeName] = $c->getAttribute('data');
			}
			$i++;
		}
		return $weather;
	}

}
// set tabstop=4

Download the Google Weather PHP Class

6 Comments

PHP Image Collage

Written by Tully on September 19, 2010 Categories: PHP

This weekend I started my first Facebook application. I decided to create an application that will take your friends photos and make a collage out of them. I intend to make the size of the collage a variable that can be selected from a drop-down HTML element. I would like the user to be able to create a collage that is the size of there screen resolution. This way they could make a wallpaper for there desktop with all there friends. Below is an example collage that was created using my PHP Collage Class and Facebooks graph API.

Using the class is easy:

include ‘Collage.php’;
$time = time();
$type = ‘jpg’;
$imageObj = new Collage($images, 250, 250);
$imageObj->execute();
$imageObj->saveFile(“images/{$time}.jpg”, $type);
echo
“<img src=\”images/{$time}.{$type}\” />”;

PHP Collage Class:

/**
 * This class is used to create an image collage from
 * an array of image links.
 *
 * @author Tully Rankin
 * @website http://www.TullyRankin.com
 */
class Collage {

	/**
	 * Holds array of image links
	 */
	public $images = array();

	/**
	 * Height of the collage image
	 */
	public $height;

	/**
	 * Width of the collage image
	 */
	public $width;

	/**
	 * Holds the buffer of all images
	 */
	public $imgBuf = array();

	/**
	 * Stores the created collage image
	 */
	public $imgOut;

	/**
	 * Holds array of Exception objects
	 */
	public $errors = array();

	public function __construct(Array $images, $height=1024, $width=768)
	{
		try {

			if (empty($images))
				throw new Exception('Images can not be empty.');

			$this->images = $images;
			$this->height = $height;
			$this->width = $width;

			$iTmp = "";

			$this->_addImagesToBuffer();
			$this->imgOut = imagecreatetruecolor($this->width, $this->height);
		} catch (Exception $e) {
			$this->errors[] = $e;
		}
	}

	/**
	 * Creates the collage
	 */
	public function execute()
	{
		$tmpHeight = 0;
		$tmpWidth = 0;

		try {
			do {
				foreach($this->imgBuf as $image) {
					if ($tmpWidth <= $this->width) {
						@imagecopy($this->imgOut, $image, $tmpWidth, $tmpHeight, 0, 0, imagesx($image), imagesy($image));
						@imagedestroy($image);
						$tmpWidth += 50;
					} else {
						$tmpWidth = 0;
						@imagecopy($this->imgOut, $image, $tmpWidth, $tmpHeight, 0, 0, imagesx($image), imagesy($image));
						@imagedestroy($image);
						$tmpWidth += 50;
						$tmpHeight += 50;
					}
				}
				$this->_addImagesToBuffer();;
			} while($tmpHeight <= $this->height);
		} catch (Exception $e) {
			$this->errors[] = $e;
		}
	}

	/**
	 * Saves the image to a file
	 *
	 * @param string $name The name of the image.
	 * @param string $type The image type to save as.
	 */
	public function saveFile($name, $type="jpeg")
	{
		try {
			ob_start();
			switch($type) {
				case "png":
					@imagepng($this->imgOut);
					break;
				case "jpg":
				case "jpeg":
					@imagejpeg($this->imgOut);
					break;
				case "gif":
					@imagegif($this->imgOut);
					break;
				default:
					throw new Exception("Unknown image type");
			}
			$contents = ob_get_contents();
			ob_end_clean();
			file_put_contents($name, $contents);
		} catch (Exception $e) {
			$this->errors[] = $e;
		}
	}

	/*
	 * Creates an image from each image given in the constructor.
	 * Adds it to public imgBuf array
	 */
	protected function _addImagesToBuffer()
	{
		$this->imgBuf = array();
		foreach($this->images as $imageSrc) {
        	$iTmp = imagecreatefromjpeg($imageSrc);
            array_push($this->imgBuf, $iTmp);
        }

	}
}

Click Here to view the class as a plain text file.

7 Comments

Craigslist Quick Search

Written by Tully on September 12, 2010 Categories: PHP Tags: , , ,

I wanted a quick way to search craigslist from the command line, so I decided to write a simple PHP script to do so. The below code takes 3 arguments. The first is the query string to search. The second is the minimum price for the listing. The last parameter is optional and just limits the results to whatever given integer you give it. This script only searches the Los Angeles area, but you could very easily just change the URL to your location.

if ($argc < 3) {
echo "Usage: php {$argv[0]} query minimumPrice [limit]n";
exit;
}

$argv[1] = urlencode($argv[1]);

$q = “http://losangeles.craigslist.org/search/sss?query={$argv[1]}&srchType=A&minAsk={$argv[2]}}&maxAsk=&hasPic=1?;

$ch = curl_init($q);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);

$dom = new DomDocument();
$dom->loadHTML($output);

$ps = $dom->getElementsByTagName(‘p’);

$count = (isset($argv[3])) ? $argv[3] : ’50?;
$i = 0
foreach ($ps as $p) {
if ($i >= $count)
break;
if ($p->getAttribute(‘class’) == ‘row’) {
echo $p->nodeValue;
}
$i++;
}
echo “n”;
8 Comments

MySQL Import CSV With Quotes

Written by Tully on July 8, 2010 Categories: MySQL Tags: , , ,

I was tasked to write a automated script to download a CSV file and import it into our database. This is an easy task but ran into an issue I hadn’t faced before. The CSV file had quotes on some columns and not on others. This was mix matched so my import script was not working properly. After doing some research I was able to get this working with the MySQL directive OPTIONALLY ENCLOSED BY.

Optionally Enclosed By Example
load data local infile 'example.csv' into table example_table
fields terminated by ','
OPTIONALLY ENCLOSED BY '"'
lines terminated by '\n'
(Column1, Column2, Column3)

No Comments

C++ Random String

Written by Tully on July 2, 2010 Categories: C++ Tags: , , , ,

Yesterday I was working with vectors and pointers. I decided to create a simple script to display random phrases for fun. The code I wrote uses only 2 custom functions. The first function is to get a random number between 0-4 and display that index of the vector. The second is a function to display 70 newlines to clear the screen. To get a random index I use the srand and rand functions. The first function srand is used to seed the rand function. To get a number between 0-4 I used the expression (rand() % 4) which will produce 1 number between 0 and 4. In the main of my program I create a infinite while loop and use the usleep function to sleep the program after each run. I used this function so there was time to read each phrase.

C++ Random String


// Display Random String
// C++ Example
// www.TullyRankin.com
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

string randomPhrase( const vector & p );
void clearScreen();

int main()
{
   vector phrases(4);
   phrases[0] = "The more I C, the less I see.";
   phrases[1] = "Backups? We don’t need no stinking backups.";
   phrases[2] = "Avoid the Gates of Hell. Use Linux";
   phrases[3] = "When you say \"I wrote a program that crashed Windows\",
   people just stare at you blankly and say \"Hey, I got those with the system, *for free*";
   clearScreen();
   while ( true )
   {
   cout << randomPhrase( phrases ) << endl;
   usleep(5000000);
   clearScreen();
   }
   return 0;

}

string randomPhrase( const vector & p )
{
   int size = p.size();
   srand( time(NULL) );
   return p[rand() % 4];
}

void clearScreen()
{
   for( int i = 0; i < 75; i++ )
      cout << endl;
}
No Comments

Selection Sort Algorithm

Written by Tully on July 1, 2010 Categories: C++ Tags: , , ,

Today I read a new chapter from DIETEL C++ How To Program on Pointers and Pointer-Based String. This chapter has been great on helping me understand how pointers work and why they are efficient. One of the algorithms the book discussed was the Selection Sort Algorithm. This was a simple algorithm but explains that it is inefficient on large lists and can even be slower on it’s similar algorithm the insertion sort. The way this algorithm works is that it iterates through the array selecting the smallest element in the array and swapping it with the first element. This process continues until it reaches the second to last element in the array. I have provided an example of the sort in C++ which you can view from the link below.

Selection Sort Algorithm

No Comments