Erica’s Wish, 5K Run – August 7th
Grâce à my co-worker Brian, I have signed up for my first 5k run next month, organized by the Running Room. It turns out it’s really not that hard to motivate me – just call it a challenge, and often I wouldn’t be able to resist.
I will try to fit the last few weeks of the “Coach to 5k” program I am doing now in a month and my goal is to run these 5k in around ~25 minutes which is not unachievable, yet demanding. It’s being hard so far, but I am pushing myself harder each time I want to give up – and it’s been very rewarding. Plus if there is anything I’ve learn since joining the workforce – it’s even harder to stay healthier and get consistent exercise than when you are in school.
Wish me luck and happy running.
No more excuses.
I backup everything at work, and I barely backup anything at home (and by backing up I don’t mean Ctrl+Cing and Ctrl+Ving files around). Today, I ran out of excuses, so I wrote three lines to backup my entire home partition to my NAS with rsync. I know it’s not perfect, but it’s a damn good start:
echo "Backup log for DESKTOP - `date`" > bckp.log rsync -r -u -t -v /home/myuser/ /media/bckp >> bckp.log 2>&1 mail -s "DESKTOP backup log - `date`" x.y@z.com < bckp.log
What’s your excuse?
Heap, heap hooray!
“Tanks are not afraid of mud” – an ironic Russian expression figuratively meaning that some people are not scared, or even sometimes prefer to choose a long way over a short one, for no apparent reason. Sometimes I like to do that too.
At some point, yesterday night, I’ve decided that the best way to approach my data structures’ course assignment question on binary heaps (insert a list of elements in the heap, draw a list of diagrams showing the resulting tree after every insertion) would be spending half an hour writing a Python script that would do something similar
So I looked at Graphviz (which by the way, is awesome – you can use it for describing complex diagrams in plain text and then generating images from it) and came up with a half-completed binary heap structure (I only needed insertion) and a script that will generate digraphs after every insertion, both of them here. Nothing special at all - but I like how I can now continue typing up my assignment in LyX, or maybe I just wanted an excuse to play with Python (:
These are how the pictures look for [10, 5, 12, 3, 2, 1, 8, 7, 9, 4]:
Misleading errors are worse than no errors at all
Sometimes it seems it’s often near to impossible to write a large piece of software that will be able to fail with meaningful error messages. It is also arguable that some trace information is better than no information at all – unfortunately generic errors can often do more harm than good.
Here I am, setting up a multi-partitioned DB2 instance on my Ubuntu machine. I was doing that for a colleague, trying to defend the work I put into getting all of those fancy DB2 certifications I have. First, I’ve attempted to add a second partition to the existing instance:
db2start dbpartitionnum 1 add dbpartitionnum hostname port 1 without tablespaces
To which DB2 said:
06/07/2011 11:16:21 1 0 SQL6048N A communication error occurred during START or STOP DATABASE MANAGER processing
The gut feeling was telling me that I should look into db2diag.log. Instead, I spent next 10 minutes poking around everything that had to do with network, ports, and protocols because I thought that “communication error” would be related to these things. Eventually I did get back to db2diag.log to find this:
...db2start or db2stop failure from node 1: env: /home/demoadm/sqllib/adm/db2rstar: No such file or directory
Turns out the problem was that ksh was missing (it’s not installed by default on Ubuntu), so the nodes setup scripts would silently fail. I guess since db2rstar has to do something with communications, the initial error was technically correct, but boy do I wish that there was a check in place for the presence of ksh that would fail db2start with a different error message.
In this case, I think I would’ve rather seen an “unexpected system error” which would’ve made me look in db2diag.log right away
By the way, adding partition on Ubuntu after installing ksh will still five you an error message:
06/07/2011 11:24:20 1 0 SQL6073N Add Database Partition operation failed. SQLCODE = "-6048". SQL6073N Add Database Partition operation failed. SQLCODE = "-6048".
Ignore that. Edit db2nodes.cfg manually and add a new partition there; reissue db2start and you should have a working instance with two partitions:
user@server:~/sqllib$ db2start 06/07/2011 11:47:55 1 0 SQL1063N DB2START processing was successful. 06/07/2011 11:47:55 0 0 SQL1063N DB2START processing was successful. SQL1063N DB2START processing was successful.
Архитектура приложений с открытым исходным кодом
В мае 2011 в свет вышла книга под редакцией Эми Браун и Грега Уилсона под названием “Архитектура приложений с открытым исходным кодом” (The Architecture of Open Source Applications). В настоящий момент книга переводится на несколько популярных языков. Поскольку среди них оказался и русский, то сейчас всеми силами идёт поиск желающих помочь в переводе \ редактировании русского варианта книги. Все доходы от продаж книги идут на благотворительные цели. Если вы согласитесь помочь с проектом, мы обязательно добавим ваше имя в список людей трудившихся над русским переводом книги
, Если у вас есть время и желание – связывайтесь.
Из введения книги:
Можно потратить всю жизнь на то, чтобы научиться тонкому мастерству столяра, но столярничество и архитектура совсем не одно и то же. Отбросив на минуту долото и рубанки, давайте посмотрим на здание, в котором работает столяр: очевидно, что перед тем, как он сможет начать работу, здание сначала должно быть придумано неким архитектором – задача сродни не только ремеслу и науке, но также и искусству.
Еще можно потратить всю жизнь на то, чтобы научиться не менее тонкому мастерству программирования, но считать программирование и архитектуру программного обеспечения одной наукой тоже неправильно. Многие разработчики годами ломают голову над сложными вопросами проектирования: должно ли приложение быть расширяемым? Если да, то какой способ следует использовать: встроенный язык программирования, поддержку плагинов или совершенно новый, вчера придуманный способ? Имеет ли смысл распределять нагрузку программы по принципу клиент-сервер и как в таком случае решить что в приложении будет играть роль клиента, а что будет играть роль сервера? Все эти вопросы связаны с программированием не более чем вопрос “где поставить лестницу?” со столярничеством.
Несмотря на то, что архитектура зданий и архитектура программного обеспечения имеют между собой много общего, существует одно важное отличие: в то время, как архитекторы изучают примеры тысяч конструкций во время учебы и последующей карьеры, большинство разработчиков знакомятся только с небольшим количество “хорошо известных” приложений. К сожалению, во многих случаях эти приложения оказываются “хорошо известными” по причине того что ученик и автор – одно и тоже лицо. Часто, программистам не удается познакомиться с архитектурой известных приложений и критикой этих архитектур, написанной экспертами-практиками. Результат неутешителен: зачастую новые поколения программистов повторяют ошибки, а не успехи предыдущих разработчиков.
Эта книга – попытка изменить текущее положение дел. Каждая глава посвящена архитектуре одного приложения с открытым исходным кодом: его общей структуре, взаимодействию отдельных частей, ответам на вопросы почему все было сделано именно так, как было сделано, и знаниям, полученным авторами во время проектирования этого приложения. Главы книги написаны людьми, которые знают эти приложения лучше любых других разработчиков, людьми, которые имеют десятки лет опыта проектирования и исправления неудачных архитектур простых и сложных приложений. Приложения, обсуждаемые в этой книге, отличаются как в своём размере (от небольших графических редакторов и веб-приложений до более внушительных наборов инструментов для компиляции и многомиллионных пакетов визуализации), так и по своему возрасту (некоторым всего лишь несколько лет, некоторые на всех парах приближаются к 30-летнему юбилею). Однако есть одна вещь, которая объединяет все программные продукты, представленные в этой книге: их авторы потратили немало времени на осмысление и проектирование своих приложений и теперь готовы поделиться своими опытом с вами. Мы надеемся, что вы оцените их труды по достоинству.
Priest
The only vampire-themed movie I’ve recently seen that I have enjoyed a lot. The funny thing is that the best part of it for me was not the vampire part of the story, but the 1984 motives – very convincing “religion-gone-wild” dystopia. Overall, enjoyable movie.
How to compare CLOBs in DB2 with a UDF
Although sometimes it might be less than desirable to do CLOB comparison in SQL statements, suppose you need to write a SELECT that compares two CLOB fields in the where clause:
SELECT COUNT(*) FROM tableA, tableB WHERE tableA.clob = tableB.clob
Seems easy enough, except when you try to run it, DB2 will make a sad face:
SQL0401N The data types of the operands for the operation “=” are not compatible or comparable. SQLSTATE=42818
A few solutions come to mind:
- If you are writing an external application, you can do comparison in the application code – retrieve CLOBs, pass them to a method, get a result, carry on. This is kinda inefficient for remote applications (network overhead) plus not elegant, considering the extra logic you need to put in the application;
- You can use an additional column in both of the tables to store corresponding CLOB’s hash, update hash whenever CLOB value has changed, and use the value of the hash field in the comparison operations. This approach will obviously fail if you rely on an exact match since hash values may collide;
- You can use DBMS_LOB module that provides a COMPARE function. With this function, the query in question becomes:
"SELECT COUNT(*) from tableA, tableB WHERE DBMS_LOB.COMPARE(tableA.clob, tableB.clob) = 0"
This would be my solution of choice if not for the fact that it’s only available as of DB2 9.7;
- Write a UDF that will do comparison for you and will essentially replace the missing COMPARE function from DBMS_LOB module.
I had to deal with DB2 9.5 and didn’t have much options, so I decided to go with a UDF. Here’s how it worked out:
1. First, let’s lay down a few rules. In my case, two CLOBs were considered equal if:
- neither of the CLOBs was NULL;
- sizes of the two CLOBs were equal;
- pairs of characters at the corresponding positions in both CLOBs matched.
Further more, the function was to return 1 if two CLOBs were equal and 0 in all other cases.
2. Here is a Java class with a single method that solves the problem:
import java.io.IOException;
import java.util.Arrays;
import COM.ibm.db2.app.Clob;
import COM.ibm.db2.app.UDF;
public class ClobCompare extends UDF {
/** Returns 1 if the both CLOBs are the equal, and 0 otherwise. */
public void clobsEqual(COM.ibm.db2.app.Clob clobA, COM.ibm.db2.app.Clob clobB, int result) throws Exception{
if (clobA == null || clobB == null){
set(3, 0);
return;
}
char[] clobCharArrayA = null;
char[] clobCharArrayB = null;
// Allocate space for CLOB arrays.
try {
clobCharArrayA = new char[(new Long(clobA.size())).intValue()];
clobCharArrayB = new char[(new Long(clobB.size())).intValue()];
} catch (IOException e){
System.out.println(e.getMessage());
}
// Read CLOBs.
try {
clobA.getReader().read(clobCharArrayA);
clobB.getReader().read(clobCharArrayB);
} catch (IOException e){
System.out.println(e.getMessage());
}
// Compare.
if (Arrays.equals(clobCharArrayA, clobCharArrayB)){
set(3, 1);
} else {
set(3, 0);
}
}
}
By the way, since it’s a UDF, you could handle exceptions better (namely, by signaling SQLSTATE) although I did not do it for the sake of keeping this example short.
3. Now we need to compile the code and drop the class file somewhere DB2 will be able to find it:
/opt/ibm/db2/V9.5/java/jdk64/bin/javac ClobCompare.java cp ClobCompare.class /home/db2inst1/sqllib/function/
4. Almost there, just need to create a function within the specific database:
CONNECT DB TEST; CREATE FUNCTION clobsEqual(a CLOB(1048576), b CLOB(1048576)) RETURNS INTEGER LANGUAGE Java EXTERNAL NAME 'ClobCompare!clobsEqual' FENCED THREADSAFE NO SQL NOT NULL CALL NO EXTERNAL ACTION DISALLOW PARALLEL PARAMETER STYLE db2general;
5. Let’s check if it works:
db2 "values clobsEqual(clob('abc'), clob('abc'))"
If you did everything right, you will see a ’1′ returned. If DB2 dies, make sure you put class in the right folder and check the names of the class / method if you did any changes. Also, if you can’t find the problem right away, try looking in db2diag.log for more info (located in ~/sqllib/db2dump by default).
5. As a side note, if you recompile your code, you do not need to recreate the function. To make sure DB2 uses the latest compiled code available it is sufficient to do this:
db2 "call sqlj.refresh_classes()"
while connected to the database.
Assuming we’ve completed all of the above steps, we can now rewrite our query as:
"SELECT COUNT(*) from tableA, tableB equalsClob(tableA.clob, tableB.clob) = 1"
Enjoy!
Black Swan vs. La Vie En Rose
I have seen Black Swan tonight and I feel like I am on the “hate” side of the “love-it-or-hate” crowd, and here is why.
First, I have to mention that this movie has definitely brought the memories of the exceptional La Vie En Rose. Yes, the life stories of Nina Sayers and Edith Piaf are not exactly the same – different artistic genres, lives, countries, but both of the movies try to show personal sacrifices and struggles the heroines experience on their path, albeit with more psychological twist in the Black Swan.
While the actor play is quite outstanding in both movies, my perception of the heroins in these two movies was quite different. In La Vie En Rose, you follow Edith’s life from her very childhood. You see both her shining talent and her struggles, and you can see exactly what events in her life made her, for the lack of better words, a bit messed up psychologically. You learn to sympathize and feel for her as the movie develops and towards the end you feel sorrow both for her tragic and sometimes unfair life and also for her death because of how much more good she could’ve brought to the world through her passion and talent.
My perception of Nina’s story was different – it’s established early on that she tries to achieve perfection in things she does professionally and also that she is a talented ballerina – we don’t, however, see the struggles she had possibly undergone to get to this point of her life. The sexual theme seems to be a very important one for the story after the first twenty minutes or so. Okay, I get it, you need to get the audience’s attention and, of course, no one prohibits you from including the sexuality themes to achieve that, but please, please do not make those awkward scenes and dialogs with the ballet director, or crotch-grabbing-on-stage moments part of the story line – that’s just feels plain tasteless.
The final scenes where I confirmed that the heroine was on the coucou side made me feel cheated – not enough valuable story time (in comparison to the “thriller” and sex scenes) – I had no time to deeply sympathize with Nina but was instead slapped with an overly dramatic ending. I would have probably been more satisfied if it was revealed at the end that Lily was slipping something in Nina’s coffee to cause visions and drive her insane.
Bottom line: 1) I don’t understand how they managed to get ~$172M in revenue; 2) If you haven’t seen La Vie En Rose – watch it, maybe you’ll see what I mean.
First steps at ASL
I have recently started taking ASL101@CHS (The Canadian Hearing Society).
Among my friends I’m famous for picking up random skills and sometimes even managing to master them to a certain level. The idea of learning new things, especially languages, excites me. My ability to read in Old Slavonic is not something I would put on my resume, my French still needs a lot of improvement so that I don’t sound like such a foreigner, and my Spanish doesn’t extend pass being able to read and understand simple texts, but nonetheless I am still happy and proud of what I have achieved in each of these languages.
The latest language affair of my life is the American Sign Language. I think that I owe much of my inspiration to start learning more about it to the two youtubers who became famous because of their exceptional ability to translate English music into ASL: CaptainValor and allyballybabe. Does it not blow your mind how much you can express with facial expressions, movements, and signs and without saying a single word?
I doubt I will ever become that good, even at expressing my emotions in ASL in day-to-day conversations, but watching all those videos has certainly sparkled my interest in this beautiful language. I have done two classes so far and I am absolutely charmed. Did you know that like spoken languages ASL has dialects? Do you know that ASL itself is not a universal sign language? Do you know that a universal sign language does exist, but is not doing well because it’s very artificial to the signing communities around the globe (just like Esperanto is to the spoken communities)? Do you know that it’s a language on its own and is not in any way a form of English? Do you know that ASL humor can be as funny as English humor? I bet you’d said ‘no’ to at least few of them. I know I would if I were asked these questions before I got introduced to ASL and the Deaf culture.
Point of interest: ASL101 is only $185 (30 hours of instructions) + $90 (textbook that is good for ASL101/102/103) at the Canadian Hearing Society. The group is small (only about 10 people at the Mississauga campus this semester), and the teacher is exceptional – patient, expressive, methodical, funny. So here’s an idea I’d like to offer you: next time you decide to learn a foreign language, should you, perhaps, give ASL a try?
Migrating Ubuntu system on a new hard drive
This boxing day, I got me some extra RAM for me desktop!
Installation required turning off the machine beforehand, and when I tried to brought it up, it became evident that it was not just the startup that got killed with that restart. My old hard drive that was doing some interesting noises once from time to time started dieing in real time. I wanted to save myself some hours of reinstalling new system, backing up data, and customizing things – I do have backups of most important stuff, but owning Ubuntu means that I have to do a system reinstall every couple of releases (somehow it’s the video support that breaks completely every now and then). So this is what I did:
- Went to the store, got a new hard drive, hooked it up as a master (sda), hooked the old one as a slave (sdb).
- Booted from Ubuntu Live CD, and did this:
-
sudo dd if=/dev/sdb of =/dev/sda bs=2M
- Fired up GParted to grow the existing partition (the new drive was like four times as big as the old one), which involved removing the swap, growing the partition, and recreating the swap at the end of the disk.
- Unhooked the old drive, rebooted.
- Corrected swap’s entry in /etc/fstab to refer to the right UUID.
- Rebooted again.
Voilà, my old everything was on the new hard drive, which I hope will live as long as old one did (R.I.P. 26 September 2006 – 26 December 2010).








