Eli : Memcached, MySQL, Highcharts

Friday, February 6 2015

Solve PHP Warning : session_start() [function.session-start]: Node no longer exists

PHP Warning : session_start() [function.session-start]: Node no longer exists

This error is really annoying and can be hard to solve, it appears in two forms and only after a session has already been set.
This error will output two different messages :

PHP Warning:  Unknown: Node no longer exists in Unknown on line 0
PHP Warning : session_start() [function.session-start]: Node no longer exists in {session_start() file} on line 32

Solution is really simple, you have a SimpleXMLElement in your $_SESSION that does not deserialize properly.

Finding what variable trigger the error

PHP only tells you where the error kicks in (the session_start()), not where it really happened. To verify the diagnostic, first find your session.save_path

In PHP

[PHP]echo ini_get('session.save_path')

or simply

print_r($_SESSION)

On your server

php -i | grep session.save_path

Then go to this directory and open a sess_XXX file, then find a string looking like

myVariable|O:16:"SimpleXMLElement":0:{}

In serialized code, it means your variable myVariable is an Object, whose class name is 16 characters long and is SimpleXMLElement, 0:{} means it's empty.

Fixing the error

You need then to add a string cast in your PHP script for this variable when you assign it to the $_SESSION

# Invalid code
$_SESSION[myVariable] = $simpleXML->node->anotherNode->variable
# Correct code
$_SESSION[myVariable] = (string)$simpleXML->node->anotherNode->variable

If you have a more complex SimpleXMLElement (eg : a XML node, not just a string), then use the asXML() method

# Invalid Code
$_SESSION['myVariable'] = $simpleXML->node
# Accessing the variable
$myVariable = $_SESSION['myVariable'];
# Correct Code
$_SESSION[myVariable] = $simpleXML->node->asXML()
# Accessing the variable
$myVariable = new SimpleXMLElement($_SESSION['myVariable']);

Don't forget to change your access to this session variable as it will not be a SimpleXMLElement but rather a string containing XML.


Summing Graph Data by Series in Highcharts/Highstocks

How to Sum series in Highcharts & Highstocks

This quick code will do the trick and add a nice sum of all series values in the legend label for each series

legend: {
enabled: true,
labelFormatter: function() {
var count = 0;
for (var i = 0 ; i < this.yData.length; i++) {
count += this.yData[i];
}
return this.name + ' [' + count + ']';
}
}

Quick explanation of Highcharts legend parameters

labelFormatter : function() { } : called by Highcharts to make legend label, for each item, return the text for the legend builder.
this.yData : contains series data, in a Javascript array.
this.name : series label, defined in the series array on your chart definition.

Hope this help


Subclipse : svn: This client is too old to work with the working copy (format 31)

org.apache.subversion.javahl.ClientException: Unsupported working copy format

This message show up if your are trying to use Subclipse 1.7 client with a Subversion 1.8 working copy or Subclipse 1.6 client with a newer version working copy.
Even if older clients and servers inter-operate transparently with 1.8 servers and clients, when a working copy is upgraded to Subversion 1.8, Subclipse 1.6 and client can no longer be used on it.

You need to get a newer Subversion client but you already upgraded Subclipse

Here is the trick, if Tortoise follow the rule "Version 1.8.X means builts against Subversion 1.8.X", Subclipse not. Why ?

Subclipse follows an odd/even release numbering convention.
The 1.7.x release stream of Subclipse was built against development builds of Subversion 1.7.
The release of Subversion 1.7.0 started the Subclipse 1.8.X release branch.

So if you tried to upgrade Subclipse with http://subclipse.tigris.org/update_1.8.x that will not work with Subversion 1.8.

What to do

To be simple :

Subclipse 1.4.x works with Subversion 1.5.x features and working copy.
Subclipse 1.6.x works with Subversion 1.6.x features and working copy.
Subclipse 1.8.x works with Subversion 1.7.x features and working copy.
Subclipse 1.10.x works with Subversion 1.8.x features and working copy.

So if you got this error with (format 31), use the check for upgrade option on your Eclipse and add this url
http://subclipse.tigris.org/update_1.10.x

