Dynamic image resizing in PHP

Via Darren Hoyt we found a reference to TimThumb, a quick and fast PHP script for on-the-fly image resizing. Once the script is on the server, and named timthumb.php, you can use the following reference to launch it:
<img src="/scripts/timthumb.php?src=/images/whatever.jpg&h=150&w=150&zc=1" alt="" />
Here's the source code for timthumb.php:

// TimThumb script created by Tim McDaniels and Darren Hoyt with tweaks by Ben Gillbanks
// http://code.google.com/p/timthumb/

// MIT License: http://www.opensource.org/licenses/mit-license.php

/* Parameters allowed: */

// w: width
// h: height
// zc: zoom crop (0 or 1)
// q: quality (default is 75 and max is 100)

// HTML example:

if( !isset( $_REQUEST[ "src" ] ) ) { die( "no image specified" ); }

// clean params before use
$src = preg_replace( "/^(\.+(\/|))+/", "", $_REQUEST['src'] );
$src = preg_replace( '/^(s?f|ht)tps?:\/\/[^\/]+/i', '', $src );
$new_width = preg_replace( "/[^0-9]/", "", $_REQUEST[ 'w' ] );
$new_height = preg_replace( "/[^0-9]/", "", $_REQUEST[ 'h' ] );
$zoom_crop = preg_replace( "/[^0-9]/", "", $_REQUEST[ 'zc' ] );

if( !isset( $_REQUEST['q'] ) ) { $quality = 80; } else { $quality = preg_replace("/[^0-9]/", "", $_REQUEST['q'] ); }

// set path to cache directory (default is ./cache)
// this can be changed to a different location
$cache_dir = './cache';

// get mime type of src
$mime_type = mime_type( $src );

// check to see if this image is in the cache already
check_cache( $cache_dir, $mime_type );

// make sure that the src is gif/jpg/png
if( !valid_src_mime_type( $mime_type ) ) {
$error = "Invalid src mime type: $mime_type";
die( $error );
}

// check to see if GD function exist
if(!function_exists('imagecreatetruecolor')) {
$error = "GD Library Error: imagecreatetruecolor does not exist";
die( $error );
}

// set document root
$doc_root = $_SERVER['DOCUMENT_ROOT'];

// get path to image on file system
$src = $doc_root . '/' . $src;

if(strlen($src) && file_exists( $src ) ) {

// open the existing image
$image = open_image($mime_type, $src);
if ($image === false) { die ('Unable to open image : ' . $src ); }

// Get original width and height
$width = imagesx($image);
$height = imagesy($image);

// generate new w/h if not provided
if($new_width && !$new_height) {
$new_height = $height * ($new_width/$width);
}
elseif($new_height && !$new_width) {
$new_width = $width * ($new_height/$height);
}
elseif(!$new_width && !$new_height) {
$new_width = $width;
$new_height = $height;
}

// create a new true color image
$canvas = imagecreatetruecolor($new_width, $new_height);

if( $zoom_crop ) {

$src_x = $src_y = 0;
$src_w = $width;
$src_h = $height;

$cmp_x = $width / $new_width;
$cmp_y = $height / $new_height;

// calculate x or y coordinate and width or height of source

if ( $cmp_x > $cmp_y ) {

$src_w = round( ( $width / $cmp_x * $cmp_y ) );
$src_x = round( ( $width - ( $width / $cmp_x * $cmp_y ) ) / 2 );

}
elseif ( $cmp_y > $cmp_x ) {

$src_h = round( ( $height / $cmp_y * $cmp_x ) );
$src_y = round( ( $height - ( $height / $cmp_y * $cmp_x ) ) / 2 );

}

imagecopyresampled( $canvas, $image, 0, 0, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h );

}
else {

// copy and resize part of an image with resampling
imagecopyresampled( $canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height );

}

// output image to browser based on mime type
show_image( $mime_type, $canvas, $quality, $cache_dir );

// remove image from memory
ImageDestroy( $canvas );

} else {

if( strlen( $src ) ) { echo $src . ' not found.'; } else { echo 'no source specified.'; }

}

