Site Sponsors:
Quick PHP Persistence  

Easy Enough?


One of the reasons why SQL databases are such a performance bottleneck in modern enterprise systems is that people store absolutely everything in them. Indeed, over the decades I encounter more and more blank stares when I respond to queries by telling friends that - even given the millions of search-able recipes, quotations, events, and graphics shared throughout my popular sites, that we have never felt the need to use SQL. -Binary searches, text indexing, and data storage routines are easy enough to write?

Requirement Triage


Indeed, it is due to the many fallacies one often discovers in the "one technology fits all" mantra that savvy technical folks refuse to do things like log HTML hits to an enterprise resource. -Without clear business justification, when it comes time to store billions of simple n-keyed records a day - into a bottleneck-sensitive database - perhaps folks are doing so because they do not realize that there is an easy alternative? (After all, to make any database work, someone had to write things like indexing and binary searches (and a whole lot more - wink - wink), at some point?)

When it comes to demonstrating customized, responsive solutions to domain-specific challenges, such was the case when I was recently showing off a performance-boosting notion designed to use PHP CRUD. When discussing how we can quickly & easily save data to an indexed file, the "I'm from Missouri" (i.e. 'show me') -urge came up with a succinct demonstration:


class user_info {

var $data = array();

function __construct() {
$this->data[0] = -1;
$this->data[1] = '';
$this->data[2] = '';
$this->data[3] = '';
$this->data[4] = false;

}

public function getPayload() {
return $this->data[4];
}

public function setPayload($str) {
$this->data[4] = $str;
}

public function getAlias() {
return $this->data[3];
}

public function setAlias($str) {
$this->data[3] = $str;
}

public function getPassword() {
return $this->data[2];
}

public function setPassword($str) {
$this->data[2] = $str;
}

public function getEmailt() {
return $this->data[1];
}

public function setEmail($email) {
$this->data[1] = $email;
}

public function getAccount() {
return $this->data[0];
}

public function setAccount($ss) {
$this->data[0] = $ss;
}

public function isNull() {
return ($this->data[0] === -1);
}

public function toString() {
$result = implode('|', $this->data);
return $result;
}

public function fromString($str) {
$this->data = explode('|', $str);
return true; // gigo
}

}


Simple String


The crux of the above example is a demonstration of how we can quickly read and write class information to a string. No XML. No JSON. Just a nice, efficient, cross platform representation of an easily extensible data format.

Exploding Arrays


By using arrays, encapsulation, and PHP's implode() and explode() feature, a classy lifestyle can get instances stored relatively quickly. -Best of all, when using an encapsulated array(), we are free to rapidly extend the number of fields / columns we keep without change requests, hours of meetings, or ever contacting your friendly neighborhood DBA ;-)

After storing data, comes the searching. While I consider my indexing technologies to be intellectual property, at the end of the day such things are easy enough to write for oneself.

Class Egocentricity


For what it is worth, working within the confines of typeless languages (such as PHP) can also bring a few conveniences to mind. Indeed, while an accomplished object-oriented designer might be interested in designing an instance out of a controller, for maintenance reasons some odd 'typeless-convenience' patterns may surface:


class user_info_crud extends user_info {
var $info;
var $db;

public function __construct() {
user_info::__construct();
$this->info = new IndexedDataInfo();
$this->info->data_min = 1024;
$df = home('front_end_data/user_info.crud');
$this->info->setFileNames($df);
$this->db = new IndexedData();
}

public function create() {
$res = $this->db->append($this->info, '');
if ($res === false)
return false;
$this->setAccount($res);
return $this->update();
}

public function read($ss) {
$str = $this->db->read($this->info, $ss);
if ($str === false)
return false;
return $this->fromString($str);
}

public function update() {
if ($this->isNull() == false) {
$str = $this->toString();
return $this->db->update($this->info, $this->getAccount(), $str);
}
return false;
}

public function delete() {
if ($this->isNull() == false)
return $this->db->update($this->info, $this->getAccount(), '');
return true;
}

public function tally() {
return $this->db->tally($this->info);
}

public function destroyDatabase() {
return $this->info->delete();
}
}


