Sunday, May 25, 2008

Cep Telefonu ile RSS takip etmek isteyenler için : gozgezdir.appspot.com


İki ay kadar önce Google, Appengine'i duyurduğunda hemen bir developer hesabı almak için başvurmuştum fakat appengine'e ilginin çok fazla olması sebebiyle benim başvurumu diğer binlerce başvuru gibi beklemeye almışlardı. Neyse lafı fazla uzatmayayım geçen hafta Google'dan appengine hesabımın aktif hale getirildiğini söyleyen bir mail aldım. Artık ben de google'ın alt yapısını kullanarak fantastik web uygulamaları geliştirebilecektim (Hem de beleş, cebimden kuruş para harcamadan.)

Yazıya devam etmeden "Appengine de nedir yav?" diyenler için ufak bir açılama yapmak gerekiyor sanırım. Google Appengine, yazdığınız web uygulamalarını Google'ın kullandığı altyapıda çalıştırmanızı sağlayan bir sistemdir. Demek istediğim şu, siz uygulamanızı yazıyorsunuz ve Google sunucularına deploy ediyorsunuz. Google'ın veritabanlarını, Google'ın CPU'larını, Google'ın disklerini ve Google'ın bantgenişliğini kullanarak kullanıcılarınıza web uygulamanızdan servis veriyorsunuz.

Google Appengine'i tasarlayan google mühendisleri programlama dili olarak Python'u seçmişler. Yani Appengine'e deploy edilecek web uygulamasının Python ile yazılması gerekiyor. İleriki sürümlerinde Appengine'in Ruby'yi de destekleceğinden bahsediliyor. Günün birinde Java'yı da desteklerler mi bilmiyorum ama ben Python ile web uygulamalarının ne kadar kolay yazıldığını gördükten sonra java ile bu işe bir daha hayatta bulaşmam :)

Google Appengine üzerinden çalıştırmayı düşündüğünüz web uygulamasını kafanıza göre yazamıyorsunuz. Google yazdığınız uygulamanın Google mimarisi üzerinde ölçeklenebilir olması için bazı şartlar-kısıtlar koymuş. Uygulama geliştiricilerin bu şartlara uymasını bekliyorlar. Örneğin thread'leri kullanmak yasak, Filesystem işlemleri yapmak yasak,Socket açmak yasak. Bu yasakları koymuşlar ama uygulama geliştiricilere aşağıdaki imkanları veriyorlar:

  • 500 MB'a kadar ücretsiz alan.
  • Her ay 5 milyon sayfa görüntüleme. Günde 166 bin sayfa görüntüleme demek oluyor ki zaten böyle bir web uygulamanız varsa parasını verir Appengine premium hesabı alırsınız.
  • Uygulama geliştiriciler bir Google Appengine hesabı ile en fazla 3 uygulama çalıştırabilirler.
  • Socket açmak yasak demiştik fakat Appengine URL Fetch API'sini sunuyor. HTTP ve HTTPS destekliyor.
  • Filesystem işlemleri yapmak yasak demiştik fakat uygulamalar kendi upload ettikleri dosyaları okuyabilirler (konfigurasyon dosyalarını mesela)
  • Google Accounts : uygulamanızı halihazırda google'a üye olan herkes kullanabilir. Authentication Google User API ile yapılabilir.
  • Web uygulamaları Google Appengine Email servisini kullanarak mail atabilirler.
  • Appengine servislerinin bence en canalıcı olanı Datastore servisi. "Distributed data storage service" türkçeye nasıl çevireceğimi bilemedim. Datastore API'sini kullanarak milyonlarca kayıtlı tabloları Google sunucularında saklayabilirsiniz. (500MB'ı geçmemek şartıyla)
  • Python runtime environment kırpılarak kullandırılıyor. Socket açmak, thread başlatmak gibi servisler kapatılmış. Fakat diğer yasaklanmamış standart Python modülleri bir uygulama için yeterli oluyor. 3rd Party modulleri uygulamanız ile beraber upload ederek kullanabilirsiniz. Örneğin ben Gözgezdir'de RSS parser olarak UniversalFeedParser kullandım.
  • WSGI uyumlu web framework'leri ile çalışabiliyor. Kendi içinde Appengine WebApp Framework var. İsteyenler Django'yu da kullanabiliyorlar. Ben Appengine içinde gelen WebApp framework'ü kullanmayı tercih ettim.