function show_image ($mime_type, $image_resized, $quality, $cache_dir) {

// check to see if we can write to the cache directory
$is_writable = 0;
$cache_file_name = $cache_dir . '/' . get_cache_file();

if( touch( $cache_file_name ) ) {
// give 666 permissions so that the developer
// can overwrite web server user
chmod( $cache_file_name, 0666 );
$is_writable = 1;
}
else {
$cache_file_name = NULL;
header('Content-type: ' . $mime_type);
}

if(stristr( $mime_type, 'gif' ) ) {
imagegif( $image_resized, $cache_file_name );
}
elseif( stristr( $mime_type, 'jpeg' ) ) {
imagejpeg( $image_resized, $cache_file_name, $quality );
}
elseif( stristr( $mime_type, 'png' ) ) {
imagepng( $image_resized, $cache_file_name, ceil( $quality / 10 ) );
}
if( $is_writable ) { show_cache_file( $cache_dir, $mime_type ); }
exit;

}

function open_image ($mime_type, $src) {

if(stristr($mime_type, 'gif')) {
$image = imagecreatefromgif($src);
}
elseif(stristr($mime_type, 'jpeg')) {
$image = imagecreatefromjpeg($src);
}
elseif(stristr($mime_type, 'png')) {
$image = imagecreatefrompng($src);
}
return $image;

}

function mime_type ($file) {

$frags = split("\.", $file);
$ext = strtolower( $frags[ count( $frags ) - 1 ] );
$types = array(
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'bmp' => 'image/bmp',
'doc' => 'application/msword',
'xls' => 'application/msword',
'xml' => 'text/xml',
'html' => 'text/html'
);
$mime_type = $types[$ext];
if(!strlen($mime_type)) { $mime_type = 'unknown'; }
return($mime_type);

}

function valid_src_mime_type ( $mime_type ) {

if( preg_match( "/jpg|jpeg|gif|png/i", $mime_type ) ) { return 1; }
return 0;

}

function check_cache ( $cache_dir, $mime_type ) {

// make sure cache dir exists
if(!file_exists($cache_dir)) {
// give 777 permissions so that developer can overwrite
// files created by web server user
mkdir( $cache_dir );
chmod( $cache_dir, 0777 );
}
show_cache_file( $cache_dir, $mime_type );

}

function show_cache_file ( $cache_dir, $mime_type ) {

$cache_file = get_cache_file();

if( file_exists( $cache_dir . '/' . $cache_file ) ) {

// check for updates
$if_modified_since = preg_replace('/;.*$/', '', $_SERVER[ "HTTP_IF_MODIFIED_SINCE" ]);
$gmdate_mod = gmdate('D, d M Y H:i:s', filemtime( $cache_dir . '/' . $cache_file ) );
if(strstr($gmdate_mod, 'GMT')) {
$gmdate_mod .= " GMT";
}

//error_log("TimThumb: $gmdate_mod == $if_modified_since");

if ( $if_modified_since == $gmdate_mod ) {
header( "HTTP/1.1 304 Not Modified" );
exit;
}

// send headers then display image
header( "Content-Type: " . $mime_type );
header( "Last-Modified: " . gmdate('D, d M Y H:i:s', filemtime( $cache_dir . '/' . $cache_file ) . " GMT" ) );
header( "Content-Length: " . filesize( $cache_dir . '/' . $cache_file ) );
header( "Cache-Control: max-age=9999, must-revalidate" );
header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + 9999 ) . "GMT" );
readfile( $cache_dir . '/' . $cache_file );
exit;

}

}

function get_cache_file () {

$request_params = $_REQUEST;
$cachename = $_REQUEST['src'] . $_REQUEST['w'] . $_REQUEST['h'] . $_REQUEST['zc'] . $_REQUEST['q'];
$cache_file = md5( $cachename );
return $cache_file;

}

