Full-service Internet Marketing & Web Development
Recent Posts

Featured Posts
|
MapReduce 101: Parallel ProgrammingMike Peters, December 21, 2009 |
Two of the best video tutorials explaining the basics of MapReduce.
If you're used to MySQL, you can think of "Map" as several queries running "SELECT" where data is extracted from multiple tables. And you can think of "Reduce" as the "GROUP BY" operator where data is joined together to form a short result.
For more information about MapReduce, see Google's Introduction to Parallel Programming and MapReduce
If you're used to MySQL, you can think of "Map" as several queries running "SELECT" where data is extracted from multiple tables. And you can think of "Reduce" as the "GROUP BY" operator where data is joined together to form a short result.
For more information about MapReduce, see Google's Introduction to Parallel Programming and MapReduce
|
Never use VARCHAR in MySQLMike Peters, December 15, 2009 |
When using strings in MySQL, you have a choice between several field types:
* VARCHAR: String of 0..65,535 characters with an extra byte to designate the length.
* CHAR: String of a fixed length of 0 to 255 characters.
* TEXT / BIGTEXT: String of 1..4GB characters with an extra byte to designate the length. Unlike VARCHAR, text fields cannot be compared, can't "order by", can't use "like" on them etc.
* BLOB: For binary or unicode strings. Supports 8bits per character and unlike the previous types, the string is not converted to a character-set prior to insertion.
Quick tip: Never ever use varchar.
Replace VARCHAR with CHAR whenever possible, or use TEXT if your strings are longer than 255 characters.
While VARCHAR offers slightly improved storage space (it will only take up n+1 characters on disk), there are a few major pitfalls with this variable type:
#1. If you have any field in the table that is a CHAR (fixed size) field, all VARCHARs will be stored as n+1, so you don't get any reduced storage benefits.
#2. If you're using MySQL replication, you may end up with a few nasty "master/slave table column type mismatch" errors - this is a big one
#3. CHAR fields offer better performance over VARCHAR
-
We first learned about the issues with VARCHAR when replication began breaking with these cryptic messages:
"Table definition on master and slave does not match: Column 37 size mismatch - master has size 255, testtable on slave has size 256. Master's column size should be <= the slave's column size."
Both tables were identical and mysqldump'ing one on top of the other didn't help. It seems to be rooted to MySQL's internal implementation of VARCHAR.
To convert all table VARCHAR fields to CHAR, use this PHP snippet:
View 1 Comment(s)
* VARCHAR: String of 0..65,535 characters with an extra byte to designate the length.
* CHAR: String of a fixed length of 0 to 255 characters.
* TEXT / BIGTEXT: String of 1..4GB characters with an extra byte to designate the length. Unlike VARCHAR, text fields cannot be compared, can't "order by", can't use "like" on them etc.
* BLOB: For binary or unicode strings. Supports 8bits per character and unlike the previous types, the string is not converted to a character-set prior to insertion.
Quick tip: Never ever use varchar.
Replace VARCHAR with CHAR whenever possible, or use TEXT if your strings are longer than 255 characters.
While VARCHAR offers slightly improved storage space (it will only take up n+1 characters on disk), there are a few major pitfalls with this variable type:
#1. If you have any field in the table that is a CHAR (fixed size) field, all VARCHARs will be stored as n+1, so you don't get any reduced storage benefits.
#2. If you're using MySQL replication, you may end up with a few nasty "master/slave table column type mismatch" errors - this is a big one
#3. CHAR fields offer better performance over VARCHAR
-
We first learned about the issues with VARCHAR when replication began breaking with these cryptic messages:
"Table definition on master and slave does not match: Column 37 size mismatch - master has size 255, testtable on slave has size 256. Master's column size should be <= the slave's column size."
Both tables were identical and mysqldump'ing one on top of the other didn't help. It seems to be rooted to MySQL's internal implementation of VARCHAR.
To convert all table VARCHAR fields to CHAR, use this PHP snippet:
@mysql_query("SET GLOBAL WAIT_TIMEOUT = 600000");
@mysql_Query("SET WAIT_TIMEOUT = 600000");
$Result1 = @mysql_query("SHOW TABLES FROM $DBNAME");
$cnt1 = @mysql_num_rows($Result1);
while ($cnt1)
{
$cnt1--;
if (!($Row1 = @mysql_fetch_array($Result1)))
{
continue;
}
$tablename = $Row1[0];
$Result3 = @mysql_query("DESCRIBE $tablename");
$cnt3 = @mysql_num_rows($Result3);
while ($cnt3)
{
$cnt3--;
if (!($Row3 = @mysql_fetch_array($Result3))) continue;
if (strpos($Row3['Type'],'varchar')!==false)
{
$pos = strpos($Row3['Type'],'(');
$length = substr($Row3['Type'],$pos+1);
$pos = strpos($length,')');
$length = substr($length, 0, $pos);
// If length is over 255, nothing we can do about it
if ($length>255) continue;
if ($length<1) continue;
// Length is below 255, we can convert
$sql = "alter table $tablename change ".$Row3['Field']." ".$Row3['Field']." char($length) default '' not null";
@mysql_query($sql);
}
}
}
@mysql_Query("SET WAIT_TIMEOUT = 600000");
$Result1 = @mysql_query("SHOW TABLES FROM $DBNAME");
$cnt1 = @mysql_num_rows($Result1);
while ($cnt1)
{
$cnt1--;
if (!($Row1 = @mysql_fetch_array($Result1)))
{
continue;
}
$tablename = $Row1[0];
$Result3 = @mysql_query("DESCRIBE $tablename");
$cnt3 = @mysql_num_rows($Result3);
while ($cnt3)
{
$cnt3--;
if (!($Row3 = @mysql_fetch_array($Result3))) continue;
if (strpos($Row3['Type'],'varchar')!==false)
{
$pos = strpos($Row3['Type'],'(');
$length = substr($Row3['Type'],$pos+1);
$pos = strpos($length,')');
$length = substr($length, 0, $pos);
// If length is over 255, nothing we can do about it
if ($length>255) continue;
if ($length<1) continue;
// Length is below 255, we can convert
$sql = "alter table $tablename change ".$Row3['Field']." ".$Row3['Field']." char($length) default '' not null";
@mysql_query($sql);
}
}
}
View 1 Comment(s)
|
How to Flush DNSMike Peters, December 6, 2009 |
At times you want to force your machine to "forget" (flush) all DNS entries, so that it reloads any recent changes.
This is useful when you've recently updated the ip-address of a domain and want your machine to see the new changes, without relying on any previously stored cache.
Here's how to flush your DNS cache:
Windows
Open a CMD dos box and run:
ipconfig /flushdns
If you get an error about "this requires elevation", do this: Click on the Windows Start button, type "cmd", then right click on the program and select "Run as Administrator"
Mac
In Mac OSX Leopard, you can use the command
dscacheutil to flush the DNS resolver cache:
dscacheutil -flushcache
In Mac OSX versions 10.5.1 and before, the command lookupd -flushcache performed the same task:
lookupd -flushcache
Linux
In Linux, the nscd daemon manages the DNS cache.
To flush the DNS cache, restart the nscd daemon.
To restart the nscd daemon, use the command:
/etc/init.d/nscd restart
This is useful when you've recently updated the ip-address of a domain and want your machine to see the new changes, without relying on any previously stored cache.
Here's how to flush your DNS cache:
Windows
Open a CMD dos box and run:
ipconfig /flushdns
If you get an error about "this requires elevation", do this: Click on the Windows Start button, type "cmd", then right click on the program and select "Run as Administrator"
Mac
In Mac OSX Leopard, you can use the command
dscacheutil to flush the DNS resolver cache:
dscacheutil -flushcache
In Mac OSX versions 10.5.1 and before, the command lookupd -flushcache performed the same task:
lookupd -flushcache
Linux
In Linux, the nscd daemon manages the DNS cache.
To flush the DNS cache, restart the nscd daemon.
To restart the nscd daemon, use the command:
/etc/init.d/nscd restart
|
Mercurial Hook: Forbid 2 headsMike Peters, December 6, 2009 |
The Mercurial version control system offers a powerful mechanism to let you perform automated actions in response to events that occur in a repository. In some cases, you can even control Mercurial's response to those events. No comments
The name Mercurial uses for one of these actions is a hook (aka trigger).
One of the most popular hooks is the ability to reject multiple heads.
What are multiple heads?
Multiple heads are a case where the code repository contains changes from two (or more) developers, that haven't been merged. These changes may potentially overlap and break the application flow.
Having multiple heads occurs in two cases:
* As part of a merge (generally temporary)
* Bugfix versions (generally permanent)
At any time, you can view the head(s) of a repository with the command: hg heads
Pitfalls to watch-for with Multiple Heads
Consider the following scenario:
* It's Monday morning. Bob and Linda each pull a copy of the repository to their local Mercurial HG.
* Bob makes a few changes to index.php and pushes them to the server Monday afternoon.
* Linda makes a few additional changes to index.php and pushes them to the server on Tuesday morning.
Since Linda doesn't have the most recent copy of index.php (with Bob's changes), her copy of index.php will create a second "head" to the project.
There are now two development branches - the one with Bob's changes and the one with Linda's changes, neither one having all changes in place.
While TortoiseHG will often block Linda's push with a warning that it will create multiple heads, it is possible to push with -f (force). Some Mercurial plugins automatically push with -f, creating the second head on the live server repository.
Yes you can run 'hg merge' on the live server to merge Bob and Linda's changes (the two heads) locally, but you never ever want to run hg merge on a live server.
Running 'hg merge', adds "<<<<< local >>>>> other" comments into the source files, as part of its file-diff process. This temporarily breaks the syntax of your source files for the duration of the merge.
If this is a live server, your scripts will all STOP WORKING until the merge is complete and the "<<<<< local >>>>> other" notations are removed from the source files.
Rejecting Multiple heads - Do the merge offline
Instead of allowing multiple heads on the live server, a much better approach is to reject multiple heads, forcing the engineers to merge changes locally, before pushing any change that will create a second head.
In the example above, when Linda attempts to push the changes on Tuesday, her push will be rejected with an error message of "Trying to push more than one head, try run hg merge before it."
Linda then has to pull the recent changes, retrieving Bob's additions, merge the changes locally and then push a version that incorporates both her changes and Bob's into the server.
The benefits of this approach are:
#1. Server scripts are never rendered inactive by a local 'hg merge' run
#2. Engineers always need to retrieve (and test) the latest version, prior to being able to upload changes that may conflict with others.
#3. The live server always has a single development graph, containing the most recent changes.
Installing NetBeans Forbid2Heads Mercurial hook
Step 1: Locate your HG extensions folder
The folder name is 'hgext' and it is typically installed under Mercurial's home folder. For example:
/usr/home/mercurial/work/mercurial-1.3.1/hgext
Step 2: Install forbid_2heads Python script
Create a new folder named 'forbid_2head' under 'hgext' and save this file under /hgext/forbid_2head/forbid_2head.py:
# win32text.py - LF <-> CRLF translation utilities for Windows users
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
#
# To forbid pushes which creates two or more headss
#
# [hooks]
# pretxnchangegroup.forbid_2heads = python:forbid2_head.forbid_2heads
from mercurial import ui
from mercurial.i18n import gettext as _
def forbid_2heads(ui, repo, hooktype, node, **kwargs):
if len(repo.heads()) > 1:
ui.warn(_('Trying to push more than one head, try run "hg merge" before it.n'))
return True
Step 3: Add hook to Mercurial config file
Update your Mercurial hgweb.config, adding the new hook under the 'hooks' section, like this:
[hooks]
pretxnchangegroup.forbid_2heads = python:forbid_2head.forbid_2heads
--
Attempting to push changes to the repository that will create multiple heads is now blocked.
Users will be presented with an error message and the transaction rolled back, until the user merges changes locally, so that no multiple heads are created:
--
The live server repository will always have a single development branch. Engineers will be forced to merge changes locally, before new changes can be pushed:

View 1 Comment(s)
The name Mercurial uses for one of these actions is a hook (aka trigger).
One of the most popular hooks is the ability to reject multiple heads.
What are multiple heads?
Multiple heads are a case where the code repository contains changes from two (or more) developers, that haven't been merged. These changes may potentially overlap and break the application flow.
Having multiple heads occurs in two cases:
* As part of a merge (generally temporary)
* Bugfix versions (generally permanent)
At any time, you can view the head(s) of a repository with the command: hg heads
Pitfalls to watch-for with Multiple Heads
Consider the following scenario:
* It's Monday morning. Bob and Linda each pull a copy of the repository to their local Mercurial HG.
* Bob makes a few changes to index.php and pushes them to the server Monday afternoon.
* Linda makes a few additional changes to index.php and pushes them to the server on Tuesday morning.
Since Linda doesn't have the most recent copy of index.php (with Bob's changes), her copy of index.php will create a second "head" to the project.
There are now two development branches - the one with Bob's changes and the one with Linda's changes, neither one having all changes in place.
While TortoiseHG will often block Linda's push with a warning that it will create multiple heads, it is possible to push with -f (force). Some Mercurial plugins automatically push with -f, creating the second head on the live server repository.
Yes you can run 'hg merge' on the live server to merge Bob and Linda's changes (the two heads) locally, but you never ever want to run hg merge on a live server.
Running 'hg merge', adds "<<<<< local >>>>> other" comments into the source files, as part of its file-diff process. This temporarily breaks the syntax of your source files for the duration of the merge.
If this is a live server, your scripts will all STOP WORKING until the merge is complete and the "<<<<< local >>>>> other" notations are removed from the source files.
Rejecting Multiple heads - Do the merge offline
Instead of allowing multiple heads on the live server, a much better approach is to reject multiple heads, forcing the engineers to merge changes locally, before pushing any change that will create a second head.
In the example above, when Linda attempts to push the changes on Tuesday, her push will be rejected with an error message of "Trying to push more than one head, try run hg merge before it."
Linda then has to pull the recent changes, retrieving Bob's additions, merge the changes locally and then push a version that incorporates both her changes and Bob's into the server.
The benefits of this approach are:
#1. Server scripts are never rendered inactive by a local 'hg merge' run
#2. Engineers always need to retrieve (and test) the latest version, prior to being able to upload changes that may conflict with others.
#3. The live server always has a single development graph, containing the most recent changes.
Installing NetBeans Forbid2Heads Mercurial hook
Step 1: Locate your HG extensions folder
The folder name is 'hgext' and it is typically installed under Mercurial's home folder. For example:
/usr/home/mercurial/work/mercurial-1.3.1/hgext
Step 2: Install forbid_2heads Python script
Create a new folder named 'forbid_2head' under 'hgext' and save this file under /hgext/forbid_2head/forbid_2head.py:
# win32text.py - LF <-> CRLF translation utilities for Windows users
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
#
# To forbid pushes which creates two or more headss
#
# [hooks]
# pretxnchangegroup.forbid_2heads = python:forbid2_head.forbid_2heads
from mercurial import ui
from mercurial.i18n import gettext as _
def forbid_2heads(ui, repo, hooktype, node, **kwargs):
if len(repo.heads()) > 1:
ui.warn(_('Trying to push more than one head, try run "hg merge" before it.n'))
return True
Step 3: Add hook to Mercurial config file
Update your Mercurial hgweb.config, adding the new hook under the 'hooks' section, like this:
[hooks]
pretxnchangegroup.forbid_2heads = python:forbid_2head.forbid_2heads
--
Attempting to push changes to the repository that will create multiple heads is now blocked.
Users will be presented with an error message and the transaction rolled back, until the user merges changes locally, so that no multiple heads are created:
Quote:
|
pushing to http://mydomain.com/ searching for changes 4 changesets found adding changesets adding manifests adding file changes added 4 changesets with 2 changes to 7 files (+1 heads) Trying to push more than one head, try run "hg merge" before it. transaction abort! rollback completed abort: pretxnchangegroup.forbid_2heads hook failed [command returned code 1] |
--
The live server repository will always have a single development branch. Engineers will be forced to merge changes locally, before new changes can be pushed:

View 1 Comment(s)
|
How to install PHP 5.2.11 with php-fpmMike Peters, November 10, 2009 |
This post will walk you through the process of installing PHP 5.2.11 to run under NGinx using PHP-FPM.
NGinx doesn't have built-in support for running PHP, it uses a third-party daemon to spawn instances of php-cgi and then communicates with those instances over sockets.
PHP-FPM is a replacement for spawn-cgi. Runs faster and is more reliable.
Step 1: Download PHP 5.2.11 and apply PHP-FPM patch
Step 2: Configure PHP
Step 3: Install
Step 4: Start PHP-FPM
NGinx doesn't have built-in support for running PHP, it uses a third-party daemon to spawn instances of php-cgi and then communicates with those instances over sockets.
PHP-FPM is a replacement for spawn-cgi. Runs faster and is more reliable.
Step 1: Download PHP 5.2.11 and apply PHP-FPM patch
cd /home
mkdir temp
cd temp
wget http://www.softwareprojects.com/files/auto/php-5.2.11.tar.gz
wget http://www.softwareprojects.com/php-5.2.11-fpm-0.5.13.diff.gz
tar zxvf php-5.2.11.tar.gz
gzip -cd php-5.2.11-fpm-0.5.13.diff.gz | patch -d php-5.2.11 -p1
mkdir temp
cd temp
wget http://www.softwareprojects.com/files/auto/php-5.2.11.tar.gz
wget http://www.softwareprojects.com/php-5.2.11-fpm-0.5.13.diff.gz
tar zxvf php-5.2.11.tar.gz
gzip -cd php-5.2.11-fpm-0.5.13.diff.gz | patch -d php-5.2.11 -p1
Step 2: Configure PHP
cd php-5.2.11
'./configure' '--enable-fastcgi' '--enable-fpm' '--enable-calendar' '--enable-ftp' '--enable-mbstring' '--enable-mysql' '--with-curl' '--with-dom' '--with-mcrypt' '--with-gd' '--with-iconv' '--with-jpeg-dir=/usr/lib' '--with-mysql=/usr/local/mysql' '--with-openssl' '--with-soap' '--with-sockets' '--with-zlib' '--enable-zip'
make all
'./configure' '--enable-fastcgi' '--enable-fpm' '--enable-calendar' '--enable-ftp' '--enable-mbstring' '--enable-mysql' '--with-curl' '--with-dom' '--with-mcrypt' '--with-gd' '--with-iconv' '--with-jpeg-dir=/usr/lib' '--with-mysql=/usr/local/mysql' '--with-openssl' '--with-soap' '--with-sockets' '--with-zlib' '--enable-zip'
make all
Step 3: Install
make install
strip /usr/local/bin/php-cgi
strip /usr/local/bin/php-cgi
Step 4: Start PHP-FPM
/usr/local/sbin/php-fpm start
|
How to install PHP ChartDirector under FreeBSDMichel Nadeau, November 6, 2009 |
PHP ChartDirector is a powerful PHP extension that allows to generate very complex charts. You can visit their Web site here.
This tutorial will show you how to install it under FreeBSD.
1. Download PHP ChartDirector
The download page is located here -
http://www.advsofteng.com/download.html
Make sure you pick the FreeBSD version for PHP, and make sure you choose the good version between 32 and 64-bit. At the time of writing this post, the latest 32-bit version available for FreeBSD was this one -
http://download2.advsofteng.com/char...freebsd.tar.gz
Now that you have the download link, the first thing to do is to find out where is your PHP extensions directory. You can find it by checking at phpinfo()'s output or in your php.ini file (which is usually located in /usr/local/lib/php.ini). Just search for "extension_dir" in php.ini - you will find it right away. In our case, our extensions directory was "/usr/local/lib/php/extensions/current". We can now download and extract ChartDirector...
When extracting ChartDirector, it creates a "ChartDirector" folder that contains these files/folders:
We are mainly interested by the "lib" directory. Let's copy the files that we need...
You can get rid of these 2 PHP files:
2. Determine the right version
To determine the right version of the DLL that you must use, refer to this page -
http://www.advsofteng.com/doc/cdphpdoc/phpinstall.htm
For example, if you have PHP 4.4.9, you will use this one -
PHP Version 4.2.1 and above: phpchartdir421.dll
Even if it's FreeBSD and not Windows, you are going to specify a DLL as the extension in your php.ini file. You can delete all the others DLL's that you are not using, but make sure you keep the "fonts" folder and the "libchardir.so" file - they are required. So your extensions directory might look like this:
3. Configure the extension in php.ini
Now that we have all we need, we're going to configure php.ini to add the PHP ChartDirector extension.
Open your php.ini and add a line like this one in the extensions section:
Make sure you use the right DLL for your PHP version. Save your php.ini file and restart your PHP engine and/or Web server (Apache, FastCGI, etc.) to reload your PHP configuration.
To test PHP ChartDirector, you can use the "phpdemo" directory that you can find in the PHP ChartDirector archive. Just copy the folder in the root of your Web server and point it with your browser (ex: http://yourWebAddress/phpdemo). This demo is also very convenient for charts examples.
View 1 Comment(s)
This tutorial will show you how to install it under FreeBSD.
1. Download PHP ChartDirector
The download page is located here -
http://www.advsofteng.com/download.html
Make sure you pick the FreeBSD version for PHP, and make sure you choose the good version between 32 and 64-bit. At the time of writing this post, the latest 32-bit version available for FreeBSD was this one -
http://download2.advsofteng.com/char...freebsd.tar.gz
Now that you have the download link, the first thing to do is to find out where is your PHP extensions directory. You can find it by checking at phpinfo()'s output or in your php.ini file (which is usually located in /usr/local/lib/php.ini). Just search for "extension_dir" in php.ini - you will find it right away. In our case, our extensions directory was "/usr/local/lib/php/extensions/current". We can now download and extract ChartDirector...
cd /usr/local/lib/php/extensions/current
wget http://download2.advsofteng.com/chartdir_php_freebsd.tar.gz
tar xvfz chartdir_php_freebsd.tar.gz
wget http://download2.advsofteng.com/chartdir_php_freebsd.tar.gz
tar xvfz chartdir_php_freebsd.tar.gz
When extracting ChartDirector, it creates a "ChartDirector" folder that contains these files/folders:
doc/
lib/
phpdemo/
LICENSE.TXT
README.TXT
lib/
phpdemo/
LICENSE.TXT
README.TXT
We are mainly interested by the "lib" directory. Let's copy the files that we need...
cd /usr/local/lib/php/extensions/current
mv ChartDirector/lib/* .
mv ChartDirector/lib/* .
You can get rid of these 2 PHP files:
rm FinanceChart.php
rm phpchartdir.php
rm phpchartdir.php
2. Determine the right version
To determine the right version of the DLL that you must use, refer to this page -
http://www.advsofteng.com/doc/cdphpdoc/phpinstall.htm
For example, if you have PHP 4.4.9, you will use this one -
PHP Version 4.2.1 and above: phpchartdir421.dll
Even if it's FreeBSD and not Windows, you are going to specify a DLL as the extension in your php.ini file. You can delete all the others DLL's that you are not using, but make sure you keep the "fonts" folder and the "libchardir.so" file - they are required. So your extensions directory might look like this:
fonts/
libchartdir.so
phpchartdir421.dll
libchartdir.so
phpchartdir421.dll
3. Configure the extension in php.ini
Now that we have all we need, we're going to configure php.ini to add the PHP ChartDirector extension.
Open your php.ini and add a line like this one in the extensions section:
extension=phpchartdir421.dll
Make sure you use the right DLL for your PHP version. Save your php.ini file and restart your PHP engine and/or Web server (Apache, FastCGI, etc.) to reload your PHP configuration.
To test PHP ChartDirector, you can use the "phpdemo" directory that you can find in the PHP ChartDirector archive. Just copy the folder in the root of your Web server and point it with your browser (ex: http://yourWebAddress/phpdemo). This demo is also very convenient for charts examples.
View 1 Comment(s)
| « Previous Posts | » Next Posts |