If it's another error with another working copy error, check the Subclipse version working with your Subversion version, and use the right upgrade url.

Subversion Working Copy Format

Here is a little more explanation about the Subversion working copy format number, from the source code itself.

There is no format version 0; we started with 1.
The bump to 2 introduced the ".svn-work" extension. For example,
".svn/props/foo" became ".svn/props/foo.svn-work".
The bump to 3 introduced the entry attribute
old-and-busted.c::ENTRIES_ATTR_ABSENT.
The bump to 4 renamed the magic "svn:this_dir" entry name to "".
== 1.0.x shipped with format 4
== 1.1.x shipped with format 4
== 1.2.x shipped with format 4
== 1.3.x shipped with format 4
The bump to 5 added support for replacing files with history (the
"revert base"). This was introduced in 1.4.0, but buggy until 1.4.6.
The bump to 6 introduced caching of property modification state and
certain properties in the entries file.
The bump to 7 changed the entries file format from XML to a custom
text-based format.
The bump to 8 placed wcprops in one file per directory (named
upgrade.c::WCPROPS_ALL_DATA)
== 1.4.x shipped with format 8
The bump to 9 added changelists, keep-local, and sticky depth (for
selective/sparse checkouts) to each entry.
== 1.5.x shipped with format 9
The bump to 10 added tree-conflicts, file externals and a different
canonicalization of urls.
== 1.6.x shipped with format 10
The bump to 11 cleared the has_props, has_prop_mods, cachable_props,
and present_props values in the entries file. Older clients expect
proper values for these fields.
[...]
The bump to 29 renamed the pristine files from '<SHA1>' to '<SHA1>.svn-base'
and introduced the EXTERNALS store. Bumped in r1129286.
== 1.7.x shipped with format 29
The bump to 30 switched the conflict storage to a skel inside conflict_data.
Also clears some known invalid state. Bumped in r1387742.
The bump to 31 added the inherited_props column in the NODES table.
Bumped in r1395109.
== 1.8.x shipped with format 31

Source : http://svn.apache.org/repos/asf/subversion/trunk/subversion/libsvn_wc/wc.h

Hope this explain you the difference between TortoiseSVN and Subclipse version numbers and explain the format number in Subversion working copy


Calculate and Optimize MySQL Database Size

Computing MySQL database size can provide you useful informations : disk usage, index size, number of rows, lack of index, collations and many more.
Calculating these values use the information database : INFORMATION_SCHEMA, the place that stores information about all the other databases that the MySQL server maintains.

Simple Query to show MySQL Database Usage

This query will show the index and data size in Mb, number of rows per table with database type, partitions and collation.

SELECT TABLE_NAME AS "Table", 
       TABLE_ROWS AS "Rows", 
       CONCAT((FORMAT((DATA_LENGTH) / POWER(1024,2),2)), ' Mb') AS "Data Size", 
       CONCAT((FORMAT((INDEX_LENGTH) / POWER(1024,2),2)), ' Mb') AS "Index Size",
       CONCAT((FORMAT((DATA_LENGTH+ INDEX_LENGTH) / POWER(1024,2),2)), ' Mb') AS "Total Size",
       TRIM(TRAILING ', ' FROM CONCAT_WS(', ', ENGINE, TABLE_COLLATION, CREATE_OPTIONS)) AS "Type"
FROM information_schema.TABLES
WHERE information_schema.TABLES.table_schema = "${Your Database Name}"

This MySQL query execution will output something like this :

 Table                |    Rows | Data Size|Index Size|Total Size| Type
MySQL_TABLE_A         |      342|   0.19 Mb|   0.00 Mb|   0.19 Mb| InnoDB, utf8_general_ci
MySQL_TABLE_B         |     8747|   6.52 Mb|   0.70 Mb|   7.22 Mb| InnoDB, utf8_general_ci
MySQL_TABLE_C         |        0|   0.02 Mb|   0.00 Mb|   0.02 Mb| InnoDB, latin1_swedish_ci
MySQL_TABLE_D         |     4265|   1.52 Mb|   0.42 Mb|   1.94 Mb| InnoDB, utf8_general_ci
MySQL_TABLE_E         |     1934|   0.44 Mb|   0.16 Mb|   0.59 Mb| InnoDB, utf8_general_ci