Topics: PHP | 1 Comment »

Spiraling quine in Perl


#!/usr/bin/perl
$_='
$q ="\ 47"; wh
ile ($ ;=
$z += .5 ){
%c= $r=0;$/ ="";whi le(2
0+ $z>($;+=.05)){$c{int$ _+ 2
6+ 2*($ r+= .0 2) *
s in$ ;}{1 -$_
+1 0+ int $r*c o s
$ ;} =1for(0. .1) }$
t =r ever se;$ /. =`
c le ar `. " #!
/ usr /bi n/ pe
rl \n\ $_ =$q \n" ;
fo r$y (1..20){$c{$_} {
$ y }? $ /.=chop$t :
($/ . =" \4
0") for(0. .53) ;
$/. ="\n"}pri nt"$/$ q;
s; ". chr(9 2)."s;;g;eval\n "}

';s;\s;;g;eval

Courtesy of PerlMonks

Topics: perl, quine | No Comments »

PHP imagefilter without GD

This code is intended for imagefilter() to work on the servers which don't have PHP GD extension.

//include this file whenever you have to use imageconvolution…
//you can use in your project, but keep the comment below
//great for any image manipulation library
//Made by Chao Xu(Mgccl) 3/1/07
//www.webdevlogs.com
//V 1.0
if(!function_exists(‘imagefilter’)){
function imagefilter($source, $var, $arg1 = null, $arg2 = null, $arg3 = null){
#define(’IMAGE_FILTER_NEGATE’,0);
#define(’IMAGE_FILTER_GRAYSCALE’,0);
#define(’IMAGE_FILTER_BRIGHTNESS’,2);
#define(’IMAGE_FILTER_CONTRAST’,3);
#define(’IMAGE_FILTER_COLORIZE’,4);
#define(’IMAGE_FILTER_EDGEDETECT’,5);
#define(’IMAGE_FILTER_EMBOSS’,6);
#define(’IMAGE_FILTER_GAUSSIAN_BLUR’,7);
#define(’IMAGE_FILTER_SELECTIVE_BLUR’,8);
#define(’IMAGE_FILTER_MEAN_REMOVAL’,9);
#define(’IMAGE_FILTER_SMOOTH’,10);
$max_y = imagesy($source);
$max_x = imagesx($source);
switch ($var){
case 0:
$y = 0;
while($y<$max_y) {
$x = 0;
while($x<$max_x){
$rgb = imagecolorat($source,$x,$y);
$r = 255 - (($rgb >> 16) & 0xFF);
$g = 255 - (($rgb >> 8) & 0xFF);
$b = 255 - ($rgb & 0xFF);
$a = $rgb >> 24;
$new_pxl = imagecolorallocatealpha($source, $r, $g, $b, $a);
if ($new_pxl == false){
$new_pxl = imagecolorclosestalpha($source, $r, $g, $b, $a);
}
imagesetpixel($source,$x,$y,$new_pxl);
++$x;
}
++$y;
}
return true;
break;
case 1:
$y = 0;
while($y<$max_y) {
$x = 0;
while($x<$max_x){
$rgb = imagecolorat($source,$x,$y);
$a = $rgb >> 24;
$r = ((($rgb >> 16) & 0xFF)*0.299)+((($rgb >> 8) & 0xFF)*0.587)+(($rgb & 0xFF)*0.114);
$new_pxl = imagecolorallocatealpha($source, $r, $r, $r, $a);
if ($new_pxl == false){
$new_pxl = imagecolorclosestalpha($source, $r, $r, $r, $a);
}
imagesetpixel($source,$x,$y,$new_pxl);
++$x;
}
++$y;
}
return true;
break;
case 2:
$y = 0;
while($y<$max_y) {
$x = 0;
while($x<$max_x){
$rgb = imagecolorat($source,$x,$y);
$r = (($rgb >> 16) & 0xFF) + $arg1;
$g = (($rgb >> 8) & 0xFF) + $arg1;
$b = ($rgb & 0xFF) + $arg1;
$a = $rgb >> 24;
$r = ($r > 255)? 255 : (($r < 0)? 0:$r);
$g = ($g > 255)? 255 : (($g < 0)? 0:$g);
$b = ($b > 255)? 255 : (($b < 0)? 0:$b);
$new_pxl = imagecolorallocatealpha($source, $r, $g, $b, $a);
if ($new_pxl == false){
$new_pxl = imagecolorclosestalpha($source, $r, $g, $b, $a);
}
imagesetpixel($source,$x,$y,$new_pxl);
++$x;
}
++$y;
}
return true;
break;
case 3:
$contrast = pow((100-$arg1)/100,2);
$y = 0;
while($y<$max_y) {
$x = 0;
while($x<$max_x){
$rgb = imagecolorat($source,$x,$y);
$a = $rgb >> 24;
$r = (((((($rgb >> 16) & 0xFF)/255)-0.5)*$contrast)+0.5)*255;
$g = (((((($rgb >> 8) & 0xFF)/255)-0.5)*$contrast)+0.5)*255;
$b = ((((($rgb & 0xFF)/255)-0.5)*$contrast)+0.5)*255;
$r = ($r > 255)? 255 : (($r < 0)? 0:$r);
$g = ($g > 255)? 255 : (($g < 0)? 0:$g);
$b = ($b > 255)? 255 : (($b < 0)? 0:$b);
$new_pxl = imagecolorallocatealpha($source, $r, $g, $b, $a);
if ($new_pxl == false){
$new_pxl = imagecolorclosestalpha($source, $r, $g, $b, $a);
}
imagesetpixel($source,$x,$y,$new_pxl);
++$x;
}
++$y;
}
return true;
break;
case 4:
$x = 0;
while($x<$max_x){
$y = 0;
while($y<$max_y){
$rgb = imagecolorat($source, $x, $y);
$r = (($rgb >> 16) & 0xFF) + $arg1;
$g = (($rgb >> 8) & 0xFF) + $arg2;
$b = ($rgb & 0xFF) + $arg3;
$a = $rgb >> 24;
$r = ($r > 255)? 255 : (($r < 0)? 0:$r);
$g = ($g > 255)? 255 : (($g < 0)? 0:$g);
$b = ($b > 255)? 255 : (($b < 0)? 0:$b);
$new_pxl = imagecolorallocatealpha($source, $r, $g, $b, $a);
if ($new_pxl == false){
$new_pxl = imagecolorclosestalpha($source, $r, $g, $b, $a);
}
imagesetpixel($source,$x,$y,$new_pxl);
++$y;
}
++$x;
}
return true;
break;
case 5:
return imageconvolution($source, array(array(-1,0,-1), array(0,4,0), array(-1,0,-1)), 1, 127);
break;
case 6:
return imageconvolution($source, array(array(1.5, 0, 0), array(0, 0, 0), array(0, 0, -1.5)), 1, 127);
break;
case 7:
return imageconvolution($source, array(array(1, 2, 1), array(2, 4, 2), array(1, 2, 1)), 16, 0);
break;
case 8:
for($y = 0; $y<$max_y; $y++) {
for ($x = 0; $x<$max_x; $x++) {
$flt_r_sum = $flt_g_sum = $flt_b_sum = 0;
$cpxl = imagecolorat($source, $x, $y);
for ($j=0; $j<3; $j++) {
for ($i=0; $i<3; $i++) {
if (($j == 1) && ($i == 1)) {
$flt_r[1][1] = $flt_g[1][1] = $flt_b[1][1] = 0.5;
} else {
$pxl = imagecolorat($source, $x-(3>>1)+$i, $y-(3>>1)+$j);

$new_a = $pxl >> 24;
//$r = (($pxl >> 16) & 0xFF);
//$g = (($pxl >> 8) & 0xFF);
//$b = ($pxl & 0xFF);
$new_r = abs((($cpxl >> 16) & 0xFF) - (($pxl >> 16) & 0xFF));
if ($new_r != 0) {
$flt_r[$j][$i] = 1/$new_r;
} else {
$flt_r[$j][$i] = 1;
}

$new_g = abs((($cpxl >> 8) & 0xFF) - (($pxl >> 8) & 0xFF));
if ($new_g != 0) {
$flt_g[$j][$i] = 1/$new_g;
} else {
$flt_g[$j][$i] = 1;
}

$new_b = abs(($cpxl & 0xFF) - ($pxl & 0xFF));
if ($new_b != 0) {
$flt_b[$j][$i] = 1/$new_b;
} else {
$flt_b[$j][$i] = 1;
}
}

$flt_r_sum += $flt_r[$j][$i];
$flt_g_sum += $flt_g[$j][$i];
$flt_b_sum += $flt_b[$j][$i];
}
}

for ($j=0; $j<3; $j++) {
for ($i=0; $i<3; $i++) {
if ($flt_r_sum != 0) {
$flt_r[$j][$i] /= $flt_r_sum;
}
if ($flt_g_sum != 0) {
$flt_g[$j][$i] /= $flt_g_sum;
}
if ($flt_b_sum != 0) {
$flt_b[$j][$i] /= $flt_b_sum;
}
}
}

$new_r = $new_g = $new_b = 0;

for ($j=0; $j<3; $j++) {
for ($i=0; $i<3; $i++) {
$pxl = imagecolorat($source, $x-(3>>1)+$i, $y-(3>>1)+$j);
$new_r += (($pxl >> 16) & 0xFF) * $flt_r[$j][$i];
$new_g += (($pxl >> 8) & 0xFF) * $flt_g[$j][$i];
$new_b += ($pxl & 0xFF) * $flt_b[$j][$i];
}
}

$new_r = ($new_r > 255)? 255 : (($new_r < 0)? 0:$new_r);
$new_g = ($new_g > 255)? 255 : (($new_g < 0)? 0:$new_g);
$new_b = ($new_b > 255)? 255 : (($new_b < 0)? 0:$new_b);
$new_pxl = ImageColorAllocateAlpha($source, (int)$new_r, (int)$new_g, (int)$new_b, $new_a);
if ($new_pxl == false) {
$new_pxl = ImageColorClosestAlpha($source, (int)$new_r, (int)$new_g, (int)$new_b, $new_a);
}
imagesetpixel($source,$x,$y,$new_pxl);
}
}
return true;
break;
case 9:
return imageconvolution($source, array(array(-1,-1,-1),array(-1,9,-1),array(-1,-1,-1)), 1, 0);
break;
case 10:
return imageconvolution($source, array(array(1,1,1),array(1,$arg1,1),array(1,1,1)), $arg1+8, 0);
break;
}
}
}
?>

Topics: PHP | No Comments »

Recursive quicksort


#include
#include
void qsort(int a[],int,int);
void partition(int a[],int,int,int *);
void print(int *,int);
void swap(int *,int *);

void main()
{
int a[30],i,n;
flushall();
clrscr();
printf("
enter how many data u want :");
scanf("%d",&n);

printf("
enter the data :");
for(i=0;i {
printf("
%d .",i);
scanf("%d",&a[i]);
}
qsort(a,0,n-1);
printf("
SORTED DATA:
");
print(a,n-1);
getch();
}
void qsort(int a[],int lb,int ub)
{
int j;
if(ub>lb)
{
partition(a,lb,ub,&j);
qsort(a,lb,j-2);
qsort(a,j+2,ub);
}
}
void partition(int a[],int lb,int ub,int *j)
{

int mid=(lb+ub)/2,temp,up,down,pivot;
pivot=a[mid];
up=ub;
down=lb;
while(down {
while( a[down] <= pivot && down <= ub )
{
down++;
if(a[down]lb)
swap(&a[down],&a[down-1]);
}
while(a[up]>pivot)
{
up--;
if(a[up]>a[up+1]&&up swap(&a[up],&a[up+1]);
}
if(down {
swap(&a[down],&a[up]);
if(a[down]0)
swap(&a[down],&a[down-1]);
if(a[up]>a[up+1]&&up swap(&a[up],&a[up+1]);
}

}
for(int i=0;i if(a[i]>a[i+1])
swap(&a[i],&a[i+1]);
*j=up;
}
void print(int a[],int n)
{
for(int i=0;i<=n;i++)
printf("
%d . %d",i,a[i]);
}
void swap(int *p,int *q)
{
int t;
t=*p;
*p=*q;
*q=t;
}

Topics: C++ | No Comments »

Nice CSS tab menu with PHP


if (isset($_REQUEST['tab'])) {
$tab = $_REQUEST['tab'];
} else {
$tab = 0;
}
?>



switch ($tab) {
case 1: //Manage User Tab1
?>

break;
case 2: // Manage User Tab2

?>

break;
default: // Manage User TabDefault
?>

break;
}
?>



Topics: PHP, apache, css | No Comments »

A vertical menu done in CSS


body{
background: #fff;
line-height: 1.1;
color: #666;
font: small Verdana, Geneva, Arial, Helvetica, sans-serif;
}

#Navigator {
width: auto;
background: #fcfcff ;
padding: 0 6px .5em 12px;
overflow: visible;
min-width:750px;
clear: both!important;
top:1em!important;
margin-bottom:1em!important;
}
.fixclear {
display:block;
position:relative
}

#NavData {
float:left;
clear: left;
width:225px;
margin:0;
}

div.NavMain {
background:#FcFcFf;
position:relative;
margin-bottom:1em;
width:auto!important;
width:100%;
border:1px solid #CAD6E8 ;
padding:1em 0 1.5em 0;

}

h2, h3{
color:#036;
background: transparent;
font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif
}

h4 {
font: bold 100% Verdana, Arial, Helvetica, sans-serif;
}

a:link{
color: #06c;
background: transparent;
}
a:visited{

color:#4B5970;
background: transparent;
}
a:hover{
color: #f60;
background: transparent;
}

#Navigator div h3 {
font: normal .9em Verdana, Arial, Helvetica, sans-serif;
height:1em;
padding:2px 1.5em 4px .5em;
clear: right;
color:#99ACCA ;
background:transparent url(bulletr.gif) right center no-repeat;
margin:0;
position:absolute;
right:-1px;
top:-.8em;
border:0 none;
}

div.NavMain * {
margin:4px 6px 6px 10px;
}
div.NavMain * * {
margin:0;
}
div.NavMain h4 {
color: #E14900;
}

div.NavMain ul, div.NavMain ol{
margin: 5px 0 10px 5px;
padding:0 0 0 5px;
font-size:77%;
font-weight:bold;
}

div.NavMain li {
margin: 0 5px 5px 18px;
padding:0
}
div.NavMain ul li {
list-style-image: url(Bullet.gif);
}
div.NavMain ul li:hover {
list-style-image:url(Bullet.gif)
}
div.NavMain p {
font-size:77% ;
margin-bottom:10px
}

Topics: css | No Comments »

CSS message quoting

QUOTE
First quote

QUOTE
More quotes


Topics: css | 1 Comment »

Fading alerts in JavaScript







Title




Topics: ajax, html, javascript | No Comments »

Find the square root of a number with any precision


function bcgetscale(){
return strlen(bcadd(1,0))-2;
}

//Version 0.2 of BCRoot
//By Chao XU
//From www.webdevlogs.com
//Change Log: It uses a lot bcsqrt() to make the speed fast
//fix a small decimal bug, where the last decimal could be wrong

function bcroot($a, $n, $scale='default'){
$default = bcgetscale();//Get the scale
if($scale == 'default'){
$scale = $default;//use default scale
}
if($n & ($n-1)){//check if $n is the power of 2, return 0 if is
//decbin is the reason this function can't have number
//larger than 2^31
$bin = decbin($n);
$i = strlen($bin)-1;
$pow = 0;
while($i){
if($bin[$i]==='0'){
++$pow; –$i;
}else{
break;
}
}
$n = bcdiv($n, bcpow(2, $pow),0);
//now use Newton’s method to find the number
bcscale($scale+15);
$x = 1;
$k = 0;
$limit = ceil(log($scale+15)/log(2))+1;
while($k<$limit){
$t1 = bcdiv(1,$n);
$t21 = bcmul(bcsub($n,1),$x);
$t22 = bcdiv($a,bcpow($x, $n-1));
$t2 = bcadd($t21,$t22);
$x = bcmul($t1, $t2);
++$k;
}
$i = 0;
while($i < $pow){
$x = bcsqrt($x,$scale+3);
++$i;
}
bcscale($default);
return bcadd($x,0,$scale);
}else{
//here use many bcsqrt, because this is FAST
$i = 0;
$pow = log($n)/log(2);
while($i < $pow){
$a = bcsqrt($a,$scale+3);
++$i;
}
return bcadd($a,0,$scale);
}
}

And now use it

$the_number = 3;
$the_nth_root = 12;
$the_precision = 30;
bcroot($the_number, $the_nth_root, $the_precision);
//returns 1.095872691135244380160019128072.
//Which is the 12th root of 3

Topics: PHP | No Comments »

Measuring the speed of MySQL replication

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use DBI;
use Time::HiRes qw/ usleep gettimeofday tv_interval/;
use English qw( -no_match_vars );

my $username1 = 'user1';
my $password1 = 'user2';
my $username2 = 'pass1';
my $password2 = 'pass2';
my $host1 = 'host_IP1';
my $host2 = 'host_IP2';
my $port1 = '3306';
my $port2 = '3306';

my $dbh1=DBI->connect("dbi:mysql:test;host=$host1;port=$port1",
$username1, $password1,
{RaiseError => 1})
or die "Can't connect: $DBI::errstr\n";

my $dbh2=DBI->connect("dbi:mysql:test;host=$host2;port=$port2",
$username2, $password2,
{RaiseError => 1})
or die "Can't connect: $DBI::errstr\n";

my $loops = 10; # how many times we loop (with size increase)
my $num_of_inserts = 5; # how many records we insert for each loop
my $initial_blob_size = 1_000; # how big is the record we start with
my $replica_db = 'test'; # which database we use for testing

my $master_dbh = $dbh1;
my $slave_dbh = $dbh2;

my ( $exists_db ) = $master_dbh->selectrow_array(qq{SHOW DATABASES LIKE '$replica_db'});
unless ($exists_db) {
eval {$master_dbh->do(qq{CREATE DATABASE $replica_db}) };
if ( $EVAL_ERROR ) {
die "execution error $DBI::errstr\n";
}
}

# creating the measurement table
eval {
$master_dbh->do( qq{
CREATE DATABASE IF NOT EXISTS $replica_db});
$master_dbh->do( qq{
USE $replica_db } );
$master_dbh->do( qq{
DROP TABLE IF EXISTS replica_speed });
$master_dbh->do( qq{
CREATE TABLE replica_speed (
id int(11) NOT NULL auto_increment,
insert_sequence int not null,
seconds bigint(20) default NULL,
microseconds bigint(20) default NULL,
ts timestamp(14) NOT NULL,
big_one longtext,
PRIMARY KEY (`id`),
KEY insert_sequence (insert_sequence)
)
} );
};
if ($EVAL_ERROR) {
die "table creation error $DBI::errstr\n";
}

# give some time to the table creation to get replicated
usleep(200_000);
my $insert_query = qq{
INSERT INTO $replica_db.replica_speed
(insert_sequence, seconds, microseconds, big_one)
VALUES ( ?, ?, ?, ?) };
my $retrieve_query = qq{
SELECT seconds, microseconds, id, insert_sequence
FROM $replica_db.replica_speed
WHERE insert_sequence = ?
};
my $slave_sth = $slave_dbh->prepare($retrieve_query);

# checking max_allowed_packet to make sure that we are not
# exceeding the limits
my ( undef, $master_max_allowed_packet) = $master_dbh->selectrow_array(
qq{ SHOW VARIABLES LIKE "max_allowed_packet" } );

my ( undef, $slave_max_allowed_packet) = $slave_dbh->selectrow_array(
qq{ SHOW VARIABLES LIKE "max_allowed_packet" } );

my $max_allowed_packet = $master_max_allowed_packet;
if ( $slave_max_allowed_packet < $master_max_allowed_packet) {
$max_allowed_packet = $slave_max_allowed_packet;
}
my @results = ();

LOOP:
for my $loopcount (0 .. $loops )
{
usleep(200_000);
# let's start with an empty table
$master_dbh->do( qq{ TRUNCATE $replica_db.replica_speed } );
my $size = $initial_blob_size * ($loopcount || 1);
if ($size > $max_allowed_packet) {
$size = $max_allowed_packet - 1000;
}
my $master_insert_time = 0.0;
my $big_blob = 'a' x $size;

# inserting several records in the master
for my $sequence (1 .. $num_of_inserts ) {
my ( $secs, $msecs ) = gettimeofday();
$master_dbh->do($insert_query, undef, $sequence, $secs, $msecs, $big_blob);
$master_insert_time = tv_interval( [$secs, $msecs], [gettimeofday()]);
}
my $replication_delay = 0;
my $total_retrieval_time = 0;
my $baredelay = undef;
# fetching data from the slave
RETRIEVAL:
while ( ! $replication_delay ) # waiting for data to arrive from master to slave
{
my $retrieval_start_time = [gettimeofday()];
$slave_sth->execute( $num_of_inserts);
my $info = $slave_sth->fetchrow_arrayref();
my $retrieval_stop_time = [gettimeofday()];
my $retrieval_time = 0.0;
$retrieval_time = tv_interval(
$retrieval_start_time,
$retrieval_stop_time);
next RETRIEVAL unless $info->[0];
# retrieval time is counted only after a successful fetch
$total_retrieval_time += $retrieval_time;
$replication_delay = tv_interval( [$info->[0], $info->[1]], $retrieval_stop_time);
$baredelay = $replication_delay - $total_retrieval_time - $master_insert_time;
printf "%4d %5d %5d %12d %12d %12d %12d\n",
$loopcount, $info->[2], $info->[3] , $info->[0] , $info->[1] ,
$retrieval_stop_time->[0], $retrieval_stop_time->[1];
}

push @results,
{
data_size => $size,
master_insert_time => $master_insert_time,
slave_retrieval_time => $total_retrieval_time,
replication_time => $replication_delay,
bare_replication_time => $baredelay,
}
}

# displaying results
my @header_sizes = qw(4 9 13 15 16 9);
my @headers = ('loop', 'data size', 'master insert', 'slave retrieval', 'total repl. time', 'bare time');
printf "%s %s %s %s %s %s\n" , @headers;
printf "%s %s %s %s %s %s\n" , map { '-' x $_ } @header_sizes;
my $count = 0;
for my $res (@results)
{
printf "%4d %9d %13.6f %15.6f %16.6f %9.6f\n" , ++$count,
map { $res->{$_} }
qw/data_size master_insert_time slave_retrieval_time replication_time bare_replication_time/;
}

Topics: perl | No Comments »

« Previous Entries