Asus, where is the B204 w/Linux?

Dear Asus (pron: “a-sue-s”, not “ace-us”, apparently),

I’ve been looking for a small set-top home media player running Linux, with an HDMI on board, capable of running 1080p video. Looking around I’m quite fond of the Eeebox B204, but I don’t want to pay for MS Windows. I like the Bluetooth for my remote keyboard/mouse/input, and the battery UPS is cute up until the point the battery has lost its ability to charge/discharge.

I wanted to email you, but your asus.com web site has telephone numbers only. Its been a long, long time for you to bring this product to market in the UK. You’re also reselling different models in different markets, and your branding of the models is somewhat confusing: the B204 is “better/higher spec” than the B206 that was released at the same time?

Having said that, the on-line retailers I am Google-Frugal-Shopping searching through all seem to list the product, but have zero stock. Are there supply line issues? Is the product recalled? Or is it selling really well? Where are the Linux versions (sans-Microsoft-tax)? And why is your UK channel selling these at a considerable mark-up compared to the US retail prices? Currency does fluctuate, but I’m sure that UK£ and US$ are not on parity…. yet.

Sincerely,
JEB

MySQL views versus tables

An annoyance: at work we’ve been using MySQL 5.0.x for a reasonably high volume service. We recently swapped a table we were using from MyISAM, to a view containing several normalised MyISAM tables. Despite having indexes to make the joins in the table efficient, it seems that a SQL query with a “NOT IN (x, y, z)” style WHERE clause performs so much worse than the non-normalised original MyISAM table. So while a view may look equivalent to the original table, it won’t perform the same for all queries.

EasyCAP 4 channel input USB Video Capture

Video capture card; a gotcha

Once again, life proves when it comes to commercial offerings, you get what you pay for.

I found a £13 (~US$20) USB device with 4 composite video inputs, and one audio input, called an EasyCAP 4 channel device, on Amazon. I was planning on streaming 4 video captures from it at some quality. The unit turned up very efficiently, and emblazoned across the stick is “4 CHUSB DVR”, and a neat little Win32 utility called Multiviewer 2.0, by Zhong Kai Ran.

Fire up the software and an impressive 4-screen display is shown, however, its not until you plug in a video camera to one input that you can see that the device rotates through each of the video inputs; it doesnt appear to be able to stream all four simultaneously. A pity. So, if you’re looking for a “poor man’s multi-camera CCTV”, this is a very good choice, but be aware that you’ll only get (configurable) number of seconds from each channel in sequence (or selectable) but not a live continuous stream of all four inputs.

At least, that’s my experience under MS Windows thus far. I haven’t yet thrown it at a Linux system yet to see if it detects the device and/or it works any differently, but I’d suspect not.

Either way, it’s a start at what I’m looking to do anyway, so I am not too disappointed.

Next up, a small PC to house it in that I can run my GStreamer video processing on… hmmm… I want an Asus Eee Box B204 with its cute built in HDMI… its flirting with me promising Full-HD 1080p, but I guess if/when I have a spare £300 to play with I may find its also a little short!

Debian 5.0 Lenny is out

As of around 23:00 UTC today, Debian GNU Linux 5.0 is kind-of out and about. The official web site isn’t updated yet, and final CD images are being generated now, but the symlink of stable has come to rest on Lenny; testing is now Squeeze, and dear old 4.0 Etch is oldstable. For those not aware, the code names are all characters from Disney/Pixar’s Toy Story.

Lenny runs on 11 different CPU architectures, including the standard i386 32-bit and its equivalent 64-bit (AMD64). It ships with kernel 2.6.26. It has MySQL 5.0.51a (which has interesting STATISTICS table in the INFORMATION_SCHEMA).

Some of the gotchas that may come up:

  • Kernel 2.4 is dropped
  • Firmware for various devices may have been split out into separate packages; example, on an HP BL460 blade system, you’ll need to install firmare-bnx2
  • Apache 1 has been dropped; use Apache 2

See this for a rough summary and the release news story for more.

Logging to MySQL in 3rd Normal Form

I’m at it again with my Log3NF! When last I did this, Debian‘s Perl packages were in no shape for using MySQL stored procedures, but time has passed and everything is ready….

Any web server software, like Apache, can log requests that come in when people browse sites. Typically people record the accesses and do statistical analysis on it – to see visitor numbers, people stealing graphics, preferred browser versions of the visitors, where people are being linked-to from, etc. All of this data can be quite voluminous, and much of it is repetitive.

For a long time there has existed the ability to log this data to a simple flat MySQL (or other) database. However, most of those implementations have used just one table to store all the records in a log line. This means the data still has to be split apart for analysis.

