tetoshop.com tetocserepshop.com mestercentrum.com

Archívum

A Szerkesztő archívuma

Mercurial – első tapasztalatok egy elosztott verziókezelővel

május 7th, 2011 8 hozzászólás

Már régóta szemezek az elosztott verzió kezelő rendszerekkel. Egyfelől azért, mert úgy látom ez a trend (néhány év múlva az elosztott verzió kezelők fogják átvenni az  SVN helyét, úgy ahogyan annak idején az SVN került az akkoriban elterjedt CVS helyére), másfelől magam is szembesültem már az SVN néhány hátrányával, amiken az elosztott verziókezelő rendszerek felülemelkednek. No de mi is az az elosztott verzió kezelő rendszer?

Feltételezem, hogy az olvasó találkozott már  központi (centralizált) verziókezelő rendszerrel. Ilyen például a hagyományos SVN, vagy a CVS. Központi verziókezelő esetén ugye van egy központi szerver (pl. SVN szerver), a felhasználók pedig innen húzzák le, illetve ide tolják fel a saját változtatásaikat. Minden feltöltést egy letöltésnek kell megelőznie, ami az adott felhasználó gépén összefésüli a szerveren lévő és a lokális változatot. Ha az összefésülés automatikusan megoldható (általában megoldható), akkor azt a rendszer el is végzi, ha nem, akkor kézzel kell összefésülnünk a változatokat, majd az eredményt feltöltjük, és onnantól az lesz az aktuális változat. Az egyes változatokat vissza lehet keresni, egy egy állományt vissza lehet állítani a régi állapotra, és változatonként pontosan nyomon követhetjük, hogy hol mi változott. Nagyon röviden valami ilyesmiről szól egy központi verziókezelő.

Elosztott (decentralizált) verziókezelő esetén más a helyzet. Ott egyetlen központi tároló (repository) helyett minden felhasználónak van egy saját külön tárolója a gépén. A külön tárolónak külön verziókezelése van, tehát nem kell minden egyes változást a központi szerverre tölteni. Itt rögtön látszik is az elosztott verziókezelők egyik nagy előnye az SVN-el szemben. SVN esetén ha valami nagy feladaton dolgozunk, és a feladat megoldása közben menteni szeretnénk egy egy mérföldkövet, azt csak az egyetlen központi tárolóba menthetjük. Így választhatunk, hogy vagy félkész dolgokat mentegetünk a központi tárolóba (ezzel esetleg működésképtelen vagy hibás verziókat hozva létre), vagy mindaddig nem készítünk verziót, amíg el nem készültünk a feladattal (így viszont a feladat ideje alatt elveszítjük a verziókezelésből eredő előnyöket). Mindkét megoldás rossz, de mindenki saját szája íze szerint választhat, hogy melyik a kisebbik. Elosztott verziókezelés esetén nincs ilyen gond, hiszen a saját lokális tárolójába mindenki olyan verziókat hoz létre, amilyet akar (lehetnek ezek között működésképtelen, félkész állapotok is), és csak akkor tölti fel az egészet a központi tárolóba, ha kész van a feladattal (esetleg le is tesztelte, stb.). Így a központi tárolóban mindig egy stabil, használható változat van. Ez már önmagában nagy előny, de mint látni fogjuk, ez csak egyetlen a sok közül. Tehát egy központi tároló helyett itt több tároló van, és mivel nincs is olyan fogalom, hogy “központi” tároló, ezekből a lokális tárolókból tetszőleges hierarchiák kialakíthatóak. Tehát pl. egy projekt 2 nagyobb feladatra osztható, és mindkét feladaton dolgozik 2-2 fejlesztő. Ebben az esetben a két fejlesztőnek van 1-1 saját tárolója, ezekből mindig az adott feladat tárolójába szinkronizálnak, és ha az adott feladat elkészül, akkor tolják ki az egészet a “központi”, stabil tárolóba. De hasonló módon akár az is megoldható, hogy 2 “központi” tárolót tartunk fenn. Az első egy “testing”, a második egy “stabil” változat. Ha elkészül egy feladat, akkor az a “testing” rendszerbe kerül. Itt valaki leteszteli, és ha megfelelőnek találja, kihelyezi a stabil tárolóba. Ez csak néhány példa a teljesség igénye nélkül, de sok más elrendezés is elképzelhető. Például ami nekem nagyon tetszett, hogy nyílt forrású projektek esetén ha a forráskód tárolására SVN-t használnak, akkor két módon lehet beszállni a fejlesztésbe. Az egyik, hogy elérési jogot kérünk a tárolóhoz. Itt ugye az a dolog veszélye, hogy akinek ilyen jogot adunk, abban nagyon meg kell bízni, hisz kontrollálatlanul telepakolhatja a kódot mindenfélével. A másik eset, hogy a felhasználó elvégzi a módosítást, majd generál egy patch-t, amit elküldhet a projekt vezetőjének, aki átnézi azt, és kézzel befésüli az SVN-be. Ez viszont elég kényelmetlen. Elosztott verziókezelő esetén a dolog igen gördülékenyen megy, mivel a felhasználó csinál egy másolatot (klónt) a központi kódbázisról, elvégzi a változtatásokat (itt használhatja a lokális változatának saját verziókezelését), majd ha elkészült, értesíti a projekt gazdáját, hogy húzza át a módosítást a fő kódbázisba. Ez tulajdonképpen olyan mint mikor az ember patch-et küld egy SVN-es projekthez, de sokkal egyszerűbb, és gördülékenyebb.

A legismertebb ilyen elosztott verziókezelő a Git. Ezt a linux kernel fejlesztéséhez hozták létre, de mostanra már sokan mások is használják. Git-ben tárolják pl. az Android forráskódját, a Diaspora-t, az Appcelerator forráskódját, a Facebook is ezt használja a nyílt forrású projektjeihez, és még több ezer projekt, amiket jellemzően a GitHub-on hosztolnak. (A GitHub egy Git alapú code hosting szolgáltatás, olyan mint a Google Code Hosting, vagy a Sourceforge, bár sok szempontból sokkal fejlettebb.) A Git után szorosan második helyen áll a Mercurial. Nem kell szégyenkeznia a Git mellett, hisz olyan projektek használják, mint a Mozilla böngésző, Python programozási nyelv, OpenJDK, Netbeans, stb. Ráadásul a Google Code Hosting-on is használhatjuk az SVN alternatívájaként. Valójában nekem is szimpatikusabb a Mercurial, mint a Git, mivel a Git egy scriptekből és programokból összelapátolt valami, míg a Mercurial tulajdonképpen egy Python program, így ha kell, ebbe jobban bele lehet nyúlni (pl. plugint fejleszteni hozzá), ráadásul az egész valahogy jobban egyben van. Van még néhány elosztott verziókezelő (pl. Bazaar, amit az Ubuntu Linux használ), de mind közül nekem a Mercurial tetszett legjobban, így erről fogok írni.