The above demonstrates how we might use PHP CRUD to maintain a list of user accounts. By using the logical, zero-based record-offset as the record identifier / account number, users have that identifier, as well as the email address (etc.) to manage their front-end web-access account. --In addition to leveraging file-level POSIX securities (usr/group, etc), the security conscious can even use PHP CRUD's base64 encoding as another line of defense.

Proper Packaging


But the real point is this: In as much as PHP is - for the moment - extremely typeless - rather than having your CRUD operations return - and manage - objects - it is often easier in PHP to use the above design pattern. While it always seems laughably obscene to derive a controller from an entity (such as we do above), doing so can often make OIOO (One-In One-Out - pronounced "ohio") operations far, far easier to deal with.

Indeed, in the final analysis, the ability to wrap a controller around an object is often what templates (also referred to as parametrized types) are all about.

Better still, if push comes to shove (as it often may), we can always retrieve or otherwise manage an array of user_info.

Enjoy,


-Rn



[ view entry ] ( 2204 views )   |  permalink  |  related link
JDK Issues - JPanel 

X11 Errors


There I was - poised to release another version of "The Sierra Bible", when we noticed - yet again - that not all Java Implementations are equal. Each have their own problems.

In this case, a buglet we were stalking came down to how The Sun 1.6 JDK implemented their hooks into the platform window manger (in this case, X11.) While Open JDK was working just fine, Sun's implementation was proving to be - uh - exceptional.

Exception Situation


Be they hosted by JDialog or JFrame, more and more folks are using panels.

Here is a JDialog using a JPanel:


public jdlgPopUp(JFrame parent, JPanel pan, String sTitle) {
super(parent, false);
initComponents();
this.getContentPane().add(pan, "card");
setTitle(sTitle);
pack();
}


Again, all worked fine under Open JDK. Under Sun, however, we saw:


Exception in thread "AWT-EventQueue-0" sun.awt.X11.XException: Cannot write XdndAware property
at sun.awt.X11.XDnDDropTargetProtocol.registerDropTarget(XDnDDropTargetProtocol.java:79)
at sun.awt.X11.XDropTargetRegistry.registerDropSite(XDropTargetRegistry.java:554)
at sun.awt.X11.XWindowPeer.addDropTarget(XWindowPeer.java:1633)
at sun.awt.X11.XComponentPeer.addDropTarget(XComponentPeer.java:1509)
at java.awt.dnd.DropTarget.addNotify(DropTarget.java:493)
at java.awt.Component.addNotify(Component.java:6687)
at java.awt.Container.addNotify(Container.java:2567)
at javax.swing.JComponent.addNotify(JComponent.java:4685)
at java.awt.Container.addNotify(Container.java:2578)
at javax.swing.JComponent.addNotify(JComponent.java:4685)
at java.awt.Container.addNotify(Container.java:2578)
at javax.swing.JComponent.addNotify(JComponent.java:4685)
at java.awt.Container.addImpl(Container.java:1068)
at java.awt.Container.add(Container.java:927)
at com.soft9000.VerseWorker.jdlgPopUp.<init>(jdlgPopUp.java:41)

The above exception was obviously bumped into while negotiating the X11 interface ("Cannot write XdndAware property".) Some variation of the problem was the same no matter if we were using JDialog, or JFrame. The result was - on error - that only Suns' JDK fails to display the application. Without a UI, you've got to kill the zombie explicitly.

(Note: Many implementations can assist with Java 'zombie management' by providing a PID as the prefix for a process name:
ManagementFactory.getRuntimeMXBean().getName();
)

The Solution


The solution, however, was to have a little faith in the Java specification! Indeed, is as much as every other JRE we had was able to "pass the test", we decided to simply add - then remove - another container from jdlgPopUp:


public jdlgPopUp(JFrame parent, JPanel pan, String sTitle) {
super(parent, false);
initComponents();
this.getContentPane().removeAll();
this.getContentPane().add(pan, "card");
setTitle(sTitle);
pack();
}

-Adding another component insured that the dialog initially did what it takes to register another container (in this case, a mere JScrollPane,) properly.

Using .removeAll(), in-turn, then ensured that those same X11 Structures were in place. -All things attributed & properly ORed so that our JPanel can re-use them.

Conclusion


Of course it all works fine now. After the above, our beta-testing continues on-schedule.

Indeed, by laying our hands upon just about every pre-installed, de-facto, or add-on JRE we can lay think of (Windows, OS X, Ubuntu, Oracle, IBM, etc,) the mission is all about supporting our fellow software enthusiasts.

