Archive for February, 2006

cvs history

Released February 22nd, 2006

For alot of people, CVS is history; they’ve switched to SVN and are loving life. For those of us continuing the use this venerable tool, I present the following cobbled together bit of utility.

It’s a bash function. and a nice way to keep an eye on what’s happening on a cvs repository. I work with a team of around 7 guys, and I like to keep an eye on what’s changed and who changed it.

It works like this, summarizing what I consider to be the highlights from the cvs history command, and defaults to showing checkins for the current date:

$ cvshist
M 2006-02-22 10:34 EDT jsmith  1.3  InternalOperation.java         APRJ7A/src/com/ppc/oepica/model/internal
M 2006-02-22 10:53 EDT jsmith  1.37 FooBarCopier.java              APRJ7A/src/com/ppc/oepica/model/external
M 2006-02-22 11:26 EDT darrend 1.23 CommonJobBase.java             APRJ7A/src/com/ppc/oepica/model/common

I use the date command, which gives me some flexibility when specifying a date

$ cvshist yesterday
$ cvshist 2 days ago
$ cvshist january 10
$ cvshist 2006-01-11

Here’s the source. I’ve used this on linux and cygwin; you’ll need bash, gnu date, and cvs.

$ declare -f
cvshist ()
{
  export CVSROOT=:pserver:darrend@shlnxtest1:/home/cvs;
  TARGET_DATE=$(date -d "$*" +%Y-%m-%d);
  cvs history -a -z EDT -c -D $TARGET_DATE | sed "s/\s*==.*$//" | grep "$TARGET_DATE"
}

quick and dirty ruby

Released February 16th, 2006

At work I received an email from someone that listed libraries I should use when connecting to their AS400 system. I wanted a quick way to convert their whitespace table into a nice comma-separated list. Below is the first 6 lines from about 50 or so.

Sequence
 number   Library
    10    QTEMP            

    20    DDMFLIB2
....

If it’s computable but a one-off, I immediately go to Ruby nowadays. 10 years ago it would have been Perl, 15 or 20 years ago the choice would have been probably a meld of sed|awk.

I always go with __END__ in these situations; Ruby stops processing at the __END__ line, but you are given an enumerable access to the contents that follow with the magical DATA object.

matches = DATA.collect { |line| line.match(/\\s+\\d+\\s+(\\w+)/) }
matches.compact!
puts matches.collect { |match| match[1] }.join(', ')

__END__
Initial library list:                            

Sequence
 number   Library
    10    QTEMP            

    20    DDMFLIB2
    30    APPSDEV
    50    FILES2                                                       

   110    QRPG                                                              

Let’s try it out (running Ruby/Windows in a Cygwin terminal):

dday@xpmachine21 ~
$ ruby liblist.rb
QTEMP, DDMFLIB2, APPSDEV, FILES2, QRPG

Success!

IE ‘Code’ bug

Released February 16th, 2006

We had a problem with how code was being displayed on the blog. IE wasn’t respecting the width of the code block and it was throwing the entire layout off.

Here is how I fixed it:

pre code {
 padding: 5px;
 display: block;
 overflow: auto;
/*I had to add this so ie wouldn't put scrollbars both ways.  Seems to be ignored by firefox*/
 overflow-y: visible;
/*I had to add this for ie to respect the width.  I don't know why it didn't respect its container's width*/
 width: 450px;
}

Smooth scrolling image list

Released February 15th, 2006

I had someone ask me about fitting more images in a small area and the way flickr does their image scrolling came to mind. I wanted to see how hard it was to do and as it turns out it isn’t hard to do at all thanks to script.aculo.us.

I’m making this as simple as I can to illustrate just how nice the new tools like script.aculo.us are.

Step 1. You need a box and some images. You will also need to know the size of the images or at least the size of the largest one. In an attempt to keep this simple I’m going to assume all the images are the same size.