Akit mélyebben érdekel a Mercurial, a http://hginit.com/ címen találhat egy nagyon jó angol nyelvű összefoglalót, de én is írok róla néhány sort.  Ha ki szeretnénk próbálni ennek a verziókezelő rendszernek a képességeit, legegyszerűbb, ha letöltjük a TortoiseHg klienst. Ez beépül a Windows jobb gombos menüjébe, így a fájlkezelőben könnyen adminisztrálgathatjuk a tárolóinkat. A kísérletezéshez hozzunk létre egy tárolót. Ehhez a TortoiseHg-ban van egy “Create repository here” menüpont. Az első dolog, amit észrevehetünk, hogy maga a tároló egy egyszerű könyvtár néhány speciális fájlal, tehát alapvetően nincs szükség szerverre a működéshez. Ez már önmagában is hasznos lehet. Ha kész a tároló, hozzunk is létre benne néhány fájlt. Eztán ha a tároló könyvtárán jobb gombot nyomunk, feltűnik az ismerős commit parancs. Ezzel az SVN-hez hasonlóan rögzíthetjük a változásokat, és létrehozhatunk egy verziót, ami az SVN-el ellentétben nem egy szerveren, hanem a könyvtárban lévő egyik mappában jön létre. Készítsünk még 1-2 verziót. Van egy Hg Workbench menüpont is, amivel szépen fában látjuk a változatokat, megnézhetjük a különbségeket, stb. Eztán jöhet a trükk, ami az elosztott verziókezelők legnagyobb előnye.  A menüben találunk egy “Clone” parancsot. Ezzel a teljes tárolót lemásolhatjuk még egy példányban, verzió történettel, mindennel együtt. A clone után mér két tárolónk van (két sima könyvtár néhány speciális fájlal és mappával). Most csináljunk néhány verziót az egyik, majd néhány verziót a másik tárolóban. Ez jelképezi a több fejlesztési ágat. A gyakorlatban ez úgy néz ki, hogy minden egyes fejlesztő klónozza magának a tárolót, és abba dolgozik. Szóval csináljunk néhány verziót mindkét tárolóban. Ha ezzel megvagyunk, akkor jön az, hogy a másodlagos (pl. fejlesztési) tárolót fésüljük vissza az elsődleges tárolóba. Ezt két módon tehetjük meg. Vagy a cél tárolóba húzzuk (pull) a változásokat a forrás tárolóból, vagy a forrás tárolóból nyomjuk (push) a cél tárolóba a dolgokat. Mindkét módozatnak van értelme. A push-ra jó példa, amikor mondjuk egy fejlesztő befejezett egy feladatot a saját lokális tárolójában, és ezt betolja a központi fejlesztői tárolóba (kb. az SVN commitnak felel meg). A pull használata pedig például akkor lehet hasznos, ha a stabil szál felelőse áthúzza a változásokat a fejlesztői szálból. Például GitHubon (ez Git alapú, de a mechanizmus ugyanaz) úgy szállhatunk be egy nyílt forrású projekt fejlesztésébe, hogy klónozzuk a projekt tárolóját, megcsináljuk a változtatásokat (ehhez semmilyen interakció nem kell ugye a projekt gazdájával), majd ha megvagyunk, küldünk egy pull request-et (ez kb. egy üzenet, hogy “kérlek, húzd át a változásokat az én tárolómból”) a projekt gazdájának, aki átnézi, hogy mit változtattunk, és ha mindent rendben talál, áthúzza a változásokat a projekt fő tárolójába. Ez nagyon gördülékeny módja a nyílt forrású projekthez való hozzájárulásnak, sokkal kényelmesebb, mint SVN hozzáférést kunyerálni, vagy patch-eket küldeni. A példa kedvéért tehát nyissuk meg az elsődleges tárolónkat a Hg Workbench-ben, és húzzuk át a változásokat a másodlagosból. Ha ez megvan, láthatjuk a Workbench-ben, hogy a másodlagos tároló történettel, mindennel együtt egy új ágként megjelent a mi tárolónk történetében (magyarul látszik, hogy ott ketté vált a fa). Ez már majdnem jó, már csak egyesíteni kell a két ágat. Ehhez van a workbench-ben egy merge művelet. Ez igazából ugyanúgy megy, mint SVN-ben a merge-ölés, ha lehet, automatikusan merge-öl a rendszer, ha nem, akkor kézzel kell ezt megtenni. (Elvileg a Mercurial mindenféle metaadatot gyűjt a merge segítésére, de ezt a részét annyira nem próbáltam.) Ha megvan a Merge, jöhet egy commit, és rögtön egy szálon megy tovább az egész. Tehát ha a fejlesztés végén ránézünk a fára, lépten-nyomon kis elágazásokat és visszacsatolásokat fogunk látni, amik az egyes fejlesztések.

Úgy nagyon dióhéjban ennyi lenne a Mercurial bemutatása. Feltűnhetett, hogy minden műveletet a fájlrendszerben végeztünk, de ahogyan SVN esetén, természetesen itt is megvan a lehetősége annak, hogy egy repository-t egy szerveren tároljunk, amit HTTP-n, HTTPS-en, vagy SSH-n keresztül lehet elérni. A dolgok mechanizmusán ez nem sokat változtat, egyszerűen az ilyen tároló nem a fájlrendszerben van, hanem egy távoli szerveren, de ugyanúgy lehet klónozni, lehúzni (pull) róla a változásokat (ami az SVN update-hez hasonló), vagy felnyomni (push) oda a változásokat (ami az SVN commit-hoz hasonló). Célszerűen csak a fejlesztő lokális tárolóját érdemes a fájlrendszerben tartani, minden olyan tárolót, amit többen használnak (közös fejlesztési ág, stabil ág, stb.), szerveren érdemes tartani.

Remélem ezzel a kis ismertetővel sikerült kicsit kedvet csinálni az elosztott verzió kezelő rendszerek, azon belül is a Mercurial használatához.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

Vizautók és hidrogén hajtás

március 6th, 2011 Nincsenek hozzászólások

Nemrégiben írtam már egy posztot a vízautókkal kapcsolatban. Ott azt próbáltam fejtegetni, hogy miért nem jogos a “jelenlegi ismereteink alapján ez nem lehetséges” típusú elutasítás ezekkel a találmányokkal kapcsolatban. Most kicsit más szempontból írnék ugyanarról. Nevezetesen, hogy mi az amit már tudunk, de mégsem élünk vele. Kezdjük is hát az elején.

A benzin (és vele minden más kőolaj származék üzemanyag is) fogy. Nem áll belőle rendelkezésre végtelen mennyiség. E mellett a benzin szennyezi a környezetet, és drága is. Mivel az áruszállítás miatt a benzin ára beépül mindenbe, ezért minden drágább lesz, így az olajsejkeken kívül mindenki rosszul jár. Mondjuk ők cserébe szigeteket építhetnek Dubaj-ban, de ez minket cseppet sem vigasztal. Az egyszerű halandó embernek marad a folyamatos fizetés, a szmog, meg a tüdőrák. Nem csoda hát, hogy mikor felreppen a hír, hogy ezen túl benzin helyett vizet tankolhatunk az autóba, sokak szeme felcsillan. A föld nagy része (ha jól emlékszem, azt tanították, hogy 70%-a) víz, így abból jutna mindenkinek. Attól sem kellene félni, hogy elfogy, mert a vízautó ugye vizet pufogna ki, ami idővel visszapotyog az óceánokba, így közel ingyen közlekedhetnénk. A kérdés már csak az, hogy kivitelezhető-e a dolog. A válasz pedig szerintem egyértelműen igen, csak nem úgy, nem annyira egyszerűen, mint gondolnánk. Le is írom miért.

Ha hihetünk az energiamegmaradás törvényének (van esély rá, hogy nem mindig működik, de eddig erre nem volt példa), akkor a semmiből nem lesz energia. Tehát csak úgy magától nem fog menni az autónk. A benzintől azért megy az autó, mert abban koncentrált energia van. Ha elégetjük, más anyagokká alakul. Ekkor szabadul ki belőle az energia, és ettől megy az autó. Szóval a benzin esetén egy anyag másik anyaggá alakul, innen van energiánk. Amikor tehát autózunk, akkor az évmilliók során a kőolajban tárolt energiát használjuk el. A vízautókkal szemben azért szkeptikusak az emberek (köztük én is), mivel itt nincs ilyen átalakulás. Víz megy be, víz jön ki, sem kémiai, sem fizikai változás nem jött létre, tehát honnan lenne energiánk? Erre aztán az a válasz, hogy bizonyos speciális körülmények között ez a folyamat energiát csatol ki az univerzum végtelen energiatengeréből, vagy még durvább esetben az, hogy maga az energiamegmaradás hibás, és lehet semmiből energiát termelni. Nos, érthető, ha az ilyesmitől viszolyognak a fizikusok, hiszen ilyenre még soha sehol nem láttunk példát, sőt, minden jel arra utal, hogy az energiamegmaradás igaz, és nagyon kemény alaptörvénye a fizikának. Ennek ellenére, ahogyan az előző postban már írtam, egy fizikusnak kutya kötelessége kivizsgálni minden ilyen esetet, még akkor is, ha az aktuális modellnek az ellent mond. Hiszen mindig csak a megfigyelésekből vonhatunk le következtetéseket, soha nem járhatunk el fordítva. Tehát egy megfigyelést nem cáfolhatunk az eddigi következtetéseink alapján. Azért az esetek döntő többségében (tulajdonképpen eddig mindig) a fizikusoknak volt igaza, tehát mikor felreppen egy ilyen újabb “vízautós hír”, joggal feltételezhetjük, hogy végül az derül ki róla, hogy a dolog nem működik.

Szóval a “vizet tankolok a kocsiba” dolog működésére elég kis (persze soha nem 0) esély van, viszont a poszt elején azt írtam, hogy mégis megoldható a dolog. Lássuk hogyan. Ehhez viszont először térjünk vissza a benzinhez. Hogyan működik a benzin? Ahogy már írtam, a benzinben kémiai formában energia tárolódik. Mikor elégetjük, ez az energia kiszabadul, és ez hajtja az autót. Tulajdonképpen minden égésnek ez az alapja, ez történik például akkor is, ha fából tüzet rakunk. Itt a fa hamuvá alakul, és a felszabaduló energia jelenik meg hőként. No de hogy kerül a fába az energia? Erre való a fotoszintézis. A fa elnyeli a napfényt, aminek hatására bizonyos anyagok más anyagokká alakulnak. Ily módon a fa a nap energiáját saját anyagában konzerválja. Mikor elégetjük, akkor tulajdonképpen a nap évek alatt összegyűjtött energiája szabadul fel. Ez tulajdonképpen majdnem ugyanaz, mint mikor napelemmel feltöltjük mondjuk a zseblámpánk elemét, amivel aztán este világíthatunk. A fa is egyfajta “napelem”, csak kicsit bonyodalmasabb a működése. Valójában itt a földön szinte minden dolog a napból nyeri az energiáját, “a föld mint gépezet energiaforrása a nap”. Mi emberek például étkezéssel nyerjük az energiánkat, állatokat és növényeket eszünk. Az állatok is növényeket esznek, onnan nyerik az energiát, a növények pedig fotoszintetizálnak, tehát végső soron mi is napenergiával működünk. De a vízerőművet hajtó vizet is a nap mozgatja, vagy a szélerőművet hajtó szelet, és végső soron a kőolaj és a földgáz is rothadó állatok és növények maradványaiból keletkezik, ami egykor ugyancsak a naptól kapta az energiáját. No de hogy jön mindez a vízautókhoz?

