Home Page

Site BEST viewed with:
FireFox & JavaScript
Compatible with: IE6+
Further info here.

Warning: you do not have javascript enabled. This WILL cause layout glitches.

Welcome to my domain. This is an open space where I, Jeffrey Riaboy, am keeping a compendium of my projects, thoughts, news, and miscellaneous ideas. I am a self taught programmer/computer nerd that works in C++ by choice, and too many other languages due to the facts of life. I have been programming virtually my whole life and working with computers since before I can remember. They are my passion, hobby, job, first love, and have served me well, though, been a constant pain in the anatomy. I hope you can find something of interest or use here, as that is the reason I spend my time creating and organizing this content. Enjoy. ^_^
The original (well... last) intro page to my website before this became the home. It is a flash portal to my personal sites of the past.
[1999-2001?] My ancient NES emulator made in Visual Basic (which was made to prove the power and flexibility [not speed] of the language). But alas, one of my friends, David Finch beat me to it by optimizing BasicNes [Don Jarrett].
[2002] A chronicle of my experiences and tinkering from early ’02 to early ’04 on an addictive yet horribly crappy MMORPG. Site also has some nice “hacking”/reverse engineering tutorials.
Ragnarok Hacking
I’ve temporarily set this to link to the Projects section of this website until I’m ready to announce the new website this will link to.
Updates Archive
Section: Misc > Old Intro

So for a long time, http://castledragmire.com (without the www) brought up an intro page, made in flash, while with the www brought this projects page (Dakusan’s Domain) up. I’ve decided it was time to retire it, if anyone ever stumbled upon it. I think I made this flash in December of 2004, using the PSD of the below image, that my good Friend Adam Shen had kindly provided to me. I would never claim to be good at design or making visual things, but I was proud of it :-)

Old Website Title
Added v1.0 of this new project
Download Content

M3U files in the Plex Playlist Importer now support absolute paths (smb shares and drive letters). v1.0.0.3 Binary and Source

Other updates include:
  • The readme files and project content have also been updated with clarifications and “how it works”.
  • Fixed bug caused by NULL song duration in Plex database
Download Content
Post Archive
RSS Feed
MySQL replication ring status reporting script

I just threw together a quick script to report status on a MySQL replication ring. While replication rings have been the only real multi-master MySQL solution for replication (with the ability for nodes to go down without majorly breaking things) until recently, I have read that MariaDB (still not MySQL) now allows a slave to have multiple masters, meaning many replication topologies are now possible (star, mesh, etc). This script could easily be adapted for those circumstances too.

This script will report all the variables from “SHOW MASTER STATUS” and “SHOW SLAVE STATUS” from all servers in your replication ring, in a unified table. It also includes a “Pretty Status” row that lets you quickly see how things look. The possibilities for this row are:

  • Bad state: ...
    This shows if the Slave_IO_State is not “Waiting for master to send event”
  • Cannot determine master’s real position
    This shows if the Position variable on the master could not be read
  • On old master file
    This shows if the slave’s “Master_Log_File” variable does not equal the master’s “File” variable
  • Bytes behind: xxx
    This shows if none of the above errors occurred. It subtracts the master’s “Position” from the slave’s “Read_Master_Log_Pos”. This should generally be at or around 0. A negative value essentially means 0 (this should only happen between the last and first server).

The “Seconds_Behind_Master” variable can also be useful for determining the replication ring’s current replication status.

The code is below the example. The entire source file can also be found here. The 3 variables that need to be configured are at the top of the file. It assumes that all servers are accessible via the single given username and password.

Server Name
Pretty Status
Bytes behind: 0
Bytes behind: 0
Slave_IO_StateWaiting for master to send eventWaiting for master to send event
Not given
Not given


$Servers=Array('SERVER1.YOURDOMAIN.COM', 'SERVER2.YOURDOMAIN.COM'); //List of host names to access mysql servers on. This must be in the order of the replication ring.
$SlaveUserName='SLAVE_RING_USERNAME'; //This assumes all servers are accessible via this username with the same password

//Get the info for each server
$ServersInfo=Array(); //SERVER_NAME=>Array('Master'=>Array(Col1=>Val1, ...), 'Slave'=>Array(Col1=>Val1, ...)
$ColsNames=Array('Master'=>Array('Server Name'=>0), 'Slave'=>Array('Pretty Status'=>0)); //The column names for the 2 (master and slave) queries. Custom column names are also added here
$CustomFieldNames=array_merge($ColsNames['Master'], $ColsNames['Slave']); //Store the custom column names so they are not HTML escaped later
foreach($Servers as $ServerName)
    //Connect to the server
    $Link=@new mysqli($ServerName, $SlaveUserName, $SlavePassword);
        die(EHTML("Connection error to $ServerName server: $Link->connect_error"));

    //Get the replication status info from the server
        'Master'=>$Link->Query('SHOW MASTER STATUS')->fetch_array(MYSQLI_ASSOC),
        'Slave'=>$Link->Query('SHOW SLAVE STATUS')->fetch_array(MYSQLI_ASSOC)
    mysqli_close($Link); //Close the connection

    //Gather the column names
    foreach($ColsNames as $ColType => &$ColNames)
        foreach($MyServerInfo[$ColType] as $ColName => $Dummy)

//Gather the pretty statuses
foreach($Servers as $Index => $ServerName)
    //Determine the pretty status
    if($SlaveInfo['Slave_IO_State']!='Waiting for master to send event')
        $PrettyStatus='Bad state: '.EHTML($SlaveInfo['Slave_IO_State']);
    else if(!isset($MasterInfo['Position']))
        $PrettyStatus='Cannot determine master’s real position';
    else if($SlaveInfo['Master_Log_File']!=$MasterInfo['File'])
        $PrettyStatus='On old master file';
        $PrettyStatus='Bytes behind: '.($MasterInfo['Position']-$SlaveInfo['Read_Master_Log_Pos']);

    //Add the server name and pretty status to the output columns
    $ServersInfo[$ServerName]['Master']['Server Name']='<div class=ServerName>'.EHTML($ServerName).'</div>';
    $ServersInfo[$ServerName]['Slave']['Pretty Status']='<div class=PrettyStatus>'.EHTML($PrettyStatus).'</div>';

