Korn shell scripting

April 12, 2010

I was wondering how to call functions from one shell script to another. I played a bit and produced this example which shows how to do that:

First file is myfile.sh

  1. #!/bin/ksh
  2. myVar=myvariableValue;
  3. print $myVar;
  4. myFoo(){
  5. print “function myFoo was called”;
  6. }
  7. myFoo;
  8. . ./myFile2.sh
  9. myFoo2;
  10. print “print variable from myFoo2 \’$myVar2\'”;

On line 13 we are calling function defined in another file, and on line 14 using variable defined in another file.

Line 11 does the whole trick. Here is another file myFile2.sh

  1. #!/bin/ksh
  2. print “myFile2 was called”
  3. myVar2=”variable in myFile 2″;
  4. myFoo2(){
  5. print “function myFoo2 was called”
  6. }

As part of my job I now have to work with ksh (Korn Shell) scripts under AIX servers.  If you are looking for Korn, a “nu metal” style band, then you are in the wrong place :)

I had previously not written any shell scripts, so is here basics that I am learning at the moment.

To access command history

Usually in bash, or probably other shell (even on windows too) a command history can be accessed simply by pressing <UP> and <DOWN> keys. This is not the case with ksh. In fact, your command line is more like in vi “insert mode”. That is, you can type commands, but if you press up or down, you wont access command history, and pressing <LEFT> or <RIGHT> wont move your cursor, instead it will produce more or less random unexpected results.

You can quit this “insert” mode by pressing quit (more or less like in vi and vim). Then you can use regular keys ‘j’ and ‘k’ to move up or down in history. ‘h’ and ‘l’ can be used to move your carret and edit your current command. ‘a’ (append) and ‘i’ insert, as well as all other standard vi / vim text editing commands are useful.

Refer to vi cheat sheet for more details on vi commands.

P.s. yes, on the servers i am working there are is no vim, only vi.

I’ve read in Ayendes blog about Esent, which is an embeddable database storage engine (ISAM) which is part of Windows.

There is also a managed API being created at CodePlex. What I did is implemented a backend for SourceGrid using Esent PersistentDictionary. This is similar to windows DataGrid, which takes data from DataSet (or DataTable, or DataView) structure.

However, with DataSet there are two problems.

  • Whole data must be kept in memory. I did home-testing and found that keeping 1 million rows in DataTable increases my app memory consumption from roughlt 50MB to 250MB.
  • Data is not persistent.

Essent backend solved both of these two problems (although sorting is not available with PersistentDictionary out of the box). This image shows the result:

Of course the data is simplistic, first column is just ID, second is one of the 5 random strings. Whole esent DB file takes 674 MB on disk. There is at the moment a small problem with hidden rows implementation, but that can be fixed easily. If hidden rows feature is temporarily disabled, then the data can be viewed immediately, scrolling works just fine.

I plan to make other backends too. Probably the next one will be NHibernate backend, with embedded FireBird as an example. Hope that it will support sorting, and will handle data (at least on local computer) easily. I will try to test SourceGrid against 10 mln rows.

Today I was playing around with SourceGrid. I noticed that for some reason simply resizing the window would cause the window to flicker, even though the data store was not beeing accessed.

The problem was in the fact that GetTotalHiddenRows method was a linear implementation, simply looping through all the rows. Even though the dataset was not that big (60k rows), that caused a lot of troubles.

The problem was fixed by implementing a simple ref-counting. That is, the moment the row became hidden, it produced an event. That event was caught by hidden rows calculator, which exposed a simple property TotalHiddenRows.

The result can be seen in this dotTrace image:

We can see a reduction in calls to PingGridRows.GetCount by 1 million, and GridVirtual.GetFixedRows by 2 million.

That solved this issue

Branching in Mercurial

April 3, 2010

There is a good article A Guide to Branching in Mercurial.

Basically, it says that there are a few ways to do branching, so just choose one and work with it. I chose Branching with Named Branches and it was really quite simple to make a simple branch and merge it with the default tip.

Basically just call hg branch myFeature and you mark your local working copy as being a branch with a name “myFeature”. If someone clones your copy (you should try cloning your copy in your local file system), the it will default to default tip, not to your branch.

After some development time, you must synchronize both branches. You do this simply with hg pull or hg push command. It’s just a matter of whether you want to push your changes to other repo, or get others changes from another branch.

When you update your local copy, it is interesting to start TortoiseHG repository explorer and see that there are two separate development trees. To merge those, you have to call hg merge -r revNR .  RevNR is the other branches tip revision number.

Note that while working this way, you wont get “branch <yourBranch> has two heads”.  AFAIK, this might happen if two separate developers would commit into the same branch, and then would try to merge.

Mercurial .hgrc file

April 1, 2010

I have puzzled myself  a few times wondering where is mercurial .hgrc file. You can find all the answers here.

Summary;

  • (Unix, Windows) <repo>/.hg/hgrc

Per-repository configuration options that only apply in a particular repository. This file is not version-controlled, and will not get transferred during a “clone” operation. Options in this file override options in all other configuration files.

  • (Unix) $HOME/.hgrc
    (Windows) %USERPROFILE%\.hgrc
    (Windows) %USERPROFILE%\Mercurial.ini
    (Windows) %HOME%\.hgrc
    (Windows) %HOME%\Mercurial.ini

Options in these files apply to all Mercurial commands executed by this user in any directory. Options in these files override per-system and per-installation options.