Az előbbiek alapján már látható, hogy jelenlegi tudomásunk szerint energiát csak úgy lehet termelni valamiből, ha oda valahogy bekerült. A hajtóanyagnak energiát kell veszítenie, amivel aztán az autónkat hajthatjuk. Ezt szaknyelven úgy szokták mondani, hogy a zárt rendszer energiája nem változhat. A benzin esetén ez teljesül, hiszen a folyamat elején bemegy a benzin, majd kipufogó gázzá alakul. Ekkor veszít az energiájából, és ettől megy az autónk. Ha vizet öntünk az autóba, és víz jön ki, akkor semmi nem veszített az energiájából. Ha az autó mégis mozog, akkor valami misztikus helyről (pl. az univerzum kimeríthetetlen energiatengeréből, stb.) energiának kellett oda bekerülnie. Ahogy már írtam, ilyesminek a létezéséről nem tudnak a fizikában, tehát a jelenlegi tudásunk szerint ez így nem működhet. Mit lehet tehát tenni? A víz ahogyan kémia órán tanultuk, két rész hidrogénből és egy rész oxigénből áll (innen a H2O képlet). Megtehetjük, hogy energia befektetéssel a vizet alkotó részeire bontjuk. Ha így teszünk, az alkotó részekben konzerválódik a bontásra szánt energia. Amikor az alkotórészeket egyesítjük, tehát a hidrogént és az oxigént vízzé égetjük el, akkor visszakapjuk ezt a befektetett energiát. Pontosan ugyanaz történik, mikor a fa vagy éppen a benzin elégetésével visszanyerjük az abban tárolt napenergiát. Röviden tehát ahogyan a benzinben, vagy a fában tárolódik az energia, úgy a vízben (vagyis a víz kettébontott alkotóelemeiben) is tárolhatunk energiát. Tehát a benzin a fa, vagy éppen a víz is olyan mint egy akkumulátor. Ugyanúgy energiát tárol. Itt jutunk el ahhoz a kérdéshez, hogy akkor minek az egész folyamatba belekeverni a vizet? A víz bontásához is energia kell, miért nem használunk simán egy rakás akkumulátort, és hajtjuk az autókat elektromos motorokkal? A víz bizonyos szempontból  jobb erre a célra. Az elektromos hajtáshoz a kocsi motorját egy az egyben elektromos motorokra kellene cserélnünk, ezzel szemben amennyire én tudom, a hidrogénhajtáshoz csupán a kocsi átalakítására van szükség (ugyanúgy robbanások hajtják a motort, csak benzin helyett hidrogén és oxigén ég el vízzé), az alapanyag nem környezetszennyező, és az égéstermék is csak víz. Ennek fényében tehát ha nem is vizet, de hidrogént tankolhatnánk a kocsinkba benzin helyett. A hidrogént előállíthatnánk megújuló energiaforrások (pl.: víz, szél, nap, stb. energia), vagy éppen nukleáris energia felhasználásával (a tévhitekkel ellentétben ez sokkal kevésbé környezetszennyező, mint a benzin). És persze ott van az energiaforrások netovábbja, a fúziós energia, ami például a napot működteti. Ilyen fúziós erőművet még nem vagyunk képesek létrehozni, de egy nap talán ez is lehetséges lesz.

Hogy miért nem hidrogénnel hajtjuk már most az autókat? Amennyire én tudom, a hidrogén ellen felhozott legnagyobb ellenérv a tárolás/szállítás nehézsége. Míg a benzinhez elég egy sima benzines kanna, addig a hidrogén tárolásához rendkívül erős falú tartály szükséges. A benzint simán öntögethetjük, kicsit párolog ugyan, de könnyen kezelhető. Ezzel szemben a hidrogén gáz, nagy nyomáson, cseppfolyósítva tárolhatjuk, így mindenféle vastag csöveken tudjuk csak egyik helyről a másikra átnyomatni. Azt is szokták emlegetni, hogy veszélyesebb, mint a benzin, sokkal könnyebben, sokkal nagyobbat robban, mint a benzin. Erre a problémára már láttam megoldásokat, és úgy tudom, van már rá technológia, aminek használatával már viszonylag biztonságosan megoldható a tárolás. Ezek alapján úgy néz ki, hogy a hidrogénhajtás elterjedése inkább infrastrukturális, mint technikai jellegű probléma. Át kellene alakítani a kocsikat, hidrogén kutakat kellene építeni, hidrogén gyárakat, stb.

Persze a hidrogén mellett ott a tiszta elektromos hajtás is, sőt, sokak szerint ez sok szempontból jobb is. Nincs gond a tárolással (csak jó akkumulátorok kellenek hozzá), nincs gond a szállítással (csak néhány villanyvezeték kell, ami tulajdonképpen már meg is van), sőt, akár magunknak is előállíthatjuk a szükséges energiát a házunk tetején lévő napaelemmel, vagy a kertben elhelyezett szélerőművel. A dolog hátránya, hogy teljesen újra kell gondolni hozzá az autókat, a benzintartályt akkumulátorokra, a motort elektromos motorra kell cserélni. A másik gond, hogy a jelenlegi akkumulátorokkal hamar lemerül egy ilyen kocsi, így 50-100 km-enként töltőállomásokat kellene elhelyezni (bár ha jobban belegondolunk, a benzinkutak is vannak ennyire sűrűen). Alternatív megoldás, hogy a kocsiban vész esetére egy benzines generátort is beszerelünk, amivel elpöföghetünk a következő elektromos töltőállomásig. Szóval ez sem egy rossz alternatíva, de legalább olyan elszántság kellene a bevezetéséhez, mint a hidrogénhajtás esetén (elektromos töltőállomások, elektromos autók gyártása). Akit a dolog bővebben érdekel, nézze meg a “Ki ölte meg az elektromos autót?” című YouTube-on elérhető kis dokumentumfilmet, ami jó összefoglalása a témának.

Szóval van alternatívánk a benzinre, nem is egy. Hogy a váltáshoz szükséges lépéseket miért nem lépik meg, azt pontosan nem tudom. Lehet, hogy gazdasági okai vannak, lehet, hogy a fentieken kívül van még valami technikai probléma, ami megoldásra vár, de az is lehet, hogy valóban akkora üzlet a benzin, hogy sokak ellenérdekeltek abban, hogy mindez megvalósuljon. Mindenesetre nincs semmi hókusz-pókusz a dologban, jelenlegi ismereteink szerint működőképes, és megvalósítható.

De ebben a posztban nem is annyira ez a lényeg, hanem az, hogy az alapelvet megértsük. Nevezetesen, hogy a vízautókkal az a legnagyobb baj, hogy “klasszikus” (vizet töltök a tankba) formájukban sértenék az energiamegmaradás törvényét, amitől a fizikusokat kirázza a hideg. Jelenlegi ismereteink szerint energia nem lesz a semmiből. Energiát csak úgy nyerhetünk valamiből, ha egyszer valahogy oda energia került be. Ily módon mindenfajta üzemanyag csak egyfajta energiatároló közeg. A benzin a fa, a hidrogén, a rádióaktív anyagok, és végső soron egy sima akkumulátor is ugyanazt a feladatot látja el számunkra. Nevezetesen energiát tárol. Persze egymástól igen eltérő formákban. A nem megújuló energiaforrások esetén ez az energia valamikor nagyon régen került be oda, és ha ezt az energiát felhasználjuk, az “nem pótolódik vissza”, tehát az ilyen anyagok folyamatosan fogynak. Ilyen ugye a kőolaj, amiben egyszer régen energia konzerválódott, és ha elégetjük az autó motorterében, kipufogógáz lesz belőle, soha nem áll össze újra benzinné. Ez persze igaz a hidrogénre is, hiszen a hidrogén vízzé ég el, és a víz később nem fog magától hidrogénre és oxigénre bomlani. Ugyanakkor a hidrogén könnyen előállítható elektrolízissel, amihez már használhatunk más, megújuló energiákat (pl. szél, víz, napenergia), és végső soron tisztán elektromos áramot is használhatunk üzemagyagként elektromos autókban. Amennyire én tudom, ilyen energiából van elég, a nap bőségesen ellátja a földet. Tulajdonképpen mikor mi emberek még nem voltunk, akkor is nagyon jól elműködött a bolygó a nap energiájával, és valószínűleg napjainkban is történhetne így a jelenlegi környezetszennyező megoldások helyett. Szóval energia van, csak meg kell tanulnunk hatékonyan kiaknázni, és tárolni/szállítani. Lehet, hogy nem a hidrogén lesz az üdvözítő megoldás. Lehet, hogy lesz valami más anyag, amiben energiát tárolhatunk. Valami, ami olyan könnyen kezelhető, mint a benzin (szobahőmérsékleten cseppfolyós, vagy szilárd), mégsem környezetszennyező. Azt is el tudom képzelni, hogy egyszer majd genetikailag módosított mesterséges növények fognak fotoszintézis útján valamilyen anyagot előállítani, amit majd üzemanyagként használhatunk (ez a lényege a biodízelnek). Lehet, hogy nem is kémiai formában (üzemanyagként) kell tárolnunk az energiát, hanem elektromos áramként (valójában az akkumulátor is kémiai formában tárolja az energiát). Talán találunk valamilyen az eddigieknél hatékonyabb energiatároló közeget, és ez hozza el a megoldást az üzemanyag problémára. Mindenesetre tény, hogy hamarosan valamilyen irányba lépni kell majd.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tudomány Tags:

Vízautók, meg a fizikai törvények jellege

március 5th, 2011 Nincsenek hozzászólások

A napokban reppent fel egy hír a Facebook-on, hogy egy Gróf Spanyol Zoltán nevű úriember megoldotta, amire sokan úgy várnak mint egy falat kenyérre, nevezetesen, hogy ezen túl benzin helyett színtiszta csapvizet tankolhatunk az autónkba. Mivel sokáig az egyik legkedvesebb hobbim az volt, hogy ilyenek után olvasgattam (pl. Egely könyvekből megvolt tán az összes), természetesen ez is felkeltette az érdeklődésemet. Miután ez a hír már néhányszor nagy csinnadrattával felreppent, és annak rendje és módja szerint hamar el is ült, most is szkeptikus voltam, és hát ha valaki csinál egy egyszerű Google keresést, talál is jó pár ellenvéleményt. Ennek apropóján gondoltam, írok egy postot a véleményemről ebben az egész témában. Bár magam is egészséges mértékben szkeptikus vagyok, mégis sok szempontból inkább ezeknek a feltalálóknak a pártját fogom, mert valahol úgy gondolom,igazságtalanul járnak el velük, el is mondom miért.

Úgy általánosságban az ilyen “Tiltott találmányok” ellen felhozott vádak nagy része úgy kezdődik, hogy “márpedig ez a fizika törvényei szerint nem működhet”. Nos, ez az a mondat, amit egy magára valamit is adó fizikus nem mondhat ki. Ha megteszi, azzal elismeri, hogy nem érti a fizikát, és mint ilyen, méltatlan arra, hogy fizikusnak, vagy mérnöknek nevezze magát. Ha a fizikusaink annak idején ebben a szellemben gondolkodnak, vagyis nem vizsgálják ki azokat a jelenségeket, amik az akkor aktuális világnézet szerint nem működhetnek, akkor most jóval szegényebbek lennénk. Mondok is egy egyszerű példát. Ha azt mondom, hogy lehetséges az, hogy egy golyót elhajítva az egyszerre két lukon is átmenjen, akkor még csak fizikusnak sem kell lenni ahhoz, hogy valaki azt mondja, hogy hülyeségeket beszélek. Nos, az a helyzet, hogy ha elég pici a golyó, és elég közel van egymáshoz a két luk, akkor ez a jelenlegi fizikai törvények alapján igenis lehetséges. Nagyon leegyszerűsítve ez a kvantummechanika egyik alapjelensége. Egy olyan fizikus számára, aki csak a klasszikus mechanikát ismeri, ez nem csak hogy a fizika törvényeinek mond ellent, de még józan ésszel is értelmezhetetlen. Mégis, ha nincs kvantummechanika, akkor talán ma nem lennének processzorok, integrált áramkörök, számítógépek, mobiltelefonok, TV, semmi, ami a mai modern társadalom alapja. Megrekedtünk volna a sötét középkorban. Az ilyen, és ehhez hasonló jelenségek miatt a mai modern fizika már jócskán túlhaladt azon, hogy a szó klasszikus értelmében “megértsük” azt. Egyetlen egy dolgot tehetünk, megfigyeléseket végzünk, az eredményeket pedig matematikai formába öntjük. Ha elég sok mérést végeztünk, és mind azt mutatja, hogy a formulánk helyes, (akármilyen mérést is végzünk el, mindig azt találjuk, hogy a formula által megjósolt eredmény az amit valóban tapasztalunk) akkor tehetünk egy olyan kijelentést, hogy VALÓSZÍNŰLEG ez a formula minden esetben helyesen írja le a világ működését. Ugyanakkor a dolog jellegéből adódóan nem vonhatunk le abszolút következtetéseket, hiszen nem vizsgálhatjuk meg az összes peremfeltételt. Hogy még jobban megvilágítsam a problémát, mondok egy nagyon egyszerű példát. Egy nap belém hasít a felismerés, hogy a víz folyékony. Tudom, hogy hülye példa, de mégsem sokkal rosszabb, mint az a felismerés, hogy az alma leesik a fáról, pedig ha hinni lehet a legendának, Newton fejében valahogy így kezdődött az az elmélkedés, aminek eredménye a gravitáció törvényének felfedezése lett. Szóval ott tartottunk, hogy “a víz folyékony”. Ezt szeretném is fizikai törvény szintjére emelni, úgyhogy elvégzek egy rakás kísérletet. Felmegyek a padlásra, lemegyek a pincébe, bejárom az egész várost, és mindenhol azt találom, hogy a víz márpedig folyik. Mivel a nap végére nagyon elfáradok, úgy érzem, elég kísérletet végeztem, és publikálom az eredményeimet. Megszületett az első fizikai eredményem, törvényként mondhatom ki, hogy a víz márpedig folyékony. Innentől kezdve, ha valaki azt mondja nekem, hogy ő látott már nem folyékony vizet, kiröhöghetem, és mondhatom neki, hogy ez nem lehet, hiszen a fizika jelenlegi törvényei szerint a víz folyékony. Aztán eljön a tél, és meglátom az első jégcsapot. Ekkor két dolgot tehetek. Vagy elfordítom a fejem, és azt mondom, hogy bizonyára csak odaképzeltem a “szilárd vizet”, vagy odamegyek, és megvizsgálom, hogy most akkor ez hogy is van. Lehet, hogy tél közepén látom meg az első jégcsapot, pedig a szomszéd Józsi már egy hete mondja, hogy ő látott már “kemény” vizet, de mindig legyintettem rá, hogy “áh Józsi, te nem vagy fizikus, mindig csak a pincében bütykölsz, és szerintem sutyiban pálinkázgatsz is, meg különben is, a ‘kemény’ az nem egy halmazállapot, a ‘kemény’ szót mi fizikusok másra használjuk”. Pedig ha odafigyeltem volna arra a “hülye” Józsira, már egy hete hógolyózhatnék kint a többiekkel, a helyett, hogy mindenféle hülye fizika könyveket olvasgatok. Valami hasonló a helyzet a “valódi” fizikában is. Vannak törvények, a dolgok többségére alkalmazhatóak is ezek, de ha találunk valamit, amire nem, mindig késznek kell lenni megváltoztatni az addigi vélekedésünket. Az is lehet, hogy az egész eddigi világnézetünket ki kell dobni a kukába, vagy legalábbis csak az új törvények speciális eseteként értelmezni. Ez adott esetben fájdalmas lehet, de meg kell tenni, másképp együtt kell élnünk a tudattal, hogy hazugságokban élünk, és lehet, hogy jó dolgokról maradunk le emiatt, mint amilyen a hógolyózás, vagy éppen a vízzel hajtott autó. Persze azt is megértem, hogy egy fizikusnak 1000 kamu eset után semmi kedve foglalkozni az 1001.-kel, mégis meg kell tennie, ha felelősségteljes állításokat akar tenni. Ha ezt kihagyva állít biztos dolgokat, azzal a saját hitelességét veszélyezteti, és ugyanolyan “kóklerré” vélik, mint azok az emberek, akiket ő maga tart “kóklereknek”. Csak hogy érzékeljük, hogy ez mennyire igaz, gondoljunk bele, itt van az univerzum, emberi léptékkel felfoghatatlan nagyságú. Ebben a végtelen sötétségben a porszemnél is porszemebb kis piszok a mi föld bolygónk. Kis golyókat gurigatunk ide-oda, ütköztetjük őket, és felfirkantunk néhány egyszerű képletet egy papírfecniere (ez volna a Newtoni mechanika), aztán elővesszük a távcsövet, elnézünk olyan messzire, ahová a fénynek is évekig tart, míg odaér (az is lehet, hogy amit látunk, már rég nincs is ott), és a látottakra azokat a törvényeket alkalmazzuk, amiket itt papírfecniken összeszedtünk. Honnan vesszük a bátorságot mindehhez? Hogyan merjük azt állítani, hogy ami itt működik, az ott is fog? Honnan tudhatjuk, hogy a fizikai térvényeink nem csak mondjuk a naprendszer pereméig érvényesek? Mi van, ha a csillagokat csak úgy vetítik elénk Isten óriás planetáriumában, miközben az ufók reggelihez valami valóságshowként nézik az életünket, mint az emberek a Truman Show-ban? A fizika hit, olyan mint bármely vallás, az alaptétele pedig, hogy a világ egyszerűen leírható, és ha valamire sok kísérletet végzünk, ami alapján felírunk egy törvényt, az mindenre működni fog. De ez magában rejti azt is, hogy bizonyosságokat soha nem állíthatunk, mindig késznek kell lenni a megújulásra, a dolgok átértékelésére, és el kell fogadni, sőt kutatni kell azokat az eseteket, ahol az eddigi elméleteink nem működnek, mert csak így lehet fejlődni, és a fejlődéssel sok minden újat kaphatunk, mint ahogy eddig is kaptunk.