Hem Google'ın bu yeni servisini denemek hem de uzun zamandır düşündüğüm bir projeyi yapmak için kolları sıvadım. Cep telefonundan RSS okumak için ufak bir uygulama hazırladım. Halen BETA sürümünde olan bu uygulamanın ana fikri GPRS ile WEB' erişen küçük ekranlı cihazlar ile hesaplı bir şekilde RSS kaynaklarını dolaşmak. Uygulamayı tamamlamadan adresini buradan vermem doğru olur mu bilmiyorum ama belki bir kaç kişi kullanırsa tasarım ve kullanılabilirlik için benim aklıma gelmeyen fikirler verebilirler.
Google yazdığınız appengine uygulamalarını uygulamaadi.appspot.com adresinden yayınlıyor. Fakat kendi alan adınızı alıp Google üzerinden yönlendirmesini yapmanız da mümkün. Ben yine pintilik yapıp alan adına para vermedim ve http://gozgezdir.appspot.com adresinden uygulamayı yayına aldım.
İlgilenen arkadaşlar ile kaynak kodunu paylaşabilirim. Benim gibi yıllarca Java ile yazılım geliştirmiş Java'dan başka birşeyi gözü görmeyen yazılımcı arkadaşların python ile tanışıp böyle bir dil de varmış vay be demelerini isterim açıkçası :)

Thursday, April 17, 2008

Nişanlandım - I am engaged!

Selam dostlar, 29 Mart 2008 tarihinde Nurten ile nişanlandık. Nişan resimlerini yeni yeni toparlayabildim. 19 gündür parmağımda yüzük ile dolaşıyorum ama hala alışamadım. Neyse zamanla bir yolunu bulup yüzüğü kenara kaldırırım nasıl olsa :D

Resimde pişmiş kelle gibi sırıttığıma bakmayın, aslında çok stresli bir gündü benim için. Resimdeki o gülümsemenin sebebi tuzlu kahveyi içtikten sonra kızı almanın vermiş olduğu bir rahatlık olsa gerek.

Bu arada resimdekileri tanıtayım, soldan sağa babam, Nurten, ben, annem ve kardeşim. Kardeşim de abimin başını bağladık sıra bana geldi diyerekten 32 dişini bizden esirgememiş, gözümden kaçmadı he he :) .

Son olarak lafı fazla uzatmıyor ve darısı bekar arkadaşların başına diyorum.

Thursday, April 3, 2008

Command line English-Turkish dictionary

I've been reading Python tutorials since I accidentally see the Zen of Python. I think I read enough. Now its time to get hands dirty. The best way to learn a language is to write code in that language. I have implemented a command line dictionary that fetches the Turkish definition of a given English word from the site Sesli Sözlük. The python script below uses BeautifulSoup HTML/XML parser for screen-scraping.
This is sozluk.py. It reads program arguments and constructs a URL. After fetching URL content BeatifulSoup library is used to get desired parts of the HTML page. Finally results are printed to the stdout.

from BeautifulSoup import BeautifulSoup
import urllib2
import sys
import string


def getDefinitions(keyword):

url = 'http://www.seslisozluk.com/?word='+keyword
c=urllib2.urlopen(url)
soup=BeautifulSoup(c.read())
results = soup.findAll(attrs={"class" : "dict_result"})[0].contents[1].contents
definitions = [results[x] for x in range(len(results)) if ((x+2)%3)==0]
return [definition.replace(' ', '') for definition in definitions]


if __name__ == '__main__':
if len(sys.argv)<=1:
print 'missing keyword.'
else:
keyword =' '.join(sys.argv[1:])
try:
definitions = getDefinitions(keyword)
for i in definitions:
print i
except:
print "Failed to get definition of ",keyword

This is sozluk.sh. It is used to call Python Interpreter and execute sozluk.py.

#!/bin/bash
#sozluk.py is in this folder.
cd /home/ilkinulas/PITON/workspace
python sozluk.py $1

An example usage: Getting Turkish definition of word 'python'

