Web applications can be traced or debugged on many layers. The highest layer would be what some frameworks like symfony provide in their development consoles. Another layer would be to look at output from php-xdebug in kcachegrind to do profiling. But the lowest possible level is to look at actual system calls used by a running application.

FreeBSD has a base system utility called ktrace. It allows administrator to attach to a running process and log all system calls used by the process. How to use it to trace a web application running under apache?

First apache has to be started in debug mode, with only one worked running. This will make finding the apache process running our application easier to find.

This is how to start apache in debug mode:

httpd -X &
[1] 34702

Running this in the background will return the ID of the process: 34702. Now, all we have to do is to attach ktrace to this process:

ktrace -dip 34702

option “-d” means that all descendants (current child processes) of the process will also be traced and option “-i” means that all process spawned by our process will also be traced. “-p” option is used to give the PID of the traced process.

at this point we can run our application from the browser and after doing so take a look at system calls used. Ktrace saves all system calls to a ‘ktrace.out” file in the current directory. kdump utility is used to display contents of this file:

kdump -R

“-R” option will display time taken between entries so we can estimate how long a syscall took to finish.

we can detach ktrace and stop tracing the process by:

ktrace -C

nothing new or special but certainly worth joting down :) What’s done in MySQL with auto_increment statement in PosgteSQL is a bit more complicated. It requires creating a sequence first:

CREATE SEQUENCE exp_seq;

and then using it in table definition:

CREATE TABLE exp (id INT NOT NULL PRIMARY KEY DEFAULT nextval(‘exp_seq’), other varchar(30), created_at date);

Sequences are actually more powerfull than MySQL’s auto_increment as they have some interesting options. One of them is INCREMENT BY which can be very useful with some multiple master replication or multiple servers scenarios.

Operations allowed on sequences are: nextval, currval and setval.

This is a follow-up to the previous post. Instead of having your disks mounted read-write and have them broken by an unexpected reboot why not run them in read-only mode instead? Especially if your file systems are stored on a CompactFlash card and shouldn’t be written to too often anyway. If mounted read-only your partitions are never marked dirty and don’t even require fsck to be run during boot (so having fastboot enabled is fine in this case).

First of all, lets just assume that there is only one partition on the system (the root partition – /). It’s not impossible to change it’s mount options to ro and boot your system this way. OpenBSD will actually boot fine, but it will complain a bit.. First of all, it will complain about some parts of the /var subtree not being writeable. Syslog won’t certainly like not being able to write to /var/log/*, and other daemons might not like read-only /var/run and /tmp directories. Additionally, some daemons really need write access to some devices in /dev. So this is not ideal solution.

A slightly better one is to have your / partition mounted read-only and have /var /tmp and /dev mounted read-write from memory based file systems. A sample /etc/fstab doing this would look like this:

/dev/wd0a / ffs ro,noatime 1 1
swap /tmp mfs rw,noatime,nodev,nosuid,-s=20000 0 0
swap /var mfs rw,noatime,nodev,nosuid,-s=40000 0 0
swap /dev mfs rw,noatime,nosuid,noexec,-s=20000 0 0

This creates 10MB /tmp and /dev file systems and 20MB /var. The only problem now is that /var and /dev partitions are empty and we need to recreate their structure in order to make OpenBSD happy.

First, the /var parition needs all subdirectories created, this is easily done with mtree:

mtree -qdef /etc/mtree/4.4BSD.dist -p / -u

The /dev partition needs all devices created. This is usually done by running the MAKEDEV script located in /dev. Since we’re creating a new, blank /dev directory we need to make a copy of the MAKEDEV script:

cp /dev/MAKEDEV /root/

now, after mounting our memory based /dev we can do:

cd /dev; sh MAKEDEV all

and all devices should be created for us.

This all should be done during the boot process, this patch does that:

— rc.orig    2008-10-06 17:01:58.000000000 +0100
+++ rc    2008-10-06 17:03:18.000000000 +0100
@@ -212,6 +212,8 @@
mount -a -t nonfs,vnd
mount -uw /        # root on nfs requires this, others aren’t hurt
rm -f /fastboot        # XXX (root now writeable)
+mtree -qdef /etc/mtree/4.4BSD.dist -p / -u
+cp /root/MAKEDEV /dev; cd /dev; sh MAKEDEV all

random_seed

after applying the patch (don’t forget to copy the MAKEDEV file!!!) and rebooting we should have a working OpenBSD server which can survive random power loses without disk. What if you need to upgrade your system or change some config files? Easy, just remount your root file system:

mount -u -o rw /

When OpenBSD boots it checks all file system with fsck in preen mode. In this mode fsck not only checks file systems but can also frepair minor problems such as:

  • Unreferenced inodes
  • Link counts in inodes too large
  • Missing blocks in the free map
  • Blocks in the free map also in files
  • Counts in the super-block wrong

All these problems are correctable without any data loss. However, when something more serious happens to your file system, fsck -p won’t even try repairing it, it will exit with an error and wait for the administrator to make the decision of what and how should be repaired. This means that the boot procedure will be stopped and the system will drop to shell and wait for manual intervention.

What an admin usually does to fix it at this time is to run fsck or fsck -y by hand. This requires console access to manually type these commands and respond to fsck’s prompts.

FreeBSD has an rc option called fsck_y_enable to automate this process so it doesn’t require manual intervention.

This simple patch adds something similar to OpenBSD’s rc script.

This is something new I’ve just learned that only exists on OpenBSD. Up until today I thought that the only way to manually failover a carp setup was to down the carp interface on the master.

It looks like there is an easier way of doing it on OpenBSD. In fact OpenBSD uses this feature itself during the boot process. Just before setting up all interfaces it “demotes” all carp interfaces so they won’t become master interfaces for their ip addresses until all enabled system daemons, pf, ipsec etc have been configured and started. After that the whole carp group of interfaces is put back to the neutral state and they can become master interfaces (if there is no advskew set on them).

How is it done?

OpenBSD has this concept of groups of interfaces. It’s easy to spot it when you do ifconfig:

# ifconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 33208
groups: lo
inet 127.0.0.1 netmask 0xff000000
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0×3
vic0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:0c:29:9c:5e:57
groups: egress
media: Ethernet autoselect
status: active
inet 172.21.33.5 netmask 0xffffff00 broadcast 172.21.33.255
inet6 fe80::20c:29ff:fe9c:5e57%vic0 prefixlen 64 scopeid 0×1
enc0: flags=0<> mtu 1536
carp0: flags=8803<UP,BROADCAST,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:00:00:00:00:00
groups: carp

Each interface has its own default group (or groups). The default group for all carp interfaces is… the carp group! You can create your own groups and add interfaces to them. An interface can belong to multiple groups. Here’s how to create a new group and add carp0 to it:

# ifconfig carp0 group mygroup
# ifconfig carp0
carp0: flags=8803<UP,BROADCAST,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:00:00:00:00:00
groups: carp mygroup

and here is how to remove it :)

# ifconfig carp0 -group mygroup
# ifconfig carp0
carp0: flags=8803<UP,BROADCAST,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:00:00:00:00:00
groups: carp

All groups have this additional property called the demote count which is used by carp during the master election process. Using this property you can demote a group of interfaces:

# ifconfig -g carp carpdemote 128

and promote it back:

# ifconfig -g carp -carpdemote 128

and you can see the current value:

# ifconfig -g carp
carp: carp demote count 0

So how is this better than downing all your carp interfaces by doing something like this:

for i in `ls /etc/hostname.carp*`; do echo $i | awk -F. ‘{print $2}’ | xargs -I% ifconfig % down; done

When you down your carp interface they no longer take part in the whole “carp process”. Basically since they are down they no longer advertise their presence and cannot be elected as masters. So if your backup server dies and all carp interfaces on your master are down you loose your connectivity.

Carp demote counter acts in a bit similar way to advskew but has higher precendence over it. So a carp interface with advskew set to 0 and demote counter set to 10 will be ranked lower (and become slave) than another carp interface with advskew 100 and demote counter set to 0.

Plus, by logically groupping carp interfaces you can failover only one group at a time, and when you have a lot of interfaces this is certainly easier then using ifconfig down.

Flash clients don’t comply with the XMPP protocol. This is due to some limitation/security features in the flash itself. The problems are:

  • flash sends null terminated stanzas and expects the same from the server
  • opening stream header is a bit different than expected. In case of a flash client it’s:
    <flash:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='' from='' />

There are currently only two jabber servers I could find with support for this:

  • openfire, which is obvious since they also provide a flash based jabber client with their jabber server solution
  • ejabber with this patch applied. After patching ejabber needs to be recompiled with the –enable-flash-plugin option passed to the configure script.

Although FreeBSD runs under VMware  and there’s even an option for it in the GUI management tool, it doesn’t run perfectly.

timekeeping

The first problem with FreeBSD under VMware is time synchronisation. After running FreeBSD for a few minutes you’ll notice that its timer is completely out of sync comparing with the host’s timer. This is mainly due to the nature of virtualization provided by VMware connected with FreeBSD’s kernel tick value.

By default the kernel ticks every 1/1000 second which is too frequently for VMware based virtualized environment. The number of ticks per second can be adjusted either by adding HZ=100 to your kernel config file and recompiling it or by adding kern.hz=100 to /boot/loader.conf and rebooting your server.

100 is just a suggested value (it actually used to be the default value in older versions of FreeBSD) but something smaller than that, like 50 or 20, might work better for you.

on top of these changes you should also run ntpd!

network performance

Network performance can be tuned a bit by using a different ethernet card emulation in your VMware. So instead of using a driver for an AMD card, change it to the em driver for Intel cards. This requires editing the .vmx file describing your virtual server and adding:

ethernet0.virtualDev=”e1000″

You have to restart your virtual server for these changes to take place.

Imagine you have a FTP server behind your NAT/firewall server and you want to (or rather have to, because why would you really _want_ to do it?) give access to this FTP from outside world.

As FTP is a really crazy old protocol it’s not as easy as with HTTP or POP3 where you only have to redirect one port. With FTP there are actually two connections established, one on port 21 which is used to control the FTP session and is used to send commands, and the other connection is used to transfer data. The problem is with the other connection, which doesn’t usually have one set port that it would use, instead it’s port is negotiated everytime you want to download something. So what you need is a tool that will open and redirect ports needed for data session based on what’s being negotiated in the control session.

Here’s how to do it on OpenBSD using ftp-proxy and a few simple pf rules.

My internal network is 172.21.33.0/24 and my gateway’s IP on this network is 172.21.33.1. FTP server’s IP is 172.21.33.5. First, we have to set up ftp-proxy daemon in reverse-proxy mode. It’s option -R with FTP server’s IP, so add

ftpprooxy_flags="-R 172.21.33.5"

to /etc/rc.conf.local and starting the deamon manually (it will start automatically after the next reboot)

# /usr/sbin/ftp-proxy -R 172.21.33.5

Now all you have to do is to edit your /etc/pf.conf file and add

rdr-anchor "ftp-proxy/*"
rdr pass on $ext_if proto tcp from any to $ext_if port 21 -> 127.0.0.1 port 8021

before your redirection rules

nat-anchor "ftp-proxy/*"

before your nat rules

and finally, before your filtering rules:

anchor "ftp-proxy/*"

pf will use these anchors to dynamically create rules needed for new FTP sessions. That’s it, reload pf and test everything.

I couldn’t find on symfony’s website what options you can pass to the object_select_tag function. It’s definition looks like this:

function object_select_tag($object, $method, $options = array(), $default_value = null)

and options can be:

  • peer_method – peer method you want to use to fetch options. useful for sorting, limiting output etc.
  • text_method – method used to display labels for your options
  • include_custom – your customized option
  • include_title – creates a title for the whole selection based on the name of the called method
  • include_blank – adds blank (“”) option to your select tag

I’m not sure if it’s the best way of doing it, but this method of creating web services with wso2 works for me. A bonus here is that it doesn’t involve creating or modyfying any XML/WSDL files as all this is autogenerated or handled by the framework itself.

This example service will return N random digits from a given range.

wsdl autogeneration

wso2 has a nice feature of generating wsdl files based on service configuration. It can do even better than that – it can generate a wsdl file for your service based on the comments you use for functions that describe your service. Of course these comments have to be in a special format, but this format is nothing else than dotproject-style comments that can be used to automatically document your code. Here is an example, it doesn’t implement anything yet, it’s only used to generate a wsdl definition. To avoid URL changes in the service location specified in the generated wsdl I’m creating it in random/index.php in my web server’s root directory, which will be replaced by the service implementation later on:

<?php
/**
* @namespace http://server.com/random
*/

class RandomNumber
{
/**
* @var integer $number
*/

public $number;
}

/**
* @param integer $num number of random digits
* @param integer $min minimum random number
* @param integer $max maximum random number
* @return array of object RandomNumber $numbers array of random numbers generated
*/

function getRandom($num, $min, $max)
{
return new RandomNumber();
}

$service = new WSService(array("operations" => array("getRandom")));
$service->reply();
?>

When you access http://server.com/random/?wsdl you’ll get your wsdl file generated for the service documented above. Save it in your services directory as random.wsdl.

service and client autogeneration

Now we can use this file to generate both a service template and a sample client template.

In wso2-php package there is a file called wsdl2php.php. Use it to generate both templates:

> php wsdl2php.php -s random.wsdl > server.php
> php wsdl2php.php random.wsdl > client.php

you can keep a copy of your index.php file used to generate the wsdl file and replace it with the generated server.php

> cp index.php generate.php; mv server.php index.php

service implementation

At this point you can implement your service, edit your index.php file, read the comments there, and add this simple implementation to the getRandom function:

$response = new getRandomResponse();
for ($i = 1; $i >= $input->num; $i++) {
  $n = new RandomNumber();
  $n->number = rand($input->min, $input->max);
  $response->numbers[] = $n;
}
return $response;

implementation of a sample client

and now modify your client to test it, under //TODO fill in the class fields of $input to match your business logic add:

$input->num = 10;
$input->min = 1;
$input->max = 100;

and implement the business logic to consume your response:

foreach ($response->numbers as $n) {
  printf("%d", $n->number);
}

Start client.php in your browser – you should be able to see 10 randomly generated numbers ;)