| 
<?php
 /***
 This example script performs the following :
 1) Take the log file data/example.log, which contains well-formatted entries such as :
 2016-01-01 13:20:01 httptracking[11776] Processing buffered http requests...
 2016-01-01 13:20:01 httptracking[11776] 0 http requests processed
 2016-01-01 13:25:02 httptracking[11908] Processing buffered http requests...
 2016-01-01 13:25:02 httptracking[11908] 2 http requests processed
 2016-01-01 13:30:01 httptracking[12043] Processing buffered http requests...
 2016-01-01 13:30:01 httptracking[12043] 0 http requests processed
 The various fields of this log file, which resembles Apache or ssh auth logs, are :
 - A timestamp
 - A process name ("httptracking")
 - A process id, within square brackets
 - A message
 The variable-length parts of this table are :
 - the process name
 - the message part
 2.1) Create a first table, httptracking_1, which will hold the various parts of the log file
 2.2) Create a second table, httptracking_2, where the "process" and "message" fields have
 been replaced with an id in a string store table
 3) Compare the results in size and number of records
 ***/
 require ( 'DbStringStore.php' ) ;
 
 // Customize here the access parameters to your local database
 define ( MYSQL_HOST        , 'localhost' ) ;
 define ( MYSQL_USER        , 'root' ) ;
 define ( MYSQL_PASSWORD        , '' ) ;
 define ( MYSQL_DATABASE        , 'phpclasses' ) ;
 define ( LOGFILE         , 'data/example.log' ) ;
 
 // String store entry types - one for the process name, one for the message part
 define ( STRING_STORE_PROCESS    , 0 ) ;
 define ( STRING_STORE_MESSAGE    , 1 ) ;
 
 // Connect to your local database
 $dblink        =  mysqli_connect ( MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD ) ;
 
 // Uncomment this if you want to create a brand new database for running this test
 /***
 $query        =  "CREATE DATABASE " . MYSQL_DATABASE . " DEFAULT CHARSET latin1" ;
 mysqli_query ( $dblink, $query ) ;
 ***/
 
 // Select our test database
 mysqli_select_db ( $dblink, MYSQL_DATABASE ) ;
 
 // Create the version with inline variable-length fields
 create_standard_version ( $dblink, LOGFILE ) ;
 
 // Create the version with a string store
 create_string_store_version ( $dblink, LOGFILE, 'httptracking_string_store' ) ;
 
 
 /********************************************************************************
 *
 *  Helper functions.
 *
 ********************************************************************************/
 
 // Create the version with variable-length data stored in the same table
 function  create_standard_version ( $dblink, $logfile )
 {
 // Recreate the httptracking_1 table if it already exists
 mysqli_query ( $dblink, "DROP TABLE IF EXISTS httptracking_1" ) ;
 
 $query    =  "
 CREATE TABLE httptracking_1
 (
 id         BIGINT UNSIGNED     NOT NULL AUTO_INCREMENT,
 timestamp     DATETIME         NOT NULL,
 process     VARCHAR(32)         NOT NULL DEFAULT '',
 process_id     INT             NOT NULL DEFAULT 0,
 message     VARCHAR(1024)         NOT NULL DEFAULT '',
 
 PRIMARY KEY     ( id ),
 KEY         ( timestamp )
 ) ENGINE = MyISAM ;
 " ;
 mysqli_query ( $dblink, $query ) ;
 
 // Read the logfile, split each record parts and insert a new row in the table
 $fp    =  fopen ( $logfile, "r" ) ;
 
 while  ( ( $line = fgets ( $fp ) )  !==  false )
 {
 list ( $timestamp, $process, $pid, $message )    =  get_log_parts ( $line ) ;
 $process    =  mysqli_escape_string ( $dblink, $process ) ;
 $message    =  mysqli_escape_string ( $dblink, $message ) ;
 $query        =  "
 INSERT INTO httptracking_1
 SET
 timestamp    =  '$timestamp',
 process        =  '$process',
 process_id    =  $pid,
 message        =  '$message'
 " ;
 mysqli_query ( $dblink, $query ) ;
 }
 
 fclose ( $fp ) ;
 }
 
 
 
 // Create the version with variable-length data stored in the same table
 function  create_string_store_version ( $dblink, $logfile, $store_name )
 {
 // Recreate the httptracking_2 table if it already exists
 mysqli_query ( $dblink, "DROP TABLE IF EXISTS httptracking_2" ) ;
 
 $query    =  "
 CREATE TABLE httptracking_2
 (
 id         BIGINT UNSIGNED     NOT NULL AUTO_INCREMENT,
 timestamp     DATETIME         NOT NULL,
 process_ssid     BIGINT UNSIGNED        NOT NULL DEFAULT 0,
 process_id     INT             NOT NULL DEFAULT 0,
 message_ssid    BIGINT UNSIGNED        NOT NULL DEFAULT 0,
 
 PRIMARY KEY     ( id ),
 KEY         ( timestamp )
 ) ENGINE = MyISAM ;
 " ;
 mysqli_query ( $dblink, $query ) ;
 
 // Create the string store (or instanciate it if it already exists)
 // Keep the default size of 1024 characters and don't index the string value part
 $store        =  new DbStringStore ( $dblink, $store_name ) ;
 
 // Read the logfile, split each record parts and insert a new row in the table
 $fp    =  fopen ( $logfile, "r" ) ;
 
 while  ( ( $line = fgets ( $fp ) )  !==  false )
 {
 list ( $timestamp, $process, $pid, $message )    =  get_log_parts ( $line ) ;
 $process_id    =  $store -> Insert ( STRING_STORE_PROCESS, $process ) ;
 $message_id    =  $store -> Insert ( STRING_STORE_MESSAGE, $message ) ;
 $query        =  "
 INSERT INTO httptracking_2
 SET
 timestamp    =  '$timestamp',
 process_ssid    =  $process_id,
 process_id    =  $pid,
 message_ssid    =  $message_id
 " ;
 mysqli_query ( $dblink, $query ) ;
 }
 
 fclose ( $fp ) ;
 }
 
 // Get parts from one log entry, ie : timestamp, process name, process id (within square brackets) and message
 function  get_log_parts ( $line )
 {
 $line        =  trim ( $line ) ;
 $timestamp    =  substr ( $line, 0, 19 ) ;
 $remainder    =  substr ( $line, 20 ) ;
 $re        =  '/
 (?P<process> [^\[]+)
 \[
 (?P<pid> [^\]]+)
 \]
 \s*
 (?P<message> .*)
 /imsx' ;
 preg_match ( $re, $remainder, $match ) ;
 
 return ( [ $timestamp, $match [ 'process' ], $match [ 'pid' ], $match [ 'message' ] ] ) ;
 }
 |