ZON ISP (Bad) as Usual

I'm considering changing my Internet Service Provider (ISP).

I currently have a optical fiber connection, fiber to the home (FTTH), from TVTel at 30Mbit/s.
But TVTel was acquired by ZON and so I'm considered migrating to it, since the value for money seems better, at approximately the same cost I can get a 50Mbit/s optical fiber connection.

But ZON has three major problems:
  1. Extremely bad reputation when it comes to ISP;
  2. Lousy customer service;
  3. the ZON optical fiber solution is not FTTH.
They are fighting the first couple of problems and the fact is that the number of complaints against them has seen a serious decrease.
But all this made me delay the decision for some months, to see if there were other ISPs that would provide me FTTH.
Unfortunately no one else provides FTTH on the area, and since ZON seems to be discontinuing the TVTel infrastructure that they bought, that leaves the optical fiber to the local node and coaxial cable solution.

So, I decided to give it a try, specially because there is a one month trial period were one can cancel the service if one is not satisfied.
And currently, I'm not a satisfied customer. The 50Mbit/s connection on the signed contract is actually working at less than 10% of the speed.
Here is this morning speed measure from the organization responsible for the internet in Portugal, Fundação para a Computação Científica Nacional
(FCCN), where it says that this morning I almost got an "astonishing" 5Mbit/s connection:

ZON internet connection speed meter.

Look at the red graph speed on the right of the picture. Yes, it says that if we were in 2002 and using an ADSL 4Mbit/s connect that would be great. Unfortunately this we're on the end of the first decade of the 21st Century and I have a signed contract for 50Mbit/s.
For details, check the numbers on the left, the first number is the maximum download speed, the second is the average download speed, the third is the maximum upload speed and the fourth is the average upload speed.
There's no doubt what so ever, ZON optical fiber connection is easily beaten by a 8Mbit/s ADSL connection.

Here's the download information detail

ZON internet download speed.

Check the graphs on the bottom. It not even gets close to 5Mbit/s and the average speed is just above 1.2Mbit/s and the speed is just not constant, it jumps up and down.
Remember that this is an optical fiber 50Mbits/s connection.

And here is my current TV Tel 30Mbit/s download speed data, taken immediately after I got the lousy speed from ZON.

TVTel internet download speed.

The average speed is just below 22MBit/s, the first value on the left. The maximum speed is just above 22MBit/s and the minimum speed is just above 20Mbit/s. The connection is stable, regular, linear, smooth and, above all, fast!

Let me correct my first sentence on this post: "I was considering changing my ISP", because with a service like this one, ZON will definitely not get a contract with me.
But the first ISP that provides me FTTH will probably.

./M6

Recovering from a bad Hard Disk Crash

Last time I've used my computer I burned a DVD Video with K3B and shutdown openSUSE as usual.

Yesterday, when I turned the computer on, it went directly into GRUB shell which allowed me to execute some commands with no real use to me.

Obviously something was wrong, and I though that it was the Master Boot Record (MBR) that got corrupted, as I've already have experienced before.
So I got the openSUSE installation disk and boot with it in order to fix the problem. I've requested the fix option from the menu but then something weird happened.
When scanning the hard disk, it displayed a message that there was something wrong and I would not be able to edit the disk partitions. I checked the partitions and the information seems to show that everything was OK.
I needed something else to see what was wrong with the hard disk and to fix it.