So, what have I done? Well, I have written a bunch of table structures to handle each component of a standard “combined” log file, and a table that joins each of these components of a log line together. Plus I have written some table structures to hold summary data of this, so over time I can delete the original log entries and just keep the summaries. Then I have written some stored procedures to parse the incoming log entry and split it into these tables, and update the summary statistics. Here’s the main table that ties everything together – you’ll see it’s indexed in every way possible, so you cna see the possibilities for reporting from it…

CREATE TABLE Access (
ID bigint unsigned auto_increment primary key,
IPv4 int unsigned not null,
index index_IP(IPv4),
Ident_ID int unsigned,
User_ID int unsigned,
At datetime not null,
index index_At(At),
Protocol_ID tinyint unsigned,
index index_Protocol_ID(Protocol_ID),
Method_ID tinyint unsigned not null,
index index_Method_ID(Method_ID),
Status_ID tinyint unsigned not null,
index index_Status_ID(Status_ID),
Path_ID bigint unsigned,
index index_Path_ID(Path_ID),
Referer_ID bigint unsigned,
index index_Referer_ID(Referer_ID),
UserAgent_ID bigint unsigned,
index index_UserAgent_ID(UserAgent_ID),
Bytes int unsigned,
index index_Bytes(Bytes),
Server_ID smallint unsigned,
index index_Server_ID(Server_ID),
Site_ID smallint unsigned,
index index_Site_ID(Site_ID),
Timezone_ID tinyint unsigned not null
);

This supports having multiple web sites logging to it (think virtual hosting several sites) and server farms (multiple servers for big web sites, distributed global delivery).

Next up, I wrote a small script to load a pre-existing access log using this stored procedure. But thats rather slow, so I have written a “Log Handler” for Apache 2 with Mod_Perl 2. This means that as each access is performed, it is logged live to 3rd normal form in MySQL. The handler is very brief:

package JEB::Log3NFHandler;
use strict;
use warnings;
use Apache2::RequestRec ();
use Apache2::Const -compile => qw(OK DECLINED);
use Apache::DBI;
use Time::Zone;
my $dbh;

sub handler {
my $r = shift;
$dbh = DBI->connect('dbi:mysql:database=' . $r->dir_config("Log3NFDatabase"),  $r->dir_config("Log3NFDatabaseUser"),  $r->dir_config("Log3NFDatabasePassword")||"") unless $dbh;
return Apache2::Const::DECLINED unless $dbh;
my $sql = "call Log3NF(?, ?, ?, from_unixtime(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
my $sth = $dbh->prepare($sql);
$sth->bind_param(1, $r->connection->remote_ip);
$sth->bind_param(2, "-"); # Ident
$sth->bind_param(3, $r->user());
$sth->bind_param(4, $r->request_time());
$sth->bind_param(5, $r->protocol());
$sth->bind_param(6, $r->method());
$sth->bind_param(7, $r->status());
$sth->bind_param(8, $r->uri());
$sth->bind_param(9, $r->headers_in->get('Referer')||'-'); # Referer
$sth->bind_param(10, $r->headers_in->get('User-Agent')); # Useragent
$sth->bind_param(11, $r->bytes_sent()); # Bytes
$sth->bind_param(12, $ENV{'SERVER_NAME'}); # Server name
$sth->bind_param(13, $r->hostname()); # Site name
#tz_local_offset()/60
$sth->bind_param(14, "+0000"); # Timezone
$sth->execute();
$sth->finish;
return Apache2::Const::OK;
}
1; # modules must return true

You’ll notice the Timezone set to “+0000”; while the TZ variable in Mod_Perl says a location (“Europe/London”), it doesn’t give an offset from GMT. I’m also always logging ident as “-“, since I cant see how Mod_Perl makes that available. The configuration of the Database, DB User and Password are all taken from the Apache configuration file from the PerlSetVar directive.

With this data in 3rd normal form, viewing it means several joins, or making use of another of the newer facilities that saw daylight in MySQL 5.1: views. So a couple of views sit around to make this data easily accessible.

With this data being stored as it happens, I wrote a CGI script to render this data – to give me some graphs of the last 5 minutes of activity, in real time. In fact, its dynamic, so I can zoom in to the last 5 mins, or out to the last 800 minutes. This real-time analysis shows HTTP status codes, popular paths being requested (by hits and by bytes), plus a per-minute hits and bytes.

But there’s more… lets to some analysis on where these hits are coming from. MaxMind distribute a free Country CSV database that shows roughly where all these IPs are coming from. We load this CSV into a normalised form, and start to integrate this into the live and summary tables…

… at least, that’s where I am up to now.

I’ve been looking at this approach since around 2002, when I had to perform all the normalisation in client-side Perl. But abstracting away the normalisation into the MySQL stored procedure makes this much neater, and less prone to inconsistencies (the client doesn’t have to update the main table and ensure it puts in the correct foreign keys).

I will put this code up for public consumption soon, so if you’re interested in 3rd normal form logging, drop me an email!