This is also a good example why I also added database engine and MySQL collation in this query, one table is not in utf8_general_ci but in latin1_swedish_ci.

Another way to show MySQL Database Usage

This query use a MySQL function to compute size in more readable number by changing size numbers units.

DELIMITER $
DROP FUNCTION IF EXISTS byteResize$
CREATE FUNCTION byteResize(bytes FLOAT(9)) 
RETURNS VARCHAR(50)
 
BEGIN
        # Unit list
        DECLARE unit INTEGER UNSIGNED DEFAULT 1;
 
        # Resizing
        WHILE bytes > 1024 DO
            SET bytes = bytes / 1024;
            SET unit = unit + 1;
        END WHILE;
 
RETURN CONCAT(ROUND(bytes, 2), ' ', ELT(unit, '', 'K', 'M', 'G', 'T'), 'b');
 
END$
DELIMITER ;
 
SELECT TABLE_NAME AS "Table", 
       TABLE_ROWS AS "Rows", 
       byteResize(DATA_LENGTH) AS "Data Size", 
       byteResize(INDEX_LENGTH) AS "Index Size",
       byteResize(DATA_LENGTH+ INDEX_LENGTH) AS "Total Size",
       TRIM(TRAILING ', ' FROM CONCAT_WS(', ', ENGINE, TABLE_COLLATION, CREATE_OPTIONS)) AS "Type"
FROM information_schema.TABLES
WHERE information_schema.TABLES.table_schema = "${Your Database Name}"

This MySQL query will output :

 Table                |    Rows | Data Size|Index Size|Total Size| Type
MySQL_TABLE_A         |    40119|   3.52 Mb|   4.03 Mb|   7.55 Mb| InnoDB, utf8_general_ci
MySQL_TABLE_B         |  1042959| 757.45 Mb|  37.28 Mb| 794.73 Mb| InnoDB, utf8_general_ci, partitioned
MySQL_TABLE_C         | 36788508|   2.43 Gb|   3.10 Gb|   5.53 Gb| InnoDB, utf8_general_ci, partitioned
MySQL_TABLE_D         |     1876| 112.00 Kb|    0.00 b| 112.00 Kb| InnoDB, utf8_general_ci
MySQL_TABLE_E         |        0|  16.00 Kb|  16.00 Kb|  32.00 Kb| InnoDB, utf8_general_ci
MySQL_TABLE_F         |     1925| 480.00 Kb| 144.00 Kb| 624.00 Kb| InnoDB, utf8_general_ci
MySQL_TABLE_G         |  1210839|  70.78 Mb| 124.14 Mb| 194.92 Mb| InnoDB, utf8_general_ci, partitioned
MySQL_TABLE_H         |     1762|  96.00 Kb|  64.00 Kb| 160.00 Kb| InnoDB, utf8_general_ci
MySQL_TABLE_I         |    44384|  10.52 Mb|   7.55 Mb|  18.06 Mb| InnoDB, utf8_general_ci
MySQL_TABLE_J         |     1536| 176.00 Kb|    0.00 b| 176.00 Kb| InnoDB, utf8_general_ci
MySQL_TABLE_K         |    10849|   1.52 Mb|    0.00 b|   1.52 Mb| InnoDB, utf8_general_ci


This will make the MySQL table size values more readable as the first query returned 5,711.73 Mb as Table B total size.

Hope this will help you.


Javascript function setInterval() with custom parameters

Javascript method

The setInterval() method calls a function or evaluates an expression at specified intervals in milliseconds
One tricky thing is passing parameters to the function called as documentation is hard to find.

Passing Parameters to setInterval()

Make an anonymous function inside setInterval()

function load(functionParameter) {
    //function called by setInterval()
}
...
var customParameter;
setInterval(function() { load(customParameter); },  1000);


Hope this help you save time


- page 1 of 9