Category: Technology

Posted on in Technology, NoSQL

Disclaimer: I'm still learning CouchDB so there may be smarter ways of doing the things I propose here.

The problem

A typical requirement of any website is to enforce all registered usernames (and sometimes also email addresses) to be unique. This is trivial to do with a relational database like MySQL, but CouchDB doesn't have unique keys.

The standard solution

The usual way is to make the username (as chosen by the user) the _id of the User document. That will enforce uniqueness, but it also makes it difficult to change the username later, when there are lots of references to the document using the _id. It also doesn't solve the problem of having additional uniqueness requirements for other fields like email addresses.

Separating the unique id documents

Instead of the usual way, I'm using a separate document to hold the unique username as its _id, and another (auto-id) document that contains the actual user data. Each user would then be described in the CouchDB database by two documents like this:

{ "_id": "username/kennu", "type": "UsernameReservation", "user_ref": "71bacba712381adefg13712312312369" }

{ "_id": "71bacba712381adefg13712312312369",
"type": "User",
"username": "kennu",
"password": "xxxx",
"email": "webmaster@kfalck.net" }

This makes it easy to refer to the User document using the permanent auto-generated _id, while uniqueness is enforced by the separate UsernameReservation document. When the username is changed, a new UsernameReservation document is created to reserve the new name, and then the old document is deleted.

Additional unique fields can be added fairly trivially with documents like this:

{ "_id": "email/webmaster@kfalck.net", "user_ref": "71bacba712381adefg13712312312369" }

Handling the transaction