Szívesen írnék még a hidrogénről, mint energiaforrásról. Ez is egy érdekes téma, oly annyira, hogy szerintem majd egy új postot szentelek neki, egy postba elég ennyi okoskodás… ;)

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tudomány Tags:

Az élet szabadúszó fejlesztőként

február 18th, 2011 2 hozzászólás

Már jó pár éve dolgozom fejlesztőként. Abban a szerencsés helyzetben vagyok, hogy a munkám egyben a hobbim is. Igazából a programozást inkább érzem valamiféle művészetnek, ahol ugyanúgy jelen van az intuíció, az ihlet, a kód, az algoritmusok, és a komplett megoldások szépsége, mint más művészeti ágak esetén. Persze mivel ebből kell megélnem, ez sokszor amolyan megélhetési művészet, de akkor is művészet. Mikor kikerültem a főiskoláról a fejlesztők szokásos útját kezdtem járni. Egy fejlesztő cégnél helyezkedtem el viszonylag jó kezdőfizetésért. Bizonyos magánéleti okok miatt, és mivel nem találtam elég kreatívnak a munkát, 1 év után az MTA Számítástechnikai Kutatóintézetére váltottam. Itt kisebb nagyobb külföldi és magyar projekteken dolgoztam, konferenciákon vettem részt, rendszerek tervezését és fejlesztésének vezetését végezhettem, így ez a munkakör már jobban kielégítette az igényeimet. Néhány év után viszont a SZTAKI-t is magam mögött hagytam. Alapvetően jó fejlesztőnek tartom magam, és továbbléphettem volna a “jó fejlesztők” szokásos útján. Elhelyezkedhettem volna egy külföldi multinál (elvileg a Google-hez is lett volna egy kis hátszelem) valami zsíros fizetésért, mégis egy sokkal bizonytalanabb, bár annál több lehetőséget magában rejtő utat választottam. Otthagytam a biztos állásomat, és vidékre költöztem a barátnőmmel (aki azóta már a feleségem), hogy otthonról szabadúszó fejlesztőként távmunkában dolgozzak változatos projekteken. Gondoltam, hogy nem lesz olyan egyszerű a dolog, és hát tényleg nem is az …

Általában az a baj, hogy a cégek fix fejlesztőket keresnek napi 8 órás munkaviszonyba. Az ember azt gondolná, hogy a szoftverfejlesztés tipikusan az a munkakör, amit ideálisan lehetne végezni otthonról távmunkában (ami különben tényleg igaz), érdekes módon mégis csak több-kevesebb nehézség árán talál magának az ember ilyen otthonról végezhető projektmunkát. Sokáig próbáltam megérteni, hogy mi ennek az oka, és végül tapasztalatból mondhatom, hogy ez egyszerűen nem más, mint rossz beidegződés, hiszen szabadúszó fejlesztők alkalmazásának rengeteg előnye van az alkalmazottakkal szemben …

Az első és talán legegyértelműbb előny, hogy ha a fejlesztő otthonról dolgozik, úgy nincs szükség semmilyen infrastruktúra fenntartására. Nem kell irodát bérelni, nem kell számítógépeket, irodabútorokat biztosítani, nem kell áramért, fűtésért, vízért, stb. fizetni, így egy ilyen fejlesztő összességében sokkal kevesebbe kerül, mint egy alkalmazott. Amennyire tudom, a SZTAKI-ban a bevétel felét vitte el a rezsiköltség, amit egy szabadúszó fejlesztő esetén megspórolhat az őt alkalmazó cég. Negatívumnak igazából csak a személyes kontaktus hiányát lehetne felhozni, de erre viszont ott a Skype, a videokonferencia rendszerek, stb. A SZTAKI-ban több nemzetközi projektben is részt vettünk, ahol értelemszerűen nem lehetett biztosítani a személyes kontaktust. Tapasztalatból mondhatom, hogy a videokonferencia rendszerek alkalmazása vagy a Skype meetingek teljes mértékben kiváltották a személyes találkozókat.

A másik nagy előny, hogy ha az ember szabadúszó fejlesztőkkel dolgozik, a megbízónak nincs semmi kötöttsége. Egy alkalmazott esetén annak folyamatosan fizetést kell adni, aminek egyfelől adminisztrációs vonzata van (bérszámfejtés, járulékok fizetése, ha elégedetlenek a munkájával, és ki kell rúgni, akkor végkielégítés, stb.), másfelől a fix alkalmazottnak havonta kell fizetést adni, amit folyamatosan ki kell termelni. Ez egyfelől plusz terhet ró a megbízóra (könyvelés, fejlesztő eltartása), másfelől mivel a szabadúszó fejlesztők cégekként számlára dolgoznak, általában sokkal optimálisabban tudják elszámolni a költségeket, így végső soron olcsóbbak, mint egy fix fejlesztő. E mellett mivel projekt alapon történik az alkalmazás, ha az alkalmazó elégedetlen a fejlesztő munkájával, akkor a következő alkalommal nem veszi igénybe azt, nem kell neki végkielégítést fizetni, stb.

Mivel az alkalmazó cégek maguk általában projekt alapon dolgoznak, a fix alkalmazottakat viszont folyamatosan fizetni kell, ezért sokszor olyan helyzet alakul ki, hogy vagy nincs munka, és az alkalmazottak erőforrásai nincsenek lekötve, vagy (és általában ez a gyakoribb) túl sok a munka 1 emberre, és az alkalmazottak túl vannak terhelve. Én is több ilyen esetre emlékszem, mikor egyik hónapban csak tébláboltunk, mert nem nagyon volt mit csinálni, a másik hónapban viszont többször is hajnalig bent kellett maradni, hogy tartani tudjuk a határidőket. Ez sem az alkalmazónak,sem az alkalmazottnak nem jó. Van aki nem is bírja az ilyen egyenetlen terhelést, és előbb-utóbb otthagyja a munkahelyet emiatt, pedig ezt a problémát dinamikusan allokálható fejlesztőkkel nagyon könnyen át lehetne hidalni. Valójában erre építenek a mostanában egyre divatosabb outsourcing cégek is, viszont ezek a cégek meglehetősen nagy jutalékokkal dolgoznak, és mivel ők már alkalmazottakat foglalkoztatnak, sokkal drágább ez a megoldás, mint közvetlenül a fejlesztővel dolgoztatni. Az outsourcing cégeknél persze megvan az az előny, hogy biztosan megbízható fejlesztőket kap a megbízó, viszont megfelelő ütemezéssel egy szabadúszó fejlesztőről is hamar eldönthető, hogy megbízható-e, vagy nem.

Az eddigiek alapján tehát szerintem egyértelműen látszik, hogy ez a modell több szempontból is sokkal hatékonyabb mind az alkalmazó cég, mind a fejlesztő számára. Mindennek ellenére azt tapasztalom, hogy az emberek még nagyon bizalmatlanok ezzel szemben, és szabadúszó fejlesztőként nem olyan egyszerű projektet találni. Bár külföldi tapasztalatom nincs a dologgal kapcsolatban, de Magyarországon bizonyosan ez a helyzet, az ok pedig szerintem nem más, mint egy egyszerű beidegződés, egy minta, aminek megtartása a jelenlegi technikai környezetben már nem indokolt, és nem is optimális. Mára már egy cég teljes infrastruktúrája kiszervezhető, Internet kapcsolattal már mindenki rendelkezik, és egy alkalmazó cég semmivel sem tud jobb infrastruktúrát biztosítani, mint az otthoni környezet. A VPN-nek, videókonferenciának, feladat kezelő rendszereknek köszönhetően igazából teljesen mellékes, hogy a fejlesztők egymás melletti irodákban, vagy éppen külön kontinensen dolgoznak. A jelenlegi helyzet engem arra emlékeztet, ami mostanában a cloud computing (felhő infrastruktúra) körül történik. A cloud computing napjaink egyik divatszava, és tulajdonképpen az infrastruktúra bérlését jelenti egy elosztott rendszerben saját szerverek helyett. Sokáig az volt a szokványos módszer, hogy minden feladatra külön szervert állított be a cég. Így rengeteg gép dolgozik még ma is kis terheltséggel teljesen feleslegesen. A cloud computing segítségével sok funkció, vagy akár az egész géppark a cloud-ra költöztethető, így a fenntartása nagyságrendekkel olcsóbb, és biztonságosabb is, a cégek mégis bizalmatlanok a technológiával szemben. Ez a trend napjainkban kezd megfordulni, kezdik elfogadni a cégek a cloud computingot, kezdenek megbízni benne, és kezdik felismerni az ebben rejlő lehetőségeket. Úgy gondolom, hogy néhány év múlva már a cloud computing lesz a vezető irányzat, ha más nem, azért, mert a cég másképp nem lesz versenyképes, képtelen lesz a piacon versenyben maradni úgy, hogy közben ki kell termelnie saját infrastruktúrájának fenntartási költségeit. Valami hasonlót látok a munkaerő vonatkozásában is. A saját szerverek fenntartása az alkalmazottak foglalkoztatásával hozható párhuzamba, míg a cloud computingnak köszönhető erőforrás kihelyezés a szabadúszó fejlesztők foglalkoztatásának felel meg. Látszanak az erre való törekvések, az outsourcing már egészen elfogadott megoldás, és tulajdonképpen ennek a közvetlenebb, “p2p” változata a szabadúszó fejlesztők alkalmazása. A különbség annyi, hogy a cloud computing már a küszöbön van, a szabadúszó fejlesztők elfogadásához, és a jelenlegi “beidegződések” elhagyásához pedig még kell némi idő. Mint oly sokszor már, a környezet már most is adott, egyszerűen fejben kellene csak utolérni a technológiát, és élni a lehetőségekkel, aki pedig időben lép, az egyértelmű piaci előnyökké konvertálhatja a lehetőségeket.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Nincs kategorizálva Tags:

JSONP és Cross-Site Scripting

január 10th, 2011 Nincsenek hozzászólások

Aki próbált már JavaScript-ből idegen szerverrel kommunikálni, az valószínűleg belefutott már a Cross-Site Scripting problémakörbe. Röviden arról van szó, hogy biztonsági okokból egy oldalon lévő JavaScript csak az oldalt tartalmazó domain-el képes kommunikálni (onnan bármit letölteni, vagy küldeni oda). Ez bizonyára sok gonoszságtól megvéd minket, mégis vannak helyzetek, mikor jól jönne, ha idegen domainről tudnánk adatokat letölteni. Például RSS feed-et szeretnénk olvasni JavaScript-ből, vagy valami távoli szolgáltatást szeretnénk valami API-n keresztül elérni. A napokban én is egy hasonló problémával találtam szemben magam. Nevezetesen volt két oldalam (mondjuk foo.com és bar.com). Az egyiken leraktam egy cookie-t, amit a másik oldalon szerettem volna kiolvasni, és mindezt JavaScript-ből. Mivel a bar.com oldal nem láthatja a foo.com oldal cookie-jait, ezért ezt csak úgy lehet megoldani, hogy a foo.com kiolvassa a saját cookie-ját, és valahogy átadja ezt a bar.com-nak. A baj csak az, hogy a bar.com-on lévő JavaScript nem tudja semmiképp elérni a foo.com oldalt. Több dologgal próbálkoztam, iframe-el, megpróbáltam a foo.com-ról betölteni a JavaScript-et, stb. de semmi nem vezetett eredményre. Ekkor találtam rá a JSONP-re.

A JSONP igazából egy igen egyszerű kis trükk a fenti probléma megkerülésére. Ha egy ideig szenved vele az ember, valószínűleg egy idő után magától is kitalálja. A JSONP-nek annyi a lényege, hogy úgy adunk át adatokat a foo.com-ról a bar.com-nak, hogy foo.com az átadandó adatokból generál egy JavaScript-et, és ezt a bar.com egy egyszerű script taggal behúzza. Mindebből úgy alakíthatunk ki kétirányú kommunikációt, hogy a kliens URL paramétereket használ az adatok továbbítására, amire a szerver a megfelelő javascript generálásával válaszol. Hogy mindez tisztább legyen, nézzünk egy példát. Tekintsük a fenti problémát, vagyis a foo.com domainről szeretnénk lekérni a cookie megadott nevű mezőjének értékét. Ehhez hozzunk létre egy cookie.php állományt a foo.com domainen, amit a következőképpen paraméterezhetünk: foo.com/cookie.php?cookie_name=<változó neve>&callback=<javascript fv.>. Itt a változó neve ugye egyértelmű, a callback paramétert meg nemsokára megértjük. A cookie.php valahogy így fog kinézni:

<?php
$cookie_name = $_GET['cookie_name'];
$data = array();
$data[$cookie_name] = $_COOKIE[$cookie_name];
echo $_GET['callback'] . '(' . json_encode($data) . ');';
?>

ha a fenti scriptet cookie_name=test és callback=jsonp_callback paraméterrel hívjuk, az eredmény valami ilyesmi lesz:

jsonp_callback({'test': 'Test cookie value.'});

Ez pedig egy teljesen szabványos javascript hívás. Nincs más dolgunk,mint a fenti url-t egy script tag-el behúzni a hívó oldalra:

<script type="text/javascript" src="http://foo.com/cookie.php?cookie_name=test&callback=jsonp_callback"></script>

A script tag tartalmát a böngésző azonnal végrehajtja, ami ugye így azt eredményezi, hogy meghívódik a jsonp_callback függvény a {‘test’: ‘Test cookie value.’} paraméterrel. Nincs más dolgunk, mint definiálni a jsonp_callback fv.-t, és kész is vagyunk:

function jsonp_callback(data) {
alert(data.test);
}

Igazából ennyi az egész. Persze a gyakorlatban általában nem fix paraméterekkel akarunk hívni egy szerver szolgáltatást. A dinamikus paraméterezéshez dinamikusan kell előállítanunk a script tag-eket, ez DOM műveletekkel viszonylag egyszerűen megvalósítható, de van egy még kényelmesebb megoldás, ez pedig a jquery javascript library ajax hívása. Ezzel a megoldással egy egyszerű függvényhívásra van csak szükség, ami valahogy így néz ki:

$.ajax({
dataType: 'jsonp',
data: 'cookie_name=test'
url: 'http://foo.com/cookie.php',
success: function (data) {
alert(data.test);
},
});

Így tehát JQuery használatával, és némi PHP ismerettel már egész kényelmes Cross-Site Scripting megoldást készíthetünk. Akit a JSONP mélyebben érdekel, az utánanézhet a wikipediában.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

lworm (egy pehelysúlyú PHP ORM megoldás)

november 20th, 2010 Nincsenek hozzászólások

Amikor elkezdett foglalkoztatni a gondolat, hogy PHP-ban fejlesszek Google App Engine-re, az egyik legnagyobb problémának az adatbázis elérése tűnt, hiszen PHP-ból általában SQL használunk erre, ami ugye App Engine alatt nem megoldható, hiszen a datastore egy nem relációs adatbázis. Utánanéztem kicsit, hogy mások hogy oldják meg ezt, és igazából két megoldást találtam. Az egyik az App Engine által szolgáltatott JPA vagy JDO réteg használata. Itt ugye az a gond, hogy ezzel elveszítjük a rendszer hordozhatóságát, hiszen egy standard LAMP környezetben már nem állnak rendelkezésre ezek a programkönyvtárak. A másik lehetséges megoldás, hogy valamilyen SQL wrappert használunk, amin keresztül a datastore szabvány SQL adatbázisnak tűnik. Ezzel az volt a gondom, hogy feleslegesnek tűnt, hiszen az SQL réteg felett úgyis valamilyen ORM réteget használnék, és ha már így van, miért ne építsük az ORM réteget közvetlenül a datastore fölé. Így született tehát az elhatározás, hogy saját ORM réteget fejlesszek PHP-hoz, és ha már belefogtam, megpróbáltam belegyúrni az eddigi tapasztalataimat.

Az első szempont az egyszerűség volt. Minimalista megoldást akartam, ami egyszerű, de mégis hatékony. E mellett legyen transzparens, tehát az elkészült PHP alkalmazás egyaránt képes legyen futni egy általános LAMP környezetben, és az AppEngine datastore-ja felett is. Mivel annak idején a Hibernate-el volt némi nézeteltérésem, mindenképp olyan megoldást akartam, ahol az entitások memória objektumok, tehát nincsenek az adatbázishoz kötve (csúnyán mondva nem attach-oltak). Itt most nem térnék ki a részletekre, de a lényeg, hogy ennek köszönhetően az adatbázis objektumokat büntetlenül tárolhatjuk a session-ben, vagy mondjuk JSON formában mozgathatjuk őket két rendszer között. Kb. ezek voltak az előfeltételek, lássuk hát a megvalósítást.