ilkinulas@tututil:~/PITON$ sozluk.sh python
Bir proglama dili.
i., zool. piton. piton yilani. yılan. yılan. i., zool. piton. apollon'un öldürdüğü dev yılan. piton.
Delfi civarında Apollon tarafından öldürülmüş olan çok büyük bir yılan; piton, k, Python, piton, h, zool.
: Gaia'nın doğurduğu efsanevi yılan. Yüz tane başı, alev kusan yüz tane ağazı vardı. Apollon tarafından öldürüldü.
piton yılanı.
piton yılanı.
yılan.

Sunday, March 30, 2008

Ubuntu 8.04 HardyHeron Coming Soon

Ubuntu 7.10 (Gutsy Gibbon) was announced October 2007 and will be supported till 2009. After four alpha releases, Ubuntu 8.04 Beta is released and available for download. The stable release of Ubuntu 8.04 (HardyHeron) is scheduled for April 2008. I am waiting for the stable relase to upgrage my ubuntu desktop edition.
The new Ubuntu will come with

  • Gnome 2.22
  • Firefox 3.0
  • Linux kernel 2.6.24
  • Xorg 7.3 - "New Screen Resolution utility that allows users to dynamically configure the resolution, refresh rate, and rotation of a second monitor. This will be particularly handy for laptop users that connect to a projector or external monitor." - This is my favorite
  • and more

Wednesday, March 12, 2008

Monetary Calculations In Java


float and double types are not suitable for monetary calculations in Java. If this is the first time you hear this you are in trouble.

Floating point arithmetic which is used to represent float/double variables is inappropriate for exact results calculations. For example it is impossible to represent 0.1 (or any other negative power of ten) as a float or double exactly. Here is an example:
float s1 = 0;
for (int i = 0; i < 10; i++) {
s1 += 0.10;
System.out.println(s1);
}
This code prints:
0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001
1.0000001
Here's another example: (0.1+0.1+0.1) == 0.3 What is the value of this statement true or false? since the sum (0.1+0.1+0.1) is not equal to 0.3 according to JVM, rounding up the sum would result in 4 which is not expected either. I think you got the point. We can not trust float or double variables if we want exact results. Applications that makes money/credit calculations needs exact results. To represent monetary values in Java you should use the BigDecimal class.
BigDecimal bd = new BigDecimal("0");
for (int i = 0; i < 10; i++) {
bd = bd.add(new BigDecimal("0.10"));
System.out.println(bd);
}
This java example prints (as expected):
0.10
0.20
0.30
0.40
0.50
0.60
0.70
0.80
0.90
1.00

Friday, February 29, 2008

QRCodes in action!

Typing a web address with the number based keypads of cellphones is an annoying process for the majority of wireless subscribers that don't have phones with QWERTY keypads. If you don't agree try typing the address below with your cellphone:

http://www.abc.net.au/cgi-bin/common/transform.pl?telstrawallaceml2html&wap&telstra~World&imode/2175963
By using QRCodes wireless subscribers just SCAN & GO. Here is a small list of QRCodes usage:

  1. ORCodes & Facebook

  2. "Add to friends" link of facebook is encoded into a QRCode image and printed on a t-shirt. Seeing people around you, trying to scan your t-shirt with their cellphone will be freaky.



  3. QRKill - shooting game

  4. QRKill is a QRCode powered game. Players stick in their back a QRCode with his/her telephone and name encoded. They will have to kill each other capturing the code and sending an SMS. Players will be eliminated right after receiving a deathly SMS.


  5. Product Information

  6. McDonald's in Japan is printing the QRCodes on all its food packaging so customers know exactly what they are eating. By scanning the code with their cameraphone McDo lovers access all the information about the McFood including any potential allergy warnings.

    QRCodes are very popular in Japan. I haven't seen any printed QRCode in Turkey but according to me they'll catch attraction of Mobile advertisers soon. Here's another image that shows a product with information printed on it via QRCodes.



Thursday, February 28, 2008

memcached - Dağıtımlı (distributed) önbellek sistemi


