<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-20304890</id><updated>2012-01-24T09:31:25.670+01:00</updated><category term='mobile'/><category term='linux'/><category term='xml'/><category term='virtualization'/><category term='education'/><category term='floss'/><category term='business'/><category term='wiki'/><category term='javascript'/><category term='personal'/><category term='mysql'/><category term='system programming'/><category term='vmware'/><category term='security'/><category term='programming'/><category term='perl'/><category term='smp'/><category term='gtk'/><category term='aix'/><category term='rdbms'/><category term='psql'/><category term='oracle'/><category term='prolog'/><category term='c'/><category term='databases'/><category term='c#'/><category term='firefox'/><category term='applications'/><category term='glade'/><category term='ibm'/><category term='shell'/><category term='python'/><category term='cms'/><category term='unix'/><category term='symbian'/><category term='debian'/><category term='microsoft'/><category term='windows'/><category term='qemu'/><category term='services'/><category term='vim'/><category term='fun'/><category term='file sharing'/><category term='notebook'/><category term='laptop'/><category term='.NET'/><category term='backup'/><category term='system administration'/><title type='text'>Daily nitpicking by ipozgaj</title><subtitle type='html'>Random thoughts and articles, mostly IT oriented</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>62</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-20304890.post-5787697665432550328</id><published>2011-05-07T14:59:00.000+02:00</published><updated>2011-05-07T14:59:19.600+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Python for Perl programmers #1 - fileinput module</title><content type='html'>&lt;div&gt;Python for Perl programmers is a set of short posts showing how some of the most common Perl idioms can easily be implemented in Python. This time I'll show you how to translate code chunks using Perl's diamond operator to elegant Python code.&lt;br /&gt;&lt;pre&gt;while (&amp;lt;&amp;gt;) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; ...&lt;br /&gt;}&lt;/pre&gt;This loop written in Perl will iterate over all of the lines from standard input, whether it is pipe from another program or the list of the files specified as the program's arguments (argv). The same functionality can be done in Python by using the &lt;code&gt;fileinput&lt;/code&gt; module, so the previous code snippet becomes:&lt;br /&gt;&lt;pre&gt;import fileinput&lt;br /&gt;&lt;br /&gt;for line in fileinput.input():&lt;br /&gt;&amp;nbsp; &amp;nbsp; ...&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;The default order of processing is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;sys.argv[1:]&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;sys.stdin&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;If file name is specified as "-", the standard input is used instead. You can get more information on &lt;a href="http://docs.python.org/library/fileinput.html"&gt;fileinput module&lt;/a&gt; in official Python documentation.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-5787697665432550328?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/5787697665432550328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=5787697665432550328' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/5787697665432550328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/5787697665432550328'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2011/05/python-for-perl-programmers-1-fileinput.html' title='Python for Perl programmers #1 - fileinput module'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total><georss:featurename>Podsused - Vrapče, City of Zagreb, Croatia</georss:featurename><georss:point>45.8171806582869 15.872068030151354</georss:point><georss:box>45.7715416582869 15.823440030151353 45.8628196582869 15.920696030151355</georss:box></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-4646209093213451134</id><published>2010-10-20T21:55:00.000+02:00</published><updated>2010-10-20T21:55:33.405+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Managed attributes in Python</title><content type='html'>Attribute interception is a common pattern that occurs in almost every object oriented language. In addition to only changing the value of some attribute in object, in most cases you will need to implement some additional logic that deals with the changed value. Most straightforward solution for this by using &lt;i&gt;setters&lt;/i&gt; and &lt;i&gt;getters&lt;/i&gt;. This way the user of the object won't access the attribute directly - he will call the helper functions that hold all the logic needed for fetching and changing the attribute value.&lt;br /&gt;&lt;br /&gt;To be honest, there is nothing wrong with this kind of approach, but it just isn't &lt;i&gt;pythonic &lt;/i&gt; and elegant. The purpose of this article is to give a brief introduction on more advanced Python topics dealing with this problem. In most cases, you will find them to be just a syntactic sugar around setters and getters, but knowing more about these techniques will help you to read and understand code from more experienced Python programmers, and writing more effective and elegant code of your own.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;setters and getters&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;As we have already mentioned, the most simple approach is to use setter and getter functions. For demonstrative purposes, we will use an example class &lt;code&gt;Person&lt;/code&gt; with attribute &lt;code&gt;name &lt;/code&gt; that verifies the name is always properly capitalized.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;class Person:&lt;br /&gt;    def setName(self, name):&lt;br /&gt;        self._name = " ".join([e.capitalize() for e in name.split()])&lt;br /&gt;    def getName(self):&lt;br /&gt;        return self._name&lt;br /&gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; p = Person()&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; p.setName("joe smith")&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; p.getName()&lt;br /&gt;'Joe Smith'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As shown, this just works, but we need to call functions instead using the attribute name directly. The rest of the examples will show how to avoid this kind of programming.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;&lt;code&gt;__setattr__&lt;/code&gt;/&lt;code&gt;__getattr__&lt;/code&gt;&lt;/b&gt;and &lt;b&gt;&lt;code&gt;__setattribute__&lt;/code&gt;/&lt;code&gt;__getattribute__&lt;/code&gt;&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;Next, we will show how to intercept the access to the attribute, so we can add whatever logic we need to process before the actual access has been made. We can do that by using either the &lt;code&gt;__setattr__&lt;/code&gt; or &lt;code&gt;__setattribute__&lt;/code&gt;. Of course, if your goal is to implement something inside getter, and not setter, you would use the &lt;code&gt;__getattr__&lt;/code&gt; and &lt;code&gt;__getattribute__&lt;/code&gt; methods instead. Let's continue with our example - first we will show how to use &lt;code&gt;__setattr__&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;class Person:&lt;br /&gt;    def __setattr__(self, name, value):&lt;br /&gt;        if name == "name":&lt;br /&gt;            value = " ".join([e.capitalize() for e in value.split()])&lt;br /&gt;            self.__dict__[name] = value&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that simply assigning value to the attribute wouldn't work, as it would loop in the &lt;code&gt;__setattr__&lt;/code&gt; call indefinitely, so we must add it to the &lt;code&gt;__dict__&lt;/code&gt; explicitly.&lt;br /&gt;&lt;br /&gt;Approach with &lt;code&gt;__setattribute__&lt;/code&gt; is very similar, but there is one notable difference. While &lt;code&gt;__setattr__&lt;/code&gt; and &lt;code&gt;__getattr__&lt;/code&gt; will be called only for those attributes that are undefined, i.e. not on an instance and not inherited from a class, &lt;code&gt;__setattribute__&lt;/code&gt; and &lt;code&gt;__getattribute__&lt;/code&gt; will be called every time you try to access the attribute. In this matter, &lt;code&gt;__setattribute__&lt;/code&gt; and &lt;code&gt;__getattribute__&lt;/code&gt; are more generic as they will be called every time. Again, you need to be careful to avoid loops. While implementing setter with &lt;code&gt;__setattribute__&lt;/code&gt; will be the same as with &lt;code&gt;__setattr__&lt;/code&gt;, there is a notable difference while implementing the &lt;code&gt;__getattribute__&lt;/code&gt; method. Here we can't use &lt;code&gt;__dict__[name]&lt;/code&gt; as calling it would trigger the &lt;code&gt;__getattribute__&lt;/code&gt; again, causing a loop. To avoid this, you would use the &lt;code&gt;object.__getattribute__&lt;/code&gt; instead of &lt;code&gt;self.__getattribute__&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Properties&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Properties allow us to reroute the attribute's set, get or even delete operations to the functions of our choice. To do this we will use the &lt;code&gt;property&lt;/code&gt; built-in. The basic syntax that can describe the use of properties is (all of the arguments are defaulting to &lt;code&gt;None&lt;/code&gt;, and we will silently ignore the last two arguments for now):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;attribute = property(get, set, del, doc)&lt;/pre&gt;&lt;br /&gt;How to use this? Well, it's pretty straightforward. Our example from previous sections rewritten to use properties looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;class Person(object):&lt;br /&gt;    def setName(self, name):&lt;br /&gt;        self._name = " ".join([e.capitalize() for e in name.split()])&lt;br /&gt;    def getName(self):&lt;br /&gt;        return self._name&lt;br /&gt;    name = property(getName, setName)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that we have derived our &lt;code&gt;Person&lt;/code&gt; object from &lt;code&gt;object&lt;/code&gt;, stating that we want to use is it as the new style class. This is required for properties to function normally (of course, if you're using Python 3.0+ you won't need this as new style classes are implied).&lt;br /&gt;&lt;br /&gt;Properties can also be coded with decorators. In this case, base decorator &lt;code&gt;@property&lt;/code&gt; is used for getter, and &lt;code&gt;name.setter&lt;/code&gt; is used for setter. Again, the following example is merely syntactic sugar for the previous example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;class Person(object):&lt;br /&gt;    @property&lt;br /&gt;    def name(self):&lt;br /&gt;        return self._name&lt;br /&gt;    @name.setter&lt;br /&gt;    def name(self, name):&lt;br /&gt;        self._name = " ".join([e.capitalize() for e in name.split()])&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In contrast with the previous methods, properties manage only a single attribute, and therefore are easier to write as you don't need to remember all the gotchas of &lt;code&gt;__getattr__&lt;/code&gt;, &lt;code&gt;__getattribute__&lt;/code&gt; etc.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Descriptors&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The final method we will examine are descriptors. In their essence, descriptors are superset of properties, and &lt;code&gt;property&lt;/code&gt; built-in we have used before is only a specific case of descriptors. Descriptors allow us to reroute attribute's get and set (or even delete) operations to methods of another class.&lt;br /&gt;&lt;br /&gt;The template code for coding descriptors is:&lt;br /&gt;&lt;pre&gt;class Descriptor:&lt;br /&gt;    def __get__(self, instance, owner):&lt;br /&gt;        ...&lt;br /&gt;    def __set__(self, instance, value):&lt;br /&gt;        ...&lt;br /&gt;    def __delete__(self, instance):&lt;br /&gt;        ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We will again ignore attribute deletion for now. A class containing any of these three methods is descriptor. Omitting the &lt;code&gt;__get__&lt;/code&gt; or the &lt;code&gt;__delete__&lt;/code&gt; method will cause that particular type of access as unsupported, however omitting the &lt;code&gt;__set__&lt;/code&gt; method will not render the attribute as read only, it will only allow its name to be redefined (and therefore descriptor will be hidden). If you want to make your attribute read only, you should implement &lt;code&gt;__set__&lt;/code&gt; with &lt;code&gt;pass&lt;/code&gt; statement or raise an exception on assignment.&lt;br /&gt;&lt;br /&gt;Argument names for descriptor methods are somewhat strange. Let's start with &lt;code&gt;__get__&lt;/code&gt; method. The &lt;code&gt;owner&lt;/code&gt; argument is the name of the class to which the descriptor instance is attached, and the &lt;code&gt;instance&lt;/code&gt; argument is the instance of the object through which the attribute was accessed. Meaning of the &lt;code&gt;instance&lt;/code&gt; argument in the &lt;code&gt;__set__&lt;/code&gt; method is the same, and the &lt;code&gt;value&lt;/code&gt; argument holds the value to be assigned to the attribute.&lt;br /&gt;&lt;br /&gt;How do we use a descriptor? We just assign it to the attribute name. Our example, this time with descriptors, looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;class Descriptor(object):&lt;br /&gt;    def __get__(self, instance, owner):&lt;br /&gt;        return instance._name&lt;br /&gt;    def __set__(self, instance, value):&lt;br /&gt;        instance._name = " ".join([e.capitalize() for e in value.split()])&lt;br /&gt; &lt;br /&gt;class Person(object):&lt;br /&gt;    name = Descriptor()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Again, we must use new style classes if we're not using Python newer or equal to Python 3.0.&lt;br /&gt;&lt;br /&gt;An interesting thing with descriptors is that they can hold state. OK, technically speaking every of the previously described methods can also hold state, at least in the form of global variables, but by using descriptors you can use them elegantly in their own namespace - the descriptor class and instance.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;This is by far not a complete tutorial on using any of techniques described here, as there are many more things to be described, but they are simply out of the scope of this article. You should read the official Python documentation or some of the better books on Python programming (I would strongly recommend &lt;i&gt;Learning Python, 4th ed.&lt;/i&gt; from O'Reilly) to get the complete overview of managed attributes possibilities.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-4646209093213451134?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/4646209093213451134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=4646209093213451134' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/4646209093213451134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/4646209093213451134'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2010/10/managed-attributes-in-python.html' title='Managed attributes in Python'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-466100719818277363</id><published>2010-07-22T18:57:00.002+02:00</published><updated>2010-07-22T19:20:57.978+02:00</updated><title type='text'>Back on the road</title><content type='html'>After almost a year of pause, I've decided to revive this blog. Much has changed in the meantime, so I'm full of ideas and themes to write about. Some of them are:&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;cloud computing&lt;/b&gt;: I've almost completely abandoned all of the applications I've been using before (mail client, feed reader, office applications, personal information management applications etc), and switched to online and cloud versions (primarily Google's)&lt;/li&gt;&lt;li&gt;&lt;b&gt;Android platform&lt;/b&gt;: more like continuation of the previous point - I can now access all of the cloud services I use from literally anywhere, thanks to this great mobile platform&lt;/li&gt;&lt;li&gt;&lt;b&gt;development: &lt;/b&gt;migration from subversion to git, several themes on Perl, Python and shell scripting&lt;/li&gt;&lt;li&gt;&lt;b&gt;systems administration&lt;/b&gt;: several capacity planing, storage optimizations and general system tweaking themes&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;So, stay tuned! :)&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-466100719818277363?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/466100719818277363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=466100719818277363' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/466100719818277363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/466100719818277363'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2010/07/back-on-road.html' title='Back on the road'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-1058314831809519026</id><published>2009-10-24T12:09:00.003+02:00</published><updated>2009-10-24T13:31:30.650+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><category scheme='http://www.blogger.com/atom/ns#' term='microsoft'/><title type='text'>Windows 7 hype</title><content type='html'>&lt;div style="text-align: justify;"&gt;Sometimes it's really interesting to see what good marketing can do for a mediocre or even good product, even if the product itself doesn't offer anything revolutionary.. These days all you can find on RSS, IT news portals, Twitter etc can be summarized into one term - "Windows 7". First of all, I must admit - although I'm a long time Linux user/admin and that's the main thing I do for living, I got my hands on Windows 7 RTM. So here are my two cents on the new Microsoft's product and hype around it after using it for a little longer than a month.&lt;br /&gt;&lt;br /&gt;Undoubtedly, Windows 7 is the most advanced desktop OS ever released from Microsoft.  I wouldn't say it is the best desktop OS currently available, but it is probably the most consistent one. As I've never used Windows Vista, it was quite a surprise to log into this new OS, and to find dozens of new features. On the first look, it is far more visually appealing than XP. Much of concepts that I've been missing in the previous versions of Windows are now here, for example media and document libraries, better network manager, network profiles (home, domain, work, public etc). Advanced users (like myself :)), will be happy to hear that PowerShell 2.0 is included in the OS by default, and you event get a simple IDE for it (PowerShell ISE). As I can hear, it even runs much faster and uses much less resources than Vista, but I can't confirm this as I've never used Vista.&lt;br /&gt;&lt;br /&gt;Of course, there's no such thing as perfect software product, and some things must be criticized. First of all, 10 GB for basic OS installation is simply silly. With some other operating systems (most notably Linux), you get OS and almost all other software you need in much less, like 3-4 gigs at most. Memory usage is also pretty high for an OS kernel and several core services, and I don't accept "RAM is cheap nowadays" as an argument. OS should use much less memory resources than it is the case with Windows 7. Period. I've also noticed a constant disk activity even when I'm away from my computer, and this is really annoying if your hard disk is not among the most silent ones. Finally, there is a nasty bug I've encountered (and some of my colleagues, and thousands of people as I can see on the Internet) - problem with crashing after locking the screen (either with win+L or after an idle period) while being logged on domain network. I've temporary "fixed" this problem with disabling screen locking in the registry, but there is still no fix from Microsoft. My colleagues have even reported this problem to Premier support, but we are still waiting for the solution.&lt;br /&gt;&lt;br /&gt;But let's return to the main thing that made me start writing this article, marketing and hype about the Windows 7. Microsoft announces features like Aero shake, snap and peek as revolutionary, and that's what makes me laugh. First of all, you could have used such features years before Windows 7 on Linux (Beryl and Compiz). And seconds, silly GUI effects like those previously mentioned can hardly be described as something revolutionary (they could have at least "invent" virtual desktops... but no). In my opinion Mac OS or Linux are far ahead of Windows if you're main goal is to have nice desktop with eye candies. I mean, it's nice to have such things, but you can live without them.&lt;br /&gt;&lt;br /&gt;To summarize, if you're a long time Windows user, you should switch to Windows 7. If you're Linux of MacOS user, you should probably stick to your OS. Windows 7 is polished, OS somewhat faster, and with some new features, but it's not nearly so "unique and revolutionary" as Microsoft announces it.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-1058314831809519026?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/1058314831809519026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=1058314831809519026' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/1058314831809519026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/1058314831809519026'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2009/10/windows-7-hype.html' title='Windows 7 hype'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-4560436358790633097</id><published>2009-09-02T20:27:00.007+02:00</published><updated>2009-09-02T21:17:18.241+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>"Secret" Perl operators</title><content type='html'>&lt;div style="text-align: justify;"&gt;H&lt;span style="font-size:100%;"&gt;ere is a list of Perl operators you might not have seen so often as usual operators. Strictly speaking, the operators we'll show are not operators at all, yet they are ingenuous little hacks that can save you some time and lines of code in some common circumstances. On the other hand, guys who will debug or maintain your code might not be so happy about it, as these operators are commonly used to obfuscate Perl code. Here is the list&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;pre&gt;    symbol    nickname                Role&lt;br /&gt;    ------    --------                ----&lt;br /&gt;    &lt;=&gt;       spaceship               documented operator&lt;br /&gt;    0+        venus                   numification&lt;br /&gt;    }{        eskimo greeting         END{} in one-liners&lt;br /&gt;    =()=      goatse                  lenght of array&lt;br /&gt;    ~-        inchworm on a stick     high-precedence numification&lt;br /&gt;    ~~        inchworm                scalar&lt;br /&gt;    "@{[]}"                           join $", ...&lt;br /&gt;    -+-       spacestation            high-precedence numification&lt;br /&gt;    ~-        cotton candy&lt;br /&gt;    ~~         caterpillar&lt;br /&gt;    "@{[]}"    cyclops&lt;br /&gt;    -+-        cross-hair&lt;br /&gt;    ]-&gt;[       Frowning Sam&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-4560436358790633097?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/4560436358790633097/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=4560436358790633097' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/4560436358790633097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/4560436358790633097'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2009/09/secret-perl-operators.html' title='&quot;Secret&quot; Perl operators'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-7020281041006820054</id><published>2009-07-21T21:04:00.002+02:00</published><updated>2009-07-21T22:12:33.755+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='system programming'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>Don't abuse your compiler</title><content type='html'>&lt;div style="text-align: justify;"&gt;Today I was asked to take a look at some broken code to find out what was going wrong. Code snippet that caused a process to SEGFAULT was something like this:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;char *tempfile_template = "tempXXXXXX";&lt;br /&gt;mkstemp(tempfile_template);&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Of course, code was wrong as &lt;code&gt;mkstemp()&lt;/code&gt; will try to change XXXXXX in variable tempfile_template with random identifier, and &lt;code&gt;char *tempfile_template&lt;/code&gt; declares a pointer to data in &lt;code&gt;.rodata&lt;/code&gt; section that is read only.&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;$ objdump -s a.out&lt;br /&gt;...&lt;br /&gt;Contents of section .rodata:&lt;br /&gt;80484b8 03000000 01000200 74656d70 58585858  ........tempXXXX&lt;br /&gt;80484c8 585800                               XX.&lt;br /&gt;&lt;br /&gt;$ objdump -h a.out&lt;br /&gt;...&lt;br /&gt;14 .rodata       00000013  080484b8  080484b8  000004b8  2**2&lt;br /&gt;                CONTENTS, ALLOC, LOAD, READONLY, DATA&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;However, code was working before, and quick look into old Makefile revealed &lt;code&gt;-fwriteable-strings&lt;/code&gt; option, which caused string "constants" to be placed into writeable sections. The option itself was abandoned somewhere about gcc 4.0, and version of gcc used was 4.3.&lt;br /&gt;&lt;br /&gt;Clearly, this was an example of bad programming habits and poorly written code. You should always avoid using obscure options such as &lt;code&gt;-fwriteable-strings&lt;/code&gt;, as someone who will eventually read and debug your code may not be even aware that such an option exist.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-7020281041006820054?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/7020281041006820054/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=7020281041006820054' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/7020281041006820054'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/7020281041006820054'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2009/07/dont-abuse-your-compiler.html' title='Don&apos;t abuse your compiler'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-2776491414951608108</id><published>2009-07-12T17:07:00.005+02:00</published><updated>2009-07-12T19:10:36.237+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='debian'/><title type='text'>Package selection with aptitude</title><content type='html'>&lt;div style="text-align: justify;"&gt;Most of the Debian-like distributions users still use apt-* commands for package management and as interface to core packaging libraries. Even worse, they use Synaptic or similar GUI ;). Starting from Debian 4.0 (etch) aptitude is the prefered package management software,  but it seems that it still has quite small user base compared to other ways of package management.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Although I could spend hours writing arguments on why you should use aptitude, this time I'll focus only on describing techniques for package selection in aptitude. In past, if you wanted to select specific packages to perform some action on a package set, you could use &lt;code&gt;dpkg&lt;/code&gt; or &lt;code&gt;apt-cache&lt;/code&gt;. Aptitude unifies functionalities of those two programs (and many more) and what is more important it brings new syntax that enables writing of more complex selection rules than before.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;Let's start with basics. Search patterns that we'll be discussing can be used with any aptitude command like &lt;code&gt;search&lt;/code&gt;, &lt;code&gt;remove&lt;/code&gt;, &lt;code&gt;purge&lt;/code&gt;, &lt;code&gt;install&lt;/code&gt;, &lt;code&gt;hold&lt;/code&gt; etc. Aptitude search patterns enable you to make searches based on specific package properties like package name, description, author etc. Almost every search pattern can be written in two forms: short and long. You will recognise short patterns as tilda (~) character followed by a single character (search category) and a search term, and you will recognise long search pattern as a question mark followed by a search category and  a search term inside of brackets.&lt;br /&gt;&lt;br /&gt;Before we start, just a short notice: all commands will be written as they are used in bash shell. If you're using some other shell (most notably zsh) you will have problems because it probably uses different globing and escaping syntax than bash. For example, if you're using zsh you'll have to quote search patterns (write them inside of quotation marks) or/and escape special characters like tilda (~) or question mark (?).&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Simple searches&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;If you write a single word after an aptitude command, it will perform search based on package name. So, the following command will search all packages with word "python" in their name:&lt;pre&gt;&lt;br /&gt;aptitude search python&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Equivalent (but superfluous) syntax for this is:&lt;pre&gt;&lt;br /&gt;aptitude search ~npython&lt;br /&gt;aptitude search '?name(python)'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Take a note, I'll write both short and long syntax for all commands. But, let's suppose we want all packages that have word Python in their description. Then we'll use:&lt;pre&gt;&lt;br /&gt;aptitude search ~dpython&lt;br /&gt;aptitude search '?description(python)'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There are many search patterns that you could use for daily package management. For example, you may wonder how many packages you can upgrade after you have refreshed your package list with aptitude update. Just run:&lt;pre&gt;&lt;br /&gt;aptitude search ~U&lt;br /&gt;aptitude search '?upgradable'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Before I've started using aptitude, I've used the following command to purge packages that have left their configuration files on my system, but the owning packages have been removed:&lt;pre&gt;&lt;br /&gt;apt-get --purge remove $(dpkg -l | awk '/^rc/{print $1}')&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It's much more elegant to do this in aptitude:&lt;pre&gt;&lt;br /&gt;aptitude purge ~c&lt;br /&gt;aptitude purge '?config-files'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Let's find out packages that are maintained by packager "Josip Rodin":&lt;pre&gt;&lt;br /&gt;aptitude search ~m'Josip Rodin'&lt;br /&gt;aptitude search '?author(Josip Rodin)'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For list of all possible search patterns, take a look at &lt;a href="http://algebraicthunk.net/%7Edburrows/projects/aptitude/doc/en/ch02s03.html"&gt;aptitude reference manual&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li value="2"&gt;&lt;span style="font-weight: bold;"&gt;Advanced searching&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;You may combine as many simple search terms as you want by using logical operators and/or/not, and you can write even more complex searches by using &lt;code&gt;?for&lt;/code&gt; keyword. Let's start with examples. We'll search for all packages from development section that provide C compiler and their name is not gcc:&lt;pre&gt;&lt;br /&gt;aptitude search '~sdevel ~Pc-compiler !~ngcc'&lt;br /&gt;aptitude search '?and(?and(?section(devel),?provides(c-compiler)), ?not(?name(gcc)))'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Or, let's find out what currently installed packages depend on python:&lt;pre&gt;&lt;br /&gt;aptitude search '~i ~Dpython'&lt;br /&gt;aptitude search '?and(?installed, ?depends(python))'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And finally, there is a king of all complex searches with aptitude and dream of every Debian system administrator - &lt;code&gt;?for&lt;/code&gt; :). First we will examine the simplest possbile pattern:&lt;pre&gt;&lt;br /&gt;aptitude search '?for x: ?conflict(?=x)'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This will list every package that is in conflict with itself. I personally don't see why such packages even exist, but as you can find out if you run this command, they really do! :)&lt;br /&gt;&lt;br /&gt;Next, let's find out packages with cirrcular dependencies:&lt;pre&gt;&lt;br /&gt;aptitude search '?for x: ?depends(?for y: ?depends(?=x))'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you may have noticed, &lt;code&gt;?for&lt;/code&gt; search pattern doesn't have short form. If the command above is not clear on the first look, you can interpret it like this: show me every package x such that x is dependent on package y that is in turn also dependent on x.&lt;br /&gt;&lt;br /&gt;Let's examine next situation from aptitude documentation. We'll list all packages that depend on package(s) that they recommend:&lt;pre&gt;&lt;br /&gt;aptitude search '?for x: ?depends( ?for y: ?x:recommends( ?=y ) ) '&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is just a short intro in countless possibilities of aptitude. Of course, a deeper look into aptitude documentation is logical next step.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-2776491414951608108?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/2776491414951608108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=2776491414951608108' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/2776491414951608108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/2776491414951608108'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2009/07/package-selection-with-aptitude.html' title='Package selection with aptitude'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-5088146943453281685</id><published>2009-05-13T19:22:00.009+02:00</published><updated>2009-05-30T13:30:57.038+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>Process substitution</title><content type='html'>&lt;div style="text-align: justify;"&gt;In addition to widely used shell features like file globing and command substitution, modern  shells like bash or zsh support something that is called &lt;span style="font-style: italic;"&gt;process substitution&lt;/span&gt;. The goal of process substitution is to enable syntax which will allow us to get some commands marked within special characters behave as they were regular files. Common special characters for both mentioned shells are:&lt;br /&gt;&lt;pre&gt;&amp;lt;(command list)&lt;br /&gt;&amp;gt;(command list)&lt;/pre&gt;In addition to these, zsh adds additional syntax in form of:&lt;br /&gt;&lt;pre&gt;=(command list)&lt;/pre&gt;Lets start with &lt;code&gt;&amp;lt;()&lt;/code&gt; syntax. In it's simplest form, it can behave just as a regular pipe. For example, this is completely equivalent syntax:&lt;pre&gt;ls -l | sort&lt;/pre&gt;or&lt;pre&gt;sort &amp;lt;(ls -l)&lt;/pre&gt;What actually happens under the hood is that output of &lt;code&gt;ls -l&lt;/code&gt; is connected to sort command through the mechanism of named pipes (FIFOs) or by using a file in &lt;code&gt;/dev/fd&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Off course, this was a simple usage pattern and nobody would use process substitution in this way instead of classic pipe scenario. But suppose a situation where you want a command to operate on results of more than one command. For example, you want to compare content of two directories (let's forget on dircmp command for a moment):&lt;br /&gt;&lt;pre&gt;diff &amp;lt;(ls dir1) &amp;lt;(ls dir2) &lt;/pre&gt;Here the command acts just like you have saved output of both &lt;code&gt;ls&lt;/code&gt; commands to separate files, and then ran &lt;code&gt;diff&lt;/code&gt; on those two files. Or for example, you could use something like:&lt;br /&gt;&lt;pre&gt;paste &amp;lt;(cut -f1 file1) &amp;lt;(cut -f2 file2)&lt;/pre&gt;Or maybe you want to edit the output of some complex command directly into your favorite text editor - no problem, just use syntax similar to this:&lt;br /&gt;&lt;pre&gt;vi &amp;lt;(ls -l /etc)&lt;/pre&gt;Now when you know how to use &lt;code&gt;&amp;lt;()&lt;/code&gt;, usage pattern for &lt;code&gt;&amp;gt;()&lt;/code&gt; is straightforward. You can send the  standard output of a command to more than one command. For example (just make sure that MULTIOS option is set in your shell before running this, ie &lt;code&gt;setopt multios&lt;/code&gt; for zsh):&lt;br /&gt;&lt;pre&gt;ls &amp;gt; &amp;gt;(sort) &amp;gt; &amp;gt;(sort -r)&lt;/pre&gt;If you are using zsh (and you should! :), you can also use &lt;code&gt;=()&lt;/code&gt; snytax. The only difference between this syntax and &lt;code&gt;&amp;lt;()&lt;/code&gt; or &lt;code&gt;&amp;gt;()&lt;/code&gt; is that &lt;code&gt;=()&lt;/code&gt; actually creates a file on filesystem instead of using FIFO. This comes handy if command you are substituting process to is using system calls like &lt;code&gt;lseek(2)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-5088146943453281685?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/5088146943453281685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=5088146943453281685' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/5088146943453281685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/5088146943453281685'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2009/05/process-substition.html' title='Process substitution'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-7695306199963913100</id><published>2008-12-21T22:41:00.002+01:00</published><updated>2008-12-21T22:45:59.648+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='symbian'/><title type='text'>Going mobile</title><content type='html'>&lt;div style="text-align: justify;"&gt;Until now I've always had a regular cell phone, i.e. not a smart phone or any similar kind of "smart" embedded device. That was fine with me as I've always used a cell phone only for making calls and sending text messages. After trying several vendors and models, I've finally decided to try something new and buy a smart-phone. As I was a starter in that area, I decided not to buy expensive gadget like &lt;a href="http://europe.nokia.com/n96"&gt;Nokia N96&lt;/a&gt; (although I was considering &lt;a href="http://europe.nokia.com/n95"&gt;N95&lt;/a&gt; for quite a bit), so at the end I bought a &lt;a href="http://europe.nokia.com/e66"&gt;Nokia E66&lt;/a&gt;. Minimal set of features I required at the start was including wireless and GPS, and as I was biased to the &lt;a href="http://www.symbian.com/index.asp"&gt;Symbian&lt;/a&gt; based model (spoiled with Nokia's regular cell phones) I decided for E66.&lt;br /&gt;&lt;br /&gt;Wireless is an enormous gain on a cell phone, and you won't know what you're missing once you don't start using it. Now I don't even bother turning my desktop or laptop PC on just to check my email (or Facebook :), I can do it with my cell phone. Besides that, there are many good web sites optimized for small screens found on cell phones. Be sure to try Wapedia (Wikipedia), BBC, Slashdot, Facebook and dozens of other sites optimized for a mobile web browser. It's not even a problem to find an open wireless access point, at least in the big cities, but if you live in a smaller city you'll most probably use GPRS/EDGE/HSDPA (which is btw extremely expensive here in Croatia). I assume you have a wireless connection at home, so this won't be a "show stopper" at all.&lt;br /&gt;&lt;br /&gt;The next very useful thing to have on a cell phone is a GPS. Last month I was in London for ten days, and it saved me a lot of time to find locations I was interested in (and to get back on a familiar place once I got lost :). I suggest you to download maps for a location (country) you are traveling to on your PC at home (or directly via mobile browser and wireless), because you'll get quite a big bill to pay if you download it ad hoc via GPRS or EDGE (especially in roaming). Map of England for Nokia Maps was around 35 MB, so I assume you'll find similar sizes on all other GPS software. So bad that Google Maps (Symbian version) doesn't support such an option. Also, be sure to turn off a option to find GPS satellites over the Internet (AGPS), especially when in roaming, for a obvious reason. It will make your GPS device somewhat slower in finding satellites for the first time, but later you won't notice a difference (if you are using it regularly).&lt;br /&gt;&lt;br /&gt;The latest great thing I "discovered", thanks to my colleague who had already been using it, was a great application called &lt;a href="http://www.nimbuzz.com/"&gt;Nimbuzz&lt;/a&gt;. It can be used as chat program (MSN, Jabber, GTalk, ICQ...), and what's even better, it can be used for making Skype calls (or to some other SIP based applications). I've tested it and it works perfectly, now I can talk for hours without using my PC or wearing those annoying headphones with microphone. You can also take a picture or record a sound clip and it will automatically send a link to that content (uploaded to the Nimbuzz server) to the recipient over the selected instant messaging protocol. The best part of the story is that this application is totally free (as in "you don't need to pay money for it") and there are versions for Symbian, Windows Mobile etc. Give it a try, you want be disappointed.&lt;br /&gt;&lt;br /&gt;There are far too many benefits to mention them all here (for example motion sensor, great Symbian applications etc), but the bottom line is that smart phone is really worth of money you give for it, if you need such functionality. Knowing myself, I won't by a regular phone again for sure.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-7695306199963913100?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/7695306199963913100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=7695306199963913100' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/7695306199963913100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/7695306199963913100'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/12/going-mobile.html' title='Going mobile'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-8171221505108924938</id><published>2008-10-25T20:43:00.004+02:00</published><updated>2008-10-25T21:34:27.393+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='aix'/><title type='text'>Fixing fibre channel connectivity problems on AIX</title><content type='html'>&lt;div style="text-align: justify;"&gt;Unix and storage administration always brings interesting and new problems ready to be solved. Few days ago I've encountered one of those problems. Task was to configure two &lt;a href="http://en.wikipedia.org/wiki/IBM_AIX_%28operating_system%29"&gt;AIX&lt;/a&gt; powered &lt;a href="http://www.ibm.com/developerworks/wikis/display/virtualization/Virtual+IO+Server"&gt;VIO&lt;/a&gt; servers to access &lt;a href="http://en.wikipedia.org/wiki/Logical_Unit_Number"&gt;LUNs&lt;/a&gt; on &lt;a href="http://en.wikipedia.org/wiki/Clariion"&gt;CLARiiON&lt;/a&gt; storage, i.e. to make high availability environment with several AIX &lt;a href="http://en.wikipedia.org/wiki/LPAR"&gt;LPARs&lt;/a&gt; accessing storage through VIO servers.&lt;br /&gt;&lt;br /&gt;After wiring the environment, i.e. hell of finding which port is right by using only &lt;code&gt;lsslot&lt;/code&gt; and instructing technician located in data center 80 km far away, next step was to zone the &lt;a href="http://en.wikipedia.org/wiki/Storage_area_network"&gt;SAN&lt;/a&gt; switches. But something was wrong. Every VIO had one dual port &lt;a href="http://en.wikipedia.org/wiki/Fibre_Channel"&gt;FC&lt;/a&gt; &lt;a href="http://en.wikipedia.org/wiki/Host_Bus_Adapter"&gt;HBA&lt;/a&gt; and every port was connected to a different SAN switch. But instead of seeing two new &lt;a href="http://en.wikipedia.org/wiki/World_Wide_Name"&gt;WWNs&lt;/a&gt; (i.e F-ports) on switch, there were two L-ports.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;SW1&gt; switchShow&lt;br /&gt;Area Port Media Speed State     Proto&lt;br /&gt;=====================================&lt;br /&gt;...&lt;br /&gt;6   6   id    N4   Online           L-Port  1 public&lt;br /&gt;7   7   id    N4   Online           L-Port  1 public&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Situation on the other switch was OK - connected ports were reported as F-ports. For some reason one port of every HBA was L-port (loop port), and the other was F-port. After trying several things, I've managed to get things working as expected.&lt;br /&gt;&lt;br /&gt;Apparently this is quite usual problem with AIX, so here is a cookbook how to fix it. You need to unconfigure FC devices and FC SCSI I/O controller protocol, and then set the link initialization protocol to &lt;span style="font-style: italic;"&gt;Arbitrated Loop and Switch&lt;/span&gt; (AL).&lt;br /&gt;&lt;br /&gt;First, look for FC devices:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# lsdev -H -Ccdriver -F "parent name description"&lt;br /&gt;parent  name       description&lt;br /&gt;fcs0    fcnet0     Fibre Channel Network Protocol Device&lt;br /&gt;fcs1    fcnet1     Fibre Channel Network Protocol Device&lt;br /&gt;fcs2    fcnet2     Fibre Channel Network Protocol Device&lt;br /&gt;fcs3    fcnet3     Fibre Channel Network Protocol Device&lt;br /&gt;fcs0    fscsi0     FC SCSI I/O Controller Protocol Device&lt;br /&gt;fcs1    fscsi1     FC SCSI I/O Controller Protocol Device&lt;br /&gt;fcs2    fscsi2     FC SCSI I/O Controller Protocol Device&lt;br /&gt;fcs3    fscsi3     FC SCSI I/O Controller Protocol Device&lt;br /&gt;    iscsi0     iSCSI Protocol Device&lt;br /&gt;    powerpath0 PowerPath Control Device&lt;br /&gt;sissas0 sas0       Controller SAS Protocol&lt;br /&gt;sissas0 sata0      Controller SATA Protocol&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;From here we can see that FC HBAs are fcsX and FC SCSI I/O protocol devices are fcsciX, where X is in range from 0 to 3. Now, deconfigure devices and set the appropriated link initializaion mode. Don't forget to run &lt;code&gt;cfgmgr&lt;/code&gt; at the end.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;for i in 0 1 2 3&lt;br /&gt;do&lt;br /&gt;    rmdev -Rdl fscsi$i&lt;br /&gt;    rmdev -Rl fcs$&lt;br /&gt;    chdev -l fcs$i -a init_link=al&lt;br /&gt;    cfgmgr -vl fcs$i&lt;br /&gt;done&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Now you should see both fabric logins and ports listed as F-ports:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;SW1&gt; switchShow&lt;br /&gt;Area Port Media Speed State     Proto&lt;br /&gt;=====================================&lt;br /&gt;...&lt;br /&gt;6   6   id    N4   Online           F-Port  10:00:00:00:c9:76:07:33&lt;br /&gt;7   7   id    N4   Online           F-Port  10:00:00:00:c9:76:0c:2b&lt;br /&gt;...&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-8171221505108924938?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/8171221505108924938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=8171221505108924938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/8171221505108924938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/8171221505108924938'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/10/fixing-fibre-channel-connectivity.html' title='Fixing fibre channel connectivity problems on AIX'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-5682912249725928729</id><published>2008-09-06T17:31:00.003+02:00</published><updated>2008-09-06T17:43:29.723+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='system administration'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>Linux I/O accounting</title><content type='html'>&lt;div style="text-align: left;"&gt;&lt;div style="text-align: justify;"&gt;One feature one would expect from an enterprise grade operating system is definitely a good I/O scheduler, but also some tools for monitoring it's performance. Starting from 2.6.x series, Linux has selectable I/O schedulers, actually four of them: no-op, anticipatory, deadline and complete fair queuing (CFQ) scheduler. Comparing to the older kernels, it was a great step ahead, but we were still lacking tools for I/O monitoring. Why was it so?&lt;br /&gt;&lt;br /&gt;Up to the version 2.6.20, there was no I/O accounting support in the Linux kernel. Although process accounting was included in the kernel a long time ago, obtaining informations about per process I/O utilization was a very difficult task. Information you could get, for example with iostat command, was telling you that something is causing a heavy I/O load, but it was up to you to find out what process is actually causing it. Finding out that process was not an easy task, especially if you were running system with hundreds of processes, for example with ten Oracle instances.&lt;br /&gt;&lt;br /&gt;Finally, Linux kernel 2.6.20 and newer included I/O accounting. Now every running process has associated I/O information in /proc/self/io. To enable this, besides having a recent Linux kernel, you must enable the following options in your kernel build configuration:&lt;br /&gt;&lt;/div&gt;&lt;code&gt;&lt;br /&gt;CONFIG_TASKSTATS=y&lt;br /&gt;CONFIG_TASK_IO_ACCOUNTING=y&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you are running any recent Linux distribution, you probably already have this option, so there is no need for recompiling. Unfortunately, most "stable" Linux distributions you would see on production environments, like Debian or RHEL, use 2.6.18 at this moment, so you'll have a bit of work to do here.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Tool for per process I/O usage monitoring I use is iotop. It behaves much like widely used top or htop. i.e. it displays table of processes and threads on the system along with their I/O usage. Displayed data includes read and write I/O bandwidth in sampled period, and also percentage of time the thread spent while swapping in or waiting for I/O. iotop is actually a Python script, and if your favorite distribution doesn't already have it in packages, you can get it &lt;a href="http://guichaz.free.fr/iotop"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I would strongly recommend trying iotop to every professional Linux administrator and even to beginning Linux users, because it helps a lot and gives you very usable information when doing a full system diagnostics.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-5682912249725928729?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/5682912249725928729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=5682912249725928729' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/5682912249725928729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/5682912249725928729'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/09/linux-io-accounting.html' title='Linux I/O accounting'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-8348564894028936215</id><published>2008-07-26T20:26:00.004+02:00</published><updated>2008-07-26T21:27:30.632+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='qemu'/><category scheme='http://www.blogger.com/atom/ns#' term='virtualization'/><title type='text'>(K)QEMU speed tests</title><content type='html'>&lt;div style="text-align: justify;"&gt;&lt;a href="http://www.qemu.org/"&gt;QEMU&lt;/a&gt; without additional accelerators is very slow, and that is a well known fact. If you have a modern processor with virtualization options you will most probably want to use KVM. You can find out if your system can run KVM by checking the flags line in &lt;code&gt;/proc/cpuinfo&lt;/code&gt; for &lt;code&gt;vmx&lt;/code&gt; (Intel) or &lt;code&gt;svm&lt;/code&gt; (AMD).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;code&gt;$ grep -E '^flags.*(vmx|svm)' /proc/cpu&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Unfortunately my CPU doesn't have such options. I have one of those Core2Duo processors that lacks suck features (T5500, commonly used on laptops). So if you're in situation like me, you're stuck with KQEMU to speed the things up. Up to yesterday, I was not fully aware what is the performance penalty of not using one of the accelerators. I've made some tests of my own to see how virtual machine behave with and without accelerator module.&lt;br /&gt;&lt;br /&gt;Tests were run on &lt;a href="http://www.debian.org/"&gt;Debian&lt;/a&gt; GNU Linux (lenny), kernel 2.6.25 and with QEMU version 0.9.1. Underlying hardware was IBM Thinkpad R60e, Core2Duo 2x1.66 GHz with 1 GB of RAM. For testing purposes I've used guest with Red Hat Enterprise Linux 5.1. Tests were focused on three areas I was most interested in:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Processing speed, calculate as many RSA public/private keys as possible in 10 sec (&lt;code&gt;openssl speed rsa4096&lt;/code&gt;)&lt;/li&gt;&lt;li&gt;Network speed, download 10 MB file with wget (&lt;code&gt;wget URL&lt;/code&gt;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Disk speed (&lt;code&gt;hdparm -tT&lt;/code&gt;)&lt;/li&gt;&lt;/ol&gt;First, each of tests was run on host OS (Debian), then in virtual machine without KQEMU and finally in virtual machine with KQEMU module loaded. The results are:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Calculation of RSA public keys (10 sec)&lt;/span&gt;&lt;br /&gt;Host OS: 7202&lt;br /&gt;KQEMU: 6188&lt;br /&gt;QEMU: 372&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Calculation of RSA private keys (10 sec)&lt;/span&gt;&lt;br /&gt;Host OS: 98&lt;br /&gt;KQEMU: 85&lt;br /&gt;QEMU: 6&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Buffered disk I/O&lt;/span&gt;&lt;br /&gt;Host OS: 33.51&lt;br /&gt;KQEMU: 24.51&lt;br /&gt;QEMU: 25.47&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Cached disk I/O&lt;/span&gt;&lt;br /&gt;Host OS: 918.97&lt;br /&gt;KQEMU: 442.71&lt;br /&gt;QEMU: 445&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Network I/O&lt;/span&gt; (download of 10 MB file)&lt;br /&gt;Host OS: 52&lt;br /&gt;KQEMU: 53&lt;br /&gt;QEMU: 51&lt;br /&gt;&lt;br /&gt;While virtual machine I/O performance was pretty much the same in both cases (slightly better without accelerator module),  number crunching tasks like RSA key pairs generation is where KQEMU shows up. KQEMU accelerated guest achieves at most 90% of host speed, but without accelerator only about 10% which is very slow. Tests also show that disk performance on guests is around 50% of that on host.&lt;br /&gt;&lt;br /&gt;Next thing I want to check is &lt;a href="http://www.virtualbox.org"&gt;VirtualBox&lt;/a&gt; performance. I expect it to be slightly better of that of KQEMU. Unfortunately there is no &lt;a href="http://www.xen.org"&gt;Xen&lt;/a&gt; enabled kernel in Debian packages for lenny so I can test Xen performance.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-8348564894028936215?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/8348564894028936215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=8348564894028936215' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/8348564894028936215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/8348564894028936215'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/07/kqemu-speed-tests.html' title='(K)QEMU speed tests'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-4818521397801411349</id><published>2008-05-22T12:49:00.003+02:00</published><updated>2008-05-22T13:36:05.128+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='databases'/><title type='text'>SQLite Manager</title><content type='html'>&lt;div style="text-align: justify;"&gt;Playing with databases doesn't always require installation of full-featured &lt;a href="http://en.wikipedia.org/wiki/Relational_database_management_system"&gt;RDBMS&lt;/a&gt;. You have probably already come to situation where you need only a small subset of those features. For example, you may only need ability to store your data in relational manner and to use &lt;a href="http://en.wikipedia.org/wiki/SQL"&gt;SQL&lt;/a&gt; to extract or manipulate that data. Of course, natural choice for this is &lt;a href="http://www.sqlite.org/"&gt;SQLite&lt;/a&gt; - small RDBMS with footprint of only 800 kb. SQLite comes very handy for small databases (e.g. personal collections) where you don't really care about transactions, isolations or other features (although SQLite is &lt;a href="http://en.wikipedia.org/wiki/ACID"&gt;ACID &lt;/a&gt;compliant). Personally, I use it for my backup management application, in combination with &lt;a href="http://www.python.org"&gt;Python&lt;/a&gt;. You probably use SQLite every day, even if you are completely unaware of that (for example in &lt;a href="http://www.skype.com/intl/en/"&gt;Skype&lt;/a&gt;, &lt;a href="http://www.apple.com/iphone/"&gt;iPhone&lt;/a&gt;, &lt;a href="http://www.apple.com/macosx/"&gt;Mac OS&lt;/a&gt; etc). If you are using &lt;a href="http://www.mozilla.com/en-US/firefox/"&gt;Firefox&lt;/a&gt;, you are in fact using it right now.&lt;br /&gt;&lt;br /&gt;SQLite is an awesome piece of software, but it would be good if you could have some tools to manage your data on the fly, i.e. without using some glue (e.g. programming language) to access and manipulate your data. Fortunately, there is such a software, and you are just few clicks away from using it. Having SQLite embedded in Firefox browser is a great thing. You only need to install a Firefox add-on named &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/5817"&gt;SQLite Manager&lt;/a&gt;. This add-on allows you to manage any SQLite database on your computer directly through intuitive GUI in Firefox. It also includes features like data import/export (&lt;a href="http://en.wikipedia.org/wiki/Comma-separated_values"&gt;csv&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/XML"&gt;XML&lt;/a&gt;), data browsing, ability to create indexes and triggers, &lt;a href="http://en.wikipedia.org/wiki/Data_Manipulation_Language"&gt;DML&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Data_Definition_Language"&gt;DDL&lt;/a&gt;, SQL syntax help etc.&lt;br /&gt;&lt;br /&gt;You can get this add-on &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/5817"&gt;Firefox add-ons page&lt;/a&gt; (it works on Firefox 2.0 - 3.0). You can start it by selecting SQLite Manager entry from Tools menu.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-4818521397801411349?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/4818521397801411349/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=4818521397801411349' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/4818521397801411349'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/4818521397801411349'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/05/sqlite-manager.html' title='SQLite Manager'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-221868441726850930</id><published>2008-03-25T21:23:00.003+01:00</published><updated>2008-03-26T19:29:30.394+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Python decorators demystified</title><content type='html'>&lt;div style="text-align: justify;"&gt;One of the things you may have noticed if you took a look at some of the newer &lt;a href="http://www.python.org"&gt;Python&lt;/a&gt; programs is extensive use of &lt;a href="http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators"&gt;decorators&lt;/a&gt;. Decorators are relatively new concept in Python world, and they first appeared in version 2.4. Decorators can help you to avoid unnecessary code duplication and to write elegant code in many situations which could otherwise lead to ugly code. Decorators are way to do metaprogramming in Python, ie. to enhance functionality of an existing (decorated) function without modifying it's body.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;What precisely is a decorator? Let's first give a more or less formal definition in context of Python programming. Decorator is an object that acts as syntactic glue and is used to modify behavior of a method or a function. You can recognize a decorator by the following syntax:&lt;/div&gt;&lt;pre&gt;@&amp;lt;decorator_name&amp;gt;&lt;br /&gt;def &amp;lt;function_name&amp;gt;:&lt;br /&gt;   &amp;lt;function_body&amp;gt;&lt;/pre&gt;What Python interpreter actually does under the hood is translation of previous code to:&lt;br /&gt;&lt;pre&gt;&amp;lt;function_name&amp;gt; = &amp;lt;decorator_name&amp;gt;(&amp;lt;function_name&amp;gt;)&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Here decorator acts simply as a wrapper for an existing function, but as we will show later, it can add a new functionality to that function.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Although previous syntax indicates that a function may have only one decorator, that is not true - a function may have more that one decorator. By using the multiple decorators, code is translated from this syntax:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;@&amp;lt;decorator1&amp;gt;&lt;br /&gt;@&amp;lt;decorator2&amp;gt;&lt;br /&gt;def &amp;lt;function_name&amp;gt;:&lt;br /&gt;   &amp;lt;function_body&amp;gt;&lt;br /&gt;&lt;/pre&gt;to this:&lt;br /&gt;&lt;pre&gt;&amp;lt;function_name&amp;gt; = &amp;lt;decorator1&amp;gt;(&amp;lt;decorator2&amp;gt;(&amp;lt;function_name&amp;gt;))&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;In all of the examples we have assumed that decorators are already defined, but in your programs you will have to write a decorator before you can use it.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Let's start with the most basic example. We will modify a function that makes a sum of two integers so it will return a result in hexadecimal notation instead of default decimal notation.&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;def sum(a, b):&lt;br /&gt;   return a + b&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Instead of modifying the function itself, we write a decorator function. Decorator function takes a function as an argument and it returns a new function which will replace the old one.&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;def hex(fn):&lt;br /&gt; def new_fn(*args):&lt;br /&gt;    return "%x" % fn(*args)&lt;br /&gt; return new_fn&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;In the body of decorator, we have defined a new function that reads all arguments into a tupple (*args syntax), and then uses a decorated function (fn) to calculate result. The result is then returned in hexadecimal. At the end of decorator body, new function is returned. Now, we can simply modify any function that returns a single integer with this decorator. Just add "@hex" in front of function definition, and it will do it's job.&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; @hex&lt;br /&gt;... def sum(a, b):&lt;br /&gt;...     return a + b&lt;br /&gt;...&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; sum(10,5)&lt;br /&gt;'f'&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Decorators, like everything else in Python, are objects, so we can do more interesting things with them. For example we can pass arguments inside decorator to specify our output more precisely.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;What are the possible real world situations where you might use decorators?  Let's suppose you're developing a multithreaded application and you need an elegant way to mutually exclude the execution of some functions that run in separate threads. What you want to achieve is basically serialization of two or more functions, i.e. we must prevent starting of other functions when any other is already running. To accomplish this, you can use Python's built in reentrant lock object (&lt;code&gt;threading.RLock&lt;/code&gt;) inside of decorator to prevent concurrent execution.and queue object (&lt;code&gt;collections.Queue&lt;/code&gt;) to remember what functions (or transactions) must be executed after lock is released.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Good starting point to learn more about decorators is &lt;a href="http://www.python.org/dev/peps/pep-0318/"&gt;PEP 318&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-221868441726850930?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/221868441726850930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=221868441726850930' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/221868441726850930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/221868441726850930'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/03/python-decorators-demistified.html' title='Python decorators demystified'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-7663892176251129997</id><published>2008-03-15T12:20:00.002+01:00</published><updated>2008-03-15T13:15:56.317+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smp'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>irqbalance</title><content type='html'>&lt;div style="text-align: justify;"&gt;Distributing interrupt requests (IRQs) to multiple cores/processors in symmetric multiprocessing system (SMP) may be of great value in high-load situations. You may notice that your Linux SMP  kernel acts somewhat strange regarding the interrupts if you look at file &lt;code&gt;/proc/interrupts&lt;/code&gt;. Here is a situation on my laptop (dual core T5500):&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;           CPU0       CPU1     &lt;br /&gt; 0:     686825          7   IO-APIC-edge      timer&lt;br /&gt; 1:       4884          0   IO-APIC-edge      i8042&lt;br /&gt; 8:          0          0   IO-APIC-edge      rtc&lt;br /&gt; 9:       4451          0   IO-APIC-fasteoi   acpi&lt;br /&gt;12:     221600          0   IO-APIC-edge      i8042&lt;br /&gt;14:      50215          0   IO-APIC-edge      ide0&lt;br /&gt;20:          1          0   IO-APIC-fasteoi   uhci_hcd:usb1, yenta, i915@pci:0000:00:02.0&lt;br /&gt;21:     272763          4   IO-APIC-fasteoi   uhci_hcd:usb2, HDA Intel, ipw3945&lt;br /&gt;22:          0          0   IO-APIC-fasteoi   uhci_hcd:usb3&lt;br /&gt;23:          0          0   IO-APIC-fasteoi   uhci_hcd:usb4, ehci_hcd:usb5&lt;br /&gt;218:          2          0   PCI-MSI-edge      eth0&lt;br /&gt;219:      34668          0   PCI-MSI-edge      ahci&lt;br /&gt;NMI:          0          0&lt;br /&gt;LOC:      69271     348478&lt;br /&gt;ERR:          0&lt;br /&gt;MIS:          0&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;As you can see, all interrupts are being handled by only one core. To distribute IRQs evenly on all cores, we can use userspace daemon irqbalance. After I've installed irqbalance, 10 minutes later I've checked &lt;code&gt;/proc/interrupts&lt;/code&gt; again, and here are the results:&lt;pre&gt;&lt;br /&gt;           CPU0       CPU1      &lt;br /&gt;  0:     956615          7   IO-APIC-edge      timer&lt;br /&gt;  1:       7535       1560   IO-APIC-edge      i8042&lt;br /&gt;  8:          0          0   IO-APIC-edge      rtc&lt;br /&gt;  9:       5835          0   IO-APIC-fasteoi   acpi&lt;br /&gt; 12:     294198       8756   IO-APIC-edge      i8042&lt;br /&gt; 14:      68017          0   IO-APIC-edge      ide0&lt;br /&gt; 20:          1          0   IO-APIC-fasteoi   uhci_hcd:usb1, yenta, i915@pci:0000:00:02.0&lt;br /&gt; 21:     343158          4   IO-APIC-fasteoi   uhci_hcd:usb2, HDA Intel, ipw3945&lt;br /&gt; 22:          0          0   IO-APIC-fasteoi   uhci_hcd:usb3&lt;br /&gt; 23:          0          0   IO-APIC-fasteoi   uhci_hcd:usb4, ehci_hcd:usb5&lt;br /&gt;218:          2          0   PCI-MSI-edge      eth0&lt;br /&gt;219:      38105       3852   PCI-MSI-edge      ahci&lt;br /&gt;NMI:          0          0&lt;br /&gt;LOC:      86112     469976&lt;br /&gt;ERR:          0&lt;br /&gt;MIS:          0&lt;br /&gt;&lt;/pre&gt;Obviously it works ;). Now just to find some methods to do some measurements... maybe to run openssl speed to get one core to 100% and then try to copy some large files...?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-7663892176251129997?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/7663892176251129997/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=7663892176251129997' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/7663892176251129997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/7663892176251129997'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/03/irqbalance.html' title='irqbalance'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-4166115917968537505</id><published>2008-02-28T19:38:00.004+01:00</published><updated>2008-02-28T19:57:06.878+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='file sharing'/><title type='text'>File sharing using Python</title><content type='html'>&lt;div style="text-align: justify;"&gt;Suppose this very common situation: you have two machines, A and B. You have some files on A and you want to transfer those files to B. Let's assume you don't have ftp server, samba, nfs or anything similar which could make this operation trivial. If talking about home/desktop computers, this is a most common situation.&lt;br /&gt;&lt;br /&gt;Although it's possible to transfer files by using scp/sftp, netcat or something else, today I saw a very cool trick which comes handy in such situations. All you need is Python.&lt;br /&gt;&lt;br /&gt;First, change your current working directory to the directory that holds files you want to share. Then, just run this command:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;python -c "import SimpleHTTPServer;SimpleHTTPServer.test()"&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;This will run web server or port 8000 which you can use to browse and download files, on a similar way like using file://directory in your favorite browser or viewing web pages without index.html. When you are done, just press CTRL+C.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-4166115917968537505?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/4166115917968537505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=4166115917968537505' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/4166115917968537505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/4166115917968537505'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/02/file-sharing-using-python.html' title='File sharing using Python'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-2016419553704379499</id><published>2008-02-26T21:21:00.002+01:00</published><updated>2008-02-26T21:42:15.362+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Python completion</title><content type='html'>If you want completion in Python console, just execute these two lines:&lt;br /&gt;&lt;pre&gt;import readline, rlcompleter&lt;br /&gt;readline.parse_and_bind("tab: complete")&lt;br /&gt;&lt;/pre&gt;Now completion works just like in bash. You could also set any other key than tab, but most will want exactly this.&lt;br /&gt;&lt;br /&gt;If you want this to run automatically every time you run the python console, add those two lines to any file, for example into &lt;code&gt;.pythonrc&lt;/code&gt; in your &lt;code&gt;$HOME&lt;/code&gt;, and then set environment variable &lt;code&gt;PYTHONSTARTUP&lt;/code&gt; in shell startup scripts (&lt;code&gt;~/.bashrc&lt;/code&gt;, &lt;code&gt;~/.zshrc&lt;/code&gt; etc) to point to that file:&lt;br /&gt;&lt;pre&gt;export PYTHONSTARTUP=$HOME/.pythonrc"&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-2016419553704379499?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/2016419553704379499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=2016419553704379499' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/2016419553704379499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/2016419553704379499'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/02/python-completion.html' title='Python completion'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-1411093965966326471</id><published>2008-02-24T10:49:00.004+01:00</published><updated>2008-02-24T11:47:02.463+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='floss'/><title type='text'>Linux software that sux</title><content type='html'>&lt;span style="font-weight: bold;"&gt;1. Evolution&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you have used it long enough, chances that you haven't seen "xyz does not match even after sync" message is minimal. It's big, bloated and slow application full of bugs. Sadly, there is no graphical MUA on Linux that satisfies me. OK, Sylpheed is close enough, but some of it's interface and functionality is awkward and broken.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. OpenOffice&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Good for writing small documents, 50 pages at most. I wrote my diploma thesis in OOo and it was a painful experience. The funniest thing was when I tried to turn the changes tracking on document with 70 pages. After I have made some changes, I noticed that disk I/O indicator on my laptop is constantly turned on. A minute later, the only thing I could have done was to press the power switch. Apparently, OOo ate all of my memory (1 GB of physical RAM + 1 GB of swap), just to track few changes. I usually don't have praises for Microsoft's products, but Microsoft Office is miles in front of OOo, and it will probably stay so for a long time.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. Dia&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Related to previous rant on OOo, there is Dia. There are simply no words to describe the difference between Dia and Visio, Visio is better for several orders of magnitude. Dia's functionality is broken and it's symbols are just ugly. Many common symbols can't even be found in Dia.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4. KDE&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;I really don't see what is so cool with KDE. It's slow, most of it's applications are pointless, uses too many libraries so when I use apt-get to update the system I always need some new KDE libraries, it looks too baroque, uses stupid K* names for applications, imitates features from other GUIs instead of focusing on developing new ones etc. There are dozens more reasons not to use KDE. I stick to lesser evil (GNOME) simply because I'm too lazy and don't have time to configure fvwm. Hopefully I will do that one day and get rid of KDE/GNOME junk forever.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;5. Rhythmbox, Amarok, etc.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;What's the point of having a music player which uses RDBMS?!? I have 20 GB of mp3 songs and I still don't have need to use a DBMS to organize my music or find a specific song! For that purpose I systematically save my music using the filesystem hierarchy, and that's enough!. Both Amarok and Rhythmbox use idiotic interface, use fat too much memory and CPU and try to be smarter than it's user (automatic album cover downloading, song rating... come on!). I'm fan of Winamp/XMMS style of programs, but unfortunately it seems that XMMS has stuck in development (still using ugly GTK 1.x). Recently I've discovered &lt;a href="http://audacious-media-player.org"&gt;audacious&lt;/a&gt;, the XMMS fork - it looks nice and has nice plugins. I'll give it a chance, it looks promising.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-1411093965966326471?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/1411093965966326471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=1411093965966326471' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/1411093965966326471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/1411093965966326471'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/02/linux-software-that-sux.html' title='Linux software that sux'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-8190439909902077001</id><published>2008-01-10T18:46:00.000+01:00</published><updated>2008-01-10T19:41:19.671+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='laptop'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='ibm'/><title type='text'>IBM ACPI</title><content type='html'>&lt;div style="text-align: justify;"&gt;Nice thing with IBM Thinkpad (now Lenovo) laptops is ibm-acpi linux kernel module. You can access many sensors and laptop properties by simply reading and writing files in &lt;code&gt;/proc/acpi/ibm&lt;/code&gt;. For example, you can turn the thinklight on the top of the laptop on/off with:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;echo on &amp;gt; /proc/acpi/ibm/light&lt;br /&gt;echo off &amp;gt; /proc/acpi/ibm/light&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;For commands that specific file accepts, just display it with cat. Very interesting file is &lt;span style="font-style: italic;"&gt;thermal,&lt;/span&gt; which displays temperatures read from sensors scattered all over your laptop. You can also see/set fan speed with file &lt;span style="font-style: italic;"&gt;fan.&lt;/span&gt; Here is a perl script I wrote for quickly displaying laptop temperatures and fan speed. Please note that number of temperatures displayed in &lt;span style="font-style: italic;"&gt;thermal&lt;/span&gt; file changed in linux kernel 2.6.18, so before running this script make sure you have the newest kernel and loaded ibm-acpi module.&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;# (C) 2007 Igor Pozgaj&lt;br /&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;open (IF, "&amp;lt;/proc/acpi/ibm/thermal") or die "No ibm-acpi module found";&lt;br /&gt;close(IF);&lt;br /&gt;my %t = (&lt;br /&gt;   "CPU"  =&gt; $values[1],   # CPU&lt;br /&gt;   "PCI"  =&gt; $values[2],   # Mini-PCI&lt;br /&gt;   "HDD"  =&gt; $values[3],   # Internal hard disk&lt;br /&gt;   "BAT1" =&gt; $values[5],   # main battery, primary sensor (under F5)&lt;br /&gt;   "BAT2" =&gt; $values[7],   # main battery, secondary sensor (under Home)&lt;br /&gt;   "MCH"  =&gt; $values[9],   # northbridge, to DRAM bus (above track point)&lt;br /&gt;   "ICH"  =&gt; $values[10],  # southbridge (under touchpad)&lt;br /&gt;   "PWR"  =&gt; $values[11],  # power regulator (under F2 key)&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;open(IF, "&amp;lt;/proc/acpi/ibm/fan") or die "No ibm-acpi module found";&lt;br /&gt;my $fan = (split(/:\s+/, $line[0]))[1];&lt;br /&gt;close(IF);&lt;br /&gt;&lt;br /&gt;write;&lt;br /&gt;&lt;br /&gt;format STDOUT_TOP=&lt;br /&gt;                         Thermal data for IBM&lt;br /&gt;&lt;br /&gt; CPU     PCI     HDD    BAT1    BAT2     MCH     ICH     PWR      FAN&lt;br /&gt;--------------------------------------------------------------------------&lt;br /&gt;.&lt;br /&gt;&lt;br /&gt;format STDOUT=&lt;br /&gt;@## °C  @## °C  @## °C  @## °C  @## °C  @## °C  @## °C  @## °C  @#### rpm&lt;br /&gt;$t{"CPU"}, $t{"PCI"}, $t{"HDD"}, $t{"BAT1"}, $t{"BAT2"}, $t{"MCH"}, $t{"ICH"}, $t{"PWR"}, $fan&lt;br /&gt;.&lt;br /&gt;&lt;/if&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-8190439909902077001?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/8190439909902077001/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=8190439909902077001' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/8190439909902077001'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/8190439909902077001'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/01/ibm-acpi.html' title='IBM ACPI'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-4803598517039424222</id><published>2008-01-08T19:41:00.000+01:00</published><updated>2008-01-08T19:49:16.613+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='databases'/><category scheme='http://www.blogger.com/atom/ns#' term='psql'/><category scheme='http://www.blogger.com/atom/ns#' term='oracle'/><title type='text'>Queuing in PostgreSQL</title><content type='html'>&lt;div style="text-align: justify;"&gt;PostgreSQL is a great DBMS and I use it almost exclusively for all of my projects where I need database. But, let's face the facts, it still lacks many features to compete with big players in enterprise scale applications area, such as Oracle and DB2. On my current job, my role is Unix administration and database administration, so I'm more or less familiar with Oracle which I use the most. There are far too many features in Oracle that PostgreSQL doesn't have. Notable examples are RMAN (backup and restore tool), ASM (automatic storage management), AWR (automatic workload repository), EM (enterprise manager) etc.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;But let's return to the theme noted in article title. As part of my diploma thesis I'm developing application which needs some sort of queuing in database. I have a table "events" and I would like to have another table which would serve as a queue for application (if you are curious, it's event table from Snort database). Queue table should be populated at the same time as events table, but it should return rows in FIFO (First In First Out) principle and remove rows immediately after they have been fetched. Oracle has such functionality by default, it's AQ (Advanced Queuing) package, but in PostgreSQL you must implement it by yourself. As this is very common feature needed by developers, it would be very nice to see it in next major release of PostgreSQL.&lt;br /&gt;&lt;br /&gt;Obvious access is to use triggers with an additional table. So, we have two tables, event and event_queue. We define queue table like this:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;CREATE TABLE event_queue&lt;br /&gt;(&lt;br /&gt;   id        SERIAL PRIMARY KEY,&lt;br /&gt;   signature INTEGER NOT NULL&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Now, we must insert data into this table every time when base table (event) gets new rows. We use trigger and trigger function:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;CREATE FUNCTION put_event() RETURNS TRIGGER AS $$&lt;br /&gt;BEGIN&lt;br /&gt;   INSERT INTO event_queue VALUES (NEW.signature);&lt;br /&gt;   RETURN NULL;&lt;br /&gt;END;&lt;br /&gt;$$ LANGUAGE plpgsql;&lt;br /&gt;&lt;br /&gt;CREATE TRIGGER insert_event AFTER INSERT ON event&lt;br /&gt;   FOR EACH ROW EXECUTE PROCEDURE put_event();&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Now, there are two solutions for reading from queue. You could either write select by yourself (with ORDER BY id and LIMIT 1) and write another trigger which will delete row after it has been read, or you could write specialized function like this:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;CREATE FUNCTION get_event() RETURNS INTEGER AS $$&lt;br /&gt;DECLARE&lt;br /&gt;   v_sig INTEGER;&lt;br /&gt;BEGIN&lt;br /&gt;   SELECT sig INTO v_sig FROM event_queue ORDER BY id LIMIT 1;&lt;br /&gt;   DELETE FROM event_queue WHERE sig = v_sig;&lt;br /&gt;   RETURN v_sig;&lt;br /&gt;END;&lt;br /&gt;$$ LANGUAGE plpgsql;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-4803598517039424222?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/4803598517039424222/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=4803598517039424222' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/4803598517039424222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/4803598517039424222'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2008/01/queuing-in-postgresql.html' title='Queuing in PostgreSQL'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-3108871705715562604</id><published>2007-12-27T21:42:00.000+01:00</published><updated>2007-12-27T22:19:59.990+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vim'/><title type='text'>10 cool vim tips</title><content type='html'>&lt;span style="font-weight: bold;"&gt;1. Search for a word under the cursor&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Very usefull command, but most of the people use "/" to search and then search next with "n". It's enough just to position to a word and use "*" to search forward and "#" to search backward.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. ROT13 whole file&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Type "ggg?G"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. Increment/decrement number under the cursor&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Use the CTRL-a and CTRL-x key combinations.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4. Remote file editing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You can start vim like this: vim scp://username@host//path/to/file&lt;br /&gt;&lt;br /&gt;Beware, paths are absolute!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;5. Open file under the cursor&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Type "gf". This will open the file with filename as word under the cursor.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;6. Upercase/lowercase whole line&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Use "ggU" for uppercase and "ggu" for lowercase conversion.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;7. Macros&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Type "qx" where "x" is an arbitrary letter (register). Use editor as you usually do and then type "q" again to finish recording. You can call your recorded macro with "@x", or you can repeat last called macro with "@@".&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;8. ASCII code of character under the cursor&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Type "ga"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;9. File specific settings&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It's possible to give vim command inside of comments in a file. For examples, to set tab stop to four characters in a C++ source file, you could enter // vim: set ts=4. Next time you open the file, tab stop will be four characters no matter on contents of local or global vimrc.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;10. Paste output of a command&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Most of the people use :r!&lt;span style="font-style: italic;"&gt;command&lt;/span&gt;, but it is much easier to use !!&lt;span style="font-style: italic;"&gt;command&lt;/span&gt;. For example, !!ls&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-3108871705715562604?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/3108871705715562604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=3108871705715562604' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/3108871705715562604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/3108871705715562604'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2007/12/10-cool-vim-tips.html' title='10 cool vim tips'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-312686536329910125</id><published>2007-12-04T20:15:00.000+01:00</published><updated>2007-12-04T20:48:51.770+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='qemu'/><category scheme='http://www.blogger.com/atom/ns#' term='virtualization'/><category scheme='http://www.blogger.com/atom/ns#' term='vmware'/><title type='text'>VMware 2.0</title><content type='html'>&lt;div style="text-align: justify;"&gt;I've completely abandoned &lt;a href="http://www.vmware.com/"&gt;VMware&lt;/a&gt; as a virtualization solution on my PC and switched to &lt;a href="http://fabrice.bellard.free.fr/qemu/"&gt;QEMU&lt;/a&gt;. QEMU has much more features than VMware, it can virtualize many more platforms than only IA32 and IA64, has better networking options, user mode networking, port forwarding, can have console output on host OS tty, runs pretty fast with kqemu module loaded into kernel etc. There is also nice GUI for QEMU, called &lt;a href="https://gna.org/projects/qemulaunch/"&gt;qemu-launcher&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Two weeks ago &lt;a href="http://www.vmware.com/beta/server/"&gt;VMware 2.0 beta&lt;/a&gt; was released and I was really disappointed. Good old VMware console is apparently completely abandoned, and instead of it you are forced to use completely idiotic and slow web based administration console. Just to mention, the interface uses Apache and Tomcat, and it takes much of RAM that could be used better by guests. OK, it now supports up to 8 GB of RAM per guest OS, it has USB 2.0 support, full 64 bit support, you can run Vista as guest OS :), but for average home user, it's too bloated and slow. With other virtualization products such as QEMU, &lt;a href="http://www.citrixxenserver.com/Pages/default.aspx"&gt;Xen&lt;/a&gt; and &lt;a href="http://openvz.org/"&gt;OpenVZ&lt;/a&gt;, I won't miss VMware.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-312686536329910125?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/312686536329910125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=312686536329910125' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/312686536329910125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/312686536329910125'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2007/12/vmware-20.html' title='VMware 2.0'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-8127577758675582221</id><published>2007-10-10T20:56:00.000+02:00</published><updated>2007-10-10T21:29:48.567+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='backup'/><title type='text'>Disk Archive (dar)</title><content type='html'>&lt;div style="text-align: justify;"&gt;The best GNU program I've seen in the last month, maybe even in the last year is definitely &lt;a href="http://dar.linux.free.fr/"&gt;dar&lt;/a&gt;. I found out for this masterpiece on &lt;a href="http://blog.dkorunic.net"&gt;Dinko's blog&lt;/a&gt;, and after spending an hour on playing with it I was really impressed.&lt;br /&gt;&lt;br /&gt;Dar maybe lacks fancy GUI, database repository or live boot image like popular &lt;a href="http://www.bacula.org"&gt;bacula&lt;/a&gt; or &lt;a href="http://www.mondorescue.org"&gt;mondo&lt;/a&gt;, but who wants such applications for everyday home use? Dar is simple but powerful CLI tool for backup. It doesn't use dozen of other tools and libraries, apt-get said I need only two packages - the dar itself and one additional library. No database is needed, but if you need some kind of backup repository dar can make one in a single (binary) file which is managed by program dar_manager. Possibilities of this tool are enormous, just check the man page or &lt;a href="http://dar.linux.free.fr/doc/Features.html"&gt;features list&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;I use dar for regular full and incremental backups of /home and /etc directories. Following are the commands I use for backup and saving the information to dar repository.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Full backup of /home:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;dar -c /opt/backups/archives/home-full-`date +'%d%m%Y'` -z -R /home/ipozgaj -D -P .liferea/cache -P .mozilla/firefox/h48ywliv.default/Cache -P .pan2/article-cache -P .azureus/Documents&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Incremental backup of /home:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;dar -A /opt/backups/archives/home-full-07102007.1.dar -c /opt/backups/archives/home-diff-`date +'%d%m%Y'` -z -R /home/ipozgaj -D -P .liferea/cache -P .mozilla/firefox/h48ywliv.default/Cache -P .pan2/article-cache -P .azureus/Documents&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;If you're planning to use repository, you can initialize it like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;dar_manager -C /opt/backups/repository&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Adding archive to repository is simple:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;dar_manager -A /opt/archives/home-full-07102007.1.dar -B /opt/backups/repository&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;You can list the contents of repository with:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;dar_manager -l -B /opt/backups/repository&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;or you can start the interactive session with:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;dar_manager -B /opt/backups/repository -i&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-8127577758675582221?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/8127577758675582221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=8127577758675582221' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/8127577758675582221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/8127577758675582221'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2007/10/disk-archive-dar.html' title='Disk Archive (dar)'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-3177685156711676663</id><published>2007-09-04T18:57:00.000+02:00</published><updated>2007-09-04T19:49:53.372+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='databases'/><category scheme='http://www.blogger.com/atom/ns#' term='oracle'/><title type='text'>Oracle XE</title><content type='html'>&lt;div style="text-align: justify;"&gt;This month I'm attending &lt;a href="http://www.oracle.com"&gt;Oracle&lt;/a&gt; seminars (preparatory &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getCourseDesc?dc=D17090GC30"&gt;DBA I&lt;/a&gt; and &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/show_desc.redirect?dc=D17312GC30&amp;p_org_id=1001&amp;amp;lang=US&amp;source_call="&gt;DBA II&lt;/a&gt; courses for &lt;a href="http://www.oracle.com/education/associate.html"&gt;OCA&lt;/a&gt; and &lt;a href="http://www.oracle.com/education/professional.html"&gt;OCP&lt;/a&gt; certificates, and Oracle Application Server Administration Workshop &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/show_desc.redirect?dc=D18771GC21&amp;amp;p_org_id=1001&amp;lang=US&amp;amp;source_call="&gt;I&lt;/a&gt; and &lt;a href="http://education.oracle.com/pls/web_prod-plq-dad/show_desc.redirect?dc=D18773GC30&amp;p_org_id=1001&amp;amp;lang=US&amp;source_call="&gt;II&lt;/a&gt;) so I decided to try &lt;a href="http://www.oracle.com/technology/xe/index.html"&gt;Oracle XE&lt;/a&gt; at home. I was familiar that installing Oracle can be real pain (I had some bad experience with installing Oracle 9i on SLES :), so I was prepared for a long battle :). Only 30 minutes later, including the time for installing the virtual machine, I had fully functional Oracle instance. Installing Oracle XE on Linux is really a simple task. Here we go:&lt;br /&gt;&lt;br /&gt;Host machine:&lt;br /&gt;Intel Core 2 Duo 2x1.67 GHz, 2 MB cache&lt;br /&gt;1 GB of physical memory&lt;br /&gt;Debian GNU/Linux (lenny)&lt;br /&gt;&lt;br /&gt;Virtual machine (Vmware):&lt;br /&gt;512 MB of physical memory&lt;br /&gt;4 GB virtual disk (1 GB for swap)&lt;br /&gt;Fedora Core 6 (Zod), minimalistic install&lt;br /&gt;&lt;br /&gt;You should download oracle-xe-universal rpm package from &lt;a href="http://www.oracle.com/technology/software/products/database/xe/index.html"&gt;here&lt;/a&gt;. Before proceeding with installing, you must install libaio, that's only lib Oracle depends on. Also, you must have at least 700MB of swap and around 1.5GB of disk space to successfully end the installation.&lt;pre&gt;$ rpm -ivh oracle-xe-univ-10.2.0.1-1.0.i386.rpm&lt;br /&gt;&lt;/pre&gt;After that, you can proceed with instalation&lt;pre&gt;$  rpm -ivh oracle-xe-univ-10.2.0.1-1.0.i386.rpm&lt;/pre&gt;System is automatically configured to run Oracle instance. One thing you must not forget is to run configure script as root:&lt;pre&gt;# /etc/init.d/oracle-xe configure&lt;br /&gt;&lt;/pre&gt;Just accept default values and remember that web interface can be accessed  on http://hostaddr:8080/apex, and remember what you have entered for system password. Now it's time to configure environment. Installation creates "oracle" user with home directory in /usr/lib/oracle/xe. If you are familiar with Oracle, first thing you will probably do is to make this directory look more like following &lt;a href="http://www.ss64.com/orasyntax/ofa.html"&gt;OFA&lt;/a&gt; guidelines:&lt;pre&gt;# ln -s /usr/lib/oracle/xe /u01&lt;br /&gt;&lt;/pre&gt;Then add the following in your .bashrc&lt;pre&gt;export ORACLE_SID=xe&lt;br /&gt;export ORACLE_BASE=/u01&lt;br /&gt;export ORACLE_HOME=$ORACLE_BASE/app/oracle/product/10.2.0/server&lt;br /&gt;export TNS_ADMIN=$ORACLE_HOME/network/admin&lt;br /&gt;export $PATH=$PATH:$ORACLE_HOME/bin&lt;br /&gt;&lt;/pre&gt;Now logout and login as oracle user and verify that you can connect to instance:&lt;pre&gt;$ sqlplus / as sysdba&lt;br /&gt;&lt;br /&gt;SQL*Plus: Release 10.2.0.1.0 - Production on Tue Sep 4 21:26:56 2007&lt;br /&gt;&lt;br /&gt;Copyright (c) 1982, 2005, Oracle.  All rights reserved.&lt;br /&gt;&lt;br /&gt;Connected to an idle instance.&lt;br /&gt;SQL&gt;&lt;br /&gt;&lt;/pre&gt;and try to run web interface. It should look like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_KGuBdI86eCM/Rt2WxSv28PI/AAAAAAAAABk/axLVpcwzLZs/s1600-h/ora_apex.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://3.bp.blogspot.com/_KGuBdI86eCM/Rt2WxSv28PI/AAAAAAAAABk/axLVpcwzLZs/s320/ora_apex.JPG" alt="" id="BLOGGER_PHOTO_ID_5106403326098338034" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-3177685156711676663?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/3177685156711676663/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=3177685156711676663' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/3177685156711676663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/3177685156711676663'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2007/09/oracle-xe.html' title='Oracle XE'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_KGuBdI86eCM/Rt2WxSv28PI/AAAAAAAAABk/axLVpcwzLZs/s72-c/ora_apex.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-6478611951190221706</id><published>2007-08-21T09:33:00.001+02:00</published><updated>2007-08-21T10:16:41.039+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gtk'/><category scheme='http://www.blogger.com/atom/ns#' term='glade'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Glade-3</title><content type='html'>&lt;div style="text-align: justify;"&gt;As &lt;a href="http://www.debian.org/"&gt;Debian&lt;/a&gt; packagers are quite careful (some would say too careful) when adopting new versions of programs, I had a chance to work with new &lt;a href="http://glade.gnome.org/"&gt;Glade&lt;/a&gt; just a few weeks ago. I must say that I'm not too impressed. Interface is even worse than in Glade-2. Single window interface is somewhat awkward when you're working on low resolution (1024x768) and with forms in size over 640x480. Previous versions were better as working form was floating over other windows, so you always had a view on whole form. Other thing that annoys me is that working form has no window decorations on it (i.e. there is no window frame, minimize, maximize and close buttons etc). You can't even manually resize working form - you must resize it by entering it's size in pixels in object inspector.&lt;br /&gt;&lt;br /&gt;Few new top level dialogs like "recent chooser" and "assistant", and new widgets are all I see better than in previous versions. Also I like that palette icons can now be reduced to text only.&lt;br /&gt;&lt;br /&gt;Altogether, there is no significant improvement in the new version of Glade. As I read on &lt;a href="http://blog.senko.net/"&gt;Senko's blog&lt;/a&gt; and his &lt;a href="http://blog.senko.net/2007/08/06/guadec-14-days-later/"&gt;Guadec report&lt;/a&gt;, libglade is to be abandoned and GtkBuilder comes to scene. I don't know if there will be some new tools for GUI design or GtkBuilder support will be added to Glade-3, but there is much space for improvement when you take a look at the current state of Glade-3. And hopefully, Debian packagers will introduce it in &lt;a href="http://www.debian.org/releases/testing/"&gt;lenny&lt;/a&gt; very soon so I can test it :-).&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-6478611951190221706?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/6478611951190221706/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=6478611951190221706' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/6478611951190221706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/6478611951190221706'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2007/08/glade-3.html' title='Glade-3'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-3726535815711467173</id><published>2007-05-27T22:01:00.000+02:00</published><updated>2007-05-27T22:14:45.020+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>Playing with chattr</title><content type='html'>&lt;div style="text-align: justify;"&gt;One thing I've noticed among my fellow Linux colleagues is that although most of them frequently use &lt;code&gt;chmod&lt;/code&gt; to set file access permissions, only a few of them use &lt;code&gt;chattr&lt;/code&gt; to set up advanced file and directory parameters. &lt;code&gt;chattr&lt;/code&gt; is a powerful command, used to set up additional parameters to file system objects in order to optimize file access speed, security, disk space utilization etc. Here is only a brief description of how you can use some of it's options to fine tune your file system.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;1. Hashed trees indexing&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;You've been using this option for sure, but you probably didn't know. You can't set it by yourself, but system applies this option automatically for every directory which contains 255 items or more. What does it do? By default, items in directory are indexed by using trees, but this technique becomes inefficient when directory contains large number of files. So, when you create a 255th item in directory, the 'I' option is applied which instructs the kernel to index directory by using the hashed trees which speeds the things up. Example:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;&lt;br /&gt;% mkdir test&lt;br /&gt;% lsattr -d test&lt;br /&gt;------------------ test&lt;br /&gt;% for i in `seq 1 254`; do touch test/file$i; done&lt;br /&gt;% lsattr -d test&lt;br /&gt;------------------ test&lt;br /&gt;% touch test/file255&lt;br /&gt;% lsattr -d test&lt;br /&gt;--------------I--- test&lt;/pre&gt;&lt;br /&gt;2. Immutable files&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;You can use this option to lock files for deleting, editing, appending, renaming or being linked. You can even protect your files so root can't delete them, for example if you hold some of your files in /tmp because of quotas on your home directory. You can also use it to lock files for which you are sure that will never change, for example some files from the &lt;code&gt;/etc&lt;/code&gt; directory. Using this you can harden your system and protect it from malicious processes that want to modify system files. Note that all this doesn't really prevents root (more precisely, any user possessing the &lt;code&gt;CAP_LINUX_IMMUTABLE&lt;/code&gt; option) from removing the 'i' option from  file system object and then modifying/deleting it, but it will protect you from evil &lt;code&gt;rm -rf&lt;/code&gt; commands and it will come handy when you want to prevent creation of new files in a directory. Example:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;&lt;br /&gt;# whoami&lt;br /&gt;root&lt;br /&gt;# id -gn&lt;br /&gt;root&lt;br /&gt;# touch test&lt;br /&gt;# chattr +i test&lt;br /&gt;# rm -f test&lt;br /&gt;rm: cannot remove `test': Operation not permitted&lt;br /&gt;# chattr -i test&lt;br /&gt;# rm test&lt;br /&gt;rm: remove regular empty file `test'?&lt;br /&gt;# rm -f test&lt;br /&gt;&lt;/pre&gt;or&lt;pre&gt;&lt;br /&gt;# mkdir test&lt;br /&gt;# chattr +i test&lt;br /&gt;# touch test/file&lt;br /&gt;touch: cannot touch `test/file': Permission denied&lt;/pre&gt;&lt;br /&gt;3. File compression&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;When your disk space is low, it's time for compression or deleting. Instead of manually compressing and decompressing your files, you can instruct kernel to do it for use. Compressing and uncompressing is fully transparent, you can work with your files as they are not compressed at all. Just apply the 'c' option to file or directory and watch your free space. Note that this is not yet implemented in ext2 and ext file systems.&lt;br /&gt;&lt;br /&gt;You can find more details and other interesting options in chattr(1) and lsattr(1).&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-3726535815711467173?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/3726535815711467173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=3726535815711467173' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/3726535815711467173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/3726535815711467173'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2007/05/playing-with-chattr.html' title='Playing with chattr'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-8162989514419618715</id><published>2007-05-13T23:19:00.000+02:00</published><updated>2007-05-13T23:35:49.881+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Speed up your build with multi core CPUs</title><content type='html'>Multi core CPUs are becomming de facto standard today, but unfortunately most people don't know how to take advantage of multiple cores on even the most basic everyday operations. For example, dual core can speed up your code build process a lot if you pass the -j option to make, followed by the number of parallel jobs to run. I tested this option on a larger project that usually compiles in 5 minutes on my dual core T5500. I got best results with -j 4, that is four build jobs in parallel. Code now compiles in less than 2 minutes. Ofcourse, if your makefile is written in a way that no sources can be built in parallel, you won't see any improvement by using -j option, but this is less likey on any larger project.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-8162989514419618715?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/8162989514419618715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=8162989514419618715' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/8162989514419618715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/8162989514419618715'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2007/05/speed-up-your-build-with-multi-core.html' title='Speed up your build with multi core CPUs'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-2854679023485897111</id><published>2007-04-01T21:35:00.001+02:00</published><updated>2007-04-01T21:59:44.333+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>MS Office COM components</title><content type='html'>&lt;div style="text-align: justify;"&gt;This article may help you if you get into the same problems I had this week... I had to develop a .NET program which will load some Microsoft Word Documents, change some text in that documents, and then save them into PDF. As Word 2007 has "Save As PDF" option, the obvious way to do this was to use "Microsoft Word 12" COM component (for some reason, MS Office .NET components are less powerful than COM components, and everyone suggests using the COM).&lt;br /&gt;&lt;br /&gt;Then, the problems began... When I tried to run the program at home, all worked perfectly. But, when I tried the same on machine on work, program mysteriously crashed with  generic COMException or SOHException when I tried to run SearchAndReplace command. After spending few hours on Google trying to find what's wrong, I finally found out what's happening.&lt;br /&gt;&lt;br /&gt;This problem appears when you have multiple versions of Microsoft Office on your computer, or when you had an older version and then installed a new one. Some objects from Word 2007 have same name as objects from, for example, Excel 2003. So, solution for this problem is: you may either reregister components you use when you start the program (not recomended), or you can replace the following code:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;&lt;br /&gt;public void SearchReplace(string originalText, string replacementText)&lt;br /&gt;{&lt;br /&gt;  object replaceAll = Word.WdReplace.wdReplaceAll;&lt;br /&gt;&lt;br /&gt;  WordApplication.Selection.Find.ClearFormatting();&lt;br /&gt;  WordApplication.Selection.Find.Text = originalText;&lt;br /&gt;&lt;br /&gt;  WordApplication.Selection.Find.Replacement.ClearFormatting();&lt;br /&gt;  WordApplication.Selection.Find.Replacement.Text = replacementText;&lt;br /&gt;&lt;br /&gt;  WordApplication.Selection.Find.Execute(ref missing, ref missing,&lt;br /&gt;      ref missing, ref missing, ref missing, ref missing, ref missing,&lt;br /&gt;      ref missing, ref missing, ref missing, ref replaceAll, ref missing,&lt;br /&gt;      ref missing, ref missing, ref missing);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;with a variant that uses the late binding technique:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void SearchAndReplace(string originalText, string replacementText)&lt;br /&gt;{&lt;br /&gt;  object srcText = originalText;&lt;br /&gt;  object dstText = replacementText;&lt;br /&gt;  object[] parameters = new object[15];&lt;br /&gt;  object findObject = WordApplication.Selection.Find;&lt;br /&gt;   &lt;br /&gt;  parameters[0] = srcText;&lt;br /&gt;  parameters[1] = missing;&lt;br /&gt;  parameters[2] = missing;&lt;br /&gt;  parameters[3] = missing;&lt;br /&gt;  parameters[4] = missing;&lt;br /&gt;  parameters[5] = missing;&lt;br /&gt;  parameters[6] = missing;&lt;br /&gt;  parameters[7] = missing;&lt;br /&gt;  parameters[8] = missing;&lt;br /&gt;  parameters[9] = dstText;&lt;br /&gt;  parameters[10] = Word.WdReplace.wdReplaceAll;&lt;br /&gt;  parameters[11] = missing;&lt;br /&gt;  parameters[12] = missing;&lt;br /&gt;  parameters[13] = missing;&lt;br /&gt;  parameters[14] = missing;&lt;br /&gt;&lt;br /&gt;  findObject.GetType().InvokeMember("Execute", BindingFlags.InvokeMethod,&lt;br /&gt;      null, findObject, parameters);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-2854679023485897111?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/2854679023485897111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=2854679023485897111' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/2854679023485897111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/2854679023485897111'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2007/04/ms-office-com-components_01.html' title='MS Office COM components'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-5089510033372073599</id><published>2007-03-01T23:51:00.000+01:00</published><updated>2007-03-02T00:34:57.591+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtualization'/><title type='text'>Virtual PC 2007 sucks</title><content type='html'>&lt;div style="text-align: justify;"&gt;I've been playing with &lt;a href="http://www.microsoft.com/windows/virtualpc/default.mspx"&gt;Microsoft Virtual PC 2oo7&lt;/a&gt; since it was first published, and today I finally decided to get rid of that crap. Compared to other virtualization software that I tried, like &lt;a href="http://www.vmware.com"&gt;VMware&lt;/a&gt; or &lt;a href="http://www.cl.cam.ac.uk/research/srg/netos/xen/"&gt;XEN,&lt;/a&gt; Virtual PC is just a toy, not suitable for anything more than the simplest tasks. Virtual PC on production servers - oh give me a break :). Although it didn't crash a single time, the performance was simply awful. All that culminated today. I only needed a simple Ubuntu installation so I could test SELinux before I could deploy it on real server, and that simple task became a nightmare. Installation took me more than an hour (lately I did exactly the same installation on VMware - for only 15 minutes!). System was operating very slow, and every two or three minutes it was totally blocked for few seconds. High I/O systems are area where Virtual PC fails on it's knees - don't even bother trying this.&lt;br /&gt;&lt;br /&gt;After I've  lost my nerves with Virtual PC (dang, it's enough that I must do this on Windows instead of Linux, and now this!) , I returned to good old VMWare, where everything works as one would expect. It's hard to believe that a virtualization software can run so slowly on a brand new hardware (Core2Duo 2x1.7 GHz, 1GB DDR2 etc). When you look at Microsoft's latest products like &lt;a href="http://www.microsoft.com/windows/products/windowsvista/default.mspx"&gt;Vista&lt;/a&gt; or Virtual PC 2007, you suddenly start  to appreciate the fact that there are good alternatives to that crippleware - software that turns your new hardware to useless heap of plastic and metal. Avoid it if you can, it saves you money, and what is more important, it saves your nerves - priceless.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-5089510033372073599?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/5089510033372073599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=5089510033372073599' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/5089510033372073599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/5089510033372073599'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2007/03/virtual-pc-2007-sucks.html' title='Virtual PC 2007 sucks'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-6339240717295578439</id><published>2007-02-03T23:29:00.000+01:00</published><updated>2007-02-04T00:22:07.218+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='notebook'/><title type='text'>IBM - works as expected</title><content type='html'>After a long time I've finally decided to replace my old computer with a new one. My old computer was outdated a long time ago (PII @ 366 MHz), but it is a quite sentimental value for me as it is the first computer on which I ran Linux and learned most things I know today :).&lt;br /&gt;&lt;br /&gt;This time I made up my mind for a notebook. All I wanted was a robust machine for work, not a top model with ultra expensive video card fingerprint reader or other fancy stuff like that :). As Linux is my primary OS, I decided that it would be the best to get a HP or IBM model, as they have the best "Linux support". Ultimately, I decided for IBM as it has a reputation of being unbreakable, most of hardware has an open source driver, and I have previously worked on some IBM models so I knew what I could expect.&lt;br /&gt;&lt;br /&gt;The final choice was IBM ThinkPad R60e with Intel Core 2 Duo T5500 1.66 GHz 2MB cache, 1 GB DDR2, 100GB SATA,  etc. Most of things worked automatically on Debian Etch, only a minor tweaking was required. Things I needed to configure manually were sound card (Intel HDA), and wireless  card (Intel 3945). One more thing that didn't work, and which took me the most time after the installation was a video car (Intel GMA 950). I had to manually edit xorg.conf to use i810 driver and to turn on composite extensions with:&lt;pre&gt;Section "Extensions"&lt;br /&gt;Option "Composite" "Enable"&lt;br /&gt;EndSection&lt;/pre&gt;Then, direct rendering didn't work. Glxinfo said:&lt;pre&gt;# glxinfo | grep direct&lt;br /&gt;direct rendering: No&lt;/pre&gt;After that I installed package &lt;code&gt;libgl1-mesa-dri&lt;/code&gt;, and everything worked fine. Strange, it haven't been installed automatically, and &lt;code&gt;deborphan&lt;/code&gt; still says that package is not being used by any other.&lt;br /&gt;&lt;br /&gt;I still haven't played with this machine's native virtualization support, so I guess this will be the next thing I'll be working on. So far, I'm very pleased with this notebook - at least I didn't have problems like &lt;a href="http://ivoks.blogspot.com/2007/01/toshiba.html"&gt;Ante&lt;/a&gt; :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-6339240717295578439?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/6339240717295578439/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=6339240717295578439' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/6339240717295578439'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/6339240717295578439'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2007/02/ibm-works-as-expected.html' title='IBM - works as expected'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-7941342238451711669</id><published>2006-12-19T12:32:00.000+01:00</published><updated>2006-12-19T15:14:01.119+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Pydoc, gdb...</title><content type='html'>It's really amazing how you can use something for ages and yet miss some of the basic things. That happened to me today with &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;pydoc&lt;/span&gt;&lt;/span&gt;. Although I've been programming in Python for 4+ years I've never used &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;pydoc&lt;/span&gt;&lt;/span&gt;. Today I needed a fast way to generate documentation from several files where I had a lot of functions and classes documented by &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;docstrings&lt;/span&gt;&lt;/span&gt;. I was familiar with &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;pydoc&lt;/span&gt;&lt;/span&gt; (I knew for &lt;span style="font-weight: bold;"&gt;that&lt;/span&gt;), but what I didn't know was &lt;code&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;pydoc&lt;/span&gt;&lt;/span&gt; -p&lt;/code&gt;. You run: &lt;pre&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;pydoc&lt;/span&gt;&lt;/span&gt; -p 1234&lt;/pre&gt; in terminal which runs the web server and then open URL &lt;code&gt;http://localhost/1234&lt;/code&gt; in your favorite web browser. Fancy!&lt;br /&gt;&lt;br /&gt;This is not the first time I miss something crucial. For example, I've been using &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;gdb&lt;/span&gt;&lt;/span&gt; for 8 years, but it took me almost 5 years to find out for &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;TUI&lt;/span&gt;&lt;/span&gt;. Run &lt;pre&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;gdb&lt;/span&gt;&lt;/span&gt; -&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;tui&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt; and see if you're like me :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-7941342238451711669?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/7941342238451711669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=7941342238451711669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/7941342238451711669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/7941342238451711669'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/12/pydoc-gdb.html' title='Pydoc, gdb...'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-1386205318216331461</id><published>2006-12-12T11:39:00.000+01:00</published><updated>2006-12-12T12:00:22.679+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Graphviz</title><content type='html'>&lt;a href="http://www.graphviz.org/"&gt;Graphviz&lt;/a&gt; is open source graph visualization software. It can display simple graphs, digraphs, finite state machines (take a look on some &lt;a href="http://www.graphviz.org/Gallery.php"&gt;examples&lt;/a&gt;), write output to jpg, pdf, postscript etc. Program takes descriptions of graphs in a simple manner of text files, but wrapper libraries for several languages are also available. I tried only a Python interface, &lt;a href="http://dkbza.org/pydot.html"&gt;pydot&lt;/a&gt;, and it's amazing. This comes handy to me as I've been developing a Python graph library for a long time, and now I finally have a simple visualization tool.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-1386205318216331461?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/1386205318216331461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=1386205318216331461' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/1386205318216331461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/1386205318216331461'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/12/graphviz.html' title='Graphviz'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-7324200383712790341</id><published>2006-11-14T12:34:00.000+01:00</published><updated>2006-11-14T13:39:44.259+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='applications'/><category scheme='http://www.blogger.com/atom/ns#' term='business'/><title type='text'>Changes, changes...</title><content type='html'>First of all, sorry for &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;RSS&lt;/span&gt; problems during the last few days. As I've switched to the new blogger (beta), I was given an &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-corrected" id="SPELLING_ERROR_1"&gt;opportunity&lt;/span&gt; to give labels to the old posts, which I did and hence the problems.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.mono-projects.com/"&gt;Mono&lt;/a&gt; now supports &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;WinForms&lt;/span&gt; and .NET 2.0. Who knows what will happen on Linux desktop now - maybe we'll use dozens of good (GUI) programs from Windows that have no good alternative on Linux. As &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;Novell&lt;/span&gt; and Microsoft continue their cooperation I suspect that in the near future we can expect Microsoft's products in all major Linux distributions.&lt;br /&gt;&lt;br /&gt;I've heard a rumor that Vista would be Microsoft's last major OS upgrade, and that they will base their complete business on &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;SOA&lt;/span&gt;, web services and business applications.  Many interesting predictions come to my mind &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-corrected" id="SPELLING_ERROR_5"&gt;immediately&lt;/span&gt;. If these rumors are true, if Microsoft and &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;Novell&lt;/span&gt; would continue their cooperation, if &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;Novell&lt;/span&gt; would continue it's active support of Mono project,  then in future we can expect many great (&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;wierd&lt;/span&gt;?) things. As &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;virtualization&lt;/span&gt; techniques get better and better, I suspect that sooner or later we will see an OS with Linux kernel, which uses &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;virtualization&lt;/span&gt; (&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;Xen&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;Vmware&lt;/span&gt;, Virtual PC...) and virtual machines  (Mono) to run Microsoft's applications.&lt;br /&gt;&lt;br /&gt;Java is now also an open source product, released under the terms of the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;GPL&lt;/span&gt;. Only time will show how will this reflect to future of Java. My personal opinion is that Java is heavily bloated and broken, so I don't see how this will help to fix that . There is no point in fixing totally screwed things :).&lt;br /&gt;&lt;br /&gt;BTW, take a look at the &lt;a href="http://www.google.com/ig"&gt;personalized google homepage&lt;/a&gt;. You can make tabs, customize your search &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;results&lt;/span&gt; or add various widgets (weather forecast, clock, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;TODO&lt;/span&gt; list, calendar, inbox, news, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;sudoku&lt;/span&gt; :) and many other good stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-7324200383712790341?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/7324200383712790341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=7324200383712790341' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/7324200383712790341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/7324200383712790341'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/11/changes-changes.html' title='Changes, changes...'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-1738713307657534725</id><published>2006-11-05T22:10:00.000+01:00</published><updated>2006-11-12T21:16:32.696+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='education'/><title type='text'>MIT OpenCourseWare</title><content type='html'>Have you ever dreamed of  being an MIT student? Well, now is your chance! :)&lt;br /&gt;If you visit this &lt;a href="http://ocw.mit.edu/"&gt;link&lt;/a&gt;, you will get a full access to undergraduate and graduate courses on MIT. What you will get there are all complete lecture notes, exams, homeworks and other materials, and  what you won't get are the certificates and degrees.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-1738713307657534725?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/1738713307657534725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=1738713307657534725' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/1738713307657534725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/1738713307657534725'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/11/mit-opencourseware.html' title='MIT OpenCourseWare'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-577437294091590883</id><published>2006-11-05T15:20:00.000+01:00</published><updated>2006-11-05T16:09:29.304+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='databases'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='rdbms'/><category scheme='http://www.blogger.com/atom/ns#' term='psql'/><title type='text'>PostgreSQL? Or maybe MySQL?</title><content type='html'>About three years  ago when I had to do my first bigger job regarding the databases I faced a problem of selecting the proper RDBMS. At that time, &lt;a href="http://www.mysql.org/"&gt;MySQL&lt;/a&gt; was miles  far from features that &lt;a href="http://www.postgresql.org/"&gt;PostgreSQL&lt;/a&gt; had, so PostgreSQL was a logical choice. At that time, MySQL didn't have even most fundamental things one would expect from a serious DBMS, like subqueries, triggers, views, stored procedures, cursors, foreign keys, unions, full joins, constraints,  transactions (excluding the InnoDB) etc. Only notable advantage of MySQL over PostgreSQL was it's speed.&lt;br /&gt;&lt;br /&gt;When you compare that with today's situation (MySQL version 5.1, PostgreSQL version 8.2), much has improved. MySQL now has nearly all the features it lacked and it can be used for making &lt;span style="font-style: italic;"&gt;real&lt;/span&gt; databases, not only some simple storage systems in some backend web applications. If you want to see how these two open source applications look compared to a big enterprise scale player like &lt;a href="http://www.oracle.com/"&gt;Oracle,&lt;/a&gt; you can see a detailed analysis &lt;a href="http://www-css.fnal.gov/dsg/external/freeware/mysql-vs-pgsql.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now it seems that MySQL developers are implementing things much more faster that PostgreSQL guys. There is no big difference between these two systems anymore. Next time when I'll need a DBMS, I'll most certainly give a chance to MySQL.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-577437294091590883?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/577437294091590883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=577437294091590883' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/577437294091590883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/577437294091590883'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/11/postgresql-or-maybe-mysql.html' title='PostgreSQL? Or maybe MySQL?'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-116092342237253215</id><published>2006-10-15T15:31:00.000+02:00</published><updated>2006-11-12T20:47:51.371+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>C# 3.0 preview</title><content type='html'>Two days ago I was at presentation of new features in C# 3.0. Well, I'm not impressed at all. Most of "new" features are "borrowed" from other languages, most notably from Python. Here is a short list of new stuff:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;var keyword&lt;/li&gt;&lt;li&gt;anonymous types&lt;/li&gt;&lt;li&gt;object initializers&lt;/li&gt;&lt;li&gt;extension methods&lt;/li&gt;&lt;li&gt;lambda expressions&lt;/li&gt;&lt;li&gt;expression trees&lt;/li&gt;&lt;li&gt;query expressions&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;1. &lt;span style="font-weight: bold;"&gt;var&lt;/span&gt; keyword&lt;br /&gt;&lt;br /&gt;This keyword is used to declare a variable whose type is inferred from initializing expression. For example, this is the old way:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;int i = 1&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;and this is the new way:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var i = 1&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Obviously there are many requests to make C# look more like weakly typed language, but it nevertheless stays strongly typed, so this new syntax can lead to ridiculous and stupid syntax like:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;var  array = new[]{1, 2, 3, 4}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2. anonymous types and object initializers&lt;br /&gt;&lt;br /&gt;Nothing that we haven't seen before. You can now execute code like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;var point = new {x = 1, y = 2}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Are you familiar with this syntax from somewhere? Maybe from Python's dictionaries with named parameters? :)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;3. lambda expressions&lt;br /&gt;&lt;br /&gt;In Croatia there is a proverb "Vidjela žaba da se konj potkiva pa i ona digla nogu", that in free translation means "A frog saw that a horse is beeing calked, so she also lifted her leg". Enough said :). Syntax is also an excellent example of borrowing syntax from other languages which resulted with this silly syntax:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;func = () =&gt; Console.WriteLine("Something stinks from Redmond")&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;4. Expression trees&lt;br /&gt;&lt;br /&gt;This is a new type that allows expressions to be treated as data at runtime. System.Expressions.Expression&lt;t&gt; is simply an in-memory representation of a lambda expression.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;5. Query methods&lt;br /&gt;&lt;br /&gt;This is IMHO the only significant improvement in this version of C#. That is a new feature called &lt;span style="font-weight: bold;"&gt;LINQ &lt;/span&gt;(Language Integrated Query) which syntax is somewhat similar to SQL syntax. For example:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public class Point { public int x, y;}&lt;br /&gt;&lt;br /&gt;List&amp;lt;points&amp;gt; points = ...&lt;br /&gt;&lt;br /&gt;var result = from p in points where p.x == 1 select (p.x, p.y)&lt;br /&gt;&lt;/code&gt;&lt;/t&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-116092342237253215?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/116092342237253215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=116092342237253215' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/116092342237253215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/116092342237253215'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/10/c-30-preview.html' title='C# 3.0 preview'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115934295980072847</id><published>2006-09-27T09:17:00.000+02:00</published><updated>2006-11-12T20:54:15.528+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cms'/><category scheme='http://www.blogger.com/atom/ns#' term='wiki'/><title type='text'>The simplest wiki</title><content type='html'>I've found a link to &lt;a href="http://www.tiddlywiki.com/"&gt;tiddlywiki&lt;/a&gt; on &lt;a href="http://www.senko.net/"&gt;Senko's homepage&lt;/a&gt; and after I've tried it I must admit: it's awesome! Unlike other wiki systems, this one doesn't require any server side technology like PHP and MySQL. Tiddlywiki runs completely on client's computer - it includes HTML, CSS and JavaScript in only one file, so you can edit it offline. The only negative aspect of this is that empty template is around 180 kb (not so large when you look at all the features available), and all content goes in that file which can grow rather large over the time. A good starting point for using the tiddlywiki is this &lt;a href="http://www.blogjones.com/TiddlyWikiTutorial.html"&gt;tutorial&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115934295980072847?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115934295980072847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115934295980072847' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115934295980072847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115934295980072847'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/09/simplest-wiki.html' title='The simplest wiki'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115867652417232832</id><published>2006-09-19T16:33:00.000+02:00</published><updated>2006-11-12T20:55:33.171+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fun'/><title type='text'>Optical illusions</title><content type='html'>Check out &lt;a href="http://www.michaelbach.de/ot"&gt;this page&lt;/a&gt; with 66 various optical illusions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115867652417232832?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115867652417232832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115867652417232832' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115867652417232832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115867652417232832'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/09/optical-illusions.html' title='Optical illusions'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115572004094467519</id><published>2006-08-16T10:59:00.000+02:00</published><updated>2006-11-12T20:57:39.145+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>POSIX threads and manual pages rant</title><content type='html'>Sometimes it's very difficult to find out what's wrong with your code using only man pages. For example, look at this demonstrative piece of code:&lt;pre&gt;#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;&lt;br /&gt;pthread_mutex_t mutex;&lt;br /&gt;&lt;br /&gt;void *thread_func(void *param)&lt;br /&gt;{&lt;br /&gt;pthread_mutex_lock(&amp;mutex);&lt;br /&gt;pthread_mutex_lock(&amp;mutex);&lt;br /&gt;&lt;br /&gt;return NULL;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;pthread_t th;&lt;br /&gt;pthread_mutexattr_t attr;&lt;br /&gt;&lt;br /&gt;pthread_mutexattr_init(&amp;attr);&lt;br /&gt;pthread_mutexattr_settype(&amp;attr, PTHREAD_MUTEX_ERRORCHECK);&lt;br /&gt;pthread_mutex_init(&amp;mutex, &amp;amp;amp;amp;amp;attr);&lt;br /&gt;pthread_mutexattr_destroy(&amp;attr);&lt;br /&gt;&lt;br /&gt;pthread_create(&amp;th, NULL, thread_func, NULL);&lt;br /&gt;pthread_join(th, NULL);&lt;br /&gt;&lt;br /&gt;return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Error checking type of mutex is used to prevent deadlock (I just wanted to see if it works :). But when you try to compile the code you will probably get something like this:&lt;br /&gt;&lt;pre&gt;% gcc -g -W -Wall -lpthread foo.c                  &lt;br /&gt;foo.c:5: warning: unused parameter 'param'&lt;br /&gt;foo.c: In function 'main':&lt;br /&gt;foo.c:19: warning: implicit declaration of function 'pthread_mutexattr_settype'&lt;br /&gt;foo.c:19: error: 'PTHREAD_MUTEX_ERRORCHECK' undeclared (first use in this function)&lt;br /&gt;foo.c:19: error: (Each undeclared identifier is reported only once&lt;br /&gt;foo.c:19: error: for each function it appears in.)&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;After spending almost an hour on reading manual pages for POSIX threads, I was confused even more! This code should have worked! Then, I found an old Usenet post with solution for this problem. It seems that function &lt;code&gt;pthread_mutexattr_settype&lt;/code&gt; is relatively new addition to the Single Unix specification, so you need to compile the code with &lt;code&gt;-D_XOPEN_SOURCE=500&lt;/code&gt; which enables compatibility with UNIX98, or with -D_GNU_SOURCE which enables all extensions. Now everything worked as one would expect:&lt;br /&gt;&lt;pre&gt;% gcc -D_XOPEN_SOURCE=500 -g -W -Wall -lpthread foo.c&lt;br /&gt;foo.c:5: warning: unused parameter 'param'&lt;br /&gt;% gcc -D_GNU_SOURCE -g -W -Wall -lpthread foo.c  &lt;br /&gt;foo.c:5: warning: unused parameter 'param'&lt;br /&gt;&lt;/pre&gt;Where can I find that information? Man pages don't even say that it's UNIX98 extension!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115572004094467519?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115572004094467519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115572004094467519' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115572004094467519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115572004094467519'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/08/posix-threads-and-manual-pages-rant.html' title='POSIX threads and manual pages rant'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115506283462528532</id><published>2006-08-08T20:39:00.000+02:00</published><updated>2006-11-12T20:57:07.885+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Dictionaries again</title><content type='html'>Last time I wrote about two favelets for translating from Croatian to English and vice versa. A friend of mine went a step further and wrote a &lt;a href="http://www.mozilla.org/firefox"&gt;Firefox&lt;/a&gt; extension which basically makes the same, but now you can call the &lt;a href="http://www.eudict.com/"&gt;Eudict&lt;/a&gt; dictionary from a popup menu. You can download the extension &lt;a href="http://tigar.web.srk.fer.hr/crodict.xpi"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;BTW, &lt;a href="http://www.deviantart.com/"&gt;DeviantArt&lt;/a&gt; has released a new design, but most likely you won't see it today (heavy load).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115506283462528532?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115506283462528532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115506283462528532' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115506283462528532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115506283462528532'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/08/dictionaries-again.html' title='Dictionaries again'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115494570123929000</id><published>2006-08-07T11:51:00.000+02:00</published><updated>2006-11-12T20:58:37.614+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Favelets</title><content type='html'>Most of you probably have large number of bookmarks in your favourite web browser. Probably 99.9% of those bookmarks are simply links to some web pages. Most of people are not aware that bookmarks can hold much more than just links.&lt;br /&gt;&lt;br /&gt;What is favelet? Favelet is JavaScript code prefixed with &lt;code&gt;javascript:&lt;/code&gt; and saved as bookmark. What can it be used for? Well, suppose you are web designer, so you need to see how some page looks at 800x600. If you add this code to your bookmarks, you can view how it looks with only one click:&lt;br /&gt;&lt;br /&gt;&lt;a href="javascript:resizeTo(800, 600)"&gt;javascript:resizeTo(800, 600)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Today I made my life much simplier with two cool favelets :). I'm native croatian speaker, and I often need to look at online dictionary (I use &lt;a href="http://eudict.com/"&gt;eudict&lt;/a&gt;) for some english word. With this two favelts I automated that process to simply selecting the word and clicking on wanted favelet (I broke lines, but this must be a single line):&lt;br /&gt;&lt;br /&gt;From English to Croatian:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;javascript:x=escape(getSelection());if(!x)%7Bvoid(x=location.href)%7D;&lt;br /&gt;location.href='http://www.eudict.com/?lange=engcro&amp;word='+x+'';&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;From Croatian to English:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;javascript:x=escape(getSelection());if(!x)%7Bvoid(x=location.href)%7D;&lt;br /&gt;location.href='http://www.eudict.com/?lange=croeng&amp;word='+x+'';&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Eudict supports much more languages so you can customize favelets as you want.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115494570123929000?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115494570123929000/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115494570123929000' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115494570123929000'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115494570123929000'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/08/favelets.html' title='Favelets'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115480849813400484</id><published>2006-08-05T21:07:00.000+02:00</published><updated>2006-11-12T20:59:29.868+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Digital watermarking</title><content type='html'>As I mentioned before in one of my previous posts, lately I'm playing a lot with &lt;a href="http://www.gimp.org/"&gt;GIMP&lt;/a&gt;. It's amazing what can be done with that piece of software. Today I came to a wild idea to add a digital watermark to some of my best works. Most notable example of watermarking system is that of &lt;a href="http://www.digimarc.com/"&gt;Digimarc&lt;/a&gt; that may be found in &lt;a href="http://www.adobe.com/products/photoshop/"&gt;Adobe's Photoshop&lt;/a&gt;. After spending almost an hour on searching for an open source watermarking system, I finally gave up. &lt;a href="http://www.gimp.org/"&gt;GIMP&lt;/a&gt;, &lt;a href="http://www.imagemagick.org/"&gt;ImageMagick&lt;/a&gt; and all other open source tools for manipulating images lack such a feature. Well, &lt;a href="http://www.imagemagick.org/"&gt;ImageMagick&lt;/a&gt; actually has some kind of watermarking system, but it only handles a visible watermark, not a true digital one.&lt;br /&gt;&lt;br /&gt;Digital watermarking is a technique somewhat similar to &lt;span style="font-style: italic;"&gt;steganography&lt;/span&gt;, but again much different. Steganography is basically technique of hiding confidential data in carrier. Carrier may be any kind of binary data, but usually it's audio or image file. Digital watermarking also adds additional data to carrier, but it differs from steganography in several points:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;in steganography, carrier is irrelevant, only hidden data is important&lt;/li&gt;&lt;li&gt;in digital watermarking, both the carrier and hidden data are important&lt;br /&gt;&lt;/li&gt;&lt;li&gt;in digital watermarking, hidden information is used to authenticate the owner of carrier&lt;br /&gt;&lt;/li&gt;&lt;li&gt;digital watermarks are immune to cuts&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Last point is especially important for watermarking. If you watermark a picture, and someone selects and uses only a part of it, you can still prove that part of image is yours because watermark can be found in every part of the picture. That is the main reason why steganography can't be used for digital watermarking - it doesn't add information to every part of the carrier.&lt;br /&gt;&lt;br /&gt;I'm aware that digital watermarking systems are pretty sophisticated (and expensive!) technology and that many companies base their existence on such systems, but one would expect that there is at least one open source solution for that. At least, a most primitive one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115480849813400484?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115480849813400484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115480849813400484' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115480849813400484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115480849813400484'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/08/digital-watermarking.html' title='Digital watermarking'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115453909195723425</id><published>2006-08-02T18:07:00.000+02:00</published><updated>2006-11-12T20:59:58.874+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Design patterns in Python #1, Proxy</title><content type='html'>Back to programming related topics :) . This is the first of several articles where I'll try to explain some of design patterns using the Python programming language. Design patterns are standard approaches and solutions for some kinds of problems in software engineering. They are often being classified into several classes like architectural, structural, behavioral etc.&lt;br /&gt;&lt;br /&gt;In this article, we'll be dealing with fundamental architectural design pattern - Proxy. Proxy is a class functioning as interface to another class. Most known application for Proxy design pattern is reference counting, but it can be used in numerous other situations like defining an interface for class or hiding some parts of the base class. As object oriented model in Python does not allow to give access rights to class methods, Proxy comes very handy when you need to prevent lazy user to use your class in a wrong way.&lt;br /&gt;&lt;br /&gt;We'll build Proxy for simple class which has only two methods. Methods just print some strings.&lt;br /&gt;&lt;pre&gt;class Foo:&lt;br /&gt; def first(self):&lt;br /&gt;    print 'First method'&lt;br /&gt;&lt;br /&gt; def second(self):&lt;br /&gt;    print 'Second method'&lt;br /&gt;&lt;/pre&gt;Obviously from Proxy definition, it must pass method calls to base class. We'll initialize Proxy to point to base class in Proxy's &lt;code&gt;__init__&lt;/code&gt; method, and pass the method calls by using &lt;code&gt;__getattr__&lt;/code&gt; builtin method. This is the common code for all Proxy classes:&lt;br /&gt;&lt;pre&gt;class Proxy:&lt;br /&gt; def __init__(self, target):&lt;br /&gt;    self.target = target&lt;br /&gt;&lt;br /&gt; def __getattr__(self, attr):&lt;br /&gt;    return getattr(self.target, attr)&lt;br /&gt;&lt;/pre&gt;Next, we need to adapt this generic class to our &lt;code&gt;Foo&lt;/code&gt; class. Let's assume that we want to hide the method &lt;code&gt;second&lt;/code&gt;. The way to do it in Python is to inherit the Proxy class and override the base method with empty (&lt;code&gt;pass&lt;/code&gt;) statement:&lt;br /&gt;&lt;pre&gt;class FooProxy(Proxy):&lt;br /&gt;  def second(self):&lt;br /&gt;     pass&lt;br /&gt;&lt;/pre&gt;And finally, we'll test our new FooProxy class:&lt;br /&gt;&lt;pre&gt;&gt;&gt;&gt; f = Foo() &lt;br /&gt;&gt;&gt;&gt; f.first()&lt;br /&gt;First method&lt;br /&gt;&gt;&gt;&gt; f.second()&lt;br /&gt;Second method&lt;br /&gt;&gt;&gt;&gt; fp = FooProxy(f)&lt;br /&gt;&gt;&gt;&gt; fp.first()&lt;br /&gt;First method&lt;br /&gt;&gt;&gt;&gt; fp.second()&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/pre&gt;You may wonder why we didn't just inherit the &lt;code&gt;Foo&lt;/code&gt; class and override the &lt;code&gt;second&lt;/code&gt; method. Well, that way we would need to make some kind of copy constructor to copy data from base class and then we would have two nearly identical objects in memory, and that is not what we wanted in the first place. Proxy must serve just as mediator to base class.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115453909195723425?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115453909195723425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115453909195723425' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115453909195723425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115453909195723425'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/08/design-patterns-in-python-1-proxy.html' title='Design patterns in Python #1, Proxy'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115436818862823858</id><published>2006-07-31T17:19:00.000+02:00</published><updated>2006-11-12T21:00:52.814+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='applications'/><title type='text'>Healing brush soon to be found in Gimp!</title><content type='html'>One of the key goals that OSS must achieve to attract desktop users to Linux is to have proper substitutions for widely used application suites like Microsoft Office, Adobe Photoshop and Macromedia Dreamweaver. While &lt;a href="http://www.openoffice.org/"&gt;OpenOffice.org&lt;/a&gt; was already pretty good set of applications, more usable than that of Microsoft if you ask me, &lt;a href="http://www.gimp.org/"&gt;Gimp&lt;/a&gt; was still far behind Photoshop and there was nothing near as good as Dreamweaver.&lt;br /&gt;&lt;br /&gt;Recently, I've been playing a lot with Gimp. For sure, Gimp can now be used for most of everyday image manipulations that you can do with Photoshop. Some day ago, I saw that one of the Google Summer of Code projects is titled "Healing Brush for Gimp". Great! Lot of users who used Photoshop missed that feature in Gimp. If that is to be implemented, Gimp could really become "PS killer". As Google Summer of Code is coming to end, I am eagerly waiting to see those new Gimp features!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115436818862823858?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115436818862823858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115436818862823858' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115436818862823858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115436818862823858'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/07/healing-brush-soon-to-be-found-in-gimp.html' title='Healing brush soon to be found in Gimp!'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115402579229560871</id><published>2006-07-27T20:18:00.000+02:00</published><updated>2006-11-12T21:01:44.605+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='services'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>XMLTV</title><content type='html'>If you have a cable or satellite TV set, your biggest problem is probably to find something to watch. Finding out what's on by using only TV magazines and web pages generally sucks. Luckily, most of TV stations provide XMLTV data. XMLTV is XML like language, a common format used for tracking TV channels listings. Like all XML data, XMLTV is easily parsable and has clean syntax. For example, &lt;a href="http://www.hrt.hr/raspored/format/xmltv.xml?mreza=2&amp;amp;krat=HTV1"&gt;this&lt;/a&gt; is the XMLTV listing for first programme of Croatian national television).&lt;br /&gt;&lt;br /&gt;One of the most advanced applications for tracking XMLTV is &lt;a href="http://phazer.info/"&gt;Phazer,&lt;/a&gt; great work of Croatian author Kowac. Phazer is based completely on .NET and is available as standalone application, &lt;a href="http://phazer.info/"&gt;web application&lt;/a&gt; and web service. It includes many additional features like alarms. Try it out, you may like it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115402579229560871?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115402579229560871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115402579229560871' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115402579229560871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115402579229560871'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/07/xmltv.html' title='XMLTV'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115347262436803311</id><published>2006-07-21T10:15:00.000+02:00</published><updated>2006-11-12T21:02:44.363+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='business'/><title type='text'>Downfall of Yahoo?</title><content type='html'>Who of you still use Yahoo as primary search engine? Once Yahoo was probably the most advanced and most used search engine, but now little is left from the former fame. Suffering major market losses because of lack of innovations and incompetence to confront Google at any area, yesterday Yahoo suffered  yet another hard hit. Company's shares are down for almost 22 percent and estimated loss for shareholders is round 10.4 billion dollars. This was started by announcements that net income is down by 78 percent for the second quarter of last year and that Yahoo's new ad system won't be out till end of year.&lt;br /&gt;&lt;br /&gt;Surely nobody will make big investments in Yahoo in the near future. The time is coming where Yahoo will need to fight for it's own survival.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115347262436803311?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115347262436803311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115347262436803311' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115347262436803311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115347262436803311'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/07/downfall-of-yahoo.html' title='Downfall of Yahoo?'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115322014390504695</id><published>2006-07-18T12:41:00.000+02:00</published><updated>2006-11-12T21:03:30.806+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='applications'/><title type='text'>VIM's key features</title><content type='html'>&lt;a href="http://www.rayninfo.co.uk/vimtips.html"&gt;This&lt;/a&gt;  is probably the most complete vim's command list I've ever seen. It includes both basic key commands and the most common advanced operations, so that even the most advanced vim gurus could find some features they didn't know. Assuming you don't use that damned "Esc Meta Alt Control Shi(f)t" editor, you'll eventually have use of that page. Also, you may take a look at the &lt;a href="http://www.viemu.com/vi-vim-cheat-sheet.gif"&gt;vim's cheatsheet&lt;/a&gt; (1024 x 768 gif, nice if you want to print it and hold it near your monitor) .&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115322014390504695?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115322014390504695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115322014390504695' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115322014390504695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115322014390504695'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/07/vims-key-features.html' title='VIM&apos;s key features'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115289526521607478</id><published>2006-07-14T18:35:00.000+02:00</published><updated>2006-11-12T21:05:05.565+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fun'/><category scheme='http://www.blogger.com/atom/ns#' term='applications'/><title type='text'>Easter eggs</title><content type='html'>I found &lt;a href="http://www.eeggs.com/tree/153.html"&gt;interesting site&lt;/a&gt; with Easter Eggs collection. Here are some of my favorites :)&lt;pre&gt;&lt;br /&gt;$ apt-get moo&lt;br /&gt;      (__)&lt;br /&gt;      (oo)&lt;br /&gt;/------\/&lt;br /&gt;/ |    ||&lt;br /&gt;*  /\---/  ~~   ~~&lt;br /&gt;...."Have you mooed today?"...&lt;br /&gt;&lt;br /&gt;$ aptitude -v moo&lt;br /&gt;There really are no Easter Eggs in this program.&lt;br /&gt;$ aptitude -vv moo&lt;br /&gt;Didn't I already tell you that there are no Easter Eggs in this program?&lt;br /&gt;$ aptitude -vvv moo&lt;br /&gt;Stop it!&lt;br /&gt;$ aptitude -vvvv moo&lt;br /&gt;Okay, okay, if I give you an Easter Egg, will you go away?&lt;br /&gt;$ aptitude -vvvvv moo&lt;br /&gt;All right, you win.&lt;br /&gt;&lt;br /&gt;                            /----                     -------/                          /                                  /                |&lt;br /&gt;-----------------/                  -------- ----------------------------------------------&lt;br /&gt;&lt;br /&gt;Happy?&lt;br /&gt;$ aptitude -vvvvvv moo&lt;br /&gt;What is it?  It's an elephant being eaten by a snake, of course.&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115289526521607478?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115289526521607478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115289526521607478' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115289526521607478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115289526521607478'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/07/easter-eggs.html' title='Easter eggs'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115272183430255901</id><published>2006-07-12T18:02:00.000+02:00</published><updated>2006-11-12T21:05:35.379+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='services'/><title type='text'>Google strikes back</title><content type='html'>It seems that rants on Google in my &lt;a href="http://ipozgaj.blogspot.com/2006/06/first-disappointment-with-google.html"&gt;last post&lt;/a&gt; were a little bit harsh. I finally received the invitation and now I'm simply delighted with quality of Google Analytics - it's unbelievable what they're giving for free!&lt;br /&gt;&lt;br /&gt;In the meantime, I've decided to use &lt;a href="http://www.google.com/calendar/"&gt;Google Calendar.&lt;/a&gt; It comes handy if you need to share your calendar with other people and you want it to be available anywhere and anytime. You don't need any additional software besides your favorite web browser.&lt;br /&gt;&lt;br /&gt;At last, we come to &lt;a href="http://www.google.com/trends"&gt;Google Trends&lt;/a&gt; which displays search volume for specific keyword over the time. It's interesting to see graphs for some keywords, for example &lt;a href="http://www.google.com/trends?q=java&amp;ctab=1&amp;amp;geo=all&amp;date=all"&gt;this&lt;/a&gt; (Java) or &lt;a href="http://www.google.com/trends?q=ruby+on+rails&amp;amp;amp;ctab=1&amp;geo=all&amp;amp;date=all"&gt;this&lt;/a&gt; (Ruby on Rails).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115272183430255901?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115272183430255901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115272183430255901' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115272183430255901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115272183430255901'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/07/google-strikes-back.html' title='Google strikes back'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-115118418652912733</id><published>2006-06-24T22:48:00.000+02:00</published><updated>2006-11-12T21:06:08.846+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='services'/><title type='text'>First disappointment with Google</title><content type='html'>So far I'm very pleased with quality of &lt;a href="http://www.google.com/"&gt;Google&lt;/a&gt; services. I use &lt;a href="http://maps.google.com/"&gt;Google Maps&lt;/a&gt;, &lt;a href="http://gmail.com/"&gt;Gmail&lt;/a&gt;, &lt;a href="http://news.google.com/"&gt;Google News&lt;/a&gt; and dozen more of &lt;a href="http://www.google.com/options"&gt;Google's services&lt;/a&gt;. Lately I've been writing some scripts in &lt;a href="http://www.php.net/"&gt;PHP&lt;/a&gt; to track visits to my home page. Some day ago a friend of mine suggested me to try &lt;a href="http://www.google.com/analytics"&gt;Google Analytics&lt;/a&gt; which in essence does the same, but also displays plenty of other statistics. Unfortunately, this service requires that you wait for invitation. After I applied for the invitation, I've been waiting for that invitation for almost a week! Not a kind of behavior I would expect from Google...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-115118418652912733?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/115118418652912733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=115118418652912733' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115118418652912733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/115118418652912733'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/06/first-disappointment-with-google.html' title='First disappointment with Google'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-114902413141072561</id><published>2006-05-30T23:19:00.000+02:00</published><updated>2006-11-12T21:06:41.027+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='services'/><title type='text'>Digital maps</title><content type='html'>If you're up to Croatia (or you live there and travel a lot), you may find &lt;a href="http://www.mireo.hr/gelin"&gt;this&lt;/a&gt; link very useful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-114902413141072561?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/114902413141072561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=114902413141072561' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/114902413141072561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/114902413141072561'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/05/digital-maps.html' title='Digital maps'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-114856256200056777</id><published>2006-05-25T14:45:00.000+02:00</published><updated>2006-11-12T21:07:42.544+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Arrays features</title><content type='html'>One of the nice features that may be found in .NET CLS is &lt;code&gt;CreateInstance&lt;/code&gt; method from &lt;code&gt;Array&lt;/code&gt; class. Tired of arrays which starting index is 0 or 1? You can now make arrays with arbitrary starting index. Take the following example:&lt;pre&gt;using System;&lt;br /&gt;&lt;br /&gt;class Test&lt;br /&gt;{&lt;br /&gt; public static void Main()&lt;br /&gt; {&lt;br /&gt;   int[] bounds = {2000, 10};&lt;br /&gt;   int[] sizes = {6, 10};&lt;br /&gt;   int[,] array = (int[,])&lt;br /&gt;       Array.CreateInstance(typeof(int), bounds, sizes);&lt;br /&gt;&lt;br /&gt;   array[0,0] = 10;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;This creates two dimensional array which indexes are between 2000 - 2005 for first dimension, and 10-19 for second dimension. So, this example throws IndexOutOfRangeException when we try to access array element with index [0,0]. Change the index to [2002, 14] to get a proof that this works :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-114856256200056777?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/114856256200056777/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=114856256200056777' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/114856256200056777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/114856256200056777'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/05/arrays-features.html' title='Arrays features'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-114692028246950184</id><published>2006-05-06T14:42:00.000+02:00</published><updated>2006-11-12T21:08:08.747+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='applications'/><title type='text'>Opera bye bye</title><content type='html'>After 3+ years using the Opera web browser, today I've stopped using it. There are several reasons why I did that. First of all, Opera renders tables very bad - almost every day I see broken tables in Opera or they are not being displayed at all. Then the JavaScript support in Opera. When I compare all of the leading web browsers available (IE, Firefox and Opera), I think that JavaScript engine in Opera is most broken. You are lucky if author included only some minor scripts, but if the page contains some more complex scripts you will probably see broken page. Most obvious example for this are the pages which contain some Ajax functionality - most of them are not displayed in Opera at all. There are plenty more rants on Opera - it cannot integrate in my Linux system as much as Firefox (I prefer GTK over Qt), I don't want integrated email and Usenet client (Opera with -nomail option is not what I mean), I want the source to be opened... For all that, Opera is purged from my machine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-114692028246950184?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/114692028246950184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=114692028246950184' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/114692028246950184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/114692028246950184'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/05/opera-bye-bye.html' title='Opera bye bye'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-114522662125990309</id><published>2006-04-17T00:29:00.000+02:00</published><updated>2006-11-12T21:08:40.067+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><title type='text'>Back on the road</title><content type='html'>After almost two months without posting I've finally returned to blogging. Much changed in the meantime - most notable change is that I've finally switched from old 56k modem to broadband 512k DSL connection so I guess I'll be writing more often now :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-114522662125990309?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/114522662125990309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=114522662125990309' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/114522662125990309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/114522662125990309'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/04/back-on-road.html' title='Back on the road'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-114027062627855438</id><published>2006-02-18T14:41:00.000+01:00</published><updated>2006-11-12T21:09:12.854+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Automated testing in Python, part 1</title><content type='html'>As my work on &lt;a href="http://sourceforge.net/projects/ikev2"&gt;IKEv2 project&lt;/a&gt; continues, I made a little investigation on automated testing facilities built into the Python programming language. My job on IKEv2 was to built automated test environment for the IKE daemon. Testing scripts were written in Perl (because I didn't write it from scratch by myself, much of the code was already written - in Perl) and were completely separated from the IKE daemon code itself. I think that fact is the key of all problems I had (and still have :) during the development.&lt;br /&gt;&lt;br /&gt;When I looked at the Python's support for automated testing, I was shocked! It supports exactly what I was thinking off. The doctest module provides a very elegant way to test the code. What you need is to simply embed correct interpreter answers to the docstrings. E.g., I wrote a function which returns a list of prime factors of a number:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;import math&lt;br /&gt;import doctest&lt;br /&gt;import fact&lt;br /&gt;&lt;br /&gt;def factorize(n):&lt;br /&gt;    """&lt;br /&gt;        Returns list of number's prime factors.&lt;br /&gt;        Examples:&lt;br /&gt;        &gt;&gt;&gt; factorize(32)&lt;br /&gt;        [2, 2, 2, 2, 2]&lt;br /&gt;        &gt;&gt;&gt; factorize(1234)&lt;br /&gt;        [2, 617]&lt;br /&gt;    """&lt;br /&gt;    factors = []&lt;br /&gt;    while True:&lt;br /&gt;        found = False&lt;br /&gt;        for i in xrange(2, int(math.sqrt(n)) + 1):&lt;br /&gt;            if not n % i:&lt;br /&gt;                found = True&lt;br /&gt;                factors.append(i)&lt;br /&gt;                n = n / i&lt;br /&gt;                break&lt;br /&gt;        if not found:&lt;br /&gt;            factors.append(n)&lt;br /&gt;            return factors&lt;br /&gt;             &lt;br /&gt;                                                                                  if __name__ == '__main__":&lt;br /&gt;    doctest.testmod(fact)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Note the three important sections in the code: you need to import module that you are testing (the file is named fact.py), then insert the correct answers from the interpreter into the docstrings, and finally call doctest.testmod() method. There are two ways to run this. First, a verbose mode: just type&lt;pre&gt;&lt;br /&gt;$ python fact.py -v&lt;/pre&gt;&lt;br /&gt;(Not python -v fact.py!). It will print details during the testing process.&lt;pre&gt;&lt;br /&gt;Running fact.__doc__&lt;br /&gt;0 of 0 examples failed in fact.__doc__&lt;br /&gt;Running fact.factorize.__doc__&lt;br /&gt;Trying: factorize(1)&lt;br /&gt;Expecting: [1]&lt;br /&gt;ok&lt;br /&gt;... [cut] ...&lt;/pre&gt;&lt;br /&gt;The second way to run it is without -v switch. That will suppress any output unless some errors are found during the testing. For example, let's change line&lt;br /&gt;&lt;code&gt;&lt;br /&gt;for i in xrange(2, int(math.sqrt(n)) + 1):&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;to&lt;br /&gt;&lt;code&gt;&lt;br /&gt;for i in xrange(2, int(math.sqrt(n))):&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;which is obviously wrong. Now let's run the program again:&lt;pre&gt;&lt;br /&gt;$ python fact.py&lt;br /&gt;****************************************&lt;br /&gt;Failure in example: factorize(32)&lt;br /&gt;from line #7 of fact.factorize&lt;br /&gt;Expected: [2, 2, 2, 2, 2]&lt;br /&gt;Got: [2, 2, 8]&lt;br /&gt;****************************************&lt;br /&gt;Failure in example: factorize(100)&lt;br /&gt;from line #9 of fact.factorize&lt;br /&gt;Expected: [2, 2, 5, 5]&lt;br /&gt;Got: [2, 2, 25]&lt;br /&gt;****************************************&lt;br /&gt;1 items had failures:&lt;br /&gt;  2 of   5 in fact.factorize&lt;br /&gt;***Test Failed*** 2 failures.&lt;/pre&gt;&lt;br /&gt;Next time I'll write about even better thing than this - the unittest module.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-114027062627855438?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/114027062627855438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=114027062627855438' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/114027062627855438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/114027062627855438'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/02/automated-testing-in-python-part-1.html' title='Automated testing in Python, part 1'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-113943719400129050</id><published>2006-02-08T23:13:00.000+01:00</published><updated>2006-11-12T21:09:45.685+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Python's OOP</title><content type='html'>One of the things I found Python's OOP model lacks are proper constructors. For example this C++ code works just as I would expect - it first calls constructor of the base class and then that of the derived class:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;class First {&lt;br /&gt;    public:&lt;br /&gt;        First() {&lt;br /&gt;            cout &lt;&lt; "First" &lt;&lt;&gt;&lt;br /&gt;But when you try the same thing in Python you get this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class First:&lt;br /&gt;    def __init__(self):&lt;br /&gt;        print "First"&lt;br /&gt;&lt;br /&gt;class Second(First):&lt;br /&gt;    def __init__(self):&lt;br /&gt;        print "Second"&lt;br /&gt;&lt;br /&gt;if __name__ == '__main__':&lt;br /&gt;    Second()&lt;br /&gt;&lt;br /&gt;%  python foo.py&lt;br /&gt;Second&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;That is not what I want. I want that class hierarchy works as in other object oriented languages. Besides that, Python doesn't know anything about &lt;i&gt;private&lt;/i&gt; or &lt;i&gt;public&lt;/i&gt; visibility of variables - everything in object is accessible. Is that all what Python's OOP model offers to me?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-113943719400129050?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/113943719400129050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=113943719400129050' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113943719400129050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113943719400129050'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/02/pythons-oop.html' title='Python&apos;s OOP'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-113767914994831406</id><published>2006-01-19T14:52:00.001+01:00</published><updated>2006-11-12T21:10:48.822+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>map and lambda strike again</title><content type='html'>Few weeks ago I wrote a post in which I said that lambda, filter, map and reduce are not needed in Python and that all can be done with simple list operations. Well, today I found a problem where that kind of approach just gets ugly and inapplicable.&lt;br /&gt;&lt;br /&gt;Here is the problem. I have a class &lt;code&gt;Graph&lt;/code&gt; and I need a constructor for it which will take data from the file and fill the appropriate adjacency matrix. The input format is straightforward, i.e. for a simple weighted graph:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;0 2 0 1&lt;br /&gt;2 0 2 3&lt;br /&gt;0 2 0 0&lt;br /&gt;1 3 0 0&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Here is the code I wrote:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class Graph:&lt;br /&gt;  def __init__(self, filename):&lt;br /&gt;    try:&lt;br /&gt;      f = file(filename)&lt;br /&gt;      self.adj_m = [e.split() for e in [e.rstrip() for e in f]]&lt;br /&gt;      f.close()&lt;br /&gt;    except IOError:&lt;br /&gt;      print "IOError: " + filename&lt;br /&gt;      sys.exit(1)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;After this, the adjacency matrix looks like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[['0', '2', '0', '1'], ['2', '0', '2', '3'], ['0', '2', '0', '0'], ['1', '3', '0', '0']]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Naturally, graph theory algorithms are designed to deal with numbers, not strings. What I needed was this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[[0, 2, 0, 1], [2, 0, 2, 3], [0, 2, 0, 0], [1, 3, 0, 0]]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;I spent 20 minutes on examining how to convert a multidimensional list elements from strings to numbers using only list comprehension. I saw no simple and elegant way to do it. Thus, I asked a friend (btw, do visit &lt;a href="http://zwillow.blogspot.com/"&gt;his blog&lt;/a&gt; ;) for help and his solution was this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;self.adj_m = map(lambda x: map(int, x), self.adj_m)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;This is very nice. It seems that we need constructs from functional programming languages after all :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-113767914994831406?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/113767914994831406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=113767914994831406' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113767914994831406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113767914994831406'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/01/map-and-lambda-strike-again_19.html' title='map and lambda strike again'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-113727278253756166</id><published>2006-01-14T22:03:00.000+01:00</published><updated>2006-11-12T21:11:42.575+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='applications'/><title type='text'>No "sucks" this time</title><content type='html'>Today I talked with a friend and he told me that he had noticed most of my posts contains sentences like "X sucks" of "I hate X". Well, that's true, what other can you expect when you look at the title of the blog ;). But, this time I'll have a different approach. The lucky object of my praises is - Mono.&lt;br /&gt;&lt;br /&gt;Lately I play a lot with Mono and I can talk about it only in superlatives. It is a fast and robust CLI (Common Language Infrastructure) implementation. Novell have done a great job. C# is world for itself. Two years ago I was writing most of my programs in plain C. Then I discovered Python and C#. As Python became my primary language and I worked mostly on Linux, I neglected C# a lot. Few days ago when I upgraded my Debian GNU/Linux from Sarge to Etch I noticed that Mono deb packages were added to the distribution (maybe they were available before? I don't know). Ofcourse, I installed it instantly and I wasn't disappointed.&lt;br /&gt;&lt;br /&gt;As I worked in C# before I knew most of it's capabilities, so I wanted to test how fast Mono's VES (Virtual Execution System) executes CIL (Common Intermediate Language) produced by mcs (Mono C# compiler). Particularly, I was interested in Python vs Mono speed. I wrote several small programs (Sieve of Eratosthenes's, recursive quick sort, use of built in API to get a web page source...). No words are needed, I'll just say the number: C# beats Python in every segment of the test for more than 40%. I'm just interested whether Python is so slow, or Mono is so fast...&lt;br /&gt;&lt;br /&gt;I think Mono has a bright future on Linux. Moves of several big players on the market confirm that. Even Fedora 5 will contain Mono :). And I will definitely use it more often from now on. The next thing I'll examine is Gtk#...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-113727278253756166?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/113727278253756166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=113727278253756166' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113727278253756166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113727278253756166'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/01/no-sucks-this-time.html' title='No &quot;sucks&quot; this time'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-113692510551383244</id><published>2006-01-10T21:00:00.000+01:00</published><updated>2006-11-12T21:12:19.200+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Prolog is stupid</title><content type='html'>I have a new story... It is called "Prolog - The King of the Useless Programming Languages". I have learned a dozen of programming languages but none of them hasn't irritated and disappointed me as much as Prolog. Honestly, I hate it. I hate every of his predicates, rules, facts, lists and stupid examples of more stupid logic games (bonus question: have you ever seen a Prolog program which actually does something useful). I hate logical programming paradigm in general.&lt;br /&gt;&lt;br /&gt;I have to learn Prolog as part of "Intelligent systems" class that I'm listening to this semester. Why, oh why don't we learn a normal programming language like Scheme or Haskel (err, what a heck, even CLISP would be better)?&lt;br /&gt;&lt;br /&gt;BTW, check out this Prolog "pearl" (one of the best I've seen). You can write something like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;foo(bar, baz)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;but not (note the position of the white space):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;foo (bar, baz)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Prolog just sucks!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-113692510551383244?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/113692510551383244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=113692510551383244' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113692510551383244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113692510551383244'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/01/prolog-is-stupid.html' title='Prolog is stupid'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-113630602940485902</id><published>2006-01-03T17:25:00.000+01:00</published><updated>2006-11-12T21:12:55.709+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>lambda, map, filter and reduce no more</title><content type='html'>There is simply no need to use bad words on decision to remove these functions from Python. As one of the main concepts of Python is &lt;i&gt;"there should be only one (and it should be an obvious one!) way to do it"&lt;/i&gt;, it was only matter of time for language architects to make this decision. In my opinion, these functions are ugly and completely unnecessary in Python, and are probably stuffed into the language definition to rip off some programmers from the functional languages which use these functions a lot.&lt;br /&gt;&lt;br /&gt;Of course, each of those functions taken from functional languages can be easily replaced with clearer and more Python-like syntax. For example:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; l = [1, 2, 3, 4, 5]&lt;br /&gt;&gt;&gt;&gt; map (lambda x: x+1, l)&lt;br /&gt;[2, 3, 4, 5, 6]&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&gt;&gt;&gt; [element+1 for element in l]&lt;br /&gt;[2, 3, 4, 5, 6]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;There is simply no need for using &lt;code&gt;lambda&lt;/code&gt;, and second example is much more cleaner nd easy to understand. For &lt;code&gt;filter&lt;/code&gt;, similar syntax could be used:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; l = [1, 2, 3, 4, 5]&lt;br /&gt;&gt;&gt;&gt; filter (lambda x:x%2, l)&lt;br /&gt;[1, 3, 5]&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&gt;&gt;&gt; [element for element in l if element % 2]&lt;br /&gt;[1, 3, 5]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Again, no need for lambda, and all can be done with simple list operations.&lt;br /&gt;&lt;br /&gt;Then we come to &lt;code&gt;reduce&lt;/code&gt;. I must admit that there is no elegant syntax to replace it like in the previous two examples (although it is not problem to implement it with iterations and slices), but on the other hand I can hardly remember a real world example where &lt;code&gt;reduce&lt;/code&gt; was used.&lt;br /&gt;&lt;br /&gt;If you ask me, this step should have been done a long time ago. Python is developing in the right direction (at least on this matter, but that is topic for one of the incoming posts :).&lt;br /&gt;l can be done with simple list operations.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-113630602940485902?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/113630602940485902/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=113630602940485902' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113630602940485902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113630602940485902'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/01/lambda-map-filter-and-reduce-no-more.html' title='lambda, map, filter and reduce no more'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-113613847107588090</id><published>2006-01-01T19:00:00.000+01:00</published><updated>2006-11-12T21:14:51.994+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Config file parser</title><content type='html'>One of the things I like in Python at most is that &lt;i&gt;Python comes with batteries included&lt;/i&gt;. Yesterday when I finished &lt;a href="http://fly.srk.fer.hr/%7Eipozgaj/sources/python/hostinfo.py"&gt;my first web service written in Python&lt;/a&gt; I decided to make it fully configurable by using a simple &lt;a href="http://fly.srk.fer.hr/%7Eipozgaj/sources/python/hostinfo.cfg"&gt;configuration file&lt;/a&gt;. What I had in mind was a config file with syntax like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# example section&lt;br /&gt;section {&lt;br /&gt;   option&lt;br /&gt;   option = value&lt;br /&gt;&lt;br /&gt;   subsection {&lt;br /&gt;       ...&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;that is, a config file like most Unix utilities have. After few minutes spent on googling I found a standard Python module called ConfigParser. ConfigParser contains three classes (RawConfigParser, ConfigParser and SafeConfigParser) for config file parsing, but unfortunately none of them supported format which I needed. Format which ConfigParser could parse was something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# example section&lt;br /&gt;[section1]&lt;br /&gt;option: value&lt;br /&gt;&lt;br /&gt;[section2]&lt;br /&gt;option: value&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Similar format is commonly used by .ini files on Windows and some applications (e.g. Opera). Main disadvantage I found in this format was lack of sub-sectioning ability. I knew I had an alternative - XML config file, but I decided it would be an overkill for this kind of application :). So I selected ConfigParser after all.&lt;br /&gt;&lt;br /&gt;It is really a great thing that Python provides such a large number of various modules, but in this case I think lack of parser for Unix style config files is one of the notable drawbacks. I would like to see that feature in some of the incoming releases of Python.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-113613847107588090?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/113613847107588090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=113613847107588090' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113613847107588090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113613847107588090'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2006/01/config-file-parser.html' title='Config file parser'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20304890.post-113594275203680116</id><published>2005-12-30T12:37:00.000+01:00</published><updated>2006-11-12T21:15:44.983+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='services'/><title type='text'>Blog engines sux!</title><content type='html'>At the time I decided to write this blog I wanted to make my own blog engine and RSS feed generator using XHTML and Python. I decided to use XHTML because I thought using it would make it easy to convert the posts from RSS to HTML (or vice verse). For the engine itself I selected Python for two reasons. First, I have never made a single Python web script so I wanted to try something new (and I don't like PHP, it is horrible if you ask me). Second, I knew that Python provides a large number modules for manipulating XML data.&lt;br /&gt;&lt;br /&gt;After short time I realized that making an own blog engine is not so easy as it seems on the first look, and possibly a complete waste of time. I find XML parsing and generating with Python rather unintuitive and complicated and I really didn't have time to look at it in the depth. So I turned to Perl and hard core text processing (good old noob approach, who cares for XML parsing after all :)... The result was a horrible code that I deleted as soon as I completed it. After that, I consulted google and found two blog engines (I won't advertise them here, they really don't deserve that :). Both of them were horrible, bloated and unsuitable for my needs. I had a simple request - all I needed was a simple system that I could incorporate into my homepage, a simple CMS for making new blog entries and comments, and which could generate RSS feed (any version, 1.0, 2.0 or Atom, I don't care) on the fly. After all the trouble, I realized that I was asking too much, so I decided to use &lt;a href="http://www.blogger.com/"&gt;blogger&lt;/a&gt;. And the result is here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20304890-113594275203680116?l=ipozgaj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ipozgaj.blogspot.com/feeds/113594275203680116/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20304890&amp;postID=113594275203680116' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113594275203680116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20304890/posts/default/113594275203680116'/><link rel='alternate' type='text/html' href='http://ipozgaj.blogspot.com/2005/12/blog-engines-sux.html' title='Blog engines sux!'/><author><name>Igor Pozgaj</name><uri>https://profiles.google.com/108393388307072360132</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Xrk-urs6uL8/AAAAAAAAAAI/AAAAAAAAANU/uVNPm75OWxs/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry></feed>
