Tuesday, January 24, 2012

Degree of the leakage in leaky abstractions

We are software developers, so we very well know Joel's law of leaky abstractions.
That said: all non-trivial abstractions, to some degree, are leaky.

As a consequence it might be good to note that (according to my experiences) the deeper abstractions you create, the higher degree of leakage you get. To put it in another way, here's my funky interpretation (or rather conclusion) of Joel's law:
the degree of the leakage is directly proportional to the abstractional distance

Thursday, January 5, 2012

Fullnames in trac reports


So you are using the excellent trac tool to manage your project, right? And you'd like to see the fullname of the project participants in your reports.
Then here's a quick tip on how to do it. Basically trac as of v0.12 keeps users' profile data (fullname, email) in the session_attribute table. So you'll have to join it in your report queries.

Eg. let's see the very basic 'Active Tickets' report which comes with the base install. Modify it to look like this:

SELECT p.value AS __color__,
id AS ticket, summary, component, version, milestone, t.type AS type,
session_attribute.value as owner, status,
time AS created,
changetime AS _changetime, description AS _description,
reporter AS _reporter
FROM ticket t
LEFT JOIN session_attribute on t.owner = session_attribute.sid AND session_attribute.name='name'
LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority'
WHERE status <> 'closed'
ORDER BY CAST(p.value AS integer), milestone, t.type, time

Note, that for this solution to work you'll need to check if users fill their profile data correctly (in the Preferences menu).

Tuesday, August 31, 2010

A quick note on ADO.NET 2.0 and SQL performance in a normalized database

Back again after a while...

So I recently came across the problem, that an ADO.NET typed DataTable could perform pretty bad when used with the default generated CRUD commands. The situation is that if you create a typed DataTable for an SQL table in VS2008 by using an SQL SELECT, then the dataset designer will create the appropriate INSERT, UPDATE and DELETE tableadapter commands for you (if you ask for it). The main drawback of this approach is its main advantage: these generated commands will be general enough to handle columns with default values, or values generated by database-side triggers on-the-fly, etc. And at the same time UPDATE will be fairly inefficient when these tables reside in a normalized model, as it will identically update all unmodified columns in the database also, mainly those which are the foreign keys of the table. Updating unmodified columns might causes totally useless but really expensive index updates, and slow foreign key checks (even if you're using smart indexing). These costs run higher quickly if the depth of the tables grow, and can easily turn to be the main bottleneck of the overall system performance.

In such cases I suggest to override default generated UPDATE command to only update those columns which are actually subject to change.

Friday, August 22, 2008

building hypertable 0.9.0.10 on Ubuntu hardy

I saw hypertable first about half a year ago, and since then I felt like giving it a try. Today I finally took the time to download it (0.9.0.10 alpha), and tried to build it on my Ubuntu hardy. README file seemed to be precise, so I followed the instructions, and installed the packages below with apt-get as follows:

apt-get install cmake g++ libdb4.6++-dev liblog4cpp4-dev libexpat1-dev libreadline5-dev libboost-dev libboost-iostreams-dev libboost-program-options-dev libboost-python-dev libboost-thread-dev libgoogle-perftools-dev graphviz doxygen sun-java5-jdk

Then I run cmake as follows (after creating and entering build directory: mkdir -p ~/build/hypertable ; cd ~/build/hypertable):

cmake -DCMAKE_INSTALL_PREFIX=~/hypertable -DCMAKE_BUILD_TYPE="Debug" ~/src/hypertable-0.9.0.10-alpha

Cmake checked all dependencies and created the appropriate makefiles to the build dir:
-- Use thread library: -lpthread
-- Looking for required boost libraries...
-- Boost include dir: /usr/include
-- Boost thread lib: /usr/lib/libboost_thread-mt.so
-- Boost program options lib: /usr/lib/libboost_program_options-mt.so
-- Boost iostreams lib: /usr/lib/libboost_iostreams-mt.so
-- Boost python lib: /usr/lib/libboost_python-mt.so
-- Boost lib dir: /usr/lib
-- Boost version: 1_34_1
-- gcc version: 4.2.3
-- Looking for doxygen...
-- Looking for doxygen... - found /usr/bin/doxygen
-- Looking for dot tool...
-- Looking for dot tool... - found /usr/bin/dot
-- Found BerkeleyDB: /usr/lib/libdb_cxx.so
-- Berkeley DB version: 4.6.21
-- Found Readline libraries: /usr/lib/libreadline.so;/usr/lib/libncurses.so
-- Java headers found at: /usr/lib/jvm/java-1.5.0-sun/include
-- Hadoop includes not found. Please set HADOOP_INCLUDE_PATH variable
-- Hadoop libraries not found. Please set HADOOP_LIB_PATH variable
-- You decided not to build shared libraries. MapReduce will be disabled
-- Got boost 1.34.x, prepend fix directory
-- MapReduce support disabled.
-- Configuring done
-- Generating done
-- Build files have been written to: /home/qzy/build/hypertable

So all I had to do now is to start the build process by issueing make. All seemed to be compiling fine, but at 82% when building AccessGroup.o, it died with the following error message:

/usr/include/boost/multi_index/detail/index_node_base.hpp:22:42: error: boost/serialization/access.hpp: No such file or directory

Well, after some minutes I figured out this is beacuse boost serialization module was not there, so I installed it:
apt-get install libboost-serialization-dev
After this, the build procedure succesfully finished, so the only remaining step was to issue the make install command.

And voila... now I have a working hypertable on my Ubuntu hardy. Even though the stuff is still alpha, the build process is fairly painless. The only bug I found is the lack of the boost serialization module check in cmake (however README suggests to install libboost-.*-dev, I don't like unnecessary packages hanging around, so this cmake issue is still a bug).
Now it's time to take a deeper breath in the hyperspace...

Wednesday, August 13, 2008

log4net: hostname in logfile's name

I recently came across the problem that while using the excellent log4net tool with fileappender I needed to programatically include the machine name in the logfile's name (the application's config is on a shared disk area, so hard-wiring the nodename was not an option). Thanks to the log4net team, since version 1.2.9 this can be achieved via the PatternString and the ConversionPattern classes. Let's see a working c# example.

This is what you should put into your application's config (Web.config in my case) to the <log4net> section:

<appender name="SomeLogFileAppender" type="log4net.Appender.FileAppender">
<file type="log4net.Util.PatternString" >
<converter>
<name value="hostname" />
<type
value="MyNamespace.MySubNamespace.HostnamePatternConverter,MyNamespace" />
</converter>
<conversionPattern
value="debuglog-%hostname{LocalApplicationData}.txt" />
</file>
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level - %message%newline" />
</layout>
</appender>

And then the code snippet which implements HostnamePatternConverter:


using log4net;
using System;


namespace MyNamespace.MySubNamespace {

...

public class HostnamePatternConverter : log4net.Util.PatternConverter
{
protected override void Convert(TextWriter writer, object state)
{
writer.Write(Environment.MachineName);
}
}

...

}