So far, this fix works on everything we can hum at it.

Enjoy,

-Rn


[ view entry ] ( 4472 views )   |  permalink  |  related link
New Pascal Strings for PHP 
New Pascal: We use it in Java, .Net, and C/C++ - I even used them in the 118,000 recipes we have on this site.

Now is the time to share!

New Pascal Strings


Perfect for when we need to quickly index / save large "heaps" of textual data - or when we need to communicate between just about any other programming languages - we believe that the New Pascal String convention is both obvious, & simple. -So simple that we wrapped the convention up into a PHP class:


<?php
/**
* An opportunity to encapsulate the reading & writing of New Pascal Strings.
* Designed to work with my other "New Pascal Strings" readers and writers
* for Java, C/C++, and .NET.
*/
class IOPascal {

/**
* Properly open a file for cross-platform string-reading.
* @param type $file The file to read.
* @return type The file handle will be FALSE on error.
*/
public static function OpenRead($file) {
$hfile = fopen($file, 'rb');
return $hfile;
}

/**
* Properly open a file for cross-platform string-writing.
* @param type $file The file to write.
* @return type The file handle will be FALSE on error.
*/
public static function OpenAppend($file) {
$hfile = fopen($file, 'a+b');
return $hfile;
}

/**
* Read a Pascal String, as written by this, or a legacy, Pascal String writer.
* @param type $handle The handle of a file to read-from. (see <i>OpenRead</i>)
* @return type The string, as read from the file.
*/
public static function ReadString($handle) {
$char = '-';
while ($char != ' ') {
if (feof($handle))
return null;
$char = fgetc($handle);
if ($char == ' ')
continue;
$len = $len . $char;
}
if ($len)
$string = fread($handle, $len);
return $string;
}

/**
* Write a string to the file for reading by this, or a legacy. Pascal String reader.
* @param type $handle The handle of a file to write-to. (see <i>OpenAppend</i>)
* @param type $string The stirng, as destined to write-to a file.
* @return type Returns the size of the string as written to the file, else FALSE on error / partial write.
*/
public static function WriteString($handle, $string) {
$len = strlen($string);
$len = fwrite($handle, $len);
if($len == false)
return $len;
$len = fwrite($handle, ' ');
if($len == false)
return $len;
return fwrite($handle, $string);
}

}
?>


So when you feel the need to put a simple cross-tech count in front of a string - and when you do not want the newlines to stomp all over your activities - free free to use IOPascal.

Here is the test case:

<?php

include_once 'IOPascal.php';

echo '<h1>IOPascalTest.php</h1>';

$file = 'IOPascal.tmp';
$tstx = new IOPascal;

$test = 'If you can read this, then all is well';

unlink($file);
$hand = $tstx->OpenAppend($file);
if ($hand == false) {
echo 'Error 0: Access Permission Failure.';
exit(1);
}
$pos = $tstx->WriteString($hand, $test);
fclose($hand);

if ($pos != strlen($test)) {
echo 'Error 100: Basic read error.';
exit(1);
} else {
$hand = $tstx->OpenRead($file);
if ($hand == false) {
echo 'Error 101: Open Error.';
exit(1);
}
$result = $tstx->ReadString($hand);
fclose($hand);

if (strcmp($result, $test) != 0) {
echo 'Error 102: IO result mis-match?';
exit(1);
} else {
unlink($file);
$hand = $tstx->OpenAppend($file);
if ($hand == false)
echo 'Error 103<br>\n';
else {
$stuff = array('One', 'Two', '', "F\rour", "\nFive\r\n", 'Six');
foreach ($stuff as $str) {
$pos = $tstx->WriteString($hand, $str);
}
fclose($hand);
$hand = $tstx->OpenRead($file);
foreach ($stuff as $str) {
$input = $tstx->ReadString($hand);
if (strcmp($str, $input) != 0) {
echo "Error 104: Unable to read [$str]<br>";
exit(1);
} else {
echo "Okay [$str]<br>";
}
}
fclose($hand);
unlink($file);
echo 'Success.<br>';
exit(0);
}
}
}
?>


Enjoy,

-Rn


[ view entry ] ( 2541 views )   |  permalink  |  related link

<<First <Back | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Next> Last>>