TBD BİLİŞİM TERİMLERİ KARŞILIKLAR SÖZLÜĞÜ'nde "distributed" kelimesinin karşılığı olarak "dağıtımlı" yazıyor. Önceleri "distributed" kelimesi için "dağıtık", "dağıtılmış" kelimelerini kullanırdım. Madem Türkiye Bilişim Derneği "dağıtımlı" diyor bundan sonra benim de bu kelimeyi kullanmak boynumun borcudur. Bu yazıyı, okuduğum bir çok ingilizce yazının bir özeti olarak yazıyorum. (Kendi fikirlerimi eklemeyi unutmadım tabi ki :)) Yazıda ingilizce terimlerin türkçe karşılıklarını kullanmaya özen gösterdim fakat yine de tam türkçe karşılığını bulamadığım terimler var.

1. Nedir bu memcached denen şey?


Memcached, Danga Interactive http://www.danga.com/ tarafından geliştirilmeye başlanmış bir "distributed object caching" sistemidir. Yüksek trafik alan dinamik web uygulamalarının veritabanına gitme sayısını azaltmayı, bu sayede de performansı artırmayı hedefleyen bir uygulamadır.
Memcached'yi network üzerinden erişilebilen kocaman bir Hashtable olarak düşünebiliriz. Network üzerindeki herhangi bir makinadan "key" ile memcached'de sakladığımız bir nesneye, network üzerindeki başka bir makinadan aynı key ile ulaşabiliriz. Detaylar için okumaya devam...

2. Lisansı nasıl?


BSD License ile lisanslanmış. http://en.wikipedia.org/wiki/BSD_license

3. Hangi işletim sistemlerinde çalışıyor?


Linux, BSD, Windows üzerinde sorunsuz çalışıyor. Web sitesinde Solaris ile ilgili bir bilgi yok. Mail listelerine bakılınca solaris üzerinde çalıştırmak için taklalar atmak gerektiğini anlıyoruz. Memcached fazla CPU kullanmıyor ve tek ihtiyacı boş RAM. Bu yüzden memcached instance'larını çalıştıracağımız makinanın Sun sparc işlemcili bir makina olmasına gerek yok. Hızlı bir network kartı ve yeterli RAM'i olan linux PC'ler memcached çalıştırmak için yeterli olacaktır. (Ben testlerimi Ubuntu 7.10 kurulu Dell Laptop üzerinde yaptım :) )

4. Nasıl kurulur?


http://www.danga.com/memcached/download.bml adresinden indireceğiniz kaynak kodunu INSTALL ve README dosyalarını okuyarak derleyip kurabilirsiniz.
http://blog.ajohnstone.com/archives/installing-memcached/ adresinde kurulum ile ilgili bir tutorial var.

5. Nasıl çalıştırılır?


Memcached bir konfigürasyon dosyasına ihtiyaç duymaz. Gerekli bütün ayarlar komut satırından memcached daemon'u çalıştırırken verilebilir.

# ./memcached -d -m 2048 -l 192.168.43.47 -p 11211


Bu komut memcached'ye der ki:
  • (-d) daemon olarak çalışacaksın
  • (-m 2048) 2GB'dan fazla RAM kullanamazsın.
  • (-l) 192.168.43.47 makinasında çalışıyorsun
  • (-p) 11211 portunu dinleyeceksin.

Aynı makina üzerinde RAM yettiği sürece birden fazla memcached daemon çalıştırabiliriz (Farklı portlarda çalıştırmaya dikkat etmek lazım). Örneğin, herbiri 512MB kapasiteli 5 adet memcached daemon'u aynı makina üzerinde asaşıdaki şekilde başlatabiliriz. Toplamda 2.5GB'lık bir cache'imiz oluyor. (Dikkat böyle bir kullanım size mantıklı gelmeyebilir, sadece daemon'u nasıl başlattığımız göstermek için bir örnek.)

# ./memcached -d -m 512 -l 192.168.43.47 -p 11211
# ./memcached -d -m 512 -l 192.168.43.47 -p 11212
# ./memcached -d -m 512 -l 192.168.43.47 -p 11213
# ./memcached -d -m 512 -l 192.168.43.47 -p 11214
# ./memcached -d -m 512 -l 192.168.43.47 -p 11215



6. Memcached'ye uygulamalarımız nasıl erişecek?