I grabbed an old Knoppix CD, version 3.3, the only one that I know that loads correctly on my Acer laptop (by the way, don't by an Accer if you wish to have Linux on a laptop), and checked the disks. This is not the first time I use Knoppix to save a system, it's actually one of my companion disks.
Knoppix automatically mounted both windows partitions correctly but the Linux EXT4 and Swap partitions were missing.
Now I start to get worried...

I got into a shell and checked the partitions with fdisk.
I detected the problem immediately: I had two partitions starting at the same cylinder! I even recall its number, 2086.
The second partition had an Id of f, which is awkward since the Id is a numeric value, and was marked as the boot partition. Using fdisk to see what my chances were of correcting this I realized that a drastic solution would probably be the only solution. When I deleted that second weird partition, the following partitions were gone to.

So, before I do something that I could regret latter, I checked the content of the Windows partitions to find out that if anything would go wrong I already had a backup of everything.
The data on the Linux partition seemed already lost, so I would have to settle for the backups.
On the other hand, I was still able to save everything from the Windows partitions, but that would be unecessary.

I finally decided what to do and how to do it.
I've deleted that second weird partition, defined the first partition as boot and saved the partition table.
I could have tried to recreate the partition table with fdisk, but since I had backups of everything, I just went for the full disaster scenario.

I then rebooted with the openSUSE installation disk, created a second partition, that I reserved to replace the lost second partition for Windows, and created a third one for Linux, where I installed openSUSE.

When openSUSE installation finished I've reboot and started Windows, which loaded just fine from the saved first partition. When Windows loaded, it was time to format that previous reserved second partition as NTFS.

The whole thing took me a couple of hours but I got both Windows and openSUSE up and running again. Today I'll restore the backups, which will probably take a couple hours more.

Moral of the story:
  1. Always have a Knoppix disk at hand.
  2. Backups are a tech best friend.

./M6

openSUSE

I've just moved from Kubuntu to openSUSE.
The reason is simple, Kububtu 9.10 revealed too unstable for me. In just a couple of months I had to reinstall once and when troubles reappear for the second time, I talked with a friend and decided to give a try to openSUSE.

So far, so good. It's a lot more stable and my hardware seems to be better supported, even my ATI Mobility Radeon X700 that always gave me headaches in Linux works fine. Unfortunately the 3D support seems not be be fully working, but that is not a issue, at least for now.

I kept KDE as my window manager, it suits better my needs. The first look and feel at it was very pleasant. Even the desktop wallpaper is very good.
One of the first things I've learn was to add the Packman repository, since the default official repositories does not have some software for "some legal uncertainties". For instance, it does not have the mpeg2enc from mjpegtools, one has to remove the mjpegtools, add the Packman repository and add the mjpegtools again in order to have the Packman mjpegtools package installed, which does have the mpeg2enc.
Other great software, like 'Q' DVD-Author and DeVeDe, also comes from the Packman repository, so it is critical to include it.

Some things are different, specially when it comes to the administration part. Maybe it is because openSUSE has so much affinity with SUSE servers, it has a lot of easy administration tools right out-of-the-box.
But some things seem the same. The Network Manager still sucks. Why is it so hard to use, specially when its flag is "Pain-Free Networking"? Since Network Manager appeared, all it gave me was problems. In Kubuntu it simply did not connect via wifi, and now I can't enable it, even after I defined it to be my network manager and enabled it!...

Anyway, everything seems to work just fine and I'll keep openSUSE for a while, specially because it seems very stable.

./M6

DB2 How To

While I was searching for the loading method that accepted a dynamic query from inside a stored procedure, I found a simple and very useful DB2 How To.

Here it is: DB2 How Tos.

./M6

DB2 Copy Schema With Tables

Recently I needed to automate a DB2 schema backup.
My requirements were quite easy, just create a new schema and copy the tables and their content into the new schema.

What initially started as a simple task reveled to be a hard task and resulted in a quite simple script.

The first problem was to execute several commands in the DB2 Command Editor. I was getting syntax errors because the statement termination character was set to be the same as the SQL end statement character ;.
Setting it to # solved my problem, but I did waste some time with this so keep in mind to change the statement termination character to avoid such problem.

I've created a specific schema for this automation task COPY_DATABASE_SCHEMA, so all the procedures will be created there.

Here is the procedure that will copy a table content:

/**
* Copies, with replacement, the content from the source table
* into the target table.
* It will not check for success, i.e. no loading validation
* will be performed.
*
* @sourceTable: the full qualified source table name
* @targetTable: the full qualified target table name
*/
create procedure COPY_DATABASE_SCHEMA.COPY_TABLE(
sourceTable VARCHAR(128),
targetTable VARCHAR(128))
LANGUAGE SQL
begin
declare v_version_number INTEGER default 1;
declare v_cursor_statement VARCHAR(32672);
declare v_load_command VARCHAR(32672);
declare v_sqlcode INTEGER default -1;
declare v_sqlmessage VARCHAR(2048) default '';
declare v_rows_read BIGINT default -1 ;
declare v_rows_skipped BIGINT default -1;
declare v_rows_loaded BIGINT default -1;
declare v_rows_rejected BIGINT default -1;
declare v_rows_deleted BIGINT default -1;
declare v_rows_committed BIGINT default -1;
declare v_rows_part_read BIGINT default -1;
declare v_rows_part_rejected BIGINT default -1;
declare v_rows_part_partitioned BIGINT default -1;
declare v_mpp_load_summary VARCHAR(32672) default NULL;

set v_cursor_statement =
'DECLARE C1 CURSOR FOR SELECT * from ' || sourceTable;
set v_load_command =
'load from C1 of cursor insert into ' || targetTable;

call db2load(1, v_cursor_statement, v_load_command, v_sqlcode,
v_sqlmessage, v_rows_read, v_rows_skipped,
v_rows_loaded, v_rows_rejected, v_rows_deleted,
v_rows_committed, v_rows_part_read,
v_rows_part_rejected, v_rows_part_partitioned,
v_mpp_load_summary) ;
end#
Please note that the target table must already be created in order for this procedure to work.
This procedure was the hard part. Copying the contents of any table requires a dynamic prepared query statement to use as a cursor, and the load command is not available inside a procedure, so the db2load procedure from SYSPROC must be used.

Here is the procedure that will create a schema, create the tables on it and copy the contents:


/**
* Copies an entire schema into a new schema named with the current date.
* @sourceSchema: the source schema name
* @targetSchema: the target schema name
* @tableNameSelection: the tables name to include ('%' for all tables)
*/
CREATE PROCEDURE COPY_DATABASE_SCHEMA.COPY_DATABASE(
sourceSchema VARCHAR(50),
targetSchema VARCHAR(50),
tableNameSelection VARCHAR(150)
)
LANGUAGE SQL
BEGIN
-- Variables
DECLARE stmtSchema VARCHAR(250);
DECLARE stmtTableStructure VARCHAR(200);
DECLARE stmtTableContents VARCHAR(250);
DECLARE stmtAlias VARCHAR(250);
DECLARE tableName VARCHAR(128);
DECLARE numPages BIGINT;
DECLARE nError INTEGER DEFAULT 0;
DECLARE at_end SMALLINT DEFAULT 0;
DECLARE not_found CONDITION FOR SQLSTATE '02000';
DECLARE V_SQL VARCHAR(200);
DECLARE V_STMT STATEMENT;
DECLARE V_LOAD_STMT STATEMENT;
DECLARE TGT_TABLE_CUR CURSOR WITH HOLD WITH RETURN FOR V_STMT;
DECLARE LOAD_CUR CURSOR FOR V_LOAD_STMT;
DECLARE CONTINUE HANDLER for not_found SET at_end = 1;


-- Create schema
SET stmtSchema = char('CREATE SCHEMA ' concat char(targetSchema));
EXECUTE IMMEDIATE stmtSchema;
SET CURRENT SCHEMA targetSchema;


-- Copy tables and views
SET V_SQL = 'SELECT name, npages FROM SYSIBM.SYSTABLES
WHERE CREATOR = ''' || trim(sourceSchema) || '''
AND NAME LIKE ''' || trim(tableNameSelection) || '''
order by name';
PREPARE V_STMT FROM V_SQL;
OPEN TGT_TABLE_CUR;

fetch_loop:
LOOP
FETCH TGT_TABLE_CUR INTO tableName, numPages;
IF at_end <> 0 THEN
LEAVE fetch_loop;
ELSE
SET stmtTableStructure = 'CREATE TABLE ' ||
targetSchema || '.' || tableName || ' LIKE ' ||
sourceSchema || '.' || tableName ;
EXECUTE IMMEDIATE stmtTableStructure;

IF numPages > 0 THEN
call COPY_DATABASE_SCHEMA.copy_table(
sourceSchema || '.' || tableName,
targetSchema || '.' || tableName);
END IF;
END IF;
END LOOP fetch_loop;

CLOSE TGT_TABLE_CUR;
END#
It dynamically issues DB2 SQL commands to create the schema and the tables structure and makes use of the previously created COPY_TABLE to copy the tables content. See the code comments for more information.

To use this just
call COPY_DATABASE_SCHEMA.COPY_DATABASE('originalSchemaName',
'newBackupSchemaName', '%');


Since I also need to discard old copies, I have created a procedure to drop a schema, including all the tables on it.
/**
* Drops an entire schema even if it has tables.
* Views are not supported.
* @schemaName: the name of the schema to drop
*/
CREATE PROCEDURE COPY_DATABASE_SCHEMA.DROP_SCHEMA(
schemaName VARCHAR(50)
)
LANGUAGE SQL
BEGIN
-- Variables
DECLARE stmtDropSchema VARCHAR(250);
DECLARE stmtDropTable VARCHAR(250);
DECLARE tableName VARCHAR(128);
DECLARE at_end SMALLINT DEFAULT 0;
DECLARE not_found CONDITION FOR SQLSTATE '02000';
DECLARE V_SQL VARCHAR(200);
DECLARE V_STMT STATEMENT;
DECLARE TGT_TABLE_CUR CURSOR WITH RETURN FOR V_STMT;
DECLARE CONTINUE HANDLER for not_found SET at_end = 1;

-- Copy tables and views
SET V_SQL = 'SELECT name FROM SYSIBM.SYSTABLES
WHERE CREATOR = ''' || trim(schemaName) || '''
AND CREATOR NOT LIKE ''SYS%''';
PREPARE V_STMT FROM V_SQL;
OPEN TGT_TABLE_CUR;

fetch_loop:
LOOP
FETCH TGT_TABLE_CUR INTO tableName;
IF at_end <> 0 THEN LEAVE fetch_loop;
ELSE
SET stmtDropTable = 'DROP TABLE ' ||
schemaName || '.' || tableName;
EXECUTE IMMEDIATE stmtDropTable;
END IF;
END LOOP fetch_loop;

CLOSE TGT_TABLE_CUR;

-- Drop schema
SET stmtDropSchema = char('DROP SCHEMA ' concat
char(schemaName) concat ' RESTRICT');
EXECUTE IMMEDIATE stmtDropSchema;
END#

This procedures have some limitations, for instance views are not supported.
Nevertheless, it is a good start to all that need to clone a schema or a table.

./M6

Layer Intromission

I'm using JTOpen JDBC driver to access AS/400 via DB2.
It works pretty well, but unfortunately it tries to be more than it should be, a JDBC driver that allows a Java application to access a DB2 database.

It interacts with the AS/400 system in a way it should not. For instance, when it's time to change the password, the driver pops-up a notification window stating that it's time to change the password and asks the user if he wishes to do it now.
If this feature seems nice, let me tell you that it is totally wrong!
First, it is a JDBC driver, not an AS/400 system administration application.
Second, this kind of promiscuity among layers has disastrous results.

When one uses a JDBC driver one expects that it operates with the database and nothing else.
When JTOpen starts getting "smart" by interacting with the system, awkward things happen.
For instance, an entire critical system can fail because the driver hang on a "password will expire soon, do you wish to change it now" message and waits for user action instead of doing what it is suppose to do: database work.
Please not that this is not a "password expired" message but a "you must change your password within x days, do you wish to do it now" question.

Here is a real example of such problem: I executed a command line batch which was hold by the JTOpen driver "would you like to change your password now" question.

JTOpen "Would you like to change your password now" User Dialog Box Question.

I got lucky because the command was issued by me, but what if it was issued by a scheduler on a Saturday morning? It would only be noticed Monday morning and a critical job would not have been performed because the JDBC driver messed up.

./M6

iSeries AS/400 Cheat Sheet

I am using IBM iSeries AS/400 a lot these days. Since I am not a specialist on such system, I've gathered some simple commands to help me to understand what's going on with my jobs and act on them when necessary.

Here's a simple list of some commands:

Working Active Jobs
Description: shows working active jobs.
Command: wrkactjob

Working Submitted Jobs
Description: shows the list of the working submitted jobs
Command: wrksbmjob

Working Object Lock
Description: shows the locks on an object, like a file.
Command: wrkobjlck (library/object)

CPU Usage Statistics
Description: shows CPU usage statistics, usually filtered to show only resource usages above 2%.
Command: who

Working System Status
Description: shows system overview usagestatus.
Command: wrksyssts

Working Disks Statistics
Description: shows disk usage statistics.
Command: wrkdsksts

Display Message Descriptions
Description: shows detailed information about the messages in a message file.
Command: dspmsgd range(messageId) msgf(library/file)

Display File
Description: shows the contents of a file.
Command: df library/file

Work with Objects
Description: shows a list of names and attributes of specified objects in specified libraries.
Command: wrkobj file

./M6

Hide Warnings in R

I've made a presentation about FRBF, an algorithm that I've just implemented in R, and I've used a small trick: I've hidden the warnings.

This is useful for demos and presentations because this way people are not distracted by non-relevant information and they can focus on what is really important.

All that is required is to use options(warn=-1) in the beginning of the script.

./M6

Clear R Console

I've been searching for a way to clear the R console, something like a cls() function.
But it seems R does not provide one.
I've found and tried a solution for Windows that emulated the CTRL+L command, which clears the console, but it simply did not work.

So, after some more research I've found this extremely easy, quick and dirty solution: cat(rep("\n",128)).
It does precisely what I need and is system independent.

./M6

Reset Windows and Linux Passwords

I've just came across a fantastic tool for system administration.
Ever used a system that no one recalls the administration password?
Or have you ever inherited a system that the only person who administrated it retired?

This tool will certainly ease the trouble of resetting the administration password: Kon-Boot.

./M6

Tutorial and Presentation Creation Software

I've just came across with the best - so far - solution between functionality, quality, export formats and price for tutorial and presentation creation software, including desktop video capture.

This great solution is Wink.
I've tested several solutions like this one before, all usually they all do the same:
capture the screen, compose the frames with some tags or highlight rectangles and export it to a Flash SWF video.
But Wink is different. It does not capture the screen as a simple bitmap, it also captures the objects, like the mouse pointer, and allows to freely specify the frames per second for screen capture and video export.
This allows a much more flexible frame composition, like positioning the mouse cursor on any part of the screen, change its pointer and export the video with comfortable frame per second ratio where the mouse cursor is automatically moved even if it has been positioned on a different location from where it was captured.

./M6

Unix/Linux Cheat Sheets

I've just found a great collection of several Unix and Linux cheat sheets.
It covers system commands and tools like AWK and SED.
It's the Linux-Unix cheat sheets - The ultimate collection.

./M6

How to Create PDF from LaTeX

I was using Ghostscript to generate a PDF document written in LaTeX, and I was getting the default red boxes links around the text, which are really ugly.

The search for information about how to remove those red box links returned a very useful document, How to Create PDF from LaTeX.
As the title implies, it is a document that teaches how to create a PDF file from LaTeX, but it covers topics like how to configure the links, which was precisely what I was looking for.

./M6

Algorithms in LaTeX

I've found this great easy to follow document about algorithms in LaTeX:
The algorithms bundle.

It covers the algorithm and algorithmic environments, the state, comment, loops, conditions and even its customizations.

./M6

Detexify - LaTeX symbol classifier

I was looking for a LaTeX symbol code when I faced, once more, the problem of taking too much time to find the code for a certain symbol.
LaTeX usually has what one needs, but finding it can take a while.

But this time I got luck. I found Detexify2 - LaTeX symbol classifier which will recognize a handwritten symbol and show the LaTeX corresponding matches.

It worked great for me, and this is now one great tool to have nearby whenever I'm using LaTeX.

./M6

KDE on Windows

I've just installed the KDE on Windows and my XP is now a happier operating system.

I was looking for Amarok, since that's by far the player I love most, but the release I'm using, 4.3.00, seems not to have it yet.
Nevertheless, I've setup some packages and now I'm able to run things like Kate, Dolphin and KMahjongg .
I love Dolphin as a file manager, since it's philosophy is suited to my needs and usage.
Too bad the Shift+F4 in Dolphin and the terminal command in Kate does not call the DOS box like it calls a terminal in Linux.

This project is not in the final state, so there's not many applications and it can be unsuitable for daily use.
But this is a very cool project and I'll keep an eye on it and, when possible, I'll try to make some changes like using Dolphin, Amarok, Kate and other applications that I prefer to Windows alternatives.

Here's some pictures of some application running on my XP:

Dolphin running on Windows XP


Konqueror running on Windows XP


KWrite running on Windows XP


KDE system settings running on Windows XP

./M6

Reorder columns in R

I got the need to reorder the column order or a data frame in R and after searching a little, I've found a very easy way to do it.

Having a data frame named test like

a b c d e
[1,] 1 11 21 31 41
[2,] 2 12 22 32 42
[3,] 3 13 23 33 43
[4,] 4 14 24 34 44
[5,] 5 15 25 35 45

all that is required is to reassign the data frame using a new column order, like

new_column_order <- c("b", "c", "a", "e", "d")

test <- test[,new_column_order]

And that solves the problem.

This seems to work both with a data frame and a matrix.

./M6

MVC vs. MVP

I've found an interesting description about Model-View-Presenter and Model-View-Controler and how they differ in StackOverflow: What are MVP and MVC and what is the difference?

./M6

Free Cheat Sheets for Developers

Here's a set of free cheat sheets for developers: http://refcardz.dzone.com/
There's lot of information about Drupal, Java Concurrency, Java Server Pages, Maven, JavaFX and a many more.

./M6

Morgan Stanley Report about How Teenagers Consume Media

Morgan Stanley has released a study made by a 15 year old summer intern, Matthew Robson. Matthew researched about his friends and colleagues habits of media consumption and the results are very interesting, in particular when compared with adult people habits.

How Teenagers Consume Media

./M6

TomTom Maps are not that Good.

I have a TomTom One XL GPS. It was a gift, so I did not choose it myself.
It was a great gift and one of the first things I did was to update its map.
After doing it I tried it out.
To my disappointment, it didn't had the street where I live. It just had part of the surrounding neighborhood, so it look like I was in the middle of nowhere, like doing off-road with my car...

TomTom says there's an average of 15% of roads and streets changing every year. The neighborhood where I live was finished in 2001, meaning it has already 8 years.
There were a couple, or so, new TomTom maps that came out but none had my street. Finally, the current version, 8.25, has my street but it comes with an error on its name...

8 years of delay and it came out with an error!...
Unbelievable...

I do know TomTom buys the maps, it does not make them themselves, they get them from Tele Atlas if I'm not mistaken, but I have nothing to do with it. I have a TomTom product, not a Tele Atlas, so it is TomTom who's responsible for the products they sell, even if it includes technology they get from others.

TomTom states it works hard to deliver the ultimate naviagtion experience. The problem is that TomTom fails in the basics: the maps.
And it's not the problem it took 8 years to include my street on its maps, its the fact that the maps need to be cleaned up and you need to know extra information about your destination before you're actually be able to search for your destination:
  1. The street names have errors and are totally unnormalized. For instance, if you're looking for an avenue, you don't know if it starts with "Avenue", "Av." or "Av". Needless to say that if you're looking for street ABC but it's registered in the system as ABB, you'll have trouble to find it. You have to look for all possible combinations and watch out for typos.
  2. It does not allow you to search for middle strings, you always have to search for the beginning of the string. If you're looking for X, and you don't know if it's an avenue, a street or a town square, you're unable to simply search for X, and you fail to find it.
  3. You must know extra information about your destination. For instance, if you need to find destination X on city A, you must provide the X zip code or the civil parish. Needless to say that in many countries, Portugal included, the zip codes have mistakes and people don't always know the name of the civil parish where X is located. If people knew this kind of information, probably they also knew X and would not require TomTom to guide them.

All this combined, I feel frustrated using my TomTom GPS because it does not have, or I'm unable to find, around 20% of my destinations... Talking about "the ultimate navigation experience": do it the hard way, see on a paper map, watch the stars, or stop and ask for directions...

I don't need a search engine running on my TomTom, though it would be extremely helpful, but name normalization and reducing all these search barriers would result on much better search results for the user.

./M6

Subversion Merge Tracking

If you've been using Subversion (Svn) with branches and had to perform a merge, than you've already screamed in despair just like I've just done.
Svn, up to version 1.5, was unable to perform merge tracking correctly, a major functionality to everyone who has to work with several versions of the same application.

But fortunately, version 1.6 already has merge tracking working correctly.
I already had Svn 1.6 client installed, so all I need to do was upgrade the Debian server to Lenny and the manually upgrade the Svn server to version 1.6.
Everything went well, and there weren't many dependencies needed to be installed manually, so it was even easier than I expected.

Having everything in place, it was time to perform the merge. The merge consisted in including the maintenance branch into the development branch.
This was the second time this kind of merge was going to be performed. Since the previous merge was done without merge tracking, the logs and the graph was kind of useless to know the files history.
Even worst, when the merge was tested, it looked like the first merge had to be repeated. I did not understood this Svn weird behavior and found no reason for it, but there were files that were selected to be merged twice. The first merge was going to happen to the file contained up to revision 2636 and the other merge from revision 2637 up to the Head revision.

It had to be done carefully, but 8 hours later, the merge was done with no problems.

Since this merge was performed with the merge tracking functionality working, now it is possible to automatically track the file evolution. I'm hopping to have a faster, and with less stress, merge in the future.

./M6

Once Accenture. Always Accenture.

Yesterday I attended to Accenture Alumni cocktail party.
It was an event exclusively for former Accenture employees and, obviously, for Accenture Senior Managers and above.

I've been with Accenture twice, and loved it both times.
I always felt that Accenture really care about its people. The proof is in such meetings, Accenture cares about you even if you're no longer with them.
The event itself was very nice and allowed us to chat with people that we haven't seen for awhile. Many of us updated the mobile numbers between two drinks, sushi and ice cream.

Obviously such events have a business return. There were a lot of business cards changing hands, contacts updated and new contacts made.
There's also the marketing part of it, people that attended surely chatted about it with current coworkers or write about it in their blogs.
And precisely how many companies do you know that invite former employees for a cocktail?

On the way out, everybody got a Bonsai with a "thank you" card for helping Accenture to be the company that it is.

Well, tank you Accenture for the cocktail and for the challenges that I was given and that allowed me to be a better professional.
./M6

Gimp and .eps Files

I use Gimp on all systems and I've some Encapsulated PostScript (.eps) files on Windows that I need to open and edit. In order to Gimp on Windows open .eps files, it requires Ghostscript to be in your system.

Here's how to do it:
  1. Download and install Gimp;
  2. Download and install Ghostscript
  3. Setup the environment variable GS_PROG to the Ghostscript executable file, like C:\Program Files\gs\gs8.64\bin\gswin32.exe.
Now Gimp should be abble to open EPS files.

./M6

JFace TreeView with Manual Expand of TreeItems

I have a FilteredTree with check items and I was trying to expand the tree whenever the user checks an item on it. By default, the tree does only expand a TreeItem when the user clicks on the + icon and retracts when the user clicks on the - icon.
Since this tree has check items, I wanted the tree to expand when the user clicks on the check box.

This proved to be a lot harder than I expected, partially because I was using the wrong object, partially because it is lazy, and partially because it was hard to find an answer for what I was doing wrong.
So, I'm posting here how to manually expand a TreeView, which is part of a FilteredTree.

To begin with, the TreeView requires the following classes to be defined:

1. Your tree node that will hold the data of each tree item:
private class Node {

private final Node parent;
private final String word;
private List children = new ArrayList();

Node(Node parent, String word) {
this.parent = parent;
this.word = word;
if(parent != null) {
parent.children.add(this);
}
}

public Node getParent() {
return parent;
}

public Collection getChildren() {
return new ArrayList(children);
}

public boolean hasChildren() {
return children.size() > 0;
}

public void setChildren(Collection newChildren) {
if(newChildren != null) {
children = new ArrayList(newChildren);
}
}

public String getWord() {
return word;
}

}
Please note that this class can be whatever class you require, this is only an example.

2. A tree content provider that will provide the content for the tree:
private class NodeContentProvider implements ITreeContentProvider {

@Override
public Object[] getChildren(Object element) {
return ((Node)element).getChildren().toArray();
}

@Override
public Object getParent(Object element) {
return ((Node)element).getParent();
}

@Override
public boolean hasChildren(Object element) {
return ((Node)element).hasChildren();
}

@Override
public Object[] getElements(Object inputElement) {
return (Object[]) inputElement;
}

@Override
public void dispose() {
// unused
}

@Override
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
// unused
}

}

3. The label provider that will provide the label for each item in the tree:
private class NodeLabelProvider extends LabelProvider {

private final TreeViewer viewer;

NodeLabelProvider(TreeViewer viewer) {
this.viewer = viewer;
}

@Override
public String getText(Object element) {
Node node = (Node) element;
return node.getWord();
}
}

I'll create a FilteredTree, but since it makes use of TreeView, using only a TreeView is trivial:

PatternFilter patternFilter = new PatternFilter();
FilteredTree filteredTree = new FilteredTree(cTree,
SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CHECK,
this.patternFilter);
filteredTree.setInitialText("type your filter text here");
TreeViewer treeViewer = filteredTree.getViewer();

// Assign the label provider
treeViewer.setLabelProvider(new NodeLabelProvider());

// Assign the content provider
treeViewer.setContentProvider(new NodeContentProvider());

// Populate the tree with elements
Node ex1= new Node(null, "Example 1");
new Node(ex1, "Example 1.1");
new Node(ex1, "Example 1.2");
new Node(ex1, "Example 1.3");
Node ex2= new Node(null, "Example 2");
new Node(ex2, "Example 2.1");
Node[] nodes = Node[] {ex1, ex2}
viewer.setInput(nodes);

// Event for item selection
treeViewer.getTree().addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
TreeItem item = (TreeItem) event.item;
Node node = (Node)item.getData();
// Manually Expand
treeViewer.expandToLevel(node, 1);
treeViewer.update(node, null);
}
});

Please note that the tree selection event always expands the selected node, you may wish to retract it or do another operation, like check all its descendants.
This is actually quite simple, but I was calling treeViewer.expandToLevel with the TreeItem instead of using the Node object, and that was the cause of my problems.

If you're looking for a similar example but using custom images, check Eclipse Nuggets.
./M6

Mediocrity is a choice

As Seth Godin states on a small post, quality is the result of choices one get to make every day.
Here's the full post: On the road to mediocrity.

./M6

Success is a Continuous Journey

Business success is a continuous journey, not a destination. I've learned this long ago, but I couldn't say it better than Richard St. John:



It's not about falling, it's about getting up again...

./M6

RCP save workbench status

In Rich Client Platform (RCP) application, the workbench status can be easily saved and restored by simply including the snippet bellow in the ApplicationWorkbenchAdvisor class, that extends WorkbenchAdvisor.

@Override
public void initialize(IWorkbenchConfigurer configurer) {
super.initialize(configurer);

// tell eclipse to save workbench state when it quits
// (things like window size, view layout, etc.)
configurer.setSaveAndRestore(true);
}

This will automatically save the status of the workbench when the application is closed and will automatically restore that status when the application is executed again. The settings are saved on the [runtime-{your-product}]/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml file.

./M6

Selecting a value from a SWT CCombo on RCP

It looks like the CCombo custom SWT object lacks some selection functionality. I'm using a CCombo as a table cell editor on my Rich Client Platform (RCP) application and I've found out that it is (almost) impossible to detect the user selection with both the keyboard and the mouse.

The selection listener does not work as expected. Documentation says:
  • the widgetSelected method is triggered whenever a selection occurs in the control, i.e. when the user browses the option list this event is triggered;
  • the widgetDefaultSelected method is triggered when default selection occurs in the control, i.e. when the user selects an option from the list this event is triggered.
One might think, as I thought, that all one has to do is to catch the widgetDefaultSelected event and one would know which option the user has selected from the list.
This is only true when the user performs the selection using the keyboard, i.e. after browsing through the options list the Enter/Return key is pressed.
If the user decides to use the mouse, the widgetDefaultSelected event is not triggered at all, but widgetSelected is.

I though I could detect the user selection with the mouse listener. I was wrong. After trying a couple more possibilities, it turns out there's no (easy) way to detect if the user has performed a selection using the mouse...

So I had to do a workaround for it. Since the widgetSelected is triggered by the mouse clicks, I tried to use that event. Unfortunately the event has no real useful information, like if it was triggered by a right button mouse click. But fortunately, the CCombo object does have a couple of methods that allowed to infer that a selection has been made. In particular, it has a method to check if the options list is visible or not. Since a selection with the mouse makes the options list disappear, I've used it.

Here's the snippet:

// Selections events
combo.addSelectionListener(new SelectionAdapter() {
// Selection changed, check if the options are still visible
public void widgetSelected(SelectionEvent e) {
// If list is not visible assume that the user has
// performed selection with the mouse
if (!combo.getListVisible()) {
setEditionValue(combo);
}
}

// Option selected
public void widgetDefaultSelected(SelectionEvent e) {
// User performed a selection with the keyboard
setEditionValue(combo);
}
});
This is not a perfect solution, it's a workaround, but it's working just fine for me.

./M6

Current time as numeric value in R

To get the current time, just use the Sys.time() function, see the Sys package for more information.
To get the current time as a numeric value in R, just use unclass(Sys.time()).
This seems to be higher accurate, 0.01 seconds.

./M6

tofrodos package

Kubuntu does no longer has the "old" DOS tools. I needed to use the dos2unix command and I found out it was no longer part of the standard core installation. Obviously it's still available, so all I had to do was install the tofrodos package, just sudo apt-get install tofrodos and the problem is solved.

./M6

R Package with S4 Objects

I've finished the development of the (beta version) clustering algorithm on R for my MSc thesis and I'm releasing it for tests.

I've developed it mainly in Windows, but when it comes to the packaging part, I've switched to Linux. This is mainly because R packaging in Windows implies to install a lot of base Linux applications and tools on Windows. For those that wish to go that road, here's what you have to do: read Making tutorial about R Packages Under Windows: A Tutorial by Peter Rossi.
For everyone else, just boot your Linux.

Before I start, I took a look at Writting R Extensions. This is the first step for all that wish to build an R extension. A fast and easy way to know how to pack, is to read the An Introduction to the R package mechanism.

My implementation uses S4 objects, and that was a problem, since I had all kinds of warnings and errors during the package tests and installation. Here's the transcriptions of the post I've sent to the R-Help list asking for help:
Here's what I do:

*1.* in R console, I do and get:
> package.skeleton(name='remora')remora-package
Creating directories ...
Creating DESCRIPTION ...
Creating Read-and-delete-me ...
Saving functions and data ...
Making help files ...
Done.
Further steps are described in './remora/Read-and-delete-me'.
Warning messages:
1: In dump(internalObjs, file = file.path(code_dir,
sprintf("%s-internal.R", :
deparse of an S4 object will not be
source()able
2: In dump(internalObjs, file = file.path(code_dir,
sprintf("%s-internal.R", :
deparse of an S4 object will not be
source()able
3: In dump(internalObjs, file = file.path(code_dir,
sprintf("%s-internal.R", :
deparse of an S4 object will not be
source()able
4: In dump(internalObjs, file = file.path(code_dir,
sprintf("%s-internal.R", :
deparse of an S4 object will not be source()able


I don't know why I get these warnings. I've followed R
implementation rules and the S4 objects work fine.


*2.* Performing the 'R CMD build remora' command I get:

* checking for file 'remora/DESCRIPTION' ... OK
* preparing 'remora':
* checking DESCRIPTION meta-information ... OK
* removing junk files
* checking for LF line-endings in source and make files
* checking for empty or unneeded directories
* building 'remora_1.0.tar.gz'

And the remora_1.0.tar.gz file seems ok.

*
3.* Performing the 'R CMD check remora' command I get:

* checking for working pdflatex ...sh: pdflatex: not found
NO
* checking for working latex ...sh: latex: not found
NO
* using log directory '/home/fmm/thesis/R/src/remora.Rcheck'
* using R version 2.8.1 (2008-12-22)
* using session charset: UTF-8
* checking for file 'remora/DESCRIPTION' ... OK
* checking extension type ... Package
* this is package 'remora' version '1.0'
* checking package dependencies ... OK
* checking if this is a source package ... OK
* checking for executable files ... OK
* checking whether package 'remora' can be installed ...
ERROR
Installation failed.
See '/home/fmm/thesis/R/src/remora.Rcheck/00install.out'
for details.

*4.* the log file contains:

* Installing *source* package 'remora'
...
**
R

**
data

** preparing package for lazy
loading
Error in parse(n = -1, file = file) : unexpected '<' at 745:
`.__C__remoraConfiguration` <- 746: <> -> code2LazyLoadDB
-> sys.source -> parse Execution halted
ERROR: lazy loading failed for package
'remora'
** Removing
'/home/fmm/thesis/R/src/remora.Rcheck/remora'
fmm@Darkmaster:~/thesis/R/src$ grep -i __C__remoraConfiguration *
fmm@Darkmaster:~/thesis/R/src$ grep -i __C__remoraConfiguration */*
remora.Rcheck/00install.out:745: `.__C__remoraConfiguration`
<- remoraConfiguration is a constructor for the
remoraConfiguration S4 object.
# # Class configuration definition.
# CLASS_REMORA_CONFIGURATION <- "remoraConfiguration" class_configuration
<- setClass(CLASS_REMORA_CONFIGURATION, representation(
number_clusters = "numeric", class_name = "character",
weighting_function="character", scale_variance="logical", s="numeric",
d="numeric", alfa="numeric", eta = "numeric", niter="numeric",
niter_changes="numeric", perform_sum="logical", verbose="logical"),
prototype = list(number_clusters=numeric(), class_name=character(),
weighting_function=character(), scale_variance=logical(),
s=numeric(), d=numeric(), alfa=numeric(), eta=numeric(), niter=numeric(),
niter_changes=numeric(), perform_sum=logical(), verbose=logical()))
# # Builds a Remora configuration object.
# # [...]
# remoraConfiguration <- function(number_clusters, class_name,
weighting_function = FUNCTION_REMORA_EUCLIDEAN,
scale_variance=TRUE, s_value = 0.001, d = 0.3, alfa = 0.9, eta = 0.01,
niter=-1, niter_changes=5, perform_sum = TRUE, verbose=FALSE)
{
result_configuration <- new(CLASS_REMORA_CONFIGURATION)
[...]
result_configuration
}

But, unfortunately, no help came from there...
I've never stopped the search for the answer, and I've finally found it. It's actually quite easy.
Instead of packing it from the current environment, I've just passed the package.skeleton the list of source files to build the package. Here's the small R script I've done to automate the packaging procedure for my "Remora" package:

cat('\nPacking Remora...\n')

file_lst <- character(5)
file_lst[1] <- '/home/m6/thesis/R/src/1_classes.r'
file_lst[2] <- '/home/m6/thesis/R/src/2_common.r'
file_lst[3] <- '/home/m6/thesis/R/src/3_model.r'
file_lst[4] <- '/home/m6/thesis/R/src/4_predict.r'
file_lst[5] <- '/home/m6/thesis/R/src/5_main.r'

package.skeleton(name = "remora", force = TRUE, namespace = TRUE,
code_files = file_lst)

cat('\nDone.\n')
Now it's time to go to the directory created, with the name of the package, from now on {package}, and edit the following files:
  • {package}/DESCRIPTION, the description of the package;
  • {package}/NAMESPACE, the list of functions and classes to export to the user;
  • {package}/man/{package}-package.Rd, the package help file, the \examples section must provide executable code, since R check command will execute this code;
  • {package}/man/{class_name}-class.Rd, the classes help files;
  • {package}/man/{function_name}.Rd, the functions help files;
All files under
/man/ are tex files and will be compiled to provide the functions help when invoked by the user.
It's only necessary to document the classes and functions that will be exported, i. e. exported in the
NAMESPACE file, since all the others will not be visible to the user. All the other .Rd files may be deleted.

After the package has been created, I've tested with the "R CMD check {package}
" command. My package name is "remora", so my command was "sudo R CMD check remora".
I had to run this command with the administration role, so I prefixed it with the
"sudo" command. I believe this is a characteristic of the Kubuntu distribution.

Finally I've build the package with the
"R CMD build {package}" command that created the tar.gz file for distribution.

To install it, just use the
"R CMD INSTALL {package}" command. I've entered R and it worked fine.
To uninstall just execute
"R CMD REMOVE {package}".

./M6

Bing

But It's Not Google.
That's Bing, the Microsoft rebranded and reformated search engine.

Bing has a nice background picture and allows me to search in English or Portuguese, but when there's a tie, the Portuguese result shows up first.

For what I could tell, it's definitely not Google.
Google is currently more than a search engine.
On Google I can ask simple questions like "4 times 5" or "1 euro in usd" and I get "4 times 5 = 20" and "1 Euro = 1.4225 U.S. dollars", this one depending on near real time
In Bing I only get regular search engine results.

Bing answer for 4 times 5.

When trying to search information in news group "linux.debian.laptop", I can do it in Google and since Bing knows it, Bing shows the Google Groups for "linux.debian.laptop".

As Seth Godin puts it, looks like Microsoft is trying to be the next Google, but currently here's already a next Google: Google.

Why should people change for something that works well to something that seems not to have a real distinguishing factor? At least for now, it's still, as alomost in Google, a Beta version. Even if Microsoft adds a few cool features, how much time it Google take to clone it and improve it?

I don't really know why Microsoft is investing so much time, money and effort in such a battle when they could be doing something remarkable.

Update
I've just discovered that actually Bing does some math and it knows how to answer 4 times 5.

What I also discovered is that, like many Microsoft applications, it thinks it knows what is best for me and, as always, it thinks wrong!
I've specifically have told Bing that I wanted results in English, but it ignored me and gave me results in Portuguese and looks like in Portuguese it was unable to compute 4 times 5.
Looks like Bing thinks that since I'm located in Portugal, I cannot ask questions in English! Is this stupid or what?
If it thinks it's smart enough to know what's best for me, I've asked the same question in Portuguese, "4 vezes 5" and, as I expected, it failed to answer the question.
Not very smart, Bing...

Bing is not Google, and they can say that again!
Keep up like that and definitely it will continue to live obfuscated by Google, like the "eternal wanna be"...

./M6

Java by API examples

I was seeking information for the FilteredTree Jface object and I've found a great knowledge repository for Java, SWT, JFace EJB, and other technologies, like C#, C++, Python, SQL Server, and many more.

In the Java By API examples, everything is by example and it's hierarchically organized, which helps a lot when one's exploring Java packages, for instance.

You can take a look at it in http://www.java2s.com/.

./M6

Java Developers Almanac

I was seeking JDBC information and I found the Java Developers Almanac.
It has a great collection of snippets, organized by Java packages, very useful, specially for Java new comers.
Here's an example for java.sql package.

./M6

RCP Message Dialog

It looks like every time I need a message dialog in an Rich Client Platform (RCP) application, it takes me too much time finding which JFace dialog class is better for me...

This time I decided to post it here so that the next time I won't waste time.
All the methods needed are statically available in the org.eclipse.jface.dialogs.MessageDialog class:
  • MessageDialog.openConfirm, for a confirmation dialog with an Ok/Cancel button set.
  • MessageDialog.openError, for an error dialog with an Ok button.
  • MessageDialog.openInformation, for an information dialog with an Ok button.
  • MessageDialog.openQuestion, for a question dialog with and Yes/No button set.
  • MessageDialog.openWarning, for warning dialog with an Ok button.
The org.eclipse.jface.dialogs.MessageDialogWithToggle is similar,but allows the user to adjust a toggle setting, like Yes Always/Yes/No or Yes/No/Never.

You can use org.eclipse.jface.dialogs.DialogSettings for a dialog setting, supporting loading and saving of properties in an XML file.

You can use org.eclipse.jface.dialogs.ProgressMonitorDialog to display progress during a long running operation.

And you can design your own dialog windows, just extend the org.eclipse.jface.dialogs.IconAndMessageDialog class.


Note: in RCP, you can get the shell using PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();.

./M6

Find Java Class Path in the System

Many times one has to know where in the system some Java class is located, usually when one has to perform file operations relative to the class location.

In Java such task is not straight forward to accomplish, so I'm posting here a snippet that will return the full path of the class location.

import java.security.CodeSource;
import java.security.ProtectionDomain;

public class Utilities {
protected static final String getApplicationLocation() {

final ProtectionDomain pd = Utilities.class.getProtectionDomain();
final CodeSource cs = pd.getCodeSource();

return cs.getLocation().getPath().replaceFirst("/", "");
}
}

./M6

RCP Open and Save File Dialogs

I'm currently developing an Eclipse application, and since some of the usual functionalities is the open and save file, or project, I'm posting here a nice code snippet for using open and save dialogs in Rich Client Platform (RCP) applications.

Both the FileOpen and FileSave classes bellow are ready for usage as a command default handler for the extension org.eclipse.ui.commands in the plugin.xml file. Don't forget to create the menu entry to use this command.

Here's the open file snippet (don't forget to update the package)
package your.package.in.here;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;

/**
* Opens a file
*/
public class FileOpen extends AbstractHandler implements IHandler {

@Override
public Object execute(ExecutionEvent event)
throws ExecutionException {

Shell shell = PlatformUI.getWorkbench().
getActiveWorkbenchWindow().getShell();

FileDialog dialog = new FileDialog(shell, SWT.OPEN);
dialog.setFilterExtensions(new String[] {"*.txt", "*.*"});
dialog.setFilterNames(new String[] {"Text File", "All Files"});
String fileSelected = dialog.open();

if (fileSelected != null) {
// Perform Action, like open the file.
System.out.println("Selected file: " + fileSelected);
}
return null;
}
}


And here's the save file snippet (don't forget to update the package):
package your.package.in.here;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;

/**
* Save file as...
*/
public class ProjectFileAs extends AbstractHandler implements IHandler {

@Override
public Object execute(ExecutionEvent event)
throws ExecutionException {
Shell shell = PlatformUI.getWorkbench().
getActiveWorkbenchWindow().getShell();

FileDialog dialog = new FileDialog(shell, SWT.SAVE);
dialog.setFilterExtensions(new String[] {"*.txt", "*.*"});
dialog.setFilterNames(new String[] {"Text File", "All Files"});
String fileSelected = dialog.open();

if (fileSelected != null) {
// Perform Action, like save the file.
System.out.println("Selected file: " + fileSelected);
}
return null;
}
}

./M6

Wolfram, Computational Knowledge Engine

From time to time, I see something that is totally mind blowing.

The last time it was 6th Sense, a couple of months ago, and not it's Wolfram|Alfa, Computational Knowledge Engine.
It's a real knowledge engine, in the sense that it knows things, it knows a lot of stuff about things. And better yet, it uses the knowledge about things to enrich the answer, from simple useful information up to correlations.

This is truly amazing, one has to see it in order to see it in order to fully understand it.

I can hardly wait to use it.

./M6

Is IT Doing a Bad Job for Business?

I was following a LinkedIn discution about what areas of IT managment gives most problems and there was a very interesting oppinion about where all the listes problems really came from.


Robert Hossary said that
"departments have mostly lost the ability to understand business processes. They do not research the tools required to best suit a process or solve a problem. To many of these departments and their personnel the Operating System or specific program becomes a religion and therefore they cannot see beyond the brand.
[...]
If IT did their research and embraced the correct tools for the job rather than the best gadget for cool status then maybe they could solve issues like; resource allocation; project management; ability to sell change to management and train users; working with other departments; working with a small budget and so on."

I must say I tend to agree with this point of view.

I've already wrote about how a bad IT choice ruined and organization productivity. It was one of the worst cases I've remember, and suffered with.
The IT decided to go into full virtualization, this means every one used virtual machines.
Productivity fall, specially in the development teams and even the business managers saw that was ruining their timings and, in some cases, their budgets.
When confronted with that productivity problem, the IT manager said it was the best choice, and it was it. The best choice? For whom?
Not for the organization, that's for sure.
But virtualization was cool back then, so they've just had to have it.

On another occasion, I remember I was trying to persuade my manager to get us a requirement tool for the analysis phase. It was expensive so it was not easy to get approval. But one day we got lucky! We had the chance to get exactly the requirement tool we needed, almost for free! One of the holding companies, to which we were very close, decided not to use the requirement tool anymore, since they moved to something else. So, there was a good chance we could get it cheap, with a one year support service included and all. Sounds great, doesn't it? Well, not for my manager, that stated "if that's not good enough for them, then it's not good enough for us"!
Actually it was excellent for us, but with that "childish" behavior we ended up with no tool at all!

Everyone makes bad decisions. Sometimes those bad decisions come from a bad "home work" and sometimes it just proved not to work as expected, despite all the investigation and tests performed.
When things don't work, what matters is to act upon it in order to fix it and to learn from that. What went wrong and why? Answering those questions and avoiding similar mistakes will result on a much better IT management. This is actually true for any area, not just for IT.

If IT management actually did its job well, then it would be doing a good job for the business. It would have a lot more time to focus on important issues instead of "fighting" in the political arena to defend bad choices. I believe this is also true for any area, not just for IT.

./M6

Online Business, Giving a Hard Time to Customers

Yesterday I was browsing Playmobil web site to check their current offer, products and price.
But when it comes to online business, Playmobile, as many others, does not get it.
One has to go through a painful registration process, including giving your correct zip code and fiscal number, just to see the prices!
This dosen't make any sense.

And today, I was checking a LinkedIn question about displaying the products price to casual visitor. "Should a website display prices and quantity to casual visitors?" was the question.

Why do companies and marketeers keep insisting in give a hard time to customers?
Why do they think one will register in order to see a product price?

In such cases, people just leave and go make business somewhere else.
I know I do!

If you have an online business, actually any business at all, you should give as much information as possible to customers. You should make their life as easy as possible.
I bet those same organizations and marketeers all say they like to make the shopping experience a pleasant one, so that the customer is pleased and return for more business.
Well, where's that philosophy in cases such as the Playmobil web site?

Does the CEO, CFO and, specially, the shareholders know how much they are loosing for sending customers away?

They shoud read the The $300 Million Button article and seriously rethink they online business user interaction.

./M6

ATI Radeon on Linux (Really) Sucks

ATI drivers for Linux never worked well. I have an Mobility Radeon X700 and I've been struggling with it for over 4 years on several Linux distributions.

I'm using Kubuntu for several months now, and on the previous version I was able to use the ATI drivers without the 3D acceleration. The drivers had to be installed from the Hardware Drivers System application. If I tried the official driver downloaded from ATI, it simply crashed.

I've recently upgraded Kubuntu to 9.04, and the Xorg configuration and ATI driver being used, were gone. Once again, I've tried the official ATI driver, version 9.4, and, once again, it crashed the system in such a way that I had to reboot through hardware. I've uninstalled the driver and tried the same procedure that worked on the previous Kubuntu version. It didn't work and it also crashed.
The problem was, I was able to install and uninstall the driver through the Hardware Drivers System application.
So, for two day I've been fighting to make the ATI driver to work or to go back to the previous configuration and driver.
I was unable to make the driver to work, so I spend some hours trying to revert into the previous working configuration.

Finally, I found the answer in the Ubuntu Documentation site, under the Community Documentation section, in the RadeonDriver article. Everyone's having problems with Radeon graphic cards under Linux, specially Ubuntu/Kubuntu, should read it.

Here's the magic command line that made X work again:
apt-get remove --purge xorg-driver-fglrx
The command must be executed as root.

If you've been suffering with ATI bad Linux support and decided not to use the official drivers, but if you wish to keep fighting, check the Radeon article on X.Org Foundation wiki.

./M6

Eclipse RCP Tutorial with Eclipse 3.4

I was digging for some RCP development information and I've found this nice tutorial: Eclipse RCP - Tutorial with Eclipse 3.4

As for the complete RCP development documentatio, it can be found in the Eclipse documentation site.

./M6

Anti-Virus or Anti-Productivity?

On the data migration project I'm currently involved, the desktops being used belong to the peoject sponsor and therefor I do not have administration privelidges. I'm a somewhat power user but I'm not abble to install everything nor I'm abble to configure Windows nor McAfee.

The anti-virus, McAfee, consumes over 150Mb, almost as much as Windows itself, of my 1GB RAM and takes control of the processor in such a way that it's a true anti-productivity tool! Every task performed takes too much time, to many times I can see the screen being, literally, drawn line by line.

The system administrators were kind enough to reconfigure the anti-virus rules in order to skip .jar files, since almost all work is performed in Java and in Java developed applications.
This helped a bit but did not solved the problem.

Why is that the worst thing than a virus is the anti-virus?
And why is that anti-virus are, currenlty, anti-productivity tools? Anti-virus should protect the system, they should not consume a considerable part of its resources.
And finally, why is that Windows system administrartors don't know how to correctly configure these tools? The anti-virus companies default configuration also sucks.

It doesn't make sense to scan files like .jar, .java, .class, .c, .cpp, .obj, .py, .h, .csv, .ini, .xml, .js, .html, .swf, .zip, etc..
Yes, I do know that there's dangerous stuff as .vbs scripts, but scanning a local .css file? What sence does that make?
By know, Windows system administrators are saying, "ah, thoes are all just small files, it takes a couple of seconds to scan"... Well, to those I ask, "how much time is a couple of seconds times over 700 .jar Eclipse files"?
And why is that .zip files are scanned twiced? Why scan the .zip file and not the files only when, and if, they are unzipped?

Some years ago I was working for a company that configured the anti-virus in such a stupid way that it scanned everything.
My system became so slow that I've actually measured the productivity lost for the company developers.
Each developer was loosing aproximately 4 hours per week, i.e. 2 working days per month, 24 days per year. At the end of the year, the company was loosing one entire month of work per developer! Hey, stop the anti-virus and give me that moth as extra hollidays, the company productivity would be the same!
The company had 6 developers at that time, which means 6 months of productivity loss. Half an year.

I would like to know how many company CEOs, CTOs, etc. and share holders out there know how much they're loosing because the entire organization is being affected by such anti-productivity tools.

./M6

Good Design and Bad Design

I've crossed with several design web sites. There's lot of them out there, but these I found particulary interesting.

One has an article with 50 lessons about graphy design theory. It's called 50 Totally Free Lessons in Graphic Design Theory and I've learned a lot from it. If you're looking for design information, this site will certainly be helpful.

Another one is a web site that collects web pages that suck. It's called Web Pages That Suck and it states that "it give us the opportunity to learn from other people's mistakes without having to make them ourselves". I agree. It's a good example of how not to design web pages.

Finally there is an article about basics of good web design. It's called 9 Essential Principles for Good Web Design and has useful information about how to do good web design.

./M6

DbVisualizer for DB2 on iSeries

In a previous post I refered that I would be using SQuirreL SQL to access DB2 on AS/400 unless I find some limitiations.
Well, such limitation have been found. I don't know why, but the connection to AS/400 through JTOpen times out every time I run a SQL command, looks like it has a 30 seconds timeout.
I was unable to overcome this, since the driver option for that had no effect when SQuirreL SQL has no option to reconnect automatically nor to keep the session alive.
This has become extremely annoying, uncomfortable, and finally, unusable.

This forced me to search for another solution. And this time it was DbVisualizer. I've used it a couple of times before and I liked it. It's also a Java application and the JTOpen configuration was straight forward.

I'm using it and I'm loving it. The timeout problem simply does not exist. I found DbVisualizer better in many ways, specially in the user interface, witch is better designed.
As before, I'll stick with DbVisualizer, unless I find some limitations or something better comes up.

./M6

Software Development Cycle

A friend just sent me a funny link to a summary of the Software Development Cycle.
A bit later, another friend sent me the Software Life Development Cycle.
Actually, sometimes things do work like that in software development...

./M6

Merge PDF files

I've just scanned three pages and I wanted to create a single PDF combining them all.

Since the Free Cute PDF writer does not support such a functionality, I had to found something else.

After some search, I came across with PDFCreator. I've tried it and it worked fine.
It installs a PDF printer driver but has some extended functionality, like combining several prints into one PDF, several output formats and specific configuration for all output formats.

The printer monitor GUI could have a better look and feel, but the application works fine, making its looks a minor detail.

For now I'll keep Cute PDF and PDFCreator, but if PDFCreator works as I expect it will work, it's bye-bye Cute PDF and hello PDFCreator.

./M6

SQuirreL SQL for DB2 on iSeries

In the data migration project I'm currently in, the data is located on an AS/400 and I need to access it trough a DB2 connection.
The iSeries Navigator sql interface has some interesting features, like the visual query explain, but it lacks some basic features, like syntax highlight and saving properties changes.
Therefor I've decided to use something else.

I've downloaded SQuirreL SQL and installed it. SQuirreL SQL supports any JDBC connection, since it is written in Java, and during installation I've selected the JDBC for iSeries AS/400 connection.

Then I downloaded JTOpen, the OS/400 and i5/OS JDBC. The installation is quite simple, just unzip the file and update the CLASSPATH to refer the .jar file, I'm using jt400.jar driver.

When SQuirreL SQL starts, it automatically detects the JTOpen(AS/400) driver, so all I had to do was to create a database connection using that driver. I did some configurations on the connection, in particular I only load, and cache, the necessary schemas for my work.

I already had tried SQuirreL SQL with JTOpen to access AS/400 before. It was an older version and it crashed too many times to be really useful.
But this time it seems to be stable, so I'll stick with it for now, unless I find some limitations or something better comes up.

Update: some limitations have came up, and I changed to DbVisualizer.

./M6