Find your next scenic drive!

November 24, 2006

A feed for mFiles.co.uk...

One of the music sites that I've enjoyed over the years has been mFiles. Not only does it provide you with great commentary ranging from classical composers to modern pieces, but it also provides you with pieces of music in MIDI, MP3, and, my personal favorite, free sheet music. I have found it to be a great place to get introduced to various musical styles and composers.

One thing that I noticed a while ago was that this site did not have a feed, so to keep up with the site's regular updates, one had to visit the site regularly.

After approaching Jim Paterson (the site's webmaster) about an RSS feed, I decided to write a little program that will generate an RSS feed from mFiles. This service has been replaced by http://feeds.mfiles.co.uk/mfiles-musicfiles .

My program is very simple, and usually visits mFiles once a day, parses through the articles, and generates an RSS 2.0 feed. The feed currently only contains the titles of the articles and a link to mFiles.co.uk. A few notes about the feed:

  • If you click on a link and the title does not match, use the Find feature of your browser to find the article that you clicked on. This is something that will eventually be improved.
  • The feed only contains the titles of the articles; it does not contain any of the article's content. I have done this for many reasons, but primarily since I did not want any plagiarism to occur.

If you have any suggestions, problems, or questions about the feed, please feel free to contact me, or if you have questions about mFiles, please contact mFiles directly.

I hope that you will find this useful!

November 23, 2006

Error Changing Samba Password...

When I went to change my Samba password earlier today, I got this error message:

eyt@zaterdag 19% smbpasswd
Old SMB password:
New SMB password:
Retype new SMB password:
Error connecting to (Connection refused)
unable to connect to SMB server on machine Error was : SUCCESS - 0.
Failed to change password for eyt

Googling did not say it directly, but it appears that the problem above was that my smb.conf did not mention (localhost) for the listening interfaces; adding to the interfaces setting in the global section resolved my problem, as demonstrated here:

interfaces =

After this quick change and restarting Samba, I was able to change my password and all was happy again.

August 3, 2006

Corrupted Comments Table...

I was recently cleaning up the endless comment spam this blog gets, and at some point while doing this, I noticed that one comment ended up not being deletable. From the bBlog admin interface, it was not evident that there was a problem, and I decided to look at it when I got home. When I got home, I had received a couple more comment spams, but I could not delete these or the previous one from the admin interface, and so I decided to drop to the mysql interface.

The mysql interface seemed fine at first, as it allowed me to select * from bB_comments, however, when I attempted to delete all the items on hold, I noticed something different:

  • mysql> delete from bB_comments where onhold = 1;
  • ERROR 126 (HY000): Incorrect key file for table './bBlog_table/bB_comments.MYI'; try to repair it

Some of my initial search results were non-conclusive as to what the deal was, and so I hoped that by restarting MySQL, that the error would be more evident. MySQL started up fine, but my query results now were different:

  • mysql> delete from bB_comments where onhold = 1;
  • ERROR 145 (HY000): Table './Blog/bB_comments' is marked as crashed and should be repaired

From that error message, I landed on this message that indicated that the repair was as simple as running the REPAIR query, as described here:

  • mysql> REPAIR Table bB_comments;
  • +-------------------------+--------+----------+----------+
  • | Table | Op | Msg_type | Msg_text |
  • +-------------------------+--------+----------+----------+
  • | bBlog_table.bB_comments | repair | status | OK |
  • +-------------------------+--------+----------+----------+

And now I am back in business and able to delete my comment spam. It is unclear what corrupted the table to begin with; I was impatient in deleting the comment spam, but I doubt that is the root cause. If it happens again, I will take a look.

August 2, 2006

Searching for nil in all the wrong places...

A few days ago, I was adding some migrations to a Ruby on Rails project, but when I went to initialize a newly created database, I saw this error:

  • rake aborted!
  • You have a nil object when you didn't expect it!
  • You might have expected an instance of Array.
  • The error occured while evaluating nil.first

This being the third or so time working in Ruby, I immediately thought that it was something I did, so I started up the automatically generated scripts/application, pasted my new code into there, and proceeded to use it. The code had a couple issues that I fixed and I was confident enough to try again.

But again, I got the same error message. I then decided to add a couple prints around the new code, and re-run it, but the error above occurred without my print outs. Not sure how to proceed, I asked for some assistance from some co-workers. The advice was great, and I learned a lot about Ruby and Rails, but it still did not resolve my problem.

Finally someone recommended adding --trace to the my command:

  • eyt@zaterdag 5031% rake --trace migrate
  • ** Invoke migrate (first_time)
  • ** Invoke environment (first_time)
  • ** Execute environment
  • ** Execute migrate
  • rake aborted!
  • You have a nil object when you didn't expect it!
  • You might have expected an instance of Array.
  • The error occured while evaluating nil.first
  • .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:253:in `migration_files'
  • .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:252:in `sort_by'
  • .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:252:in `each'
  • .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:252:in `sort_by'
  • .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:252:in `migration_files'
  • .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:235:in `migration_classes'
  • .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:223:in `migrate'
  • .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:190:in `up'
  • .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:181:in `migrate'
  • .../lib/ruby/gems/1.8/gems/rails-1.0.0/lib/tasks/databases.rake:3
  • .../lib/ruby/gems/1.8/gems/rails-1.0.0/lib/tasks/databases.rake:2:in `call'
  • .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:202:in `execute'
  • .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:202:in `each'
  • .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:202:in `execute'
  • .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:180:in `invoke'
  • .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:1454:in `run'
  • .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:1454:in `each'
  • .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:1454:in `run'
  • .../lib/ruby/gems/1.8/gems/rake-0.6.2/bin/rake:7
  • .../bin/rake:18:in `load'
  • .../bin/rake:18

So that is very interesting. Note how there is nothing in the above points to anything of mine. In pondering this with one of my coworkers, I explained how one of the things that I tried during debugging it was renaming the name of the class and filename, and that struck a cord.

It turns out that the mess above was all caused by my filename. I had named my file revision_add_blah_to_myApp and named my class AddBlahToMyApp. The problem with this is that the Rails convention for class names requires me to either name my file revision_add_blah_to_my_app or name my class AddBlahToMyapp. This very subtle issue caused this most unusable error message to cause a few completely wasted hours.

I have blogged before about great and not so great exceptions and their handling. I think this also falls in that category of not-so-great. It would have been nice to know that this problem originated with an attempt to load a class that did not exist, for example. In that case, I would have looked at that issue more closer than looking for references to first (and indirect references thereof) where the object invoking that method could have been nil.

June 25, 2006

Clearing an empty java.util.HashMap...

Here is an interesting question; which of the following programs executes faster:

  1. public class ProgramA {
  2.   public static void main( String [] args ) {
  3.     java.util.Map<String, String> map = new java.util.HashMap<String, String>( 100000000 );
  4.     long start = System.currentTimeMillis();
  5.     for ( int i = 0; i < 100; ++ i ) {
  6.       map.clear();
  7.     }
  8.     System.err.println( ( System.currentTimeMillis() - start ) + "ms" );
  9.   }
  10. }
  1. public class ProgramB {
  2.   public static void main( String [] args ) {
  3.     java.util.Map<String, String=> map = new java.util.HashMap<String, String=>( 100000000 );
  4.     long start = System.currentTimeMillis();
  5.     for ( int i = 0; i < 100; ++ i ) {
  6.       if ( ! map.isEmpty() ) {
    // this line is not in the above.
  7.         map.clear();
  8.       }
  9.     }
  10.     System.err.println( ( System.currentTimeMillis() - start ) + "ms" );
  11.   }
  12. }

By simply looking at the code or reading through the documentation, you may think that they are similar since the map is empty, since presumably the clear() method would take this into consideration. But of course, if that were the answer, this would not be much of a blog post.

On my machine, Program_A runs in about 37625 milliseconds with one of my processors pegged whereas the Program_B runs in about 1 millisecond. Why? It would appear that the clear() method recreates its internal representation each time that you call it instead of looking at the current state of the object and realizing that it is indeed empty. Naturally if the initialCapacity is smaller, the program is less affected by this.

Obviously no one writes code exactly like the above snippet, but if you are calling clear() from within a loop, you may want to be aware of this.