Sunday 23 November 2008

BIOS LBA / Hard disk, apparent failure problem "Blinking cursor of doom"

A rather interesting low level problem: If you ever get a machine inexplicably stuck after POST with a blinking cursor in the top right and nothing more and want to know why or fix it, please read on!

Whilst there are a number of possible causes (like incorrect BIOS settings) I'm assuming all of those have been checked and ruled out, if so and the problem still persists then the following might be an explanation:

A while back I upgraded my ageing Dell Ispiron 6000 laptop hard drive (80gb) with a 160gb drive. I cloned the original drive to retain everything but made the partition larger to make the extra space available. The machine ran XP Pro SP2 and had been stable for a couple of years, since I first got it (after a battle with a nasty virus that I evenually managed to win a few months previously).

An easy enough job and all was good, for a while. One day the machine needed a reboot, after shutting down it came back with the Blinking cursor of Doom!

This is where, straight after POST (Power On Self Test) the machine totally hangs (before Windows starts up). My first thoughts (after oh crap) where along the lines of, has the drive died, mbr gone wrong, virus trashed the drive, partition table messed up, file system corrupt etc?

After many hours, I'd done a full chkdsk /r, fixmbr, checked the MBR (Master Boot Record) and Partition Table information, made sure the partition was active and so on, I even moved and resized the partition slightly, swapped the drive into another machine (was fine), tried a different drive in the laptop, also fine. Checked my BIOS (Basic Input Output System) for updates and so on - nothing seemed to be wrong - weird!

The MBR is the sector at cylinder 0, head 0, sector 1 - it's launched according to the BIOS boot sequence, if the BIOS finds a valid MBR it's copied to memory and executed as part of the boot sequence of the machine.

I also looked and the Windows MBR code (disassembly) from here http://mirror.href.com/thestarman/asm/mbr/STDMBR.htm to check all paths through the boot loader - all likely paths result in a message of some sort like the archaic "Please insert boot disk" type messages. I just got a blank screen with flashing cursor - how come?

I could see all the files on the disk, the disk and it's contents appears fine - so the question was what on earth was stopping the disk from being bootable!?. It defied any logic, surely if the file system is intact, has no errors, the partition table was fine and everything was set for the system to boot from it, why didn't it?

