Thursday 16 June 2011

Oracle client 11g installation under wine

I am a steadfast Fedora user both at home and at work. However, most of my colleagues tend to use Ubuntu and one of the problems I have come across a few times is the inability to install the Oracle client software under wine in Ubuntu. It all works fine under Fedora, so why does it fail on Ubuntu with the error message "java.lang.NullPointerException at oracle.sysman.oii.oiin.OiinNetOps.addNICInfo(OiinNetOps.java:109)"? I set out to find out.

After verifying that the installation error is reproducible and not just caused by a weird configuration specific to a single machine, I poked around the Oracle installation files to try to get an idea about how this error was occurring. Turns out that it is quite easy to reproduce. The following Java class does exactly that:

import java.net.InetAddress;
import java.net.NetworkInterface;

public class Test
{
	public static void main(String[] args)
	{
		try 
		{			
			InetAddress ia = InetAddress.getLocalHost();			
			NetworkInterface nic = NetworkInterface.getByInetAddress(ia);			
			String nicName = nic.getDisplayName();			
                        System.out.println(nicName);
		} 
		catch (Exception e) 
		{			
			e.printStackTrace();
		}	
	}
}


The above code runs perfectly fine on a Fedora installation but generates a NullPointerException on an Ubuntu installation at the point where nic.getDisplayName() method is called. This is caused by an oddity in network configuration of Debian based distributions. To avoid problems with fully qualified domain name resolution, Debian based workstations automatically get an entry in /etc/hosts of the form:
127.0.1.1  localhost.localdomain


Note that this is not the loopback address 127.0.0.1. Therefore, the localhost IP address ends up resolving to 127.0.1.1 - a valid "non-special" IP address. This in turn causes the above Java snippet to fail because quite correctly, it cannot detect a NIC bound to 127.0.1.1 on the local machine.
The solution is to either delete the above line from /etc/hosts or to add a new line as follows:
echo `hostname -i` "  "  `hostname -f` >> /etc/hosts



The Java code now runs without any exceptions natively, but under wine, it still causes the NPE. It appears that whatever native library used by Java (javanet.dll?) is not functioning properly under wine. In fact, under wine, Java cannot see any network interfaces at all. This can be proven by running the following piece of Java code under wine:

public class Test 
{
	public static void main(String[] args)
	{
		Enumeration nicList;
		try 
		{
			nicList = NetworkInterface.getNetworkInterfaces();		
		    while(nicList.hasMoreElements())
		    {
		    	NetworkInterface nic = nicList.nextElement();
		    	Enumeration ipList = nic.getInetAddresses();
		    	while(ipList.hasMoreElements())
		    	{
		    		System.out.println(nic.getName() + "-" + ipList.nextElement());
		    	}	    	
		    }
		} 
		catch (SocketException e) 
		{			
			e.printStackTrace();
		}
	}
}



So how does the Oracle installer run fine under Fedora and not under Ubuntu? I can't find a logical explanation for it. The only difference seems to be that the version of wine in the Ubuntu repositories is 1.2.x while Fedora ships with 1.3.x. (As always, Fedora ships with the bleeding edge development version of wine whilst Ubuntu ships with the stable release). To test whether version makes a difference, I uninstalled the stock wine installation from Ubuntu, downloaded the latest wine source (1.3.22) and compiled it as follows:

sudo apt-get -y remove wine && sudo apt-get autoremove
rm -rf ~/.wine
sudo apt-get -y install flex bison libx11-6 libx11-dev libfreetype6 libfreetype6-dev
wget http://ibiblio.org/pub/linux/system/emulators/wine/wine-1.3.22.tar.bz2
tar xvf wine-1.3.22.tar.bz2
cd wine-1.3.22/tools
./wineinstall


On my dual core Laptop with 2GB of RAM, compilation took about 1 hour.
Trying to run the Oracle client installer with the newly compiled version of wine still generates the old NPE, BUT, the installer doesn't crash there like before and actually continues to work! There's no logical explanation that I can think of for this strange behaviour, and frankly I am not too bothered about it. The important point is that I can finally mark this problem as solved and get some closure. :)

