Monday, March 31, 2008

I'm Looking at an Ich Outbreak

Looks like the stress of moving my Betta home for the week and our house being so cold (Usually around 62 middle of the day) has caused an Ich infection.

This is a nasty little parasite that grows as white spots on the fish for 7-10 days, then drop off and divide into hundreds of daughter cells, which then reinfect fish. Luckily, since I only have one fish, that isn't as much of a concern.

I've raised the temperature of the tank up to 86 and added some sea salt, which is supposed to stress the parasite and reduce it. Hopefully the salt doesn't kill anything else in my tank... My snail has already been acting stressed.

Friday, March 28, 2008

Debugging Messages in C

Ah the great feeling when, after days of work, your program finally compiles. There's nothing as rewarding as going through and checking off every cryptic "Symbol % not expected before or after ^ unless this is an odd numbered Tuesday or your last name beings with W" error message.

So now you have your compiled program; you run it... and nothing. DOA. Or worse, it does something you didn't expect. (I heard a tale this week of a program that read in and displayed user input, but was accidentally off by one: enter a, get garbage, enter b, get a) So then the question is: How do you go about dissecting this program and figuring out where the computer didn't understand what you meant? (aka you f%$&ed up) My solution is slapping this bit of code at the beginning of every program I write:

#ifdef DEBUG
#define ErR(a) fprintf(stderr, "%s\n", a)
#else
#ifdef DEBUG_SLOW
#define ErR(a) fprintf(stderr, "%s\n", a); sleep(1)
#else
#define ErR(a)
#endif
#endif

It may look nasty, but that's only because the C preprocessor lacks an elseifdef scenario. In reality, this bit of code works magic. Everywhere in code that I think would be of interest, I simply add:
ErR("Debugging message here");
And go about my business. Then when I got to compile the program, the real magic begins.

When compiling, there is a way to define symbols for the preprocessor from the command line with the -D flag. As can be seen in the snippet above, if DEBUG is defined, it will replace every ErR with a fprintf and display the message. If DEBUG_SLOW is defined, it will replace ErR with a fprintf, as well as adding in a one second pause at each message.

Sample code - hello.c:
main() {
ErR("Beginning of program");
printf("Hello World!\n");
ErR("End of program");
}

Compile with:
cc -o hello hello.c -DDEBUG
and get:
Beginning of program
Hello World!
End of program

Compile with:
cc -o hello hello.c -DDEBUG_SLOW
and get:
Beginning of program *pause*
Hello World!
End of program *pause*


Granted, this debugging macro only works for flow control problems, which is usually my problem. If you're expecting a function to call another function only every third time, with this it will be real easy to watch to see how many times the second function gets called. Then when you're done debugging, just compile the code without DEBUG or DEBUG_SLOW defined, and all the debug info goes away with no performance hit.

An extension to this would be to let the programmer call ErR with more arguments to display along with the message:
ErR("Current location: ", x, y);
But I rarely need more than the basic message. Just need to see how far the program gets before segmentation faulting.

Thursday, March 27, 2008

Timing Events in C

It's a pretty standard problem. You want to time how long something takes on your computer, be it calculating the first 10,001 primes, accessing a multidimensional array in different directions, or whatever else you can come up with. The pseudocode for it is pretty simple:

save start_time
do something of interest
save end_time
display (end_time - start_time)

I was reading through some code samples in C today, and found probably the cleanest way to solve this problem so far (allocate.c):

#include time.h
clock_t startm, stopm;
#define START if ( (startm = clock()) == -1)\
{printf("Error calling clock");exit(1);}

#define STOP if ( (stopm = clock()) == -1)\
{printf("Error calling clock");exit(1);}

#define PRINTTIME printf( \
"%6.3f seconds used by the processor.", \

((double)stopm-startm)/CLOCKS_PER_SEC);

Then in your code:
START;
// Call function of interest
STOP;
PRINTTIME;

And that's it.
Other than it's clean usage, it also has the advantage of not measuring real time, but processor time. So if this program is pushed out of the CPU by another program, that time won't be added, only the time spent running. The only shortcoming is that this macro can't be nested, but it's hard to believe it'd be that difficult to do.

Bought a Blue Apple Snail

So after all the success I've had with my Gold Apple Snail, my sister thought a snail wouldn't be a bad addition to her aquarium. We jumped in the car and drove until we ran into the first pet store. Happened to be a PetSmart. I've not heard great things about their fish sections, but what the hell. The next pet store is at least half a mile farther down, so we stop to look.

That was probably the cleanest, best stocked fish section I've ever seen. They had three rows of tanks, and maybe 15 across. Not only did they have the Gold and Black Mystery (Apple) Snails I've seen before, but they had Ivory and Blue as well.

Unfortunately the hard part of getting a snail from the pet store is picking him out. You're sitting there looking at a tank full of snail shells, and they all look dead. Not one of the snails is moving, and only maybe 1 or 2 are out of their shell at all. It's one of these two that you pick. The girl next to me in the dorms has gone through 3 snails, all DOA.

So Kristina picked out a nice little Blue one and we brought it home. Put it in one of the jars and after an hour, the little guy was floating. Not like gently lift, but we're talking cork popping out of the water. This snail is seriously buoyant, yet still alive. I've moved his jar into a warmer area in the house, and he's acting much more interested in moving, but is still stuck to the water surface. We'll see if things fix themselves tomorrow and he goes back to being the happy water-loving snail he should be.

Wednesday, March 26, 2008

Update on Debtorrent

I installed Debtorrent on my Hardy install last night and it was pretty painless. The standard sudo apt-get install debtorrent, then edit the apt source.list file and prefix every line with localhost:9988/ and away you go.

This morning I tried an apt-get update && upgrade, and what a marked improvement on the download speed. Update took a little longer, but I got about a 3x improvement on downloads. The one downside is there is no indication of progress, so it looks like it just hangs, then is magically finished, so just have faith.

Tuesday, March 25, 2008

Integrate Bittorrent into Apt-get

This was just an idle wondering to see if such a system was already implemented in some deep bowel of the internets.

Background
Bittorrent is a peer to peer file sharing system with the advantage that the file being downloaded is controlled centrally. You download a special tiny file from the web site you're visiting, load it in your bittorrent client, and it downloads the big file. The tiny file contains the fingerprint of the large file, guaranteeing it to be the correct file.

Apt-get is a program that manages all the other software installed on your computer. It's like the Apple software manager, except instead of it only being for iTunes and Safari, it's for every single piece of software running on the computer, from the web browser all the way down to the bottom of the operating system. It's really nice because it means I KNOW my computer is up to date, because if there was a newer version of any program on here, Apt-get would know about it, download it from Ubuntu's servers, and install it for me.


So back to the Google search results. Not surprisingly, Ubuntu Brainstorm was the second result, so I started to read through it (here and here) to see what people had to say, and was a little dismayed by what I saw.

There is a fundamental lack of understanding how the two technologies work.

Strong wrote:
I think this is a bad idea because of security reasons. I want my updates coming from a trusted source and not from 'some' other user. Of course Torrents have a checksum but it's theoretically possible to pad a virus with bogus data so the checksum will match again.

This is assuming that the hash being used is weak. If a peer to peer model were to be used for security updates, a strong hash (ie sha512) would need to be used. I can't find any information on it right away, but I can't believe such a robust protocol as Bittorrent doesn't allow for drop in replacement hashes. (Edit: Looks like Bittorrent uses MD5, but that doesn't matter anyways. Apt uses public-key cryptography to verify packages, so the injection security concerns are moot anyways. The package will be verified before being installed)

Eldmannen wrote:
Also BitTorrent is slow, you must seed, and wait until the speed goes up, because initially its slow.

This is because of a shortage of seeds for a torrent. If a seed is being over-asked for a file, it will look for which peer is the most valuable to the network, which means newer peers are less valuable, and given less bandwidth. The problem is this isn't a standard Bittorrent arrangment. There should be a Bittorrent client running on Ubuntu's mirrors, then the speed of the Bittorrent download is at least the same as over http, since they're both running on the same server. If a new peer is getting shunned by the Ubuntu servers, that means the Ubuntu servers are overloaded, in which case there are probably plenty of other peers to download from, or the network would be slow anyways, so no loss.

Clemdup wrote:
I wonder if p2p is suitable for small files' transfers, locating peers and enqueuing may be huge for 30kb language files...

If I were programming this, one of the first features would be to set a lower bound on file size. Many apt packages are token packages that depend on others and are only a few kB (ie ubuntu-desktop). Between the hash file and negotiating for peers, much more bandwidth would be used than just serving the file.

rgries wrote:
Here on my college campus using bit torrent is against the acceptable use policy so if ubuntu switched to bittorrent for apt updates I would not be able to use ubuntu. Please Don't ruin ubuntu with bittorrent because if it is implemented it would leave many users in the dark as far as updates go.

Apt is designed with many different sources in mind. For example I have mine setup to check for updates to everything from Ubuntu. Then check winehq.com for updates to wine, then check another half dozen websites for updates to their software packages. Ubuntu wouldn't scrap all their http mirrors in favor of Bittorrent. If Bittorrent doesn't work, uncheck that line.

Remmy wrote:
Not everyone's storage space is equal which could lead to serious problems if the disk should become too full.

Apt saves everything it downloads to your hard drive already. Look in /var/cache/apt/archives/ and you'll see every piece of software installed or updated through apt. The Bittorrent client would seed off these files, so there would be no hard drive space loss. There are ways to clean out this cache (apt-get clean) and when this is done so, the Bittorrent seeding would stop.


So all in all, people don't fully understand the technologies being mixed together, and while I agree Bittorrent proper isn't ideal for the workload generated by apt, it's very close and could probably be adapted to work well. The really sad part is that if you scroll down to the very bottom of the comment threads, someone mentions DebTorrent, which is what they're all asking for in the first place anyways. Now Ubuntu just needs to have it be installed be default, and it'll take off. Edit: It is available in Hardy, I'll need to look into how easy it is to get running on a new install.

Adsense Hints at Problem

If you aren't reading this post in the original kennethfinnegan.blogspot.com domain, go there now.

Now look at the ads being served on the side of the page.
I think this emphasizes something I've slowly been admitting to myself for the last month or so. My blog lacks focus and is confusing as all get out.

So two big things:
1. I need to decide if this failure of focus is a downfall worth fixing
2. If it is, I need to find some kind of focus to direct this blog at

So is it better to have a more strongly typed blog that excludes some readers, or the general over arching spattering of topics that I hit now?

And I guess the nasty question at the bottom of all of this, does anyone really care?

Recycling Center Run This Week

For the few people who read this who are local, I'm planning on heading down to the recycling center next weekend, so if anyone's got an old computer sitting around they want to get rid of, give me a call and we can arrange to take care of it.

I always love making this offer with the hope that someone will throw away something useful, be it just a stick of ram or a hard drive, or even an entire computer. Unfortunately one of my friends' family missed the memo and got rid of an entire working computer that I had my eye on. Granted it was a Pentium II, but how much more fun would Project Euler be on such marginal hardware?

Memories from High School

Visited my old High School today for lunch. I have to say it didn't take very long for me to be reminded how much better I've got it in college. It's nice to go back every once and a while and gain some perspective on what I've left behind and how much more I've gained.

I totally forgot how generally unattractive Fremont's female student body is...

Problems with my 40 Meter Radio

So this year my dad decided I should try and get my ham amateur radio license. This would allow me to transmit radio communications on different frequencies and at higher power than the family radios you can buy at your local drug store. For Christmas, he bought me the study guide for the rules exam, and a kit to build your own 40 meter radio receiver.

This kit was the HR40 from Ramsey. Putting it together wasn't that bad at all. Maybe 30 parts total, soldered onto the board, and had to go out and buy a new 9V battery to plug into it.

Then the horrors begin. I plug it in, turn it on, and... nothing. The greatly feared hiss was all I got. I double checked every solder joint, nothing, tried adding a random length of wire as an antenna, nothing, went in my back yard and built a 20 meter long dipole antenna, nothing.

I was stumped. At this point I had run out of time for winter break and left this kit at home as I sludged through winter quarter. Now I have returned for spring break. Great be my luck, my dad managed to pull a working Tektronix oscilloscope out of the salvage bin at his job, so I am now better armed.

I sat down and read the first three pages of the 6 inches of instruction manual. Whoever came up with RTFM forgot to add a clause for how much of the manual you really have to read. I knew enough to be dangerous and started trying to get pretty waves on the scope which I has success with. I found where the signal came out of the oscillator IC and measured it with the scope. Figured out how the digital time measurer worked on this 25 year old oscilloscope, and finally got the money shot.

The sine wave being fed into the audio amp was on the order of 0.260 microseconds. This works out to be... 1/t = f... grumble grumble... 3.8MHz! Now comes the horrible realization: Do the math for 40 meters. Divide the speed of light per second by 40 meters (m/s * 1/m = 1/s), and you get the frequency 7.5MHz. Something is horribly wrong.

I started playing with the different frequency controls. The tuning knob and an adjustable inductor inside the radio, and managed to get the frequency to drift around 3.6MHz - 3.8MHz, but that isn't good enough... I need something at least 7MHz.

So I find the Ramsey website, spend some time reading through other users having problems with the HR40 (useless), and finally break down and email Ramsey tech support yesterday afternoon asking what to try next. This morning I got an email back asking if so and so part was an ISK6883 instead of a K6886, and if so, send them my mailing address and they'll send me the correct capacitors for my radio. Hooray! I love it when technical support correctly guesses the part number. I just emailed them back and we'll see how long it takes them to get me ~1 gram of parts to solder onto my radio to supposedly make it work.

Life just wouldn't be as much fun if everything worked. That's why I'm an engineer.

Thoughts on My Next Project

This idea has been rolling around in my head for the last few weeks.

I haven't been very happy with the websites I've run into on algorithms. I want one that finds the really useful tools in programming and very clearly outlines them and strategies to implementing them.

It would have pages on linked lists, binary trees, queues, mutexes, and even go into less theory and more application algorithms like file locking. There would be nice flow charts mapping out the steps involved and even java applets like the ones floating around for sorting algorithms.

The thing is building another whole website dedicated to this would be a lot of work. Maybe I'll just post random write-ups on algorithms here... Are there any algorithms that readers would find more interesting than others?

Facebook Mirror

Now this one was a surprise to me. Apparently Facebook has a mirror setup for a lot of the major open source projects. Good to see a company with serious tubes giving back to the community of the internets.

http://mirror.facebook.com/

How to Crash Windows Vista Explorer

  • Take flash drive, insert in computer running Linux
  • sudo mkswap /dev/sdb (replace sdb with whatever name Linux assigns your flash drive
  • sudo swapon /dev/sdb
  • swapon -s
  • sudo swapoff /dev/??? (Do this for all other swap partitions listed)
  • Now open enough applications and/or files to get Linux to swap onto the flash drive.

Now you have what looks like a flash drive, but is really a *nix based explorer.exe killer! Plug it into a computer running Vista, Vista will try and auto detect what to do (play music files, display pictures, etc), and then totally crap out on you.

Note: Some times it works and some times it doesn't. I think you might just want to turn off the computer instead of swapoff...

Saturday, March 15, 2008

I've Joined Twitter

Well I did it. I broke down and have joined Twitter. Username: KWF
RSS: http://twitter.com/statuses/user_timeline/14155913.atom

And I got the Terminal updater to work. Here it is if you want to use it:
~/bin/t
#!/bin/sh
curl -u user:password -d status="$1"\
https://twitter.com/statuses/update.xml -k


~/.bashrc
PATH=$PATH:"~/bin"

Usage:
t "This is a new message"

The response will be Twitter confirming that you message got posted in XML. Now the real question is: How do I see everyone else's twits from the command line?

Friday, March 14, 2008

The Tempt of Twitter

So the thought of having a microblog has never really been appealing to me. In addition to this blog, the thought of having another blog full of one liners just didn't seem useful to me.

Thank you Zach Margolis for posting a page on his del.icio.us about using Twitter's API to update it from the command line. For some reason, just the thought of opening a terminal and posting to my blog is appealing to me... I hate you Zach Margolis.

curl -u yourusername:yourpassword -d status="Your Message Here" \
https://twitter.com/statuses/update.xml -k

Then set up an alias so you just need to type something like:
t "Your Message Here"

And you'd be all set.

Happy Pi Day

Happy Pi day everyone. One week till Spring break, then I'm out of here.

Friday, March 7, 2008

Tip of the Day - Aquarium Water for Plants

Every aquarium goes through the Nitrogen cycle. Fish waste and extra food decomposes into ammonia, which bacteria convert into nitrites, which different bacteria convert into nitrates. This is why you need to add fish slowly at first to establish these colonies of bacteria. The end result, nitrates, are still poisonous to fish, although much less than ammonia, which is why you need to do one or two partial water changes a week to dilute the nitrates.

The trick is that these bound nitrates are perfect for plants, so water your house plants or garden with the water removed from your aquarium. Along with the plants getting fertilized, they'd get watered at all, which is easier to remember when it's taking care of the fish at the same time.

Breeding Guppies

I've been spending the last few months dreaming of what I'm going to do with my next aquarium setup. There has been a variety of different ideas, but the one I keep coming back to is breeding Guppies. This isn't an option right now because I am limited to one aquarium in the dorms and my current tank isn't Guppy friendly with both a Betta and a Cichlid.

My interest in breeding Guppies has two goals. The first one is to successfully select traits and engineer my own line of colorful Guppies. My second goal is that live Guppies would make a much better food for my Betta than pellets or flake food, so some of the fry could be skimmed off for that.

I finally got around to hitting up the library today to do some research into the thought. Probably the biggest realization I had was fancy guppies vs wild guppies. Wild, or feeder, guppies are meant to be fed to larger fish, and are sold accordingly. The local pet store sells them for 12 cents a piece.

The interesting part is that, since wild guppies haven't been extensively in-bred, they are much hardier. We have never had great success with fancy guppies, so the thought of getting something a little hardier sounds good to me. It also means I'm going to start with very mixed fish, and can theoretically pick out any trait I want. If I start with a fish with a big red fin, any improvement I make would be minimal, at best.

Here's to next year's projects...

Wednesday, March 5, 2008

Why Fire Alarms are So Loud

So apparently there was a fire alarm last night in my dorm hall. At 1:30am someone on floor three burned some macaroni and set off the alarm. Both my roommate and I both slept through it and I didn't find out until this morning. Spooky...

Tip of the Day - One Dish

I can't take credit for this one as my own, but I have no idea where I read it, so I'll credit it to the tubes as an entity.

As a freshman in college, the thought of living in an apartment is big on my mind. One of the daunting tasks soon at hand will be keeping it clean, especially the kitchen.

So the trick is: you get one plate, one bowl, one fork, one spoon, and one knife. Enjoy...
If you want to eat something, you have to wash a plate for it first. You want to use your spoon; wash it.

Best case scenario: My apartment/house kitchen stays clean.
Worst case scenario: My kitchen sink has 5 dirty dishes in it.

The Power of Matlab

Now here is a language that I have a love-hate relationship with. I hate it so much because every single thing you do uses a different function, or the same function, which does something totally different.
Example: You use one function to find the derivative of two polynomials multiplied together. Now call the function again, with the same two polynomials (which are exactly the same as normal numbers) but ask for two answers instead of one, and it's d/dx (a/b) instead of d/dx (a*b) .

Simple simple simple problems require me to hang off the pages of the Matlab textbook like I'm religious, just because there are so many functions and different uses for the same functions and subfunctions that don't do anything different.

So now for the painful admission of how Matlab is a superior language. It handles numbers really well! (Not surprising, since that's what it's designed for...)

Case in point: The prime sieve
This is a good exercise to keep around for when you're teething on a new language to get a feel for the ropes. How to check for remainders, how to iterate along a list, how to grow a list, etc. My version in C comes up to a total of 69 lines of code, comment free. Matlab? Seven. Seven freakin lines for something that takes more sentences than that to describe.

% Seed the list of primes with 2
primes = 2;

for currnum = 3:100000 % currnum is 3 to BIG NUMBER
% If the number is divisible by any number in the list of primes
% skip on to the next number in the for loop
if (find(mod(currnum, primes)==0))
continue;
end

% Since no multiples were found, add this number to the end of the
% list of primes
primes = [primes currnum]; % Notice how the list just grows as you
% define it as itself and one more
end

So I really hate this language, and really hate the class teaching this language, but I have no choice but to admit that as far as scientists are concerned, this is a great language. I want to know exactly what the computer does when (does the if statement continue to evaluate after finding a multiple?), where when someone is solving a problem, they just want the freakin answer.