After much time was spent on it (I really didn't want to have to set everything up again) eventually I decided it would be quicker to re-ghost from the original 80gb drive and get back to where I was 2 or 3 months previously, then copying over any new data from the fine but un-bootable 160gb drive.

I did this and all was well again (but in the back of my mind I was never happy I'd not managed to get to the bottom of it).

My machine was working but I was puzzled. The machine starts up in the System BIOS, it runs various checks and initialises the hardware and subsystems before trying to find a bootable volume. Assuming a bootable hard disk is found, the MBR is executed, the partiton tables are examined and active partition is bootstrapped, the first "file" lauched in a windows 2000/XP/NT platform being the ntldr program responsible for starting windows (and capable of multiboot).

Whilst dissatisfied I'd not understood the problem, as days and weeks passed, the problem faded into a dim and distant memory...


--


Then, about 3 - 4 months later - after updating ITunes and needed to reboot, the same thing stuck again! Now this time, whilst rather disappointed, I knew there had to be an explanation. Maybe it was hardware related, maybe the machine was unreliable - how could I trust it again if it did this every so often?

So, this time around I thought I need to get to the bottom of this - there must be a reason, it's happened twice in a row, and suspiciously in roughly similar time spans (3 months or so) from the original disk clone - this had to be a clue.

So, after chkdsk /r etc just to check everything was ok, I got to work.

The disk was un-bootable, but the file system was fine. It hung immediately after POST, but with the briefest of flashes of the hard disk light. This had to be something low level, before windows, after POST - not much happens, especially knowing the MBR and partition tables were intact and fine too.

I renamed c:\ ntldr, IO.SYS and NTDETECT.COM, the low level bootstrap files for Windows.

After booting, the machine did exactly the same. Ahah this was a clue of sorts, if the disk was bootable but it wasn't getting as far as running ntldr then the fault was prior to that. If MBR and partition table were ok, then the fault was prior to that also, so, the BIOS?

I checked again for BIOS updates, nothing released matched the problem.

Then, after much Googling came the clue. Some BIOSes have an intrinsic 137gb limit.

That's 137gb of addressable disk, which might translate to less taking into account the overhead of the file system and block sizes etc.

Whilst Windows is happy to grow the file system behond this limit, eventually the BIOS will reach this maximum and barf. So, it could explain it....

There was only one way to find out. I resized the partition (made smaller) and created a new one in the new spare space. I copied files over from the original partition and then resized it smaller again, growing the new one until they were about the same size (2 x 80gb partitions rather than 1 x 160gb).

I restart with the downsized partition this time the machine comes up with a more helpful missing ntldr error message - ahah! it's tried to boot from the disk!

Booting up for a final time from the boot disk I renamed the files (ntldr etc) back. Reboot one last time and hey presto, it's working fine. Nothing lost, and this time I only lost a few hours (3 or 4) from my life and most importantly, I got some closure on the problem and an understanding of what happened and how to avoid it forever.

Greatly satisfied and relieve, I thought I'd share this experience in case it helps someone else in a similar position. Like anything, when you know the answer it's easy, but I've worked with computers for years and for a while there I was completely stumped with a problem that seemed, rather un-computer like, to defy all logic!

Whilst I'm entirely happy with two smaller partitions, the longer term solution is known as 48bit LBA, AKA Big LBA - http://en.wikipedia.org/wiki/Advanced_Technology_Attachment


References:

http://en.wikipedia.org/wiki/Master_boot_record
http://en.wikipedia.org/wiki/Booting#Boot_loader
http://en.wikipedia.org/wiki/Windows_NT_Startup_Process

http://mirror.href.com/thestarman/asm/mbr/STDMBR.htm
http://www.ata-atapi.com/hiwmbr.html

http://en.wikipedia.org/wiki/Advanced_Technology_Attachment

.

Applet <-> Javascript integration

It's been a while since I've done this, but I thought I'd refresh my memory on the options available. Maybe Applets have fallen out of favour a bit and whilst Javascript is popular for Rich, Dynamic Internet Applications, sometimes you need more and one way to do it is to use Applets, or integrate Applets with Javascript.

This example shows some simple ways to achieve Applet/JavaScript integration:

I've included example HTML with JavaScript source and Java source code for an Applet, to demonstrate so ways to achieve JavaScript to Java Applet integration. The simple example code demonstrates both JavaScript calling a Java Applet and a Java Applet calling JavaScript.

The JavaScript function jsShowMsg(String) is called in two different ways from the Java Applet. A single string parameter is passed, and the JavaScript function displays this using the standard alert() function to create a dialog box.

The Applet provides a showMessage(String) public method, which similarly is called by the JavaScript code when the button on the page is pressed. The String parameter is taken from the text field and displayed in the Applet.

HTML Page:


Provides the Applet on the page. Provides the JavaScript function called by the Applet, calls the Applet public method when the button is clicked (takes the String value from the input text box.

--

<HTML>
<HEAD>
<TITLE>Applet HTML Page</TITLE>
</HEAD>
<BODY>
<script type="text/javascript">

/**
* jsShowMsg - demostrates being called by an Applet, being passed a single String argument, the message
*/
function jsShowMsg(msg)
{
alert("Message from applet was: '" + msg + "'");
}

/**
* callApplet - demonstrates calling a public method on the Applet (showMessage(String))
*/
function callApplet(msg)
{
//alert("before calling Applet method with msg=" + msg);

document.testApplet.showMessage(msg);

//alert("after calling Applet method");
}
</script>

<H3><HR WIDTH="100%">Applet HTML Page - Applet <-> JavaScript integration example<HR WIDTH="100%"></H3>

<P>
<APPLET name="testApplet" codebase="classes" code="com/chillipower/TestApplet.class" width=400 height=150></APPLET>
</P>

<input type="text" id="msgTb" name="msgTb" value="A message from JS!" /><input type="button" value="button1" onclick="callApplet(getElementById('msgTb').value);" />

</BODY>
</HTML>

--


Java Applet Class:


Calls the JavaScript function in two different ways when the Applet is started. Provides a showMessage public method that the JavaScript can call.

--

package com.chillipower;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;

/**
* @author Louis B
*/
public class TestApplet extends Applet
{
String JS_MESSAGE = "Hello from Java Applet to JavaScript (using JavaScript alert)";
String JS_FUNC_NAME = "jsShowMsg";


/**
* init - applet init function
*/
@Override
public void init()
{
setBackground(new Color(0xFAFAFF));
}

/**
* start - applet start function
*/
@Override
public void start()
{
callJsByProto(JS_FUNC_NAME, JS_MESSAGE + " using showDocument :javascript protocol method");

callJsFunc(JS_FUNC_NAME, JS_MESSAGE + " using JSObject method");
}

/**
* Overide paint with simple text rendering
*
* @param g
*/
@Override
public void paint(Graphics g)
{
g.drawString("The Applet", 20, 20);
}

/**
* Simple function to show a message
*
* @param msg
*/
public void showMessage(String msg)
{
Graphics g = getGraphics();
g.setColor(Color.RED);
g.drawString("Message from JS: '" + msg + "'", 20, 40);
}

/**
* Call a named JS function, passing a single String parameter
*
* @param funcName
* @param msg
*/
private void callJsByProto(String funcName, String msg)
{
try
{
getAppletContext().showDocument
(new URL("javascript:" + funcName + "(\"" + msg +"\")"));
}
catch (MalformedURLException ex)
{
System.out.println("ex: " + ex.getMessage());
}
}

/**
* callJsFunc - call the named JavaScript function, passing the String msg argument
*
* @param funcName
* @param msg
*/
private void callJsFunc(String funcName, String msg)
{
String jscmd = funcName + "('" + msg + "')"; // Buiild the JavaScript command
String jsresult = null;
boolean success = false;

try
{
Method getw = null;
Method eval = null;
Object jswin = null;
Class c = Class.forName("netscape.javascript.JSObject"); /* works in IE too */
Method ms[] = c.getMethods();

for (int i = 0; i < ms.length; i++)
{
if (ms[i].getName().compareTo("getWindow") == 0)
{
getw = ms[i];
}
else if (ms[i].getName().compareTo("eval") == 0)
{
eval = ms[i];
}
}

Object a[] = new Object[1];
a[0] = this; /* this is the applet */
jswin = getw.invoke(c, a); /* this yields the JSObject */
a[0] = jscmd;
Object result = eval.invoke(jswin, a);

if (result instanceof String)
{
jsresult = (String)result;
}
else
{
jsresult = result.toString();
success = true;
}
}
catch (InvocationTargetException e)
{
jsresult = e.getTargetException().getMessage();
}
catch (Exception e)
{
jsresult = e.getMessage();
}

if (success)
{
System.out.println("JS eval succeeded, result is " + jsresult);
}
else
{
System.out.println("JS eval failed with error " + jsresult);
}
}
}

Debugging:

1. Using the Java ControlPanel (on 'nix, it is View Settings -> Edit the Java Runtime settings.

-agentlib:jdwp=transport=dt_socket,address=:

This makes the browser plug-in JRE open a debugging socket connection when launching the applet.

2. Open the Netneans project and attach the debugger in the SocketListen mode, using the same settings as above.



Resources:

http://windyroad.org/2006/08/14/reintroducing-javascript-and-hidden-applets-jaha/

http://java.sun.com/javase/6/docs/technotes/guides/plugin/developer_guide/java_js.html


.

Sunday 16 November 2008

Apache httpd 2.x -> Glassfish 2.x mod_jk installation


Configure Apache Httpd to Glassfish using mod_jk.


Note
, for Glassfish 3.x this process has been simplified, I'll probably add a blog entry about that sometime soon.

In this particular scenario, Apache 2.2.3 is running on Centos 5.2 x86_64 and Glassfish 2ur2 is running on OpenSolaris 10 b101, althought the process should be essentiually the same for any Operating system(s), the paths etc might change.


Apache httpd setup:


Get the Apache mod_jk connector.

http://tomcat.apache.org/connectors-doc/

Binary distribution:

http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/

Install into modules directory: e.g. /etc/httpd/modules (RH/Centos)

Configure Apache httpd:

e.g. for RH/Centos in - /etc/httpd/conf.d/

Add ajp worker mapping to httpd.conf (e.g. in /etc/httpd/conf/), in this example using virtual host entries, e.g.



# Virtual host chillipower.com
[VirtualHost 192.168.0.200]

DocumentRoot /var/www/mywebs/chillipower.com

ServerName www.chillipower.com

ServerAlias chillipower.com

DirectoryIndex index.html index.php index.htm index.shtml

JkMount /chillipower*/* worker1

[/VirtualHost]



Note in the above, the url to the glassfish context would be reached using http://mydomain.com/chillipower/ where in this instance the trailing / is important.

Load and configure the module (e.g. place this in /etc/httpd/conf.d/mod_jk.conf)

(all *.conf files are loaded by httpd.conf (before any virtual hosts etc) from the /conf.d directory in typical setups, so we can add a new mod_jk.conf and it will be loaded automatically)


LoadModule jk_module /etc/httpd/modules/mod_jk.so
JkWorkersFile /etc/httpd/conf.d/worker.properties
# Where to put jk logs
JkLogFile /var/log/httpd/mod_jk.log
# Set the jk log level [debug/error/info]
JkLogLevel debug
# Select the log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
# JkOptions indicate to send SSL KEY SIZE,
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat set the request format
JkRequestLogFormat "%w %V %T"
# Send all jsp requests to GlassFish
JkMount /*.jsp worker1
# Send all glassfish-test requests to GlassFish
JkMount /chillipower/* worker1



Add worker.properties file to configure the ajp worker, /etc/httpd/conf.d/worker.properties




# Define 1 real worker using ajp13
worker.list=worker1
# Set properties for worker1 (ajp13)
worker.worker1.type=ajp13
#worker.worker1.host=localhost.localdomain
worker.worker1.host=192.168.3.101
worker.worker1.port=8009
worker.worker1.lbfactor=50
worker.worker1.cachesize=10
worker.worker1.cache_timeout=600
worker.worker1.socket_keepalive=1
worker.worker1.socket_timeout=300




Glashfish setup:

Download Apace Tomcat 5.5.16 -> http://archive.apache.org/dist/tomcat/tomcat-5/

copy the tomcat-ajp.jar to the glassfish lib folder. e.g.

cp $CATALINA_HOME/server/lib/tomcat-ajp.jar
$GLASSFISH_HOME/lib/.

Also, download and copy the commons logging and commons modeller jar files to $GLASSFISH_HOME/lib

Commons logger -> commons-logging-1.1.1.jar from http://commons.apache.org/downloads/download_logging.cgi

Commons modeler -> commons-modeler-2.0.1.jar from http://commons.apache.org/downloads/download_modeler.cgi

Restart Glassfish...


References:

http://weblogs.java.net/blog/jfarcand/archive/2006/03/running_glassfi_1.html

.

Sunday 9 November 2008

c# code generation added rest describe code gen

Announcement: c# code generation added to google rest describe code gen api:

At last, the google rest describe code gen api now has a c# code generator. Targeting c# .net 3.5 WCF. This gives an easy route from existing services or WADL to c# client code/framework. I hope to be blogging about it soon, with some details of how it works and any limitations you shoud be aware of...


Monday 3 November 2008

I'm back! Some notes on SELinux and Apache HTTPD

Finally! I took some time out, with a big road trip to America and various other activities going on, I'd not had the time to keep the blog going. Anyway, things are back to normal now and after a recent hard disk failure I unexpectedly found myself setting up a new secure web server using CentOS 5.2 x64 and Apache Httpd 2.2.3 and PHP5. Later I'll add in a Java EE application server for more dynamic/web app stuff.

Thought that I'd type up some small notes on a problem I'd come across before, when trying to setup Mercurial HG-WEB in directories (or sym links) to directories outside of the usual /var/www

One of the problems may come from SELinux. Whilst it's tempting to turn it off, for something facing the public on the web - this would be a real last resort!

Security Contexts: - a quick explanation

Files and directories have security contexts. These can be seen using ls, e.g.

ls -aZ

By default Apache Httpd cannot access all files, it can access those with httpd_sys_content_t context types.

For example user home directories come with the context home_root_t which will give a permission denied type error if httpd tries to serve up files from there (or anywhere below!). Another common security context is default_t which will be assigned as the default for new files and folders.

An important difference between mv and cp

cp creates a new context (inherits), wheras mv actually moves it (unmodified). So a common gotcha is to create files in the user home directory and mv them to /var/www/... but this keeps the home context home_root_t - hence this creates the permission denied error.


Some handy commands:

chcon -R -h -t httpd_sys_content_t /test/

change the directory /test/ to httpd_sys_content security context type, recursively but not following sym-links.

i.e. the above would enable /test/ to be served by a documentroot in Httpd

If SELinux is suspected for the permissions problems (as opposed to httpd configuration), the SELinux restrictions will appear in the message log:

tail -f /var/log/messages


SELinux boolean flags:

can be read with

getsebool httpd_enable_cgi

and set with

setsebool httpd_enable_cgi true


Invoke the simple GUI configurator with: system-config-securitylevel


Restore the file context
(say after an mv command):

restorecon -R -v ./folderwithwrongcontext/


Additional SE Linux parameters:

Enable Samba to access home dirs:

setsebool -P samba_enable_home_dirs=1


Additional Resources:

Good overview in this link: http://docs.fedoraproject.org/selinux-apache-fc3/sn-simple-setup.html