//Output the document
function EHTML($S) { return htmlspecialchars($S, ENT_QUOTES, 'UTF-8'); } //Escape HTML
<!DOCTYPE html>
    <title>Replication Status</title>
    <meta charset="UTF-8">
        table { border-collapse:collapse; }
        table tr>* { border:1px solid black; padding:3px; }
        th { text-align:left; font-weight:bold; }
        .ReplicationDirectionType { font-weight:bold; text-align:center; color:blue; }
        .ServerName { font-weight:bold; text-align:center; color:red; }
        .PrettyStatus { font-weight:bold; color:red; }
        .NotGiven { font-weight:bold; }
//Output the final table
foreach($ColsNames as $Type => $ColNames) //Process by direction type (Master/Slave) then columns
    print '<tr><td colspan='.(count($Servers)+1).' class=ReplicationDirectionType>'.$Type.'</td></tr>'; //Replication direction (Master/Server) type title column
    foreach($ColNames as $ColName => $Dummy) //Process each column name individually
        print '<tr><th>'.EHTML($ColName).'</th>'; //Column name
        $IsHTMLColumn=isset($CustomFieldNames[$ColName]); //Do not escape HTML on custom fields
        foreach($ServersInfo as $ServerInfo) //Output the column for each server
            if($IsHTMLColumn) //Do not escape HTML on custom fields
                print '<td>'.$ServerInfo[$Type][$ColName].'</td>';
            else //If not a custom field, output the escaped HTML of the value. If the column does not exist for this server (different mysql versions), output "Not given"
                print '<td>'.(isset($ServerInfo[$Type][$ColName]) ? EHTML($ServerInfo[$Type][$ColName]) : '<div class=NotGiven>Not given</div>').'</td>';
        print '</tr>';

One final note. When having this script run, you might need to make sure none of the listed server IPs evaluates to localhost (127.x.x.x), as MySQL may instead then use the local socket pipe, which may not work with users who only have REPLICATION permissions and a wildcard host.

Cygwin install

Since I’m doing the new install thing, I figured I’d record some of my setup. So here is my cygwin install.

  • Internet utilities: wget, curl, ping, openssh, openssl-devel, mysql, nc
  • Program compilation stuff: gcc-g++, autoconf, pkg-config, automake
  • Programming languages: perl, python
  • Other utilities for programming: git, sqlite3
  • Text editor: nano

Mintty [non-default] options:
  • Text->Locale=en_US UTF-8
  • Mouse->Copy on select=Off
  • Mouse->Clicks place command line cursor=On

I also haven’t decided yet if I will do apache or PHP via cygwin or windows installs yet. May do a post about that later.

Hardware performance speed tests

So I got a new computer back in April and have finally gotten around to doing some speed tests to see how different applications and settings affect performance/harddrive read speed.

The following is the (relevant) computer hardware configuration:
  • Motherboard: MSI Z87-GD65
  • CPU: Intel Core i7-4770K Haswell 3.5GHz
  • GPU: GIGABYTE GV-N770OC-4GD GeForce GTX 770 4GB
  • RAM: Crucial Ballistix Tactical 2*8GB
  • 2*Solid state hard drives (SDD): Crucial M500 480GB SATA 2.5" 7mm
  • 7200RPM hard drive (HDD): Seagate Barracuda 3TB ST3000DM001
  • Power Supply: RAIDMAX HYBRID 2 RX-730SS 730W
  • CPU Water Cooler: CORSAIR H100i
  • Case Fans: 2*Cooler Master MegaFlow 200, 200mm case fan

Test setup:

I started with a completely clean install of Windows 7 Ultimate N x64 to gather these numbers.

The first column is the boot time, from the time the start of the "Starting Windows" animation shows to when the user login screen shows up, so the BIOS is not included. I used a stopwatch to get these boot numbers (in seconds), so they are not particularly accurate.

The second and third columns are the time (in seconds) to run a "time md5sum" on cygwin64 on a 1.39GB file (1,503,196,839 bytes), on the solid state (SDD) and 7200RPM (HDD) drives respectively. They are taken immediately after boot so caching and other applications using resources are not variables. I generally did not worry about running the tests multiple times and taking lowest case numbers. The shown milliseconds fluctuations are within margin of error for software measurements due to context switches.


Boot times are affected between multiple steps, as seen below, but not too bad. The only thing that affected the MD5sum was adding the hardware mirror raid on the SSDs, which dropped the time of the md5 by half. So overall, antivirus and system encryption did not have any noticeable affect on the computer's performance (at least regarding IO on a single file and number crunching).

What was added Boot SSD HDD Notes
Initial installation 4 - -
NIC Drivers and Cygwin 7 4.664 8.393 I'm not sure why the boot time jump so much at this point. The initial number might have been a fluke.
All Windows updates + drivers + 6 monitors 14 4.618 8.393 The boot time jumped up a lot due to having to load all the monitors
Raid 1 mirror[Windows] on SSDs + no page file 17 4.618 8.393 This was removed once I realized Truecrypt could not be used on a dynamic disk (Windows software) RAID
Raid 1 mirror[hardware] on SSDs + no page file 17 2.246 8.408
Truecrypt System Volume Encryption (SSD Raid Only) 17-18 2.278 8.424
Antivirus 18 2.324 8.408 Kaspersky 2014