Archive for the ‘Geekery’ Category

Giving Android a swap file

Friday, November 20th, 2009

I don't know if it's because I'm doing more with it than I used to, or the rose-tinted specs that come with the novelty value have worn off, or if the later updates have been designed for more powerful hardware, but my G1's been lagging a bit recently, so I figured I'd have a look at what I can do to make it faster. Turns out it's quite receptive to the idea of a swap file.
You'll need root access for this - everything below is to be run as root. Following is how I did it on my cyanogen'd G1, but I don't see why it wouldn't work on anything else - it makes use of standard linux tools. This will likely advance the death of your sdcard - it increases the reads and writes by some large margin. I don't know enough about sdcards to know how much quicker it will die, but modern ones will likely deal with it better than older ones.

Anyway, in your terminal emulator:

dd if=/dev/zero of=/sdcard/swap bs=1M count=100

You can call it whatever you like. The 'count' value (100 above) is how many MB of swap space you want. The above will create 100MB of swap.
This will take a few seconds (of the order of 50), so if it's 'hung' it's probably not crashed.

Then we make it into a swap file and activate it as swap space:

mkswap /sdcard/swap
swapon /sdcard/swap

Finally, we want to change the swappiness of the system. When the system memory is completely full, and more is requested, the kernel needs to work out how to create some space. It, generally, can do one of two things: drop some filesystem cache, or move some application memory to swap.
The swappiness value dictates the priority of either - a value of 0 means it will always try to drop fs cache rather than use swap, and a value of 100 means it will always try to use swap and preserve the fs cache. Only values between 0 and 100 inclusive are allowed, and neither guarantees any action - you can still find yourself swapping out at 0, for example - just the priority afforded each solution.
The default value for the Linux kernel is 60, which is generally not appropriate for something running completely from flash media (where the fs cache isn't so important). So I'm dropping it to 20, which seems to work for me. If it doesn't for you, try some other values, it's an on-the-fly change.

echo 20 > /proc/sys/vm/swappiness

On rebooting the phone, the above settings wont hold. The swap file will still be available (assuming the SD card is still inserted), but on reboot you'll need to run

swapon /sdcard/swap
echo 20 > /proc/sys/vm/swappiness

On the plus side, you'll be rebooting less.

Cyanogen on my G1

Saturday, November 14th, 2009

I've just upgraded to Cyanogen on my G1 and it's lovely. Well, I got root, which is basically what I always wanted.

I basically followed the instructions on the Cyanogen wiki and everything worked exactly as described, I've nothing really to add here except to say it's brilliantly easy and everyone should do it.
One small note, though, the final reboot into Cyanogen takes a long time. Mine took just shy of thirty minutes, and I've read of others taking anything above about 15.

The first obvious benefits are root access, exchange activesync support, five workspaces (as against the stock 3) and a bunch of useful apps already installed, including a nifty power control widget which replaces my collection of 5 distinct widgets. I'll write more on it when I've used it more.
In case, as I did, you've been pondering this and wondering what the end result is like, it's almost exactly as previously, but with some new features, there's some screenshots on the webpage. I've not yet found anything to have been degraded by it, and it all looks and feels the same, but a bit more polished in areas. Though it only ships with one ringtone.

PHP error on fresh install of PHPWiki:
Non-static method _PearDbPassUser::_PearDbPassUser() cannot be called statically

Thursday, November 12th, 2009

I've just installed PHPWiki 1.3.14-4 from the debian repositories and out of the box I got the following message on trying to log in to it:

Fatal error: Non-static method _PearDbPassUser::_PearDbPassUser() cannot be called statically, assuming $this from incompatible context in /usr/share/phpwiki.bak.d/lib/WikiUserNew.php on line 1118

The problem appears to be that, as of PHP 5.something, you're not allowed to have a function with the same name as a class. Apparently it's been a failure in E_STRICT mode for a while.

Anyway, the solution is to rename _PearDbPassUser() to something else, and then replace all calls to it with this new name.

I've done this and, so far, everything appears to work.

The function is defined in /usr/share/lib/phpwiki/lib/WikiUser/PearDb.php:

 
jup-linux2:/usr/share$ diff phpwiki.bak.d/lib/WikiUser/PearDb.php phpwiki/lib/WikiUser/PearDb.php
18c18
< function _PearDbPassUser($UserName='',$prefs=false) {
---
>     function _PearDbPassUserFoo($UserName='',$prefs=false) {
 

and is called in /usr/share/WikiUserNew.php:

 
jup-linux2:/usr/share$ diff phpwiki.bak.d/lib/WikiUserNew.php phpwiki/lib/WikiUserNew.php
1118c1118
< _PearDbPassUser::_PearDbPassUser($this->_userid, $this->_prefs);
---
>                 _PearDbPassUser::_PearDbPassUserFoo($this->_userid, $this->_prefs);
1157c1157
< _PearDbPassUser::_PearDbPassUser($this->_userid, $prefs);
---
>                 _PearDbPassUser::_PearDbPassUserFoo($this->_userid, $prefs);
2120c2120
< function PearDbUserPreferences ($saved_prefs = false) {
---
>     function PearDbUserPreferencesFoo ($saved_prefs = false) {
 

Munin plugins are really easy to write

Wednesday, November 11th, 2009

Munin plugins basically need to output variable names and values, and a little bit of config. They're tremendously easy to write.

My plugin is mostly useless - it graphs the value returned by /dev/urandom, and the random constants from debian and dilbert. Current graph is here and the code is as follows:

#! /bin/bash
 
case $1 in
        config)
        cat < < EOF
graph_category amusement
graph_title Random numbers
graph_vlabel value
debian.label debian
dilbert.label dilbert
urandom.label /dev/urandom
graph_scale no
EOF
        exit 0
esac
 
urandom=$(cat /dev/urandom | tr -dc '0-9' | head -c2)
 
echo "urandom.value " $urandom
echo "debian.value 4"
echo "dilbert.value 9"
 

Munin's plugins live in /etc/munin/plugins/, most of which are symlinks to scripts in /usr/share/plugins/. On restart, munin-node rechecks the plugins directory and loads any new plugins.
For a plugin called foo, munin-node will run foo configure first to get the configuration of the graph (which is passed to munin-graph), and then foo. For information as to graph configuration, see here.
It takes about 15 mins of collection for it to start making a graph, and you'll get more data every 5mins thereafter.

The script itself is mostly self-explanatory, except for:

- The values and the labels are linked by what occurs before the dot. If you define foo.label in the config output, that is what will be used to label the number that comes after foo.value in the 'normal' output. The munin tutorial sort-of hints at this, but only uses one variable.

- Munin doesn't care what order the variables come out in, it uses the labels to determine who's who. Similarly, it doesn't seem particularly fussed as to which flavour of horizontal whitespace is used.

Android G1 factory reset

Tuesday, November 10th, 2009

With the phone off and the battery in, press and hold <power>+<back> for 20 seconds or so. You'll get the standard G1 splash screen, then a screen with an exclamation mark.

Press <alt>+<L> to get to the System Recovery screen. Here you're presented with four options:

reboot system now [Home+Back]
apply sdcard:update.zip [Alt+S]
wipe data/factory reset [Alt+W]
wipe cache partition

Which you should be able to choose from with the scrollball or use the key combinations for.

DDR RAM identification and naming conventions

Tuesday, November 3rd, 2009

All (modern) PC memory is SDRAM (Synchronous Dynamic RAM). DRAM, the predecessor, responded to requests as soon as it could after the control voltages changed, SDRAM replies according to a clock cycle (which synchronises it with the system bus).

Pretty much all modern PC memory is also DDR, Double Data Rate. With Single Data Rate RAM, data is only sent when the timing signal is high1. The clock signal is high for some period of time, then low for another period of time of the same length. One cycle consists of one high period and one low period. Single Data Rate RAM can only transmit at one of these, DDR at both.

DDR is then further subdivided into DDR, DDR2 and DDR3. Though the voltages are different (2.5v, 1.8v, 1.5v respectively), the big difference in practical terms is the socket shape:



While we're here, it's worth noting that the most commonly-used difference between DDR and DDR2 RAM, the notch position, is frightfully difficult to identify without an example of the other type against which to compare. More obvious is the gap between the contacts and the notch on the DDR stick (to the right of the notch in the above pic), which is absent on the DDR2 stick.

There are two ways people refer to DDR RAM, as a DDR-XXX or PC-XXXX. For example, DDR200 is also PC1600.
The 200 in DDR200 is the clock rate of the memory modules (the chips on the memory stick). It is double the clock speed of the system it's plugged into, since it is DDR (and so operates twice per cycle).
The 1600 in the PC1600 is the maximum number of bytes per second that the RAM allows, and is not achievable in the real world.

To calculate one from the other, we do

TransferRate = SystemClockRate x DataRate x NumberOfBytesTransferred / NumberOfBitsPerByte
TransferRate = SystemClockRate x 2 x 64 / 8
TransferRate = SystemClockRate x 16
 

Since we're concerned with Dual Data Rate memory, the data rate is equal to two. It transfers 64 bytes per cycle, and each of those bytes is 8 bits long.
The SystemClockRate is the frequency of the system bus, not of the memory itself - DDR200 operates at a frequency of 200MHz, but requires a system with a clock of 100MHz. In order to find the TransferRate given the MemoryFrequency we need to do

 
TransferRate = SystemClockRate x 16
   but SystemClockRate = MemoryFrequency x 0.5
TransferRate = MemoryFrequency x 0.5 x 16
TransferRate = MemoryFrequency x 8
 

Hence 200 x 8 = 1600 means we'd expect DDR200 to give a theoretical maximum of 1600Bps, and so be PC1600.

The above are all maxima - DDR can operate at lower frequencies than its maximum. DDR266, while expecting a 133MHz system bus, can run satisfactorily in a 100MHz system, but it will only operate as DDR200.

Below are the combinations implemented in the real world:

DDR200 PC1600
DDR266 PC2100
DDR333 PC2700
DDR400 PC3200
DDR2-400 PC2-3200
DDR2-533 PC2-4200
DDR2-667 PC2-5300
DDR2-800 PC2-6400
DDR2-1066 PC2-8500
DDR3-800 PC3-6400
DDR3-1066 PC3-8500
DDR3-1333 PC3-6400
DDR3-1600 PC3-12800

The above is basically an aggregation and condensation of what is in the following articles. If you want more detail, go there:
http://en.wikipedia.org/wiki/DDR_SDRAM
http://www.hardwaresecrets.com/article/167/1

  1. or low. I don't actually know, but It's mostly immaterial. The important bit is that it's an 'or' not an 'and'. []

Simple complex password generator

Friday, October 30th, 2009

These are really easy to write, but it's always handy to have your own. This one lives here in its cgi form.

#! /usr/bin/perl
 
use strict;
use warnings;
 
## Let the browser know what we're sending it
print "content-type: text/html\n\n";
 
## Spew some HTML since we're not going to get away with plain text formatting
print "<html>\n\t<head>";
print "\t\t<title>Passwords!</title>";
print "\t</head>";
print "<body>\n\t
<h1>Avi's Magical Password Generator</h1>
 
";
 
## Define two sets of data. The first is the lengths of password we want
## to produce, the second is the allowed characters. Each space-separated
my $lengths="1 4 8 10 20 30 50 80 100";
my $characters="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 0 ! $ % ^ & _ + = : ; @ # ~ , . ? ";
 
## Split the above by space into arrays
my @chars=split(/ /, $characters);
my @lens=split(/ /, $lengths);
 
## Work out how many characters we are allowed, so that when we
## come to pick one at random we can use this number as the maximum.
my $chars_count = @chars;
 
## Spew out some html for pretty formatting:
print "
<table>\n";
print "\t
<tr>
<td>length</td>
<td></td>
</tr>
 
";
 
## The loop!
foreach (@lens){
	my $length=$_;
	my $count;
	## The first cell of the row, containing the length:
	print "\n\t
<tr>
<td>".$_."</td>
<td>";
	for ($count = 1; $count < = $length; $count++){
		## Working backwards, $chars_count is the above-defined
                ## number of characters we have to play with,
                ## rand($chars_count) picks a random number between 0 and
                ## $chars_count, and int(rand($chars_count)) makes sure
                ## it's an integer. This in the square brackets after $chars
                ## means we're picking a random element out of the array
                ## @chars, which is effectively picking a random character
                ## out of the list of allowed ones.
		print $chars[int(rand($chars_count))];
	}
	print "</td>
</td>
</tr>
 
\t\t\n";
}
print "</table>
 
\n\n";
 
print "<a href=./password.txt>sauce</a> <a href=..>home</a>";
print "</body>";</html>

*buntu 9.10

Thursday, October 29th, 2009

It's out! Torrents here and here.

Some notes from configuring rTorrent

Wednesday, October 28th, 2009

In anticipation of the new *buntus tomorrow, I'm configuring one of my servers as a torrent node for it, and for reasons unknown I've settled on rtorrent which is in the repos. The documentation is a little lacking (but does tell you how to do things like download torrents. Read it), and the most popular HowTo is quite verbose.

~/.torrentrc is the config file for rtorrent. The one from the Debian repos puts an example in /usr/share/doc/rtorrent/examples/rtorrent.rc, and apparently so does *buntu. You probably want to edit this. Path variables can be absolute or relative, and are generally relative and inside ./ by default. I've two directories, ~/torrents/ for the torrents and ~/.rtorrent/ for rtorrent's working directories.
Some variables I found to be handy:

scgi_local="~/.rtorrent/socket/rpc.socket"

Defines the socket file for scgi communication, which you only really need if you want external stats from it. I did, but haven't yet got round to using them.

session = ~/.rtorrent/sessio

The session directory, which lets multiple instances of rtorrent remember where they left off. Cannot be shared between instances.

Scheduling
rtorrent supports command scheduling, the syntax for which is occasionally documented. The syntax is approximately:

schedule = a,b,c,d

Where
a: What you want to call this scheduled command1.
b: How many seconds after rtorrent starts you want to first execute the command.
c: The interval for subsequent executions.
d: the command you want to execute.
This comes in most handy for auotmatically starting torrents in a directory:

schedule = watch_directory,5,5,load_start=~/torrents/*.torrent

Exactly what that does is left as an excercise to the reader (the example .rtorrent.rc explains, too).

  1. I don't know where this comes in handy later on []

Removing user list on Ubuntu Karmic log-on screen

Friday, October 23rd, 2009

This doesn't work any more
Install XDM instead. ;)

Karmic ships with a new version of GDM (2.28) which is rewritten, and by default presents a list of usernames, in much the same way as XP does by default. Lots of people dislike this. It's also currently lacking a graphical config tool (it is in beta...).

To change it, run this:

 
# gdm gconftool-2 --set --type boolean /apps/gdm/simple-greeter/disable_user_list true
 

This, I feel, is non-ideal since it just replaces the users list with a 'log in' Window and button which is completely superfluous - if I'm at the logon screen, I probably do want to log onto the PC, and the most logical thing for it to do is to be already asking for my username, ideally with that text box in focus. The previous login screen was pretty much ideal, and I'm not sure what benefit the new one has.

Source: https://answers.launchpad.net/ubuntu/+source/gdm/+question/86506