<div id="imageBox">
  <div id="imageBoxInside">
    <img src="http://blogs.missiondata.com/wp-admin/images/turtle_sm_1.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/elephants_sm_1.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/turtle_sm_2.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/elephants_sm_2.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/turtle_sm_3.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/elephants_sm_3.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/turtle_sm_4.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/elephants_sm_4.jpg" />
    <br/>
  </div>
</div>

Notice from this code that we have an outer box and an inner box. We will next want to make the outer box smaller than the inner box so that only a few of the images can be seen at one time.

Step 2. To hide the extra images we give the outer box a set width, in this case I want to show only 2 images at a time and each image is 180px wide so I make the outer box 360px wide. Notice that the overflow is hidden. The hidden overflow is what keeps the images that are in the inner box but not within the outer box’s width hidden.

I’m using floats to lay the images out one next to the other. Because of this we need to give the inside box a large width so that it will not wrap the floated images.

<style type="text/css">
#imageBox { margin: auto; width: 360px; border: 1px #000 solid; overflow: hidden; }
#imageBoxInside { width: 10000px; }  #imageBox img { float: left; padding: 0px; margin: 0px; }
#imageBox br { clear: both; }
</style>

Step 3. Now for the magic. You need the latest version of script.aculo.us because I use the Effects.Move function and they have changed Effects.MoveBy to Effects.Move only recently.

We now create two functions to move the images ether one step to the right or one step to the left. Each step is the size of a single image so the when one is hit it moves one image out of thew view and another image into view. As you can see from the following code this is extremely easy using the script.aculo.us library.

<script>
function moveToPrevious()
{
  new Effect.Move('imageBoxInside', { x: 180, y: 0, transition: Effect.Transitions.sinoidal });
}  

function moveToNext()
{
  new Effect.Move('imageBoxInside', { x: -180, y: 0, transition: Effect.Transitions.sinoidal });
}
</script>

Step 4. The only thing that remains is to connect everything together. We add a couple links to move call the next and previous functions defined above.

< a href="javascript:void(0);" href="javascript:void(0);" onclick="moveToPrevious(); return true;"><img src="http://blogs.missiondata.com/wp-admin/images/previous.png" />
< a href="javascript:void(0);" href="javascript:void(0);" onclick="moveToNext(); return true;"><img src="http://blogs.missiondata.com/wp-admin/images/next.png" />

And that is all there is to it. See it in action!

Quick and dirty cryptfs

Released February 15th, 2006

Here is a quick rundown on how to create a cryptfs partition that mounts during boot with Fedora Core 4.

Configure the kernel (this may already be done for you):

Device Drivers --->
  Multiple devices driver support (RAID and LVM) --->
    [*] Multiple devices driver support (RAID and LVM)
      < >   RAID support
      <*>   Device mapper support
      <*>     Crypt target support

Cryptographic options --->
  <M>   MD5 digest algorithm
  <M>   SHA1 digest algorithm
  <M>   AES cipher algorithms
   .... 

Install the userland tools:

yum install cryptsetup

Create the filesystem and format it:

cryptsetup -c blowfish -s 64 create fs_name /dev/sda2
mkfs.ext3 /dev/mapper/fs_name

Create /etc/init.d/crytptinit:

if [ -b /dev/mapper/fs_name ]; then
  /sbin/cryptsetup remove fs_name
fi
/sbin/cryptsetup -c blowfish -s 64  create fs_name /dev/sda2

Run it at the runlevels you want:

cd /etc/rc3.d
ln -s ../init.d/cryptinit S08cryptinit

Create the mount point:

mkdir /mount_point

Edit /etc/fstab:

/dev/mapper/fs_name /mount_point               ext3   defaults 0 0

Reboot. You will be asked for your passphrase when the machine boots.

Information in this post was gleaned from several places. Here is one
that matches closely.

No javascript detection

Released February 15th, 2006

Have you ever wondered what you can do if someone doesn’t have javascript turned on and it is needed on the page they are sitting at? Well here is the answer:

<html>
  <head>
    <noscript><meta http-equiv="refresh" content="0; RL=nojscript.html"/></noscript>
  </head>
  <body>
    A javascript test.
  </body>