A rendszer használatához elsőként egy YAML állományban le kell írnunk az adatbázis sémát és az entitások kapcsolatrendszerét. Ez a YAML formátum felépítésének köszönhetően nem túl bonyolult, mégis szép és átlátható. A YAML alapján a ModelGenerator osztály használatával legenerálhatjuk az entitás osztályokat. Az entitás objektumok csak egyszerű adattároló szerepet töltenek be, így felépítésük az adatbázis megvalósítástól független. Ha ezzel megvagyunk, a megfelelő Datastore factory hívásával kérhetünk a rendszertől egy datastore példányt, aminek segítségével az adatokkal kitöltött entitás az adatbázisra menthető, illetve onnan felolvasható. Ugyancsak a datastore segítségével generálhatunk lekérdezéseket, aminek segítségével egyenlőre csak szűrni és rendezni lehet az eredményeket. Ennek az az oka, hogy az alacsony szintű datastore API csak ezeket teszi lehetővé. Bár lehet, hogy ez az eszközkészlet kicsit szegényesnek tűnik, de az esetek nagy részében általában elég, vagy némi kódolással kiegészíthető. Az entitás példányok kapcsolatainak kezelésére azt találtam ki, hogy az entitás objektum minden kapcsolatához egy metódust rendeltem, ami paraméterként kapja meg az aktuális datastore-t. A metódus egy kezelő objektumot ad vissza, ami a kapcsolatnak megfelelően karbantartja a kapcsolódó objektumokat. Tehát vegyük például a User (felhasználó) és Role (szerepkör) entitásokat, melyek közt many-to-many (több-több) kapcsolat van. Ebben az esetben a User osztálynak lesz egy getRolesRelation metódusa, ami egy kezelő objektumot ad vissza. Ezen az objektumon keresztül adhatunk hozzá Role-okat az adott felhasználóhoz, ezen keresztül listázhatjuk ki a hozzárendelt szerepköröket, vagy törölhetjük azokat. Mivel ezek a Relation objektumok mindig létrehozáskor kapják meg a szükséges adatbázis kapcsolatot, az entitásnak magának nem kell az adatbázishoz kötődnie, amiről az előzőekben már írtam. Röviden tehát körülbelül ennyi.

Az eredmény tehát egy nagyon kompakt kis ORM rendszer. Jelenleg a MySQL-t és a Google App Engine Datastore-ját támogatja, de nagyon egyszerűen kiterjeszthető. Maga a kód nagyon egyszerű, áttekinthető és könnyen használható. Bár ennek a lehetőségét nem vizsgáltam meg mélyebben, de a csökkentett eszközkészletnek köszönhetően valószínűleg a datastore-on kívül más nem relációs adatbázisokra is alkalmazható lenne a rendszer, pl. MongoDB-re. A későbbiekben talán érdemes ezt az irányt is megvizsgálni. A programkönyvtár másik nagy előnye, hogy nagyon pici, így akár kódméret kritikus rendszerekben is használható lenne. A későbbiekben lehet, hogy készül Java, Python, esetleg C++ változatot, amit például mobiltelefonok programozásához lehetne használni.

A kód és néhány példa elérhető a Google Code-on a http://code.google.com/p/lworm/ címen.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

gae-filestore (Írható/olvasható virtuális fájlrendszer Google AppEngine-re)

november 16th, 2010 Nincsenek hozzászólások

A Google AppEngine egyik elég erős megszorítása, hogy a telepített alkalmazás csak olvasni tudja a fájlrendszert. Új fájlokat nem hozhatunk létre, illetve nem módosíthatjuk a fájlokat. Bármilyen adattárolásra az AppEngine által biztosított adatbázist, a Datastore-t kell használnunk. Igazából ha jobban meggondoljuk, egy webalkalmazás többnyire valóban csak az adatbázist használja, így sokszor tényleg nincs szükség fájlrendszerre, de azért néha jól jön. Egy projektem kapcsán épp ilyesmire volt szükségem, ezért készítettem egy igazán egyszerű virtuális fájlrendszer implementációt Google AppEngine-hez. A rendszer működésének megértéséhez először írnék kicsit a Datastore-ról, annak is az alacsony szintű megvalósításáról.

Az AppEngine Datastore-ja egy BigTable alapú nem relációs adatbázis rendszer. Bár pontosan nem tudom, hogy a Google alkalmazások (GMail, Google Maps, a kereső, stb.) is ezt a megvalósítást használják-e, erről nem találtam konkrét leírást, de mindenesetre ez valami nagyon hasonló dolog kell hogy legyen. A rendszer használatára két lehetőségünk van. Egyfelől kapunk egy szabványos JPA/JDO réteget, így J2EE alkalmazásainkat változtatás nélkül, vagy kisebb változtatásokat követően futtathatjuk AppEngine-en. A másik lehetőség a low-level API használata, ami közvetlen hozzáférést biztosít a DataStore-hoz, így sokkal hatékonyabb, ugyanakkor kicsivel kényelmetlenebb is, mint a szabványos réteg. Én ez utóbbiról írnék kicsit bővebben. A Datastore adattárolásának alapja az Entity. A relációs adatbázis kezelőkhöz hasonlítva az Entity az adatbázis rekordnak felel meg, azzal a különbséggel, hogy az Entity-nek nincs fix szerkezete. Ebből a szempontból az Entity inkább olyan mint egy asszociatív tömb, vagy Java terminológiával élve Map. Egy ilyen Entity-be szabadon helyezhetünk el név-érték párokat. A másik nagyon fontos komponens a Key. A Key az entitás elsődleges azonosítója. A Key 3 féle módon épülhet fel. Generálhatjuk egy string-ből vagy long-ból, ezen felül definiálhatunk egy kulcs típust (kind), ami kb. a tábla megfelelője, és végül definiálhatjuk úgy a kulcsot, hogy ezeken felül egy szülő kulcsot is megadunk. Ez utóbbi megoldással a kulcsok és ezzel az Entity-k hierarchiába szervezhetőek. Ha összeállítottunk egy Entity-t, azt egyetlen metódussal lerakhatjuk a datastore-ra, és onnan a Key segítségével vissza is olvashatjuk. Amennyiben nem a Key alapján szeretnénk visszanyerni az entitást, úgy létre kell hoznunk egy Query-t. A Query segítségével az Entitás bármely értékére szűrhetünk az alapműveletek (kisebb, nagyobb, egyenlő, stb.) használatával. Az ilyen keresések segítésére definiálhatunk indexeket, de erre sincs feltétlenül szükség, hiszen a rendszer a lekérdezések alapján automatikusan legenerálja a szükséges indexeket. Az eredményként kapott entitás listát bármely eleme alapján rendezhetjük is, és nagyjából ennyi. Ha több entitást szeretnénk összekapcsolni (JOIN), VAGY kapcsolatot kialakítani a szűrési feltételekben, vagy bármi hasonlót tenni, amire egy relációs adatbázis amúgy önmagában képes, azt kódból kell megvalósítanunk. Cserébe viszont az egész rendszer masszívan elosztott, sémamentes, flexibilis és gyors. Most hogy megismertük a Datastore-t, lássuk a virtuális fájlrendszer működését.

A virtuális fájlrendszer legfelső szintű eleme a DataStoreFile entitás. Ezek az entitások testesítik meg az állományokat és a könyvtárakat egyaránt. Egy ilyen entitásnak 4 attribútuma van. A fájl típusa (könyvtár v. fájl), az utolsó módosítás ideje, a fájl mérete, és a fájlt tartalmazó útvonal. A fájl entitás egyedi azonosítója annak elérési útja, így ez alapján nagyon könnyen elérhetőek a fájl metaadatai. Mivel a metaadatokra sokszor szükség lehet, ezért a fájl entitás mentésekor és betöltésekor a memcache-ben is tároljuk, így annak további elérése már nagyon gyorsan megy a cache-ből. A fájl tényleges tartalmának tárolása Blob-okban történik. A Blob tulajdonképpen egy byte tömb, aminek mérete maximálisan 1 Mb lehet AppEngine esetén. Én 512 Kb méretű blokkokat használtam, amiket sorszámmal azonosít a rendszer. Az egyes blokkok a fájl entitás alatt helyezkednek el (a blokk kulcsa a fájl entitás kulcsának leszármazottja). Amikor adatokat írunk vagy olvasunk a fájlból, a rendszer a fájlmutató alapján meghatározza a blokk sorszámát ahol az adat van, majd ebben módosítja a megfelelő adatot. Egyszerű kialakítás, mégis kényelmes és hatékony.

A kód szokásos módon a Google Code-on megtalálható a http://code.google.com/p/gae-filestore/ címen.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

PHP futtatása Googel App Engine-en

november 9th, 2010 Nincsenek hozzászólások

A GAE vagy Google App Engine a Google alkalmazás hoszting szolgáltatása. Nagy előnye, hogy segítségével alkalmazásunka a Google infrastruktúráján futtathatjuk. Nem kell olyan apróságokkal foglalkoznunk, mint a load balanceing, erőforrás allokáció, elosztott session kezelés, stb. hiszen a Google a terheléstől és a kérések helyétől függően optimálisan fogja “szétkenni” az alkalmazásunkat. Adatbázisként egy Google BigTable alapú nem relációs adatbázist kapunk, aminek klaszterezését ugyancsak a rendszer végzi automatikusan. E mellett kapunk még néhány “nyalánkságot”, mint amilyen az elosztott memcache, e-mail, vagy xmpp lehetőség. Amiért azonban igazán vonzó lehet induló startup-ok számára, az az, hogy a rendszer körülbelül havi 1 000 000 lapletöltésig és 500 Gb tárhelyigényig teljesen ingyenes. Ha pedig az embernek sikerült ekkora forgalmat generálnia, akkor már jó eséllyel ki tudja termelni a plusz sávszélesség és tárhely árát is, ami néhány cent gigabájtonként, tehát igen baráti. Persze ezért a nagy kényelemért némi kompromisszumot is kénytelenek vagyunk meghozni. Az egyik ilyen korlát, ami véleményem szerint nagyban gátolja a technológia elterjedését, hogy egyenlőre csak Java és Python nyelven programozható. Az egyik talán leggyakoribb kérés szokott lenni a felhasználók felől, hogy más hoszting szolgáltatókhoz hasonlóan támogassák a PHP nyelvet is. Így megnyílna az út sok népszerű web framework, és PHP fejlesztő előtt. Ezt a dolgot viszont valamiért a Google nem annyira erőlteti. Bár a PHP hivatalosan nem támogatott, mégis viszonylag egyszerű módon futtathatunk PHP scripteket AppEngine felett.