Tuesday 14 June 2011

Reading and writing GSettings from Python

Here's the class I wrote to read/write the screensaver settings from GSettings. It's probably not in the best Python style, but it illustrates the idea.


from gi.repository import Gio,GLib

class GnomeScreenLock:

IDLE_DELAY_SCHEMA = 'org.gnome.desktop.session'
IDLE_DELAY_KEY = 'idle-delay'

IDLE_ACTIVATION_SCHEMA = 'org.gnome.desktop.screensaver'
IDLE_ACTIVATION_KEY = 'idle-activation-enabled'

def getIdleDelay(self):
gsettings = Gio.Settings.new(self.IDLE_DELAY_SCHEMA)
return gsettings.get_value(self.IDLE_DELAY_KEY).get_uint32()

def setIdleDelay(self,delaySeconds):
gsettings = Gio.Settings.new(self.IDLE_DELAY_SCHEMA)
gsettings.set_value(self.IDLE_DELAY_KEY,GLib.Variant.new_uint32(delaySeconds))

def isIdleActivationEnabled(self):
gsettings = Gio.Settings.new(self.IDLE_ACTIVATION_SCHEMA)
return gsettings.get_boolean(self.IDLE_ACTIVATION_KEY)

def setIdleActivationStatus(self,activation):
gsettings = Gio.Settings.new(self.IDLE_ACTIVATION_SCHEMA)
gsettings.set_boolean(self.IDLE_ACTIVATION_KEY,activation)

Disabling screensaver/lock-screen on Gnome 3 during Flash movies

With the release of Gnome 3, most of the old Gnome APIs have undergone major changes. Many of these changes are not backward compatible at all. This presents an interesting challenge; specially at this still early stages of Gnome 3 developement - where almost everything is in a state of flux.

I regularly watch tech presentations from conferences - which are usually presented as Flash videos. Annoyingly, this means that the screen-lock will kick-in every few minutes and blank out the screen if I forget to move the mouse around.  Caffeine was the perfect answer for this situation before, but unfortunately due to API differences, it was no longer working on Gnome 3.  Setting the lock-screen activation delay to its' max value (1 hour - if using the GUI) was not an acceptable solution because I want the screen to blank out and lock itself quite quickly if I am away from the computer for a while.

My investigation into the Gnome lock-screen internals first led me to the following two dconf settings that are related to idle activation:

  • org.gnome.desktop.session.idle-delay - Number of seconds of idle activity before the screen is locked.

  • org.gnome.desktop.screensaver.idle-activation-enabled - Set whether idle detection is enabled.


Existing values for these can be obtained by running the commands:
gsettings get org.gnome.desktop.session idle-delay
gsettings get org.gnome.desktop.screensaver idle-activation-enabled

Values can be changed by using the following commands:
gsettings set org.gnome.desktop.session idle-delay 1800 
gsettings set org.gnome.desktop.screensaver idle-activation-enabled false

On my first attempt, I wrote a Python script that detects when Flash is active and sets the above settings to control the screen-lock activation. However, changes made to GSettings don't seem to propagate back to the relevant components in a timely manner. So the behaviour was mostly unpredictable. It also didn't feel like a very elegant solution to my problem either.

Going back to the drawing boards, I spent a few nights hunting for documentation about Gnome ScreenSaver and SessionManager. It should be mentioned that the one thing that Gnome 3 lacks the most is documentation. I finally ended up reading the Totem media player source code to figure out how it was disabling the screensaver during media playback. It turns out that in Gnome 3, the DBus interface for inhibiting the screensaver had moved from org.gnome.ScreenSaver interface to the org.gnome.SessionManager interface. The method signature has also changed. It now requires an application_id (Gnome specific identifier for applications that are currently running) and the toplevel XID (X Windows handle) of the application in addition to the inhibit reason and the flags. Some nice documentation on this can be found at http://people.gnome.org/~mccann/gnome-session/docs/gnome-session.html#org.gnome.SessionManager.Inhibit.