Memcached'nin network üzerinden erişilebilen büyük bir Hashtable olduğundan bahsetmiştik. Uygulamaların memcached'ye erişebilmeleri için çeşitli dillerde yazılmış istemci kütüphaneleri var. Java dışında Perl, Php, Python, Ruby, C# ve C için yazılımış istemciler mevcut. Bu adresten http://www.whalin.com/memcached/ java memcached client indirilebilir.
Yazılımcılar gerek görürlerse memcached ile haberleşmeyi sağlayacak kendi istemci kütüphanelerini yazabilirler. Memcached ile client'lar arasındaki protokolün detaylarına http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt adresinden erişilebilir.

7. Tipik bir kullanım örneği


Örnek java kodu:

public VpnAccount getVpnAccount(String msisdn) {
VpnAccount account = memcachedClient.get(msisdn);
if (account == null) {
account = getAccountFromDatabase(msisdn);
memcachedClient.set(msisdn, account);
}
return accout;
}



6. Nasıl çalışıyor? Nasıl "distribution" sağlıyor?


Evet zurnanın "zıırrrt" dediği yere geldik. Memcached network üzerinden erişebileceğimiz boş RAM'i olan herhangi bir makinada çalıştırılabilir.

Örnek 1: Bir veya birden fazla uygulamanın tek bir memcached instance kullandığı senaryo:


Bu senaryonun üzerinde fazla durmaya gerek yok. Uygulamalara memcached'nin çalıştığı makinanin IP'si ve memcached'nin dinlediği port bilgisi verilir. Bütün uygulamalar aynı cache instance'ını kullanır. A uygulamasının K anahtar kelimesi ile cache'e gönderdiği V değerini, B uygulaması K anahtar kelimesini kullanarak alabilir.
Bu mimarinin artıları:
  • Basit bir mimaridir. (Fakat tavsiye edilen mimari değil)
  • Merkezi bir cache olduğu için uygulamalar (java uygulamalarından bahsediyorum) kendi cache'lerini tutmak zorunda değil. Uygulamaların Cache'leri arasında tutarlılık kontrolleri yapmaya gerek yok.

Eksileri:
  • Tek bir cache instance = SPOF (Single point of failure)

Örnek 2:


Birden fazla memcached daemon'ın kullanıldığı senaryo.


192.168.43.47:11211, 192.168.43.48:11211 ve 192.168.43.49:11211 da çalışan 3 adet memcached daemon olsun. Bizim de bu cache'leri kullanan A,B ve C uygulamalarımız olsun. (IN uygulamalarından örnek verecek olursak GW1, GW2 ve GW3).
memcached'nin çalışması iki adımdan oluşan hashing mekanizmasına bağlıdır.
  • 1. adımda client, memcached daemon listesini kullanarak "K" anahtarının hash'ini hesaplar. "K" ile saklanan "V" değerine ulaşmak için (ya da "K" ile "V" değerini saklamak için) hangi memcached server'a gideceğini bulur.

  • 2. adımda memcached serverda (çok büyük bir hashtable olarak düşünebiliriz demiştik) "K" anahtarının hash'i farklı bir algoritma ile hesaplanır. "Hashtable lookup" ile "V" değerine erişilir.