A megoldás kulcsa a Caucho Quercus nevű Java Servlet alapú PHP implementáció, amely az App Engine-en való futtatást is támogatja. A gyakorlati megoldás sem olyan bonyolult. Töltsük le a legújabb resin verziót, és a resin.jar-t másoljuk a WEB-INF/lib könyvtárba. A web.xml-t bővítsük ki a következő bejegyzéssel:

  <servlet>
    <servlet-name>Quercus Servlet</servlet-name>
    <servlet-class>com.caucho.quercus.servlet.GoogleQuercusServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>Quercus Servlet</servlet-name>
    <url-pattern>*.php</url-pattern>
  </servlet-mapping>

Így a .php állományokat a Quercus automatikusan a QuercusServlet-nek továbbítja. Magukat a PHP állományokat a root könyvtárba helyezzük. Ezt követően az appengine-web.xml-hez adjuk hozzá a következő sorokat:

<static-files>
<exclude path="/**.php"/>
</static-files>
<resource-files>
<include path="/**.php"/>
</resource-files>

E nélkül a rendszer a php állományokat statikus fájloknak tekintené, és nem adná át a szervlet motornak. Körülbelül ennyi. Innentől kezdve már PHP-t is futtathatunk a Google App Engine-en. Ezzel a technikával elvileg sikeresen futtattak már Drupal-t, WordPress-t, és néhány hasonló PHP keretrendszert. Persze azért a PHP alkalmazások szállítása nem olyan egyszerű, hiszen ezek többnyire MySQL-t használnak, AppEngine-en viszont ugye nincs relációs adatbázis. Tehát valamilyen szintű módosításra mindenképp szükség van, de ez talán megéri mindazokért az előnyökért cserébe, amit az AppEngine, és eleve maga a Quercus adhat (pl. egyszerű PHP-Java integráció, Java libek használata, stb.).

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

SimpleRSA

október 28th, 2010 Nincsenek hozzászólások

Nem tudom hányan próbáltak már Java-ban RSA-val titkosított dokumentumokat PHP-ból olvasni, vagy fordítva, esetleg Java-ban aláírt dokumentumok hitelességét PHP-ból ellenőrizni, de mindenesetre nekem most ilyenre volt szükségem. Naív módon azt hittem, hogy a nyílt kulcsú titkosítás valami egyszerű dolog (mármint programozás szintjén a megfelelő library-k használatával), fogok valami RSA library-t, egyik oldalon elkódolom valami függvénnyel, a másik oldalon kikódolom, és ennyi. Néhány napi Google használat után, elveszve a különböző kulcsformátumok, és certificate-ek között, rá kellett döbbennem, hogy ez az egész mégsem annyira triviális. A gond forrása, hogy a PHP (és amúgy más szkript nyelvek is) az OpenSSL-t használja a titkosításhoz, míg Java esetén ott a Crypto API, aminek viszont nem sok köze van az OpenSSL-hez. Gondoltam keresek valami Java OpenSSL wrappert, de ilyet sem találtam. A gond tulajdonképpeni forrása az volt, hogy a PHP-s titkosításhoz és aláíráshoz PEM fájlból kellett volna olvasni a kulcsokat, ilyen formában viszont sehogyan sem tudtam menteni a Java-ban generált kulcsokat. Az alkalmazás jellege miatt mindenképp Java-ból akartam generálni a kulcspárt, tehát az a megoldás nem jöhetett szóba, hogy openssl-el készítem el a kulcspárt, és majd azt használom PHP és Java esetén is.  Végül a megoldást a BouncyCastle Java library hozta el számomra, hiszen végül itt sikerült PEM fájl kezelő objektumokat találnom. Össze is raktam egy teszt kódot, és csodák csodájára a PHP kód képes volt olvasni a Java-ban generált kulcsokat, visszafejteni a Java-ban titkosított doksikat, és ellenőrizni az aláírások hitelességét.

Mivel nekem is sok segítséget nyújtottak mások leírásai, szinte kötelességemnek éreztem, hogy valamiképp megosszam frissen szerzett tudásomat. Ennek az egyik formája, hogy kódrészleteket közöl az ember (én is sok ilyenekből szedtem össze az RSA-val kapcsolatos tudásomat), én azonban azt tettem, amit eddig is, összeraktam egy kis library-t, amivel nagyon egyszerűen tudunk be/ki kódolni, illetve digitálisan aláírni adatokat. Egyre inkább az a meggyőződésem, hogy az ilyen kis minimál library-k sokkal hasznosabbak, mint a kóddarabok, vagy akárhány részletes leírás, hogy ezt meg azt hogy kell csinálni. Az elkészült library Java és PHP nyelven elérhető, és metódusok szintjén azonos, így elég egyetlen programkönyvtár használatát elsajátítani.

A kódot, ahogyan eddig is mindig, feltöltöttem a Google Code-ra, itt elérhető:
http://code.google.com/p/simplersalibrary/

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Nincs kategorizálva Tags:

jin-plugin

október 20th, 2010 Nincsenek hozzászólások

Egy projektem kapcsán próbáltam valamilyen általános megoldást keresni beépülő modulok (plugin-ek) kezelésére. Ugye a lényeg röviden annyi, hogy a kész alkalmazáshoz bárki könnyen írhasson kiegészíthetőket, amiket egyszerű módon lehet telepíteni. Rövid keresgélés után rá is találtam az OSGi-re, ami tulajdonképpen minderre a szabványos megoldás. Ezt használja például az Eclipse is. Át is néztem a doksit, de úgy találtam, hogy az én igényeimhez képest ez amolyan ágyúval verébre megoldás. Valami olyan egyszerű megoldást kerestem, amit a leendő plugin fejlesztők néhány perc alatt el tudnak sajátítani. Olyat, amilyet például a PHP CMS-ek is használnak (pl. WordPress, Joomla), ahol a plugin csak néhány függvényből áll. Találtam is egy annotation alapú jspf nevű keretrendszert, ami már nagyon megközelítette azt amire én gondoltam, de ekkor már úgy voltam vele, hogy csak és kizárólag a minimalista megoldás érdekel. Ahogyan a jin-template esetén, itt is arra gondoltam, hogy ha már készítek egy egyszerű megoldást, rögtön elkészítem a PHP implementációt is, amit később más programnyelvekre történő adaptáció követhet, így kvázi megteremtve a “minimális plugin architektúra szabványát”. Ezt valószínűleg már sokan sokféle módon megtették előttem is, de sehol nem láttam publikálva ilyen jellegű különálló programkönyvtárat. Ennek valószínűleg az az oka, hogy a fejlesztők értelmetlennek találták leválasztani a plugin rendszert a kész alkalmazásról (éppen annak egyszerűsége miatt). Erre tipikus példa a PHP CMS-ekben használt plugin rendszer, ahol bár a megoldások nagyon hasonlóak, mégis minden rendszernek saját megoldása van. Így fogant meg hát a jin-plugin rendszer gondolata.

A rendszer felépítése a célnak megfelelően nagyon egyszerű. A plugin manager végignézi a paraméterként megadott könyvtárat, ahol minden pluginhez külön könyvtár tartozik. Minden könyvtárban egy yaml fájl található, ami definiálja a plugin osztályt, valamint az esetleges függőségeket. A plugin manager a függőségeket betartva tölti be a plugineket, és hívja meg a plugin osztály init metódusát. Maga a plugin kód a plugin könyvtárában található. PHP esetén a kódok helye közvetlenül a könyvtár, Java esetén pedig a classes könyvtár. Ez utóbbi esetben lehetőségünk van a program számára szükséges programkönyvtárak csomagolására is, amik a lib könyvtárban kapnak helyet. A pluginnek lehetősége van névvel ellátott szolgáltatások installálására, amiket más pluginek felhasználhatnak. Tulajdonképpen ez minden. Ennyi az a feltétlenül szükséges minimális működés, amire szükségem volt. A plugin installálása egyszerűen a plugin könyvtárba történő könyvtármásolással történik, a pluginek készítésének elsajátítása pedig a rendszer egyszerűségének köszönhetően néhány perc. Ez utóbbi szerintem bíztatólag hat a fejlesztőkre, ami igen fontos, ha azt szeretnénk, hogy minél több kiterjesztés szülessen az alkalmazásunkhoz. Már csak abban kell reménykednem, hogy a megoldásom elterjed, és így talán másokat is sikerül egy kicsit hozzásegítenem sikeres kiterjeszthető alkalmazások fejlesztéséhez.

A rendszer rövid dokumentációja, és a teljes forráskód LGPL licenc alatt megtalálható a Google Code-on:
http://code.google.com/p/jin-plugin/

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags: