Open BigPipe javascript implementation

We have released our open BigPipe implementation written for IRC-Galleria which is implemented by loosely following this facebook blog. The sources are located at github: and there’s an example demonstrating the library in action at

BigPipe allows speeding up page rendering times by loading the page in small parts called pagelets. This allows browser to start rendering the page while the php server is still processing to finish the rest. This transforms the traditional page rendering cycle into a streaming pipeline containing the following steps:

  1. Browser requests the page from server
  2. Server quickly renders a page skeleton containing the <head> tags and a body with empty div elements which act as containers to the pagelets. The HTTP connection to the browser stays open as the page is not yet finished.
  3. Browser will start downloading the bigpipe.js file and after that it’ll start rendering the page
  4. The PHP server process is still executing and its building each pagelet at a time. Once a pagelet  has been completed it’s results are sent to the browser inside a <script>BigPipe.onArrive(…)</script> tag.
  5. Browser injects the html code received into the correct place. If the pagelet needs any CSS resources those are also downloaded.
  6. After all pagelets have been received the browser starts to load all external javascript files needed by those pagelets.
  7. After javascripts are downloaded browser executes all inline javascripts.

There’s an usage example in example.php. Take a good look on it. The example uses a lot of whitespace padding to saturate web server and browser caches so that the bigpipe loading effect is clearly visible. Of course these paddings are not required in real usage. There’s still some optimizations to be done and the implementation is way from being perfect, but that hasn’t stopped us from using this in production.