</html>

If the user doesn’t have javascript turned on they will be redirected to the page nojscript.html. It doesn’t work as well as having a page in between that does the detection but if you have to do it on the page you need the javascript on this is the way to go.

Fun with Oracle Strings

Released February 13th, 2006

Today I needed to find a way to count the number of unique email domains in a table. I figured there was a way of getting the index of a string in another string and sure enough there is. This did the trick in Oracle:

select count(1), SUBSTR(email, INSTR(email, '@', 1, 1)+1) from SOMETABLE group by SUBSTR(email, INSTR(email, '@', 1, 1)+1) order by count(1) desc

The INSTR function gives you the location in a string where another string is located. See the following link for more on the INSTR function: http://www.techonthenet.com/oracle/functions/instr.php

I’ve always found the way Oracle handles case interesting. It looks like they are changing things a little starting with 10G: http://blogs.ittoolbox.com/database/solutions/archives/005951.asp

JDBC + Batch updates + Non-Standard == Oracle

Released February 11th, 2006

I recently ran into an issue where doing a large number of inserts and updates in an Oracle 8i database was taking forever. I was already using a prepared statement and commiting only after a certain number of rows. After some digging I found out that there is a special Oracle way of doing batch updates that made things a good bit faster. They do support the normal addBatch batch updates but it isn’t as fast as using their special way.

Here is an example of how to do things their way:

public static void doBatchInsert(List aLargeList, Connection connection) throws SQLException
{
  // You have to turn auto commit off, if you are doing a large set of inserts and updates you are probably doing this already.
  connection.setAutoCommit(false);

  PreparedStatement preparedStatement = connection.prepareStatement("insert into a_table(a_col) values (?)");
  // This is the magic. Set the number of statements to allow in one batch
  ((OraclePreparedStatement)ps).setExecuteBatch (10);

  int count = 0;
  for(Iterator i=aLargeList.iterator(); i.hasNext(); count++)
  {
    YourData yourData = (YourData)i.next();

    preparedStatement.setInt(1, yourData.getAnInt());
    preparedStatement.executeUpdate();

    if(count % 10 == 0)
    {
      // Send all currently queued statements
      ((OraclePreparedStatement)preparedStatement).sendBatch();
      connection.commit();
    }
  }

  ((OraclePreparedStatement)preparedStatement).sendBatch();
  connection.commit();
  preapredStatement.close();
}

For more information see the following link:
http://www.oracle.com/technology/products/oracle9i/daily/jun07.html

OSS Projects

Released February 10th, 2006

Mission Data has written a few open source packages that have been used in many projects. Sometimes in fairly large places.

  • SQLProcessor – Takes (some of) the tedium out of dealing with the JDBC API directly written by Darren Day and Leslie Hensley.
  • Lakeshore – A component based web framework written by Leslie Hensley and Steven Yelton.

Lakeshore even got a bit of press.

Commons Collections By Example: Maps

Released February 9th, 2006

I realized today just how much I used the Commons Collections library. Sure, there’s alot of anonymous inner classes, but after years of writing Swing I’ve gotten used to sort of crossing my eyes and looking past the syntactic cruft.

Here’s a silly example. Let’s map the names in the Greek alphabet to actual letters. Here’s our data

    Map nameToLetter = new HashMap();
    nameToLetter.put("ALPHA","a");
    nameToLetter.put("BETA","b");
    nameToLetter.put("GAMMA","g");
    nameToLetter.put("DELTA","d");

    String[] values = {"ALPHA","BETA","GAMMA","GAMMA","DELTA","EPSILON"};
    List valueList = Arrays.asList(values);

Let’s convert that valueList to the letters:

    Collection resultCollection = CollectionUtils.collect
    (
      valueList,
      TransformerUtils.mapTransformer(nameToLetter)
    );

    System.out.println(resultCollection);

>[a, b, g, g, d, null]

Hmm…how do we go back the other way….
(more…)