Because CouchDB doesn't have transactions, it's complicated to ensure that the username reservation happens only when the User document is also saved successfully with the corresponding username. In my code (I'm using couchdb-python and Document schema classes), I've defined a "save" method that will execute the following steps:


  1. Make sure the UsernameReservation document is created and belongs to the reserving user.

  2. Save changes to the User document.

  3. If an exception occurred, delete the UsernameReservation (unless it already existed before) and re-raise the exception.

  4. If a new User document was created, update the UsernameReservation with a reference to its _id.

  5. If the username was changed, delete the previous UsernameReservation document.

I'm pretty sure that can be made more beautiful. The basic problem is how to implement a multi-step CouchDB transaction properly in client-side code. It's impossible to make it survive server crashes and similar situations, but maybe a generic transaction could remember the _revs of the documents that were modified, and then restore them to the original state if something goes wrong.

Managing multi-master conflicts

There is one final challenge related to distributed CouchDB: what happens, if the same _id (e.g. username/kennu) is created simultaneously on two or more database servers?

In this situation, CouchDB will mark both documents as _conflicting revisions and more or less randomly choose one of them as the winner. It's up to the application to decide what to do when it encounters a username in _conflicting state. There are a few alternatives that are a bit nasty:


  • Assign a random username to both competing users and release the conflicting name to be re-acquired by whoever gets it first.

  • Put the user accounts on hold and require an administrator to manually resolve the conflict.

  • Somehow choose the winner and just apply the above to the loser.

Avoiding conflicts with a single master

Since usernames and emails are typically not changed very often, it might be more feasible to use only one master database for them. In this scenario, the application would write UsernameReservation documents only to the master, which guarantees they are never conflicting with each other.

Summary

Creating unique fields in CouchDB seems to be quite challenging compared to relational databases. It would be very helpful if CouchDB supported unique fields directly, or if it provided some kind of multi-step transactions for implementing them reliably using separate document _ids as described in this article.

Posted on in Technology, Apple

Kun ensimmäistä kertaa luin ZFS:stä jokunen vuosi sitten, olin innoissani. Vihdoinkin täysin virtuaalinen tiedostojärjestelmä, joka mahdollistaisi fyysisten levyjen lisäämisen ja poistamisen lennossa. Käyttäjä vain näkisi käytettävissä olevan kokonaislevytilan kasvavan tai pienenevän vastaavasti.

Normaalistihan uuden fyysisen levyn lisääminen virtuaaliseen levyjärjestelmään edellyttää RAID-konfiguraation päivittämistä ja koko tiedostojärjestelmän luomista uudelleen. Se on ainoa keino saada usea fyysinen levy näkymään yhtenä virtuaalisena kokonaisuutena.

Ei siis ihme, että Apple kiinnostui ZFS:stä. Sen idea sopisi mainiosti Mac OS X:ään, joka on muutenkin suunniteltu yksinkertaiseksi ja helppokäyttöiseksi mutta teknisesti edistyneeksi käyttöjärjestelmäksi.

Mutta nyt näyttää siltä, että ZFS ei ole lunastanut lupauksiaan. Solaris-käyttäjien kokemusten perusteella se on edelleen epäkypsä, sekoaa herkästi tietyissä tilanteissa ja aiheuttaa datan menetystä. Apple puolestaan on poistanut saitiltaan kaikki viittaukset ZFS:ään, vaikka siitä piti tulla osa Mac OS X:ää.

Posted on in Technology

Jouduin taas pitkästä aikaa tekemään asioita Tomcatilla ja servleteillä eli konfiguroimaan Javaa. Voi hyvänen aika että se on edelleen hankalaa ja monimutkaista. Sadoittain erilaisia propertyjä, classpatheja, jarreja ja xml-tiedostoja, tolkuttoman pitkiä error traceja.

Java-ihmisillä ei ilmeisesti koskaan käy edes mielessä, että arkkitehtuureja voisi yrittää yksinkertaistaa. Tämä on toisaalta loogista, koska he ovat lähinnä konsultteja, jotka saavat palkkion monimutkaisuuden luomisesta ja ymmärtämisestä.

Omassa tapauksessani piti tehdä simppeli servletti, joka kutsuu toisaalla olevaa SOAP-rajapintaa ja tulostaa sen palauttaman arvon. Käytännössä tämä edellytti ainakin seuraavia asioita (serverinä Ubuntu 9.04):


  • Tomcatin, Axis-kirjaston ja mod_jk:n asentaminen.

  • Mod_jk:n konfiguroiminen Apachen direktiiveillä.

  • Erillisen (turhan) workers.properties-tiedoston konfiguroiminen.

  • Tomcast-sovelluksen context-asetusten konfiguroiminen.

  • Tomcast-sovelluksen web.xml-asetusten konfiguroiminen (pitää määritellä servlet-name, servlet-description, url-mapping jne.)

  • Oikean classpathin ja komentorivin arpominen WSDL2Java-työkalulle (aina yksi puuttuva jarri lisäten ja kilometrin error tracea tulkiten).

  • SOAP-stubin generoiminen WSDL2Javalla.

  • Pohtiminen, mitä WSDL2Javan generoimasta neljästä luokasta (PortType, Service, ServiceLocator, SOAPStub) pitää oikeasti kutsua.

  • Servletin koodaaminen Javalla (tämä oli kaikkein yksinkertaisin osuus).

  • Ihmettely, miksi SOAP-stubin käyttäminen aiheuttaa Class Not Found -virheilmoituksen Tomcatissa (joka tietenkin vielä vaihtelee ja antaa hieman erilaisia ilmoituksia välillä).

  • Tomcatin permissioiden konfiguroiminen policy.d:hen siten, että servlet saa AllPermissionit, tarvittavat FilePermissionit ja RuntimePermissionin getClassLoaderiin. Ilman ei Axis toimi.

Voi tietysti väittää, että kaiken tämän osaaminen on rautaista ammattitaitoa. Minä taas väitän, että se on pelkkää puupäisyyttä. Käyttämällä SOAPin sijasta REST-rajapintaa tämän kaiken voisi tehdä vaikkapa Pythonilla tai PHP:llä yhdellä ohjelmarivillä, joka tekee yhden HTTP-kutsun.

Ratkaisun tulisi aina olla yhtä yksinkertainen kuin ongelmakin on.

Posted on in Technology

Näemmä Chromesta on nyt tarjolla esiversioita Macille ja Linuxille. Ainakin Mac-version on jo aiemminkin voinut ladata automaattisista buildeista. Ei sitä vielä kannata käyttää selaimena, mutta sillä on hyvä testata yhteensopivuutta, jos kehittää webbisaitteja.

Posted on in Technology

Kokeiltuani hetken Windows 7 RC:tä Eee PC 901:ssä kyllästyin siihen. Office 2007:n asentaminen ei onnistunut, koska se tahtoo väkisin asentaa C-asemalle monta sataa megaa tauhkaa. Myöskään Visual Studio 2008 ei asentunut, koska se on puolestaan välttämätöntä laittaa C:lle yli gigatavu tavaraa, vaikka disabloisi kaikki ominaisuudet ja määrittelisi asennuksen D:lle.

Nyt kun Ubuntusta on uusi netbook-optimoitu 9.04-versio, päätin kokeilla sitä. En tosin ihan perusasennusta, vaan otin Eeebuntu Netbook Remix 3.01:n, joka on optimoitu Asus Eee-PC:ille. Asennus sujui näppärästi suoraan usb-tikulta. Eeebuntu ei tarjoa valmiita .img-tiedostoja tikulle poltettavaksi, mutta iso-image on helppo polttaa Unetbootinilla. Tämä onnistui jopa Macilla VirtualBoxissa pyörivästä XP:stä, kun mounttasi vain USB-tikun virtuaalikoneeseen.

Pari tehostusvinkkiä Jartzalta Eeebuntuun:


  • /tmp, /var/tmp, /var/log ja /var/log/apt kannattaa mountata tmpfs:ksi, jotteivät turhat väliaikaistiedostot kuluta SSD:tä.

  • Levyn kirjoitusvälimuistin tyhjentämisen voi säätää harvemmaksi komennolla echo 1500 > /proc/sys/vm/dirty_writeback_centisecs (oletus on 500).

  • Ralinkin WLAN-ajuri on buginen eikä toimi kunnolla, jos WLAN-tukiasemassa on auto WPA/WPA2-moodi päällä. Tämän voi korjata asettamalla tukiaseman kiinteästi WPA2-moodiin tai käyttämällä vanhaa 1.7.1.1-ajuria.

Omia havaintoja:


  • Eeebuntun oletusteema (eb3) on ruma. Se kannattaa vaihtaa Ubuntun oletukseen eli Clearlooksiin.

  • Wekkula toimii Ubuntun sisäänrakennetulla hso-moduulilla, mutta ei Network Managerilla. Sen sijaan asensin ozerocdoffin, hsolinkcontrolin ja HSOconnectin. Lisäksi Firefoxista piti tuttuun tapaan disabloida about:configin kautta networkmanager.

Katsotaan tuleeko tätä Eeeubuntua nyt käytettyä enemmän sitten.

Posted on in Technology

T-Mobile G1 Android -puhelimeni ilmoitti tänä aamuna vihdoinkin, että uusi firmware-päivitys on saatavilla. Hyväksyin asennuksen ja se meni läpi ongelmitta 10 minuutissa. Nyt firmis on sitten versiota 1.5 ja Linux-kernel 2.6.27, eli melko ajantasalla ollaan.

Cupcake-päivityksen uudet ominaisuudet eivät kauheasti paista päällepäin, vaan kännykkä näyttää ja tuntuu samalta kuin ennenkin.

Esimerkiksi Androidin kalenteri on edelleen yhtä surkea kuin ennenkin. En oikein käsitä sen kuukausinäkymää: näkymässä on joka päivän kohdalla vain vihreä pallukka indikoimassa tapahtumia. Kun sitä klikkaa, joutuu kokoruudun päivänäkymään, josta ei enää pääse takaisin, vaan Back-nappi sulkee koko kalenterin.

Kamerassa on kyllä selkeitä parannuksia. Kuvausnappi toimii nyt myös kosketusnäytöltä ja kamerassa on videokuvausmoodi.

MMS:nkin sain pitkästä aikaa toimimaan, kun huomasin täältä, että mms-APN:n usernameksi pitää jostain syystä laittaa 'n'. Tosin tällä kertaa laitoin myös Internet-APN:n typeksi 'default' ja MMS-APN:n typeksi 'mms'. Nyt ensimmäistä kertaa toimivat yhtaikaa.

Posted on in Technology

Tulipa käytettyä reilut neljä tuntia isän Acer-kannettavan parissa (siinä on luonnollisesti suomenkielinen Windows XP). Tarkoitus oli luoda Nokian kännykällä ja USB-kaapelilla nettiyhteys, mikä loppujen lopuksi ihmeen kaupalla onnistuikin.

Aika vierähti taas kerran siihen epämääräiseen jatkuvaan sekoiluun, josta Windows-käyttäjän arki muodostuu. Erilaiset ohjelmat jumiutuvat, katoavat näkymättömiin taustalle, lakkaavat päivittämästä ikkunaansa, herjailevat outoja virheilmoituksia, käynnistelevät konetta uudelleen ja latautuvat ikuisuuksia tuntuvan ajan buutissa.

Pahan alku ja juuri lienee "Elisa Tietoturvapalvelu", joka yrittää blokata kaikkea mahdollista, ja todennäköisesti hidastaa koneen toimintaa 50+%. Miten näistä tietoturvahirviöistä oikein päästäisiin eroon? Sisko onneksi jo siirtyi Mac-käyttäjäksi ja peruutti oman tietoturvapalvelunsa tarpeettomana.

Toinen ohjelmistosuunnittelun mestariteos on Nokian Software Updater, joka rieputteli tällä kertaa 3120-parkaa tuntikausia jumittaen, buuttaillen, vaatien PIN-koodia ja kysellen "yhdistetäänkö USB PC-Suite-tilassa". Koko ajan NSU:n etenemispalkki pysytteli tietenkin samassa kohdassa, "aikaa jäljellä 15 minuuttia", ja "älä missään nimessä irrota tai sammuta puhelinta, jottei se rikkoutuisi tyystin". PC:n ruudulla olevat ohjeet eivät missään vaiheessa vastanneet sitä, mitä kännykässä tapahtui. Ihmeen kaupalla luuri kuitenkin vihdoin päivittyi 10.0-softaversioon, vaikka NSU välillä herjaili virheitäkin ja meni jonkinlaiseen hätävarjelutilaan.

Loppujen lopuksi One Touch -nettiyhteys saatiin sitten aivan yllättäen toimimaan, kun Nokia PC-Suite päivitettiin uusimpaan 7.1.26-versioon. Nokian webbisaitilta toki latautuu oletuksena vanhempi 7.1.18, jossa One Touch ei toimi, vaan katoaa mitään sanomatta näkymättömäksi prosessiksi Windowsin taustalle.

Itse Maciin ja iPhoneen tottuneena en voi muuta kuin ihmetellä, mikä ihmisiä oikein pitää niin juurtuneina kiinni Windows- ja Nokia-maailmassa... Näitä juttuja ei tarvitsisi kärsiä, kun maksaa sen pienen ekstrahinnan laadukkaista tuotteista.