Telekom uygulamasından bir örnek:
MSISDN'leri anahtar olarak kullanıp VpnAccount nesnelerini memcached içinde saklayalım. MSISDN "905435022434", cache server listesine göre hash'lendiğinde "905435022434"e karşılık gelecek VpnAccount'un hangi memcached daemon'da saklanacağı bulunur. (Örneğin 192.168.43.48:11211).
Uygulamaların hepsi anahtar kelimenin (yani MSISDN'in) hash'ini hesaplarken aynı hash algoritmasını kullanacağı için "905435022434" numaralı VpnAccount'a ulaşmak için bütün uygulamalar aynı memcached daemon'a gidecektir.
Bu mimarinin artıları:
  • çok iyi ölçeklenebilir (highly scalable). Ne kadar çok RAM o kadar çok cache.
  • aklıma şimdilik başka birşey gelmiyor :D

Eksileri:
  • (Eksi alanına birşeyler yazmış olmak için yazıyorum) birden fazla memcached instance'ı yönetmek zor olabilir.


9. Authentication mekanizması nasıl işliyor?


Memcached authentication kullanmıyor. Network üzerinden erişimi olan bütün client'lar "set" ve "get" yapabilirler. Üzerinde memcached çalışan host'ların firewall ayarlarının dikkatli yapılması gerekir.

10. Failover senaryoları nasıl? Memcached failover destekliyor mu?


memcached failover desteklemez. memcached'yi "set(key, value)" ve "get(key)" işlemlerini destekleyen bir Hashtable olarak olarak tanımlamıştık. Memcached instance'larının birbirlerinden haberleri yoktur. Network üzerinden kaç tane memcached'nin çalıştığı bilgisi sadece client'larda vardır. Memcached server grubundan bir server'ın çıkartılması ya da yeni bir server eklenmesi durumu ile başa çıkmak client'lara kalmıştır.
A, B, C hostlarında çalışan 3 tane memcached server oldugunu varsayalım.

hash("905435022434")%(["A","B","C"].length) --> A
hash("905435022435")%(["A","B","C"].length) --> B
hash("905435022436")%(["A","B","C"].length) --> C olsun.


("905435022434" anahtarı ile bir nesneyi aramak için A'ya, "905435022435" anahtarı ile bir nesneyi aramak için B'ye gidilecek.)
Bu üç hosttan bir tanesi örneğin B erişilemez duruma gelirse, kullanılabilen 2 tane memcached server kalır. Bu durumda

hash("905435022434")%(["A","C"].length) --> C
hash("905435022435")%(["A","C"].length) --> A
hash("905435022436")%(["A","C"].length) --> A olabilir.


Yani 3 memcached server ile çalışırken "905435022434" anahtarı ile A hostuna yönlenilirken 2 memcached server ile çalışırken "905435022434" anahtarı ile C hostuna yönlenebiliriz. Bu da "905435022434" anahatarı ile cache içinde tutulan nesnenin artık geçersiz olduğu (DB'den yeniden çekilmesi gerektiği) anlamına gelir. Aynı tip senaryo memcached server grubuna yeni bir memcached server eklendiğinde de geçerlidir.
Yukarıda bahsedilen problemi çözmek için "consistent hashing" algoritmaları geliştirilmiş. memcached client'ların verilen bir anahtar için hangi memcached server'a gideceklerini hesaplayan bu algoritmalar sayesinde memcached server grubundan bir server çıktığı zaman ya da yeni bir server eklendiği zaman "K" anahtarına karşılık gelen memcached server'ın değişmemesi sağlanmıştır.
http://www.whalin.com/memcached/ adresindeki memcached client içerisinde "consistent hashing" algoritmasının implementasyonu mevcut.

11. JVM, cache için extra hafızaya ihtiyaç duyacak mı?


Memcached kullanıldığında nesneler JVM heap'te değil başka bir process'in (bu process JVM ile aynı host'ta ya da farklı bir host'ta olabilir) kullandığı hafıza alanında saklanır. Bugün cache kullanan uygulamalarımız için JVM'i başlatırken (yaklaşık olarak) 2GB heap kullan diyoruz (-Xms2048m -Xmx2048m). Memcached kullandığımız durumda JVM bu kadar geniş bir heap'e ihtiyaç duymayacaktır - çoğu uygulamalar için 256 MB'lık bir heap yeterli olur diye düşünüyorum. Bu sayede Garbage collection sureleri kısalacaktır. (Telekom uygulamalarında Garbage Collection suresinin ne kadar önemli olduğundan söz etmeye gerek yok.)

12. Cache dolduğu zaman ne olur?


Memcached'nin cache'i dolduğu zaman, cache'e yeni bir nesne eklemek istersek LRU (least recently used) yöntemiyle eski nesneler cache'den silinir.

13. memcached'nin arkasında kim var?


memcached kaynak kodu açık bir uygulama. Arkasında bizim gibi 100'lerce yazılımcı var. Daha da önemlisi bir çok yerde kullanıyor ve kendini kanıtlamış. http://developers.facebook.com/opensource.php adresinde, facebook yazılımcılarının memcached kaynak koduna yaptıkları katkılarla, memcached performansını 20% iyileştirdiklerinden bahsediliyor.
Aşağıdaki listede memcached kullandıklarını söyleyen bir kaç tane web sitesi var. Bu sitelerin ortak özellikleri çok hit almaları ve her sayfada dinamik bilgiler göstermeleri.


14. Daha detaylı bilgiye nereden ulaşabilirim?


Bu adreste (http://www.socialtext.net/memcached/index.cgi?faq) memcached ile ilgili bir FAQ var.