Files included:

  • bigpipe.js Main javascript file
  • BigPipe class php file
  • Pagelet class php file
  • example.php Example showing how to use bigpipe
  • test.js Support file for example
  • test2.js Support file for example
  • Browser.php Browser detection library by Chris Schuld (
  • prototype.js library
  • prototypepatch.js Patches for prototype

How NoSQL will meet RDBMS in the future

The NoSQL versus RDBMS war started a few years ago and as the new technologies are starting to get more mature it seems that the two different camps will be moving towards each other. Latests example can be found at where the author talks about upcoming postgresql feature where the application developer can choose the service level and consistency of each call to give hint to the database cluster what it should do in case of database node failure.

The exact same technique is widely adopted in Cassandra where each operation has a consistency level attribute where the programmer can decide if he wants full consistency among entire cluster or is it acceptable if the result might not contain the most up to date data in case of node failure (and also gain extra speed for read operations) . This is also called Eventual Consistency.

The CAP theorem says that you can only have two out of three features from a distributed application: Consistency, Availability and Partition Tolerance (hence the acronym CAP). To give example: If you choose Consistency and Availability, your application cannot handle loss of a node from your cluster. If you choose Availability and Partition Tolerance, your application might not get most up-to-date data if some of your nodes are down. The third option is to choose Consistency and Partition Tolerance, but then your entire cluster will be down if you lost just one node.

Traditional relation databases are designed around the ACID principle which loosely maps to Consistency and Partition Tolerance in the CAP theorem. This makes it hard to scale an ACID into multiple hosts, because ACID needs Consistency. Cassandra in other hand can swim around the CAP theorem just fine because it allows the programmer to choose between Availability + Partition Tolerance  and Consistency + Availability.

In the other hand as nosql technology matures they will start to get features from traditional relation databases. Things like sequences, secondary indexes, views and triggers can already be found in some nosql products and many of them can be found from roadmaps. There’s also the ever growing need to mine the datastorage to extract business data out of it. Such features can be seen with Cassandra hadoop integration and MongoDB which has internal map-reduce implementation.

Definition of NoSQL: Scavenging the wreckage of alien civilizations, misunderstanding it, and trying to build new technologies on it.

As long as nosql is used wisely it will grow and get more mature, but using it without good reasons over RDBMS is a very easy way to shoot yourself in your foot. After all, it’s much easier to just get a single powerfull machine like EC2 x-large instance and run PostgreSQL in it, and maybe throw a few asynchronous replica to boost read queries. It will work just fine as long as the master node will keep up and it’ll be easier to program.

Good analysis paper over Stuxnet worm

The W32.Stuxnet worm has raised quite much discussion as its been analysed and technical details about its construction has been revealed. Stuxnet is special because it’s very complex and its targeted to attack very specific set of industrial process computers. These and other worm characteristics hints that the worm was created by a government  sponsored virus laboratory.

Some notable Stuxnet features include:

  • Four zero day exploits to windows operating system.
  • Stolen driver authentication certificates, including two from Realtek
  • Targeted to specific installation – it didn’t infect if it found to be in wrong computer.
  • Very installation specific payload which altered the process of the industrial control operations.

The following quote from [] sums up all this pretty well:

The attack combines an awful lot of skills — just think about the multiple 0day vulnerabilities, the stolen certificates etc. This was assembled by a highly qualified team of experts, involving some with specific control system expertise. This is not some hacker sitting in the basement of his parents house. To me, it seems that the resources needed to stage this attack point to a nation state.

Read the full analysis paper at

Also read the symantec blog at

Example how to model your data into nosql with cassandra

We have built a facebook style “messenger” into our web site which uses cassandra as storage backend. I’m describing the data schema to server as a simple example how cassandra (and nosql in general) can be used in practice.

Here’s a diagram on the two column families and what kind of data they contain. Data is modelled into two different column families: TalkMessages and TalkLastMessages. Read more for deeper explanation what the fields are.

TalkMessages contains each message between two participants. The key is a string built from the two users uids “$smaller_uid:$bigger_uid”. Each column inside this CF contains a single message. The column name is the message timestamp in microseconds since epoch stored as LongType. The column value is a JSON encoded string containing following fields: sender_uid, target_uid, msg.

This results in following structure inside the column family.

"2249:9111" => [
  12345678 : { sender_uid : 2249, target_uid : 9111, msg : "Hello, how are you?" },
  12345679 : { sender_uid : 9111, target_uid : 2249, msg : "I'm fine, thanks" }

TalkLastMessages is used to quickly fetch users talk partners, the last message which was sent between the peers and other similar data. This allows us to quickly fetch all needed data which is needed to display a “main view” for all online friends with just one query to cassandra. This column family uses the user uid as its key. Each column
represents a talk partner whom the user has been talking to and it uses the talk partner uid as the column name. Column value is a json packed structure which contains following fields:

  • last message timestamp: microseconds since epoch when a message was last sent between these two users.
  • unread timestamp : microseconds since epoch when the first unread message was sent between these two users.
  • unread : counter how many unread messages there are.
  • last message : last message between these two users.

This results in following structure inside the column family for these
two example users: 2249 and 9111.

"2249" => [
  9111 : { last_message_timestamp : 12345679, unread_timestamp : 12345679, unread : 1, last_message: "I'm fine, thanks" }

"9111" => [
  2249 : { last_message_timestamp :  12345679, unread_timestamp : 12345679, unread : 0, last_message: "I'm fine, thanks" }

Displaying chat (this happends on every page load, needs to be fast)

  1. Fetch all columns from TalkLastMessages for the user

Display messages history between two participants:

  1. Fetch last n columns from TalkMessages for the relevant “$smaller_uid:$bigger_uid” row.

Mark all sent messages from another participant as read (when you read the messages)

  1. Get column $sender_uid from row $reader_uid from TalkLastMessages
  2. Update the JSON payload and insert the column back

Sending message involves the following operations:

  1. Insert new column to TalkMessages
  2. Fetch relevant column from TalkLastMessages from $target_uid row with $sender_uid column
  3. Update the column json payload and insert it back to TalkLastMessages
  4. Fetch relevant column from TalkLastMessages from $sender_uid row with $target_uid column
  5. Update the column json payload and insert it back to TalkLastMessages

There are also other operations and the actual payload is a bit more complex.

I’m happy to answer questions if somebody is interested :)

Cassandra operation success ratio survey results

It’s known that in Cassandra the compaction hurts the node performance so that the node might miss some requests. That’s why it’s important to handle these situations and the client needs to retry the operation into another working host. We have been storing performance data from each cassandra request which we do into our five node cassandra production cluster.

We log the retry count and request type into our data warehouse solution and I’ve now extracted the data from a 10 day period and calculated how many retry requests is needed so that the results can be obtained. The following chart tells how many time an operation had to be retried until it was successfully completed. The percents tells the probability like that “the request will be successful with the
first try in 99.933 % times.”

Total amount of operations: 94 682 251 within 10 days.

Retry times operations percentage from total operations
0 94618468 99.93263 %
1 56688 0.05987 %
2 5018 0.00529 %
3 1359 0.00144 %
4 111 0.00012 %
5 25 0.00003 %

There were also few operations which needed more than five retries, so preparing to try up to ten times is not a bad idea.

The cluster users 0.6.5 with RF=3. Dynamic Snitching was not enabled.  Each operation is executed until it succeeds or until 10 retries using this php wrapper

Hotswapping disk in OpenSolaris ZFS with LSI SATA card

One of my disks in a raidz2 array crashed a few days ago and it was time to hotswap a disk. zpool status showed a faulted drive:

raidz2    DEGRADED     0     0     0
  c3t6d0  ONLINE       0     0     0
  c3t7d0  FAULTED     27 85.2K     0  too many errors
  c5t0d0  ONLINE       0     0     0
  c5t1d0  ONLINE       0     0     0

The disk is attached into an LSI Logic SAS1068E B3 SATA card which has eight SATA ports. I used lsiutil to find out that there were indeed some serious problems with the disk:

Adapter Phy 7:  Link Up
  Invalid DWord Count                                     306,006
  Running Disparity Error Count                           309,292
  Loss of DWord Synch Count                                     0
  Phy Reset Problem Count                                       0

I’m not sure what “Invalid DWord Count” and “Running Disparity Error Countmeans, but that indeed doesn’t look good. I guess I need to do some googling after this. zpool status showed problems with disk c3t7d0 which is mapped into the 8th disk in the LSI card.

I replaced the old disk and added the new disk into the system on the fly. The LSI card noticed and initialized the disk, but with a different id. The disk is now c3t8d0. This is propably because the disk wasn’t the same. I ordered zfs to replace the old disk with the new one with command “zpool replace tank c3t7d0 c3t8d0

raidz2       DEGRADED     0     0     0
  c3t6d0     ONLINE       0     0     0  14.2M resilvered
  replacing  DEGRADED     0     0     0
    c3t7d0   FAULTED     27 89.2K     0  too many errors
    c3t8d0   ONLINE       0     0     0  2.03G resilvered
  c5t0d0     ONLINE       0     0     0  14.2M resilvered
  c5t1d0     ONLINE       0     0     0  13.5M resilvered

That’s it. The resilver took me 3h16m to complete.

What are the odds?

You all know this: You learn something new like a new word and then the next day you’ll stumble across this new thing you have just learned in a newspaper. Most of this can be easily explained with some brain pattern matching: you have previously come across this word many times but because you didn’t know it’s meaning you could not remember those cases, but after you learned it you’ll brain is programmed to search for those new words or things and you’ll remember your learning experience.

Yesterday I was going to my parents place and my dad picked me up from the train station and he was listening to Car Talk and he explained what the program was all about. I’m pretty sure I haven’t never listened that radio show before but I learned the concept and thinked that I wouldn’t listened that show again for a long time, mainly because I just don’t listen to radio.

And the next day I on my comic strip learning moment with my morning coffee I read todays XKCD (I read xkcd every day) strip:

Now Randall Munroe please explain this!

Tänään tein:

  1. Kävin katsomassa Kalliossa yhtä kämppää. Vaatisi täydellisen pintaremontin ja hinta remontin kanssa menee budjettini ylitse. Tai menisi, jos tietäisin mikä budjettini on. Ainakin sain lisää kokemusta näytöistä :)
  2. Ostin koirakirjan! Koirien Pikkujättiläinen – Hoito, Kasvatus ja Rodut, Ulla Kokko, WSOY. Pistin myös sisäsivuille postit-lapun, jossa Bitey kieltää mua lukemasta sivuja 171 – 189 ;)
  3. Siivosin: imuroin, järjestin tavarahyllyä, vaihdoin lakanat (toiset tyynyliinat on jossain hukassa :() ja pesin pyykkiä.
  4. Kiroilin kun Nebulan netti pätkäisee välillä.

Asuntoa katsomassa

Erinäisten vaiheiden jälkeen päädyin elämäni ensimmäistä kertaa asuntonäytöille. Olen toki lapsena käynyt yhdessä vanhempieni kanssa katsomassa uutta koko perheen asuntoa, mutta nyt menin katsomaan asuntoa yksin itselleni. 

Ensimmäisenä kohteena oli Mäkelänkadulla sijaitseva 43m^3 kaksio. Bussipysäkki talon edessä ja takuulla tarpeeksi liikenteen ääniä pitkin kesää. Rappukäytävä oli vähän huonossa kunnossa, mm. alimmassa kerroksessa rapun alla oli jotain rojua säilössä. Hauskana yksityiskohtana oli pienen keittiön ja makuuhuoneen välissä oleva pieni ikkuna. Mitä lie suunnittelija ajatellut. 134k€ velaton hinta on maksukyvyn sisällä, mutta paikka ei silti jäänyt houkuttelemaan. Itseasiassa paikasta oli vaikea saada mitään muistikuvia tänään, vaan piti käyttää hetki aivotyötä ja virkistää muistia oikotien esittelykuvilla.

Kohteiden väliin jäi reilu tunti luppoaikaa, jonka keksin hyötykäyttää moikkaamalla Isaa ja Villeä. Puheensorinan ja kahvikupin lomassa oli mukava vaihtaa kuulumisia ja puhua koirajuttuja :)

Toisena oli Kirstinkadulla sijaitseva 51m^2 kaksio, joka oli ihan kiva, mutta sisälsi täysin onnettoman keittiön. Tiedossa olisi siis keittiöremontti ja parin väliseinän tuhoaminen, mikä luultavasti tarkoittaisi myös lattian osittaista uusimista. Rahaa ja työaikaa menisi, joten 144k€ hinta on mielestäni kohtuuton.

Illalla äiti yllätti soittamalla ja listaamalla muutaman löytämän kohteen, jotka hän oli löytänyt yhdessä Eevan kanssa. Ilmeisesti kohta puoli sukua on etsimässä minulle omistusasuntoa. Toiseen näistä järjestyikin näyttö heti seuraavalle päivälle!

Hotswapping disks in OpenSolaris

Adding new SATA-disks to OpenSolaris is easy and it’s done with cfgadm command line util if the disk is in a normal ACHI SATA controller.  I have also an LSI SAS/SATA controller SAS3081E-R which uses its own utils. 

Hotpluging disk into normal ACHI SATA controller.

First add the new disk to the system and power it on (a good sata backplane is a must) and then type cfgadm to list all disks in the system:

garo@sonas:~# cfgadm
Ap_Id                          Type         Receptacle   Occupant     Condition
c3                             scsi-bus     connected    configured   unknown
pcie20                         unknown/hp   connected    configured   ok
sata4/0::dsk/c5t0d0            disk         connected    configured   ok
sata4/1                        disk         connected    unconfigured unknown
sata4/2                        sata-port    empty        unconfigured ok

This shows that disk sata4/1 is a new disk which have been added but is not yet configured. Type

garo@sonas:~# cfgadm -c configure sata4/1

Now the disks are configured. Typing cfgadm again shows that they have been configured as disks c5t0d0 and c5t1d0. They’re now ready to use in zpools.

Hotswapping disks in LSI SAS/SATA controller

I have also an LSI Logic SAS3081E-R 8-port (i:2xSFF8087) SAS PCI-e x4 SATA controller which can be used with Solaris default drivers, but it should be used with its own drivers (i used the Solaris 10 x86 drivers). After the drivers are installed you can use the lsiutil command line tool.

garo@sonas:~# lsiutil
LSI Logic MPT Configuration Utility, Version 1.61, September 18, 2008

1 MPT Port found

     Port Name         Chip Vendor/Type/Rev    MPT Rev  Firmware Rev  IOC
 1.  mpt0              LSI Logic SAS1068E B3     105      01170200     0

Select a device:  [1-1 or 0 to quit]

First select your controller (I have just one controller, so I’ll select 1). Then you can type 16 to Display attached devices, or 8 to scan for new devices. The driver will automaticly scan for new disks once a while (at least it seems so), so the disk might just pop up available to be used with zpool without you doing anything for it.

Main menu, select an option:  [1-99 or e/p/w or 0 to quit] 8

SAS1068E's links are 1.5 G, 1.5 G, 1.5 G, 1.5 G, 1.5 G, 1.5 G, 1.5 G, 1.5 G

 B___T___L  Type       Vendor   Product          Rev      SASAddress     PhyNum
 0   0   0  Disk       ATA      ST31000340AS     SD15  09221b066c554c66     5
 0   1   0  Disk       ATA      ST31000340AS     SD15  09221b066b7f676a     0
 0   2   0  Disk       ATA      ST31000340AS     SD15  09221b0669794a5d     1
 0   3   0  Disk       ATA      ST31000340AS     SD15  09221b066b7f4e6a     2
 0   4   0  Disk       ATA      ST31000340AS     SD15  09221b066b7f5b6d     3
 0   5   0  Disk       ATA      ST31000340AS     SD15  09221b066a6c6068     4
 0   6   0  Disk       ATA      ST3750330AS      SD15  0e221f04756c7148     6
 0   7   0  Disk       ATA      ST3750330AS      SD15  0e221f04758d7f40     7

OpenSolaris network performance problems with Intel e1000g network card

OpenSolaris 2008.11 has a faulted e1000g driver which results in very poor upload performance: download speeds are around 400Mbit/sec but upload speed is just about 25Mbit/sec with 1Gbps link.

There’s a workaround which involves getting older version of the driver, or user could install SXCE snv_103 (bug report here)

Instructions to apply the workaround:

  1. Download ON BFU Archives (non-debug) from older distribution
  2. Unpack the archive (bunzip2 and tar)
  3. Unpack the generic.kernel package (in archives-nightly-osol-nd/i386) with cpio -d -i generic.kernel
  4. Create new Boot Environment (read more about this from here): beadm create opensolaris-e1000gfix
  5. Mount the new environment mkdir /mnt/be and beadm mount opensolaris-e1000gfix /mnt/be
  6. You need to copy these three files into respecting places UNDER /mnt/be/: kernel/drv/e1000g  (to /mnt/be/kernel/drv/e1000g), kernel/drv/e1000g.conf and  kernel/drv/amd64/e1000g
  7. Make the new BE active: beadm activate opensolaris-e1000gfix
  8. Boot and hope for best :)

Hosting virtual machines on Solaris

Hosting virtual machines inside an OpenSolaris box is very easy with VirtualBox. Here’s a quick tutorial how to install an ubuntu into a virtual machine:

  1. Download VirtualBox from here.
  2. Open the manual into a tab from here.
  3. Follow the installation manual at chapter 2.4. The installation scripts will install VirtualBox under /opt, so if you want, you can now create a new zfs filesystem for /opt so that it wont pollute your root installation partition.
    Note: If you are using Nexenta, you need to use /usr/sun/sbin/pkgadd instead of simply pkgadd.

    Note:If you receivere this error:

    ## Waiting for up to &lt;300&gt; seconds for package administration commands to become available (another user is administering packages)
    pkgadd: ERROR: Unable to acquire package administration lock for this system; try again later
    pkgadd: ERROR: Unable to lock this zone for administration

    The sollution is to “cp /usr/sun/bin/pkgadm /usr/bin” and repeat the step.

  4. After these steps the VirtualBox host environment is installed.

So, you have now installed the server stuff, now it’s time to install the ubuntu into a virtual machine. If you are using Windows as your desktop follow the steps in chapter 7.4. Otherwise consult the manual to find a proper installation way. The chapter 7.4 guides you to use the headless installation where you connect to the virtual machine using windows remote desktop (which is quite nice). You can download the 32-bit ubuntu iso from here, or use some other cd/dvd image to boot up your system.

If you don’t want to use nat for your virtual machine and prefer a direct ip instead, replace step

VBoxManage modifyvm "Windows XP" -memory "256MB" -acpi on -boot1 dvd -nic1 nat


/usr/lib/vna e1000g0 0:0:0:0:10:01
ifconfig vnic0 plumb
ifconfig vnic0 dhcp
VBoxManage modifyvm "Windows XP" -memory "256MB" -acpi on -boot1 dvd -nic1 hostif -hostifdev1 vnic0

where e1000g0is the name of your physical network interface (use <em>ifconfig -a</em> to look it up) and0:0:0:0:10:01is an unique MAC address you invented from your hat. The VRDP (remote desktop server) will be binded to the ip of vnic0 interface which you can check with "ifconfig vnic0".

After setting up the VM you can finally start it by typing “VBoxHeadless -s <vm name>” and then connecting into it using remote desktop. Notice that the guest operating system might have different IP, so you need to check the guest IP after installation if you wish to connect into the guest with SSH.

Miten ZFS toimii levyjen kanssa ja storagepoolin anatomia.

ZFS koostuu yhdestä levypoolista (storagepool). Levypool voi sisältää yhden tai useampia tiedostojärjestelmiä, jotka jakavat yhdessä koko levypoolin tilan. Tiedostojärjestelmien luonti on helppoa ja kevyttä, eli esimerkiksi jokaiselle käyttäjälle voidaan helposti luoda oma tiedostojärjestelmä. Tiedostojärjestelmät voivat muodostaa hierarkioita, tiedostojärjestelmille voidaan asettaa tilarajoituksia (quota), varata tietty miminimäärä tilaa (reserve space) ja tiedostojärjestelmiä voidaan jakaa (export) helposti esimerkiksi windowsiin CIFS-protokollalla (tunnetaan myös nimillä smb ja samba), tai nfs protokollalla. Yhdessä tietokoneessa voi olla useita eri levypooleja. Solaris (ja grub) osaa käynnistyä ZFS:ltä, kunhan levypoolissa ei ole raidz-virtuaalilevyjä.

Yksi levypool koostuu vähintään yhdestä virtuaalilevystä (VDEV). Virtuaalilevyjä voidaan lisätä vapaasti jälkeenpäin levypooliin, mutta niitä ei voida toistaiseksi ottaa pois storagepoolista. Levypoolin koko on sen virtuaalilevyjen kokojen summa. Levyn lisäyksen jälkeen olemassaolevaa dataa ei automaattisesti jaeta tasaisesti kaikille virtuaalilevyille, vaan ainoastaan virtuaalilevyn lisäyksen jälkeen kirjoitettu data jaetaan tasaisesti. Virtuaalilevyn lisäys siis nopeuttaa levyjärjestelmän toimintaa, mutta nopeushyöty ei tule heti esiin vanhalla datalla.

Jos virtuaalilevyssä on useampi kuin yksi levy, virtuaalilevyn koko määräytyy pienimmän fyysisen levyn koon mukaan. Eli jos levyssä on kahden, kolmen ja viiden gigatavun levyt, virtuaalilevyn koko on 2 GT * 3 = 6 GT (tässä ei oteta huomioon peilausta tai raidz:n käyttöä, jolloin levytilaa kuluu virheenkorjauksessa käytettävän pariteettidatan säilytykseen). Kuitenkin jos pienin levy vaihdetaan isommaksi (olettaen, että virtuaalilevy tukee virheenkorjausta, eli on joko peilattu, tai varmennettu raidz:lla), virtuaalilevyn koko kasvaa automaattisesti. Eli jos kahden gigatavun levy vaihdetaan neljän gigatavun levyksi, niin virtuaalilevyn koko muuttuu 12 gigatavuksi (4 GT * 3 levyä).

Virtuaalilevy (VDEV) voi olla:

  • Tiedosto (iso tiedosto joka toimii “levynä”)
  • Levyn slice tai partitio.
  • Kokonainen levy (suositeltavin tapa)
  • Joukko levyjä, joiden välillä tieto peilataan (eli mirror-levysetti)
  • Joukko levyjä jotka muodostavat RAIDZ1 tai RAIDZ2 virtuaalilevyn.
  • Erikoislevy (cache-levy, log-levy tai spare-levy)

Yhdessä levypoolissa voi olla sekoitettuna erilaisia virtuaalilevyjä, mutta tätä ei suositella. Esimerkiksi levypoolissa voi olla raidz1 ja raidz2 -virtuaalilevypakat, mutta tälläisen luonnin yhteydessä käyttäjää varoitetaan ja pyydetään erikseen hyväksymään eri vdev tyyppien sekoittaminen keskenään.

raidz (eli raidz1): Vähintään kolme levyä (jossa levy on tiedosto, slice, partitio tai kokonainen levy (suositeltavin tapa)) ja kestää yhden levyn hajoamisen. Virheenkorjaukseen käytettävä data vie yhden levyn kapasiteetin verran tilaa ja virheenkorjaukseen käytetty data jaetaan tasaisesti kaikille levyille (toimii samalla periaatteella kuin RAID-5). Tällä hetkellä levyjä ei voida lisätä tai poistaa virtuaalilevypakasta, mutta levyjä voidaan vaihtaa yksi kerrallaan isompiin levyihin, jolloin virtuaalilevypakan koko kasvaa. Mikäi virtuaalilevypakka koostuu erikokoisista levyistä, kaikki levyt käyttäytyvät levypakan pienimmän levyn koon mukaan.

raidz2: Vähintään neljä levyä ja kestää kahden levyn hajoamisen. Virheenkorjaukseen käytettävä pariteettidata käyttää kahden levyn kapasiteetin verran tilaa. Nopeampi kuin raidz1, toimii samalla tavalla kuin RAID-6. Käyttäytyy muuten kuten raidz1.

mirror, eli peilattu levysetti: Vähintään kaksi levyä. Kaikki data kopioidaan kaikille levyille, eli levypakasta voi hajota kaikki paitsi yksi levy. Levypakkaan voidaan lisätä levyjä (kunhan ne ovat vähintään samankokoisia kuin levypakan pienin levy) tai poistaa levyjä.

spare, eli varalevy: Oltava vähintään samankokoinen kun koko levypoolin pienin levy (jotta levyä voidaan käyttää varalevynä)

log ja cache -levyt: Erikoistapauksia, kotikäyttäjä ei tarvitse näitä.

Kysymyksiä ja vastauksia NASini toiminnasta.

Olen keskustellut NAS projektistani muropaketissa, jossa esitettiin lukuisia kysymyksiä projektistani:

Q: Miksi RAIDZ1 + spare, eikä RAIDZ2 ilman sparea:
A: Hankin aluksi kolme levyä ja hankin sparen jälkeenpäin. En ole tutustunut, että kumpi olisi parempi ratkaisu. Yksi storagepooli koostuu vähintään yhdesteä levysetistä (esim RAIDZ1 setti, RAIDZ2 setti, peilattu setti tai yksittäinen levy). Jos levysettejä on useampia, niin levysettien pitää (ei kuitenkaan pakko, mutta suositus) olla samanlaisia. Eli samaan storagepooliin ei kannata laittaa RAIDZ1 settiä ja RAIDZ2 settiä, tai RAIDZ1 ja MIRROR-settiä. Kun storagepoolissa on useita settejä, niin samaa sparea voidaan jakaa kaikkien settien kanssa.

Lisäksi spare voidaan ehkä säätää sammumaan kun sitä ei käytetä. En ole varma, olenko saanut tätä jo tehtyä (en ole keksinyt tapaa varmistaa asiaa), mutta sen pitäisi kait olla mahdollista. Eli tällöin levyn rikkoontuessa spare ei olisi pyörinyt tyhjillään, vaan olisi ollut paikallaan varastossa.

Valittaessa RAIDZ2:en ja RAIDZ1 + sparen välillä pitää myös hieman pohtia tehokysymyksiä. En ole varma miten RAIDZ2 käyttäytyy nopeuden suhteen, joku muu saa selvittää.

RAIDZ1:stä ei voi muuttaa jälkeenpäin RAIDZ2:ksi. Storagepoolista ei myöskään toistaiseksi voi ottaa levysettejä pois, eli storagepoolin kokoa ei voi pienentää jälkeenpäin!

Kuitenkin laajennustilanteessa voitaisiin luoda uusi storagepooli uusilla levyillä, siirtää kamat offline tilassa vanhalta poolilta uudelle, poistaa vanha pooli ja siirtää vanhan poolin RAIDZ1 + spare uuteen pooliin RAIDZ2:ena (jos se on mielekästä) ja laittaa vaikka uusi spare, joka sitten jaetaan koko poolin kesken.

Q: Nyt kun sinulla homma jo pyörii, niin olisiko jotain komponenttia, joka tuosta kokoonpanosta kannattaisi vaihtaa / valita toisin?
A: Kyllä. Itselläni oli isoja performanssiongelmia Gigabyten emolevyn sisäänrakennetun Realtek 8111B -verkkopiirin kanssa. Ongelmat korjaantuivat ostamalla 25 euron Intelin PCI Gigabittinen verkkokortti.

Q: Oliko ajureiden kanssa mitään ongelmaa?
A: Ei.

Q: Miten hyvin riittää tehot tossa prossussa?
A: Hyvin. Olen harkinnut mm. virtuaalikoneiden hostaamista koneessa, niitä varmaan menisi sinne

Q: Kuin ison CF:n laitoit?
A: Kaksi kappaletta kahden gigan kortteja. Nexentan asennusohjelmassa on bugi, joka estää suoran asennuksen kahden gigan kortille (valittaa, että “kiintolevy” on muutamaa megatavua liian pieni). Tämä on kierrettävissä, mutta en muista juuri nyt tarkasti miten se tapahtuu. Voin kuitenkin opastaa jos jollakulla tulee sama ongelma esiin ja kirjoitan siitä kunnon ohjeet blogiini.

Solaris osaa bootata ZFS:ltä, mutta vain jos ZFS ei sisällä RAIDZ levypakkoja. Eli tarkoitus oli peilata käyttöjärjestelmä kahdelle eri CF kortille. Jostakin syystä kone tunnistaa vain yhden CF kortin. Jos laitan molemmat kortit sisään, niin kone ei tunnista kumpaakaan. Tällä hetkellä minulla on siis systeemilevy vain yhdellä CF:llä. Jos saan joskus koneen tunnistamaan toisenkin CF kortin, niin voin (ymmärtääkseni) lisätä sen lennossa sisään ja peilata systeemilevyn myös toiselle CF kortille.

Q: Näillä näkymin ois tarkotuksena laittaa 6x500GB levyt raid-z2:lla, mutta saapa nähä mitä sitä lopulta keksii.. Meinaa olla ongelma toi ettei pysty levysettiin lisään uusia levyjä, tällä hetkellä on koneessa 3x500GB (jotka ei oo tyhjiä) niin ois kiva saada ne tohon NAS:siin, mutta pitäis siirtää data väliaikasesti “johonki muualle” eli menee vähän hankalaksi.. :)

A: Voit tehdä esim näin: Luot uuden levypoolin johon laitat 5 levyä RAIDZ2:een. Kopioit datat vanhoilta levyiltä tähän uuteen pooliin. Otat vanhat 500 GB levyt ja lisäksi kuudennen ylijääneen levyn ja lisäät ne yhtenä neljän levyn RAIDZ2 settinä uuteen storagepooliin.

Eli levysettiin ei voi lisätä uusia levyjä, mutta storagepooliin voi lisätä uuden levysetin (jolloin pooli “stipettää” datat levysettien välillä joka lisää performanssia)

Q: Tosin kovalevyiksi olen ajatellut 1T levyjä. Onko suositella jotain tiettyä levyä?
A: En osaa suositella. Kannattaa puntaroida hinta-koko suhteen ja haluttujen levyjen määrän kanssa ja valita optimaalinen kokoonpano levyjä.

Q: Oliko vielä joku tietty syy käyttää kahta erillistä 1GB palikkaa yhden 2GB palikan sijaan?
A: Muistit toimivat dualchannel moodissa, eli nopeammin kuin yksi 2GB palikka,.

Fixing ZFS CIFS share video lagging problems

I had some bad performance problems with my new NAS box running ZFS which resulted terrible video and audio lagging problems in windows when I tried to stream video from zfs share via CIFS to a media player running in windows. Even playing mp3 music files from CIFS share in Winamp resulted with very bad lagging, like I was playing a very scratched CD.

I asked help from opensolaris forums (very friendly people there!) and ended up bying a new Intel Gigabit Ethernet PCI card for 25 € which replased the Gigabyte motherboard onboard Realtek 8111B network chip and fixed my problems.

Sharing iSCSI volumes from Solaris to Windows XP

I just noticed that I could create iSCSI volumes onto my ZFS pool and share them easily over network to other machines. And I mean easily!

  1. Enable the iSCSI service:
    # svcadm enable iscsitgt
  2. Create a zfs stub for your volumes:
    # zfs create storagepool/volumes
    # zfs set shareiscsi=on storagepool/volumes
  3. Create a volume
    # zfs create -V 20g storagepool/volumes/test
  4. Verify that sharing was successfull:
    # iscsitadm list target
    Target: storagepool/volumes/test
        iSCSI Name:
        Connections: 0
  5. Install Microsoft iSCSI Software Initiator Version from here
  6. Go to Control Panel -> iSCSI Initiator -> Discovery, add the solaris server ip to Target Portals, then go to Targets tab and Log On to the volume.
  7. Go to the Computer Management and format the new iSCSI partition and you’re ready to go.

I benchmarked read speeds of 70 to 80 MB/sec with access time of about 2.3 ms over a 1GBps ethernet network. Not bad, could be a bit faster, but the network will anyway be a bottleneck compared to local drivers. My 160 GB RAID-0 stripe gives 260 MB/sec read times with 18.4 ms access time and 300 GB RAID-1 mirror gives 110 MB/sec with 19 ms access time (both are local drivers)

So what I can do with iSCSI volumes? I could for example use them as virtual machine disks, which would allow me to move virtual machines more easily across my network (though I dont have that many machines where to move them). Also the access time is blazingly fast, so I will also try to use them as video editing storage, as suggested in this article.

NAS projekti OpenSolariksella ja ZFS:llä


  • Nexenta OpenSolaris distribuutio
  • Tukee ZFS:ää
  • Aluksi neljä kappaletta 750 gigan Seagate Barracuda 7200.11 levyjä, joista kolme levyä muodostaa raidz1 (Solariksen RAID-5) -setin ja yksi levyistä on varalevy (spare).
  • Hotswap tuki, levyt voidaan vaihtaa lennossa.
  • Boottaus ja itse käyttöjärjesetlmä CompactFlash kortilta. /var osio on levypoolissa, jolloin CF kortille ei tarvitse juuri kirjoitella.
  • Laajennettavissa 13 SATA-levyyn asti.
  • Levytilan jako CIFS (Windowsin levyjako), FTP:n, NFS:n, SSH:n ja WWW:n yli (vain luku).
  • Tukee useita eri käyttäjiä ja tarvittaessa toimii Windows Domainissa.

Setti on kasattu isoon Antecin pelikoteloon, joka valittiin isojen tuulettimien ja ennenkaikkea runsaiden 5.25″ laitepaikkojen takia, joita kotelossa on yhdeksän. Levytilaa jaetaan CIFS:n (eli Samba, eli Windowsin levyjako) avulla ja tarvittaessa myös NFS:llä ja ehkä tulevaisuudessa myös iSCSI:llä (SCSI over Internet).

Nexenta on OpenSolaris-distribuutio, joka on käytännössä Debian OpenSolariksen kernelillä, eli ohjelmia saa helposti apt-get:llä, joka oli merkittävä valintakriteeri itselleni. Tietenkin kaikki asiat eivät toimi kuten Linuxissa, mutta Debianmaisuus teki Solarikseen siirtymisestä helpompaa.

Testeissä ZFS on toiminut erinomaisesti. Kirjoitusnopeus levypakkaan on 120 Mt/s ja lukunopeus noin 180 Mt/s. Verkon yli yhdeltä XP koneelta kirjoitusnopeus on noin 60 Mt/s gigabitin verkon yli (tässä on varmaan vielä parantamisen varaa). Testeissä yhden levyn irroitus on toiminut erinomaisesti, uuden levyn voi lisätä lennossa sisään ja itseasiassa yksi kolmesta levyistä ehti jo hajota ja ZFS hanskasi tilanteen erinomaisesti ilman ongelmia. Levyrikon sattuessa järjestelmä ottaa automaattsisesti varalevyn käyttöön ja lähettää ilmoituksen sähköpostitse. Nykyinen configuraatio antaa 1.3 TB käyttötilaa ja tilaa voi laajentaa helposti lisäämällä uusia kolmen levyn settejä järjestelmään.

Kotelosta on muutamia kuvia kamerassa, lisään ne jossakin välissä. Kokoonpano ei ole erityisen hiljainen, mutta se ei nykyisessä sijoituspaikassa ole ongelma.

Komponenttilista (verkkokaupan tuotekoodit):

  • 0266: Antec Nine Hundred ATX kotelo. 9 5.25″ laitepaikkaa ja ärsyttävät siniset ledit tuulettimissa, jotka sai helposti pimeäksi. 108.90 €
  • 5017: Corsair Twin2X 2x1GB DDR2 800Mhz KIT -muistimodulipari. 43.90 €
  • 8322: Intel Dual Core E2180 2,0GHz -prosessori LGA775-kantaan. 57.90 €
  • 8865: Sandisk 2GB CompactFlash Ultra II muistikortti. 24.90 €
  • 16539: Gigabyte GA-P35-DS3P Intel P35 ATX-emolevy LGA775 -prosessoreille. 8 SATA-väylää. 127.90 €
  • 20028: Antec NeoPower HE High Efficiency 430W -virtalähde. 60.90 €
  • 24126: Seagate Barracuda 7200.11 750GB SATA-II 4 kpl * 120.90 = 483.60 €
  • 30332: Chieftec SNT-2131SATA SATA-kiintolevykehikko. 2 * 61.90 = 123.80 €
  • Lisäksi CompactFlash to IDE adapteri noin 4 euroa.

Yhteensä: 1035.80 €, levytilaa 1.3 TB, noin 80 senttiä per gigatavu (jos on spare-levy), 70 senttiä ilman sparea. Levytilan laajennus nykyhinnoilla 2.6 TB: 424.6, jolloin hinta olisi 56 senttiä per gigatavu, 51 senttiä ilman sparea.

Vertailun vuoksi: Buffalo TeraStation Live 2TB, jolloin hyötytilaa RAID-5-setupissa olisi 1.35 TB. Hinta 731.90 €, hinta per gigatavu: 54 senttiä. Laajennus tapahtuisi ostamalla toinen boksi, jolloin tilaa olisi 2.7 TB ja hinta per gigatavu pysyisi samana, jolloin buffalo olisi omaa NAS boksiani kalliimpi.

Buffalo olisi halvempi, mutta huomattavasti hitaampi ja buffaloa ei voi laajentaa. Buffalo ei myöskään mahdollista spare-levyn käyttöä, eli levyrikon sattuessa järjestelmä on vaarassa kunnes käyttäjä vaihtaa itse rikkinäisen levyn. Solariksen ZFS mahdollistaa myös RAIDZ2:en, joka sallii kahden levyn samanaikaisen hajoamisen. Erään testin mukaan Buffalo lukee 20Mt/s ja kirjoittaa vaivaiset 3.3 Mt/s. Oma NAS boksini hakaa tämän siis nopeudessa 6-0.

FAQ: Mitä etuja ZFS tarjoaa?

Solaris tarjoaa ZFS:än, joka on monella tavalla parempi kuin Linuxin RAID ja sen tiedostojärjestelmät:
ZFS koostuu storagepoolista. Yksi pooli sisältää yhden tai useamman levysetin. Levysetti voi olla joko yksittäinen levy, peilattu levypari (tai usempi levy peilattuna keskenään), kolme tai useampi levy laitettuna raidz1:llä (Solariksen vastine RAID-5:lle), tai neljä tai useampi levy laitettuna raidz2:lla (mahdollistaa kahden levyn hajoamisen). Jos poolista loppuu levytila, niin tarvitsee ainoastaan lisätä uusi levysetti pooliin ja avot. ZFS tarjoaa myös tiedostojärjestelmän, joita on helppo muodostaa lennossa, vaikka oma jokaiselle käyttäjälle.

Linuxissa vastaava vaatisi RAID:in, LVM:n ja tiedostojärjestelmän käyttöä yhdessä. Jos linuxissa loppuu levytila, niin pitäisi lisätä uusi levysetti, liittää levysetti LVM:ään, kasvattaa LVM:ssä luodun partition kokoa ja lopuksi kasvattaa partitiolla olevan tiedostojärjestelmän kokoa. Hankalaa ja monivaiheista. Lisäksi ZFS:ssä kaikki tiedostojärjestelmät jakavat yhdessä levypoolin levytilan. Linuxissa eri tiedostojärjestelmät tarvitsevat oman partition (joka tehtäisiin LVM:llä) ja jos yksi tiedostojärjestelmä sisältää paljon hukkatilaa, mutta muut ovat täynnä, niin on pakko lisätä uutta levytilaa ja kasvattaa täysien partitioiden kokoa LVM:llä. ZFS:llä siis kaikki tiedostojärjestelmät jakavat saman tilan, jolloin hukkatilaa ei jää (ellei erikseen määritellä tiedostojärjestelmäkohtaisia quotoja, eli levytilarajoituksia)

Lisäksi ZFS suojaa paremmin levyvirheiltä.

Uusi työpaikka – Sulake Dynamoid

Allekirjoitin eilen työsopimuksen Sulake Dynamoidille ja irtisanoin tänään itseni Itellan palveluksesta. Olo on hieman ristiriitainen, olen kuitenkin kasvanut koko nuoruuteni tässä nykyisessä työpaikassa, joka aikaisemmin tunnettiin nimellä Elma ja nyt nimellä Itella Information Oy. Odotan kuitenkin innolla uusia työtehtäviä ja jään muistelemaan haikeana näitä menneitä työvuosia :)


Perinteisiä pizzoja tulee tehtyä aina välillä kotona, joskus käyttäen kaupan valmispohjia ja joskus omasta taikinasta tehtyinä. Kuitenkaan en ole koskaan tehnyt varsinaisesti pannupizzaa. Tämä ohje on osittain sovellettuna Cooking For Engineers -sivuilta.


  • 2 dl lämmintä vettä (noin +42 astetta)
  • 3 tl kuivahiivaa
  • 1 tl sokeria
  • 1/2 tl suolaa
  • 4 dl vehnäjauhoja tai pizzajauhoja tai 3 dl vehnäjauhoja ja 1 dl vehnäleseitä
  • Mozzarellajuustoa tai pizzajuustoa reilusti
  • 1 tlk tomaattimurskaa
  • Valkosipulia
  • Suolaa
  • Pippuria
  • Oliiviöljyä
  • Lisäksi täytteitä oman maun mukaan. Itse laitoin pepperonimakkaraa, jalopenoviipaleit, aurajuustoa, ananaspaloja ja aurinkokuivattuja tomaatteja.

Valmistus (tomaattikastike):

  1. Murskaa kaksi valkosipulia pieneen kattilaan (mitä pienempi sen parempi, kunhan sinne mahtuu hyvin purkillinen tomaattimurskaa).
  2. Lisää ruokalusikallinen oliiviöljyä.
  3. Keitä hiljalleen kunnes valkosipuli alkaa kevyesti ruskettua (mutta ei saa palaa!).
  4. Lisää tomaattimurska.
  5. Keitä puolella teholla keitos kasaan, jotta tomaattimurska luovuttaa ylimääräisen nesteen pois.

Valmistus (taikina):

  1. Sekoita keskenään jauhot, kuivahiiva, sokeri ja suola.
  2. Lisää lämmin vesi hitaasti sekoittaen (esim puulastalla).
  3. Vaivaa taikina esimerkiksi öljytyin käsin.
  4. Peitä kulho liinalla ja anna nousta noin kaksinkertaiseksi.

Taikinan noustua kokoa pizza:

  1. Voitele pizzavuoka voilla tai oliiviöljyllä.
  2. Muotoile taikina vuokaan käyttäen käsiä. Pohja saa olla paksu ja taikina saa nousta reilusti reunoille.
  3. Levitä tomaattikastiketta pohjalle.
  4. Mikäli haluat paljon täytteitä lisää osa täytteistä tässä vaiheessa.
  5. Lisää reilusti juustoraastetta
  6. Lisää loput täytteet
  7. Ripottele halutessasi hyvin vähän juustoraastetta täytteiden päälle, mutta älä kuitenkaan hautaa täytteitä juuston alle. Ideana on, että juusto on täytteiden alla, eikä päällä.
  8. Paista 200’C noin 20 minuuttia.