This revelation about the DBus solution led to further questions:
Q) How can I check the DBus interface on the actual system to make sure it hasn't changed since it was documented above?
A) D-Feet to the rescue. It's a very handy utility for exploring the active DBus interfaces on the system. I couldn't get it to work off the installation - possibly due to some path problem. However, I could get it to work off of the local directory by running:
d-feet -l

Q) How do I get an application_id and XID to pass to the DBus method call ?
A) I spent quite a lot of time poring through GTK documentation to figure this out - but couldn't find an easy solution. What I did find from my experiments is that these parameters are not really required for the method call to work. You can pass any string value as the app_id and any integer value as the XID and the call will still work correctly. It's an ugly hack, but as they say, perfect is the enemy of good :)

Q) How can I quickly check that the DBus method calls work?
A) I first used dbus-send as follows:
dbus-send --session --dest=org.gnome.SessionManager --type=method_call --print-reply --reply-timeout=20000 /org/gnome/SessionManager org.gnome.SessionManager.Inhibit string:"myApp" uint32:0 string:"Inhibiting" uint32:8

To see if the method call worked, I used the IsInhibited method.
dbus-send --session --dest=org.gnome.SessionManager --type=method_call --print-reply --reply-timeout=20000 /org/gnome/SessionManager org.gnome.SessionManager.IsInhibited uint32:8

The biggest gotcha here is that IsInhibited will always return false. This is because the Gnome Session Manager automatically removes the inhibition if the process calling Inhibit dies. Since Inhibit was called from the dbus-send process which immediately terminates, the inhibition is already removed by the time IsInhibited is called. I spent several hours cursing and losing tufts of hair to figure that one out.
The solution is to use something like iPython. I opened a new console window, started iPython and typed the following commands in it:
import dbus
bus = dbus.SessionBus()
proxy = bus.get_object('org.gnome.SessionManager','/org/gnome/SessionManager')
proxy.Inhibit("something",dbus.UInt32(0),"inhibiting",dbus.UInt32(8))

Then I used dbus-send to call IsInhibited from a different console window and voila!

And this finally leads us to the end. Rather than reinventing the wheel, I decided to contribute the outcome of my research back to the excellent Caffeine application. My branch of Caffeine in LaunchPad now has full support for inhibiting the screensaver in Gnome 3. Hopefully the lead developers will accept my changes back into the trunk and it will soon be widely available to everybody else.

Edit: My changes have been accepted and merged back in to the Caffeine trunk. http://bazaar.launchpad.net/~caffeine-developers/caffeine/main/revision/377

Sunday 5 June 2011

Adding your own launchers to gnome-shell dash

This one has been driving me nuts for days!

I have a few applications that I install on my home directory and never copy to the global /usr directories. Naturally, they don't show up in the applications menu. In Gnome 2, adding a shortcut to such an application was as simple as right clicking the panel and selecting "Create new launcher". Unfortunately, since Gnome 3 seems to be designed by Mac users with single mouse buttons, right clicks have become some sort of a taboo.  (Why can't I right click the desktop to change the wallpaper any more? What is wrong with that dammit!). Worse than that, only applications appearing in the "applications" menu can be added to the dash. So what do you do if you want to have quick access to one of the locally installed apps?

After a bit of Googling, I found this fantastic link: http://fedorasolved.org/Members/bookwar/gnome-3-tips

So, the steps are:

  1. Create a desktop file in ~/.local/share/applications (http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html)

  2. Reload gnome-shell (Press Alt+F2, type r and press enter)

  3. Now your app will show up in the applications list. Drag and drop to the dash to create the launcher


I am all for innovation and pushing boundaries, and  I am trying to keep a very open mind about Gnome 3. There are some pretty good ideas in there, and I appreciate the arduous task they have taken on. But come on, why do such blindingly simple things like this have to be so complicated?

 

Friday 3 June 2011

Bufferbloat

Interesting Google tech talk by Jim Gettys about Bufferbloat:  http://www.youtube.com/user/GoogleTechTalks#p/u/0/qbIozKVz73g

Also checkout netalyzr to test and gather information about your network connection : http://netalyzr.icsi.berkeley.edu/