Bir kaç gece önce, Amin Maalouf ile yapılan bir röportajı izliyordum.

Maalouf’un döne döne “batının doğuyu, kuzeyin güneyi anlamak istememesi” konusunu vurgulaması dikkatimi çekti ve bir süre sonra düşüncelerimin bu konu üstünde odaklandığını fark ettim. Elbette bu konu tüm yaşamımda aklıma ilk kez gelmiş değildi, ancak Maalouf’un, kendinin de dahil sayılabileceği bir zümreye bizde alışılmış kavramla “öteki” adını koymak istememesiydi asıl ilgilendiğim başlangıçta.
Böyle başlayan düşüncelerim bir süre havada uçuştuktan sonra bir forma girdi: Amin, “aslında benim dahil olmadığım, ancak dahil olanlara çok yakın olduğum” türünden bir ifade içindeydi. Öyleydi zira bir şekilde içinde yaşadığı toplum onu kabul etmişti; o toplum için “artık Fransız” bir Maalouf vardı. Fransızlar, işlerine geleni kendinden sayıp gelmeyeni inkar hususunda üstattırlar: Fransızca söyleyen şarkıcı ve bestecilere bakalım: Georges Moustaki, Joe Dassin, Enrico Macias.
Bunların hangisi Fransız? Fransızlara göre yanıt “hepsi”dir. Zira, bizden tolere edilebilir marjlarda farklı olan kişiyi “bizden” kabul etmek zor değildir.
Öte taraftan politikacı açık söyleyemez, sıradan vatandaş doğru söyleyemez. Politikacı, işten sıyırmak için türlü laf çevirirken, sokaktaki adam “yabancıları istemiyorum” der ve sıyrılır. Doğrusu şudur: İçinde bulunulan toplumun gelişmesine sekte vuracak ve geriye götürecek dinamikler genel sağduyu tarafından dışlanır. Fransızlar (ve onlardan gelen ilhamla, zamanla neredeyse tüm avrupa) dini kamu yaşamından çıkarabilmek zorunluluğunu yüzyıllar önce görmüşler ve bunun için sıklıkla ağır bedeller de ödemişlerdir. Kendi kilisesinin toplum üstündeki etkisini bedel ödeyerek silmiş bir toplumdan ve o toplum bireylerinden, müslüman türbanını kabul etmeyi beklemek aptallıktır. Toplum, örneğin Enrico Macias’tan kültürel bir zenginlik olarak yararlanmayı bilirken, Macias’ın ülkesinden gelen görece eğitimsiz kalabalığın, kültürlerini etkilemesine de tepki gösterir. Bu durum çok insanidir ve çok normaldir. Bana göre İslam, ilkçağların üretim-tüketim yöntemleri ve bunların idaresi hakkında bir sistemden ibaret olabilir. Benim kız çocuğum başını şu ya da bu nedenle örterse, bana göre bu durum onun seçimi/geri zekalılığı ya da ikisi birden olabilir, ancak onun ve yalnız onun seçimi olacağından saygı duyulmalıdır ve böyle olacaktır zira benden, gelişim çağında zihinsel gelişimini baltalayacak hiç bir safsata duymayacaktır. Bu durumun, günde beş vakit namaz kılıp, etrafında erişkin rol-model olarak türbanlılardan başka kimseyi görmemiş bir kız çocuğu için de böyle olacağını, bu tür çocukları yetiştiren kesim de kabul eder ve çocuk yetiştirme yöntemlerinde benimle aynı açıklığı uygularlarsa, ne benim, ne de ehl-i akl-ı selim herhangi bir kişinin tepkisine uğramazlar; ne ben onlar için, ne de onlar benim için “öteki” olurlar.
Öte taraftan, düşünce yapısının şekillenmeye başladığı yaşlarda “ne yerde ne gökte olan” bir mitolojik kahramanın hikayeleriyle büyümüş bir çocuk, ortalama üstü akıllı değilse bu döngüyü kıramayacak ve kendi çocuklarını da aynı mitolojiyle büyütecektir.
“Ana dilimi konuşmak istiyorum.” diyen kişiyi anlamak zor değildir ancak “kendi mitolojimi topluma dayatmak istiyorum.” diyen adamı, en azından ben anlayamam ve bu durumda birbirimiz için “öteki” haline geliriz. Oysa burada kişisel sorunlar yoktur, eğitim sorunları vardır, üstyapı sorunları vardır.
Bu günlerde anayasa plebisiti hususunda “Demokrasi için evet” diye kıçını yırtanların anayasanın inanç hürriyetini düzenleyen 24. maddesi hakkında ses çıkarmamaları anlamlıdır. Anlamlıdır zira “din kültürü ve ahlak bilgisi dersinin ilk ve orta öğretim kurumlarında zorunlu ders…” olduğuna dair ifade de oradadır.
Darwin’i maymun olarak gösteren karikatür suç değildir ancak müslümanlığın kurucusu ile ilgili benzer bir karikatür çizmeye kalkın, hem hukuki olarak hem de uygulamada ne olacağını benden daha iyi tahmin edebilirsiniz.

Türkiye seküler bir ülke değildir; dünyadaki iki laik ülkeden biridir (diğeri Fransa). Sekülarite ile laiklik arasındaki ayrım boşuna yapılmamıştır. Basitçe anlatmak gerekirse, seküler rejimde devlet, her türlü inanca eşit mesafede durur ve dini sembol ile kavramlarla, cemaatler ile inançların düzenlenmesiyle ilgilenmezken, laik devlet tüm dinleri resmen tanır, ancak kontrol altında tutabilmek için tanır; din ile parayı buluşturmak isteyebilecek yapıları önleyebilmek için tanır.
Bugün tehdit altında olan bizatihi cumhuriyetin yapısıdır. Bunun için izlenilmeye çalışılan yöntem de paşa paşa beraber yaşayan kişileri birbirine “öteki” kılmaktır. Oysa aslında aramızdaki tek fark, biz kentin bir semtinde rakımızı terasımızda içerken, diğer semtlerde aynı rakının masa altında içilmesinden ibarettir. Benim “mitoloji meraklısı” dediğim adam aşık olmaz mı? Düşmüş gördüğünde yardım etmez mi? Ya benim gibi düşünen adam aşkı bilmez mi? Yardım nedir, bilmez mi? Şüphesiz hepimiz biliriz, çünkü insanız.
Politikacılar ellerini yakamızdan çekerlerse, oturur çok konuşuruz, çok dertleşiriz.
Fransa’da da böyledir, Türkiye’de de böyledir.

Paylaş:
  • Print
  • FriendFeed
  • Twitter
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • DZone
  • LinkedIn
  • MySpace
  • Ping.fm
  • Reddit
  • StumbleUpon
  • Technorati

Etiketler:

Yıl 2001 ya da 2002 olacak. Tina ile, Efes’te gerçekleşecek Azize Mustafazeh konserine bilet almışız. Bir nedenden Tina’nın arabası o gün yok. Konak’tan kalkan, belediyeden kiralık bir otobüse pestil olmuşuz ki elimde iki şişe “98″ => (Bir şişe kola alınır, yarıya kadar içilir, üstüne votka eklenir; kola içer gibi votka içilir. Ramazan ayında Konya’da dahi başarıyla kullanılmış metottur).
Otobüsün kasislere girip-çıkmasının votkanın tesirine müsbet etkisinin de dahliyle kafa daha Efes’e varmadan bir milyon.
Azize’den önce İzmir Senfoni (İzSo) sahne alır. Akılları sıra Ravel’in Bolero’sunu çalacaklardır ancak İzmir’den hard-case’ler içinde getirdikleri enstrümanları güneşin batmasıyla beraber çöken Efes rutubetine aşina olamamışlardır henüz: İki dakikada bir tüm akortlar dağılır. O enstrümanların o iklimde, oraya en az sabahtan getirilmiş ve açık havaya çıkarılmış olması gerekir. Bunu ben bile bilirim de nedendir, İzSo bilemez, ya da bilmek istemez.
Neticeten, Bolero “Bokero”ya döner ve zaten sarhoş bünyeyi hallice sinirlendirir.
Velhasıl, İzSo pıl-pırt toplayıp gittikten sonra Azize peydah olur sahnede. Peydah olur da, seyirciyle ingilizce konuşmaya çalışır ve baştan tüm kitlenin antipatisini kazanmaya muvaffak olur. O da bir süre söyler ancak alkışlar cılızdır; cılız olmakta haklıdır: Elin en skimsonik rock grubu bile konsere “Merhaba İztanbul!” diye başlarken, Azeri kişi anadilinde seslense herhalde yeterlidir lakin seslenmez ve seyirciler olarak konser sonuna dek sebat ederiz.
Vakıa konser nihayete erer. Bizim Efes’ten Ürkmez’e geçmemiz lazımdır (20-30 km yol) ve Ürkmez istikametine doğru otostop çekmeye başlarız. Konserden çıkan arabalar vızır vızır önümüzden geçmektedir ve en sonunda biri durur ve dahi biz de işbu arabanın arka koltuğuna kendimizi atarız.
Arabanın ön koltuğunda iki beyefendi oturmaktadır. Tina daha sonra şöyle anlatır: “Ben asılı frakları gördüm, ayrıca adamları da bir yerden tanıyordum…”
“Nereden? Nereye?” kısa sohbetinden sonra konu İzSo’ya gelir ve öndeki adamlar sorarlar:
“Azize’den önceki senfoni konseri nasıldı?”
(Bu saatten sonra tüm hamlelerin değeri aynıdır çünkü oyun kaybedilmiştir!)
“Afedersiniz, bok gibiydi. Sen onca yıl konservatuarda oku, sonra gel, ‘konser vereceğim’ de, ama daha bir enstrümanın akordunu bile yapama! Ben olsam utanır, bir vesileyle keserdim konseri. Hadi seyirciyi keriz yerine koyuyorlar; kendilerine de mi saygıları yok bu heriflerin?” …diye saydırırken ben, Tina’nın alttan attığı tekmeler artık bacaklarımı morartmaya başlamıştır ama susmam:
“Kardeşim, madem bir iş için para alıyorsun, o işin hakkını vereceksin! Hele o birinci keman yok muydu, hayatımda elime keman almadım ama alsam daha sağlam çalardım!” … (Artık ağzım kapanmaya çalışılmaktadır Tina tarafından) .. derken öncekilerden biri Tina’ya döner ve:
“Bıraksana adamı, adam ne söylese haklı! Hayatımda böyle rezil bir temsil daha görmedim. ‘Sabahtan gelelim’ dedik, getirmediler ‘a…k…!’”

Paylaş:
  • Print
  • FriendFeed
  • Twitter
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • DZone
  • LinkedIn
  • MySpace
  • Ping.fm
  • Reddit
  • StumbleUpon
  • Technorati

Etiketler: , ,

Tor Projesi

Son birkaç yıldır ülkemizde hemen herkes domain bazlı engellemenin üstesinden gelmeyi öğrendi. Daha yakından ilgililer IP bazlı engellemenin nasıl geçilebileceğini de biliyorlar; anlatacaklarım ilk kez duyanlara:

Tor Projesi Nedir?
Web sitesinden alıntı:
“Tor kendinizi trafik analizine karşı koruyabilmenize yardımcı olan bir yazılım projesidir. Trafik analizi kişisel özgürlüğü ve gizliliği, gizli ticari eylemleri ve ilişkileri ve devlet güvenliğini tehdit eden bir çeşit ağ denetimidir. Tor iletişiminizi dünyanın her tarafından gönüllüler tarafından işletilen dağıtılmış bir ağ üzerinden sağlayarak sizi korur: birilerinin sizin Internet bağlantınızı izleyerek hangi siteleri gezdiğinizi öğrenmesini engeller, ayrıca girdiğiniz sitelerin sizin fiziksel yerinizi öğrenmesini de engeller. Tor, Internet tarayıcıları, anında mesajlaşma istemcileri, uzaktan erişim ve TCP protokolünü kullanan diğer uygulamalar dahil mevcut uygulamalarınızın bir çoğu ile çalışır. ”

Kendileri daha uygun biçimde söylemişlerdir ancak “trafik analizi”, “sizin internette yağtığınız şeylerle” o ya da bu saikle ilgilenmektir.

İnternette özgür olmak, engellenmemek, hepsinden daha basiti, çok beğendiğiniz bir sanatçının bir klibini izlemek istediğinizde can sıkıcı engellerle karşılaşmak istemiyorsanız Tor Projesi sizin içindir.

Aşaşığa Tor kullanarak Ubuntu üstünde Youtube’dan bir Enrico Macias-Ajda Pekkan klibini (herhangi biri ya da bir kurum, sizi teoride Youtube IP adresine ulaştırmak istemese dahi) nasıl izleyebileceğimizi görecdeğiz:

İlk olarak root haklarıyla gedit’i açıyoruz:

1
sudo gedit

ve akabinde Tor reposunu en alta ekliyoruz:
[code]/etc/apt/sources.list[/code]
Daha sonra sırasıyla gereken gpg anahtarını ekliyor ve apt veritabanını güncelliyoruz (herhangi bir komutta terslik yaparsa:

1
sudo !!

yazın, root şifresini girdikten sonra önceki komutu root haklarıyla çalıştıracaktır.
[code]
gpg --keyserver keys.gnupg.net --recv 886DDD89
[/code]
[code]
gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | sudo apt-key add -
[/code]
[code]
apt-get update
apt-get install tor tor-geoipdb polipo
[/code]

Artık Tor sisteminizde hazır. Bir ufak ayar kaldı:

Şu adresten Polipo ayar dosyasını alıyoruz ve yine biraz önce yaptığımız gibi root haklarıyla çalışan gedit’e
[code]/etc/polipo/config[/code] adıyla kaydedip Polipo’yu yeniden başlatıyoruz:
[code]
sudo /etc/init.d/polipo restart
[/code]

Tor artık hazır.

Son olarak Firefox’ta bizim için Tor’U istediğimiz zaman devreye alıp, istemediğimiz zaman devre dışı bırakacak olan “Tor Button” eklentisini kuruyoruz ve Firefox’u yeniden başlatıyoruz. Bu işlemden sonra sağ alt tarafta “Tor Devredışı” yazısını göreceksiniz. Bu yazının üstünü tıklatığınızda ise bu yazı “Tor etkin” şeklinde değişecek.

Ben Enrico Macias’ı seviyorum, siz istediğinizi dinleyebilirsiniz: Adres kutusuna http://youtube.com yazın ve hepsi bu kadar!

Paylaş:
  • Print
  • FriendFeed
  • Twitter
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • DZone
  • LinkedIn
  • MySpace
  • Ping.fm
  • Reddit
  • StumbleUpon
  • Technorati

Son günlerdeki Youtube’a erişimin IP tabanlı olarak engellenmesine dair endişe verici gelişmeler beni, uzun süredir yazmak istediğim bir yazıyı iş-güç arasına sıkıştırmaya itti.
Bu yazı iki bölümden oluşuyor:
1- Günümüz Türkiye’sinde internet özelinde vatandaş-devlet dengesi ne durumdadır?
2- Vatandaş yasal olarak özgürlüğünü nasıl savunur?
Yalnız “ben Youtube’da klip izlemek istiyorum hoca; ben keyfime göre takılabildikten sonra çakmışım gerisine!” diyenler yazının birinci bölümünü atlayıp doğrudan ikinci bölüme geçebilirler. Birinci bölüm düşünsel, ikinci bölüm tekniktir ve Tor Project ile kişinin, kendi girmek istediği siteleri yine kendinin nasıl belirleyebileceğini anlatır.
Geri kalanlar için ilk bölüm:
Günümüz Türkiye’sinde internet özelinde vatandaş-devlet dengesi ne durumdadır?

Konuyla ilgili herkes biliyor ancak anımsatmakta yarar var: 5651 sayılı bir yasa var ve internet ülkemizde bu yasa uyarınca “düzenleniyor”. Bazı internet sitelerinin yasaklanması uygulaması, bu yasa hükümleri uyarınca vücut buluyor.

“İnternet özgür ortam”. Bu ifade artık klişe. Burada “özgürlük nedir?” sorusunu kabaca “başkasının özgürlükleriyle sınırlı şey” şeklinde genelgeçer yanıtlamak isterim. Gerçekleştirdiğiniz eylemin bana, öbürüne ya da diğerine herhangi bir zararı, diğerinin özgürlüğünü kısıtlayıcı bir yanı yoksa, o eylemde özgür olmalısınızdır. Eski Yunan’dan beri bu kavram “demokrasi” kavramı ile beraber anılır olmuşsa insanların bin yıllardır edindikleri deneyimlerinden çıkardıkları bir şeyler var demektir.

Hukukçu olmamakla beraber, hukukçuların yorumları ve güncel uygulamalardan çıkarabildiklerim ışığında:
- Bu yasa devletin bir kurumuna “kafasına göre” ve herhangi bir mahkeme kararı aranmasına gerek olmaksızın, “yasaklanma kriterlerine uygun gördüğü” sitelere sizin-benim erişimimizi engelleyebilme hakkı veriyor. Türkçesi, bu kurumda çalışan, maaşları sizin-benim verdiğimiz vergilerle ödenen “uzmanlar”, şu ya da bu sitenin “bizim için uygun olmadığına” karar verip, mezkur yasaya dayanarak yine bizim erişimimizi engelleyebiliyor. (Aşağıda yazacaklarım doğrudan herhangi bir kurum ya da kişiyi hedef almıyor; genel saptamalar niteliğinde okunmalı)
Bu durumun gerçeklenmesini bir sürü porno siteye erişimin engellenmesi şeklinde kendini gösteren uygulamalarda görebiliyoruz. Üstelik iş “porno” olunca kimse elini taşın altına koyup “kardeşim, sana ne!” demek istemiyor. Buyurunuz, işte ben diyorum: Otuzbeş yaşında adamım. İster porno izlerim, ister masturbasyon yaparım ve bunu size soracak değilim. Keyfimin bileceği iştir. Ben gelip size “gece hanımınla şöyle yapma, böyle yap!” diyor muyum? Demiyorum çünkü haddime düşmemiştir. Benim özel hayatımda yaptıklarımın sınırını belirlemek de, başkalarının sınırlarına herhangi bir tecavüz söz konusu olmadığı durumda, kimsenin haddine düşmez. Bu durum, işçinin patronuna “Şu filmleri izleyebilirsin, bunu izleyemezsin!” demesine benzer ve uygar bir sistemde kabul edilmesi mümkün değildir. Devletin, bireyin hizmetinde olduğunu söyleyen herhangi bir sistem için görünen budur.

Yasa koyucu bu durumu göz önüne aldığı için “erişmeye” cezai yaptırım uygulamıyor, ancak “erişim sağlayıcısına” yönelik yaptırımlar öngörüyor.

Bir parantez: (Öte taraftan “genel ahlaka mugayir” kavramı var ki, işte bu kavram içine girebilecek herhangi şeyi bulundurmak da bildiğim kadarıyla suç teşkil edebilir. Herhangi bir hukuk metninin içinde “genel ahlak” türünden öznel ifadeler gördüğüm vakit tüylerim diken diken oluyor. Neye göre yargılayacaksın? Kimin ahlakı “genel”? Bu ayrıca hukukçular ve düşünürler tarafından incelenmesi gereken bir kavram.)

- Diğer nokta “youtube” gibi popüler video paylaşım sitelerinin başına gelenler:
Bu noktada yasaya dayalı bir mahkeme kararı var. Mahkeme eldeki yasaya göre elbette en adil kararı verecektir. Buna göre, Atatürk’e hakaret eden site engellenmeli. Kanımca, bırakın bize hür bir memleket hediye etmiş Atatürk’ü, herhangi sıradan kişiye hakaret, yukarıdaki “başkalarının özgürlüğü” sınırlarını ihlal etmektir ve elbette yaptırımı olmalıdır. Ancak bu yaptırım mutlaka ve mutlaka “hakareti edene” uygulanmalıdır; dünyadaki geri kalan insanlara değil. Gücünüz yetiyorsa gidip bu tür içeriği web sitesinden kaldırtırsınız. Gücünüzün yetmediği durumlarda, hıncınızı gücünüzün yettiklerinden çıkarmak adil değildir.
Tüm dünya bu hakaretleri sınırsızca izleyebilirken, ülkemizdeki insanları, bir takım yabancıların yükledikleri birkaç görüntü yüzünden cezalandırmaya çalışmak, en masum benzetmeyle “katili serbest bırakıp, cinayeti görenlere ’siz bunu görmeyin, yasaktır!’” demektir.

- Son nokta yasanın uygulanabilirliği:
Yasalar gerçekçi olmalıdır. Youtube ülkemizde zaten iki yıldan uzun süredir yasaktı ancak bu yasak ancak İnternet servis sağlayıcılarının alan adı sunucularının yüklerinin hafiflemesine yaradı, başka da bir işe yaramadı. Yürürlükteki yasa sayesinde 12 yaşındaki genç arkadaşlarımız bile “nameserver nedir?” , “DNS protokolü nasıl çalışır?” sorularına yanıt veren alanlarda küçümsenmeyecek deneyim sahibi oldu.
Youtube’a IP bazlı erişim kısıtlaması içeren güncel durumdan sonra da gençlerin, yazının ikinci bölümünde anlatacağım uygulamalar hakkında uzmanlaşmaları da sağlanacağı aşikar olduğundan, yasama organı üyeleri, şapkalarını önlerine koyup aşağıdaki sorular hakkında tekrar düşünmelidir:
1- “Özgürlük” nedir?
2- “Yasak” nedir?
3- “Üstüne oy verdiğim konu hakkında ne derece bilgi sahibiyim?”
4- “Olumlu oy verdiğim bu yasa beni tarih önünde ne duruma sokacak? İnsanlar adımı kimle beraber anacak?”

Paylaş:
  • Print
  • FriendFeed
  • Twitter
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • DZone
  • LinkedIn
  • MySpace
  • Ping.fm
  • Reddit
  • StumbleUpon
  • Technorati

Etiketler:

PHP-Pcntl süreçleri çatallamak (~fork) için gerçekten önemli bir eklenti, ancak ne yazık ki PECL paketi yok.
Hazır bir deb paketinin el altında bulunmasının faydalı olacağını düşündüm. Buradan indirebilirsiniz.

Paylaş:
  • Print
  • FriendFeed
  • Twitter
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • DZone
  • LinkedIn
  • MySpace
  • Ping.fm
  • Reddit
  • StumbleUpon
  • Technorati

Etiketler: , ,

Koskoca dünya çimpiyonatı oynanırken ben de bir-iki kelam etmek istedim.

Şimdi Fuat Bahmanoğlu burada olsa herhalde şuna benzer bir şey söylerdi: “Mene bilyond vermenize gerek yohtur. Anand’ı da Topalof’u da sol elimle utaram! Gasparov çekilende meydan boş galmıştır. Her kim ki dünya çimpiyonu olmah ister, önce Gasparof’la vuruşmalıdır! Bunlar zayıftır zayıf!”

Gerçekten de şampiyonada, biraz daha “şova yönelik” geçmiş olan dördüncü parti dışında, oyunların çoğu oldukça sıkıcı, iki tarafın da kazanmak için fazla risk almadığı mücadeleler tarzında geçiyor. Oynanacak oniki oyunun sonunda, Topalov daha fazla puanla bitirirse yeniden dünya şampiyonu olacak. Anand kazanırsa unvanını koruyacak. Eşitlik durumunda tie-break’e gidilecek. “Bu yazı yazıldığı sırada sekizinci oyun oynanıyor ve Anand ilk yedi oyun sonunda 4-3 önde”.. diyordum ki, siyahla oynayan Anand, ters renkli fil finalinde beklenmedik bir şekilde terk etti. Konum kayıp olabilirdi ancak Ali İpek’in deyimiyle “daha çok oyun vardı.” Bu durumda sekizinci maçtan sonra skora 4-4 eşitlik geldi. Şampiyonada Anand siyahlarla hep aynı slav varyantını seçmiş ve önceki oyunlarda da hep hafif kötü konumları eşitlemeyi başarmıştı ancak görülen o ki çekirge bu sefer zıplayamadı. Bakalım ilerleyen maçlarda ne olacak? Anand Slav’da ısrar edecek mi, yoksa yedeğinde sakladığı yeni ev hazırlıklarına mı tanık olacağız?
Öte taraftan Anand’In beyazlarla oynadığı Katalan da- dördüncü partideki görkemli galibiyet hariç- pek tat vermiyor. Yedinci partide bir ara açıkça ibre siyahtan yanaydı -ki dünya şampiyonluğu maçlarında siyahın açılıştan iyi çıktığı pek görülmez.
Ayrıca merak ettiğim bir husus: Artık maçın yarısı geride kalmışken bu yenilgi Anand’ı psikolojik olarak nasıl etkileyecek? (Evet, Anand’ı tutuyorum, çok mu belli oluyor? ;-) )


Video: Dördüncü maçtan sonra Anand ve Topalov (veya Bulgar analistin yorumuyla ‘Tıpalof’ el sıkışırken (tüm filmler kendi uplaodımızdır(!))

Organizasyonun resmi sitesine buradan ulaşabilir ve maçları canlı ya da “banttan” izleyebilirsiniz.

Paylaş:
  • Print
  • FriendFeed
  • Twitter
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • DZone
  • LinkedIn
  • MySpace
  • Ping.fm
  • Reddit
  • StumbleUpon
  • Technorati

Etiketler:

Ubuntu 10.04 dün yayınlandı ve Karmic’ten altı aydır az çekmemiş olan ben, henüz web sitesinde resmen duyurulmamışken repoda kararlı sürümü görür görmez yükseltme işlemine başladım.

“Vuzuh Vaşak” demek suretiyle herhalde 16.10 sürümü civarına yükseltme yapmış gibi görünmüş oldum.

  • Pencerelerde “kapat”, “küçült”, “panele indir” ikonları sola kaymış. Bana güzel göründü ancak hemen belirteyim: alıştığınız sağda görünen duruma dönmek mümkün ve şu belgede anlatılmış.
  • Gözle görülür şekilde daha hızlı boot ediyor.
  • Karmic’teki bugların hemen hepsi temizlenmiş.
  • Skype sorunsuz çalışıyor.
  • PHP 5.3.2 ile PHP 5.3.x’li günler başlamış.
  • Python 2.6.5
  • gcc 4.4
  • Multimedia işlerindeki sıkıntılar tarih olmuş.
  • Öntanımlı arama motoru Google yerine Yahoo! olmuş, iyi olmamış, ancak yeni kurulum değil yükseltme yapıyorsanız bunu görmüyorsunuz.
  • Firefox 3.6.3
  • Öntanımlı masaüstü arka planı morarmış.
  • Tüm donanımlar sorunsuz tanınıyor.
  • Çekirdek 2.6.32-21
  • Gwibber entegrasyonuyla sosyal medya desteği iyi olmuş.

Bir günlük deneyimin ardından ön sonuçlar:

  • Karmic kullanıyorsanız saniye kaybetmeden yükseltin.
  • Ubuntu Karmic’le kaybettiği prestiji tekrar kazanacak gibi görünüyor. Kullanışlı bir Gnu/Linux dağıtımı arıyorsanız Ubuntu 10.04 iyi bir seçim olacaktır.
Paylaş:
  • Print
  • FriendFeed
  • Twitter
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • DZone
  • LinkedIn
  • MySpace
  • Ping.fm
  • Reddit
  • StumbleUpon
  • Technorati

Etiketler: , ,

İki günlük bir aradan sonra serinin yeni bölümüyle(!) karşınızdayım.
Bu yazının ana konusu pcntl destekli, daemon olarak çalışan Azra Web Server. Değişiklik olsun diye önce benchmarklara bakalım. Aşağıdaki tabloda açıkça görülebildiği gibi Azra ağır yük altında bile Apache’den çok iyi, Nginx’ten biraz daha iyi.

X Ortalama (ms) real user sys
Apache 0.00938119351864 0m2.247s 0m0.068s 0m0.028s
Nginx 0,00461062550545 0m4.443s 0m0.152s 0m0.036s
Azra 0,00429985105991 0m1.992s 0m0.112s 0m0.024s

Benchmark yöntemi:
Apache, Nginx ve Azra kullanarak aşağıdaki kodu 400 kere çağırıyoruz.
test.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

$start = microtime(1);

for($n = 0; $n <= 10000; $n++)
{
    echo $n;
}
$end = microtime(1);
$elapsed = $end - $start;
echo "<br/>vakit(ms): $elapsed";
$fileHandle = fopen('serverBenchmark.txt' , 'a');
fputs($fileHandle , $elapsed . "\n");
fclose($fileHandle);

ve test için kullandığımız python kodu (benchmark.py):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import urllib2
from threading import Thread

class testSuite:
    def testConnection(self , url , thread = 0):
        page = urllib2.urlopen(url)
        data = page.read()
        page.close()
        print("Thread:%d" % thread)
           
    def simpleConnection(self , url , tourNum):
        for i in range(tourNum):
            self.testConnection(url)
       
    def threadedConnection(self , url , tourNum , threadNum):
        for i in range(tourNum):
            myThread = i % threadNum
            t = Thread(target=self.testConnection , args=(url , myThread))
            t.start()

myTestSuite = testSuite()

myTestSuite.threadedConnection('http://localhost:8114/test.php' , 400 , 10) #azra
#myTestSuite.threadedConnection('http://localhost/webserver/test.php' , 400 , 10) #apache
#myTestSuite.threadedConnection('http://localhost/test.php' , 400 , 10) #nginx

Gelişmeler:
Artık Azra, Ubuntu altında daemon olarak çalışabiliyor.
/etc/init.d/azra

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#! /bin/sh
### BEGIN INIT INFO
# Provides:          azra
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start and stop azra web server
# Description:       Start and stop azra web server
### END INIT INFO

# Author: Can Ince <[EMAIL PROTECTED]>

# Do NOT "set -e"

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="AZRA WEB SERVER"
NAME=Azra
DAEMON=/var/www/webserver/azra.php
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
PHP_CONFIG_FILE=/etc/php5/cgi/php.ini

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

# If the daemon is not enabled, give the user a warning and then exit,
# unless we are stopping the daemon
if [ "$START" != "yes" -a "$1" != "stop" ]; then
        log_warning_msg "To enable $NAME, edit /etc/default/$NAME and set START=yes"
        exit 0
fi

# Process configuration
export PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS
DAEMON_ARGS="-q -b $FCGI_HOST:$FCGI_PORT -c $PHP_CONFIG_FILE"

do_start()
{
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
                || return 1
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON \
                --background --make-pidfile --chuid $EXEC_AS_USER www-data $DAEMON -- \
                $DAEMON_ARGS \
                || return 2
}

do_stop()
{
        # Return
        #   0 if daemon has been stopped
        #   1 if daemon was already stopped
        #   2 if daemon could not be stopped
        #   other if a failure occurred
    killall azra.php
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE > /dev/null # --name $DAEMON
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        # Wait for children to finish too if this is a daemon that forks
        # and if the daemon is only ever run from this initscript.
        # If the above conditions are not satisfied then add some other code
        # that waits for the process to drop all resources that could be
        # needed by services started subsequently.  A last resort is to
        # sleep for some time.
        start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
        [ "$?" = 2 ] && return 2
        # Many daemons don't delete their pidfiles when they exit.
        rm -f $PIDFILE
        return "$RETVAL"
}
case "$1" in
  start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
        do_start
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  restart|force-reload)
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
          0|1)
                do_start
                case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
          *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
        exit 3
        ;;
esac

… ve /etc/defaults/Azra:

1
2
START=yes
VERBOSE=yes

Azra multi-process olarak çalışabiliyor.
Ana kod (azra.php)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#! /usr/bin/php-cgi
<?php
/**
 * Azra Web Server
 *
 * Web Server coded in pure PHP
 *
 * @package     Azra Web Server
 * @author      Can Ince
 * @copyright           Copyright (c) 2010, Logikit / Can Ince.
 * @version             0.0.2
 * @license     http://www.opensource.org/licenses/mit-license.php
 * @link        http://can.logikit.net
 */


set_time_limit(0);

interface server
{
    public function setWebRoot($path);
    public function setPort($port);
    public function serve();
}

final class webserver implements server
{
    public $socket;
    private $_port , $_webroot , $_queryString , $_webRootWithoutSlash, $_input , $_file , $_verbose , $_remoteAddr , $_remotePort;
    public function __construct()
    {
        $this->_verbose = 0;
        $_SERVER = array();
        $_COOKIE = array();
    }
   
    public function setPort($port)
    {
        $this->_port = $port;
    }
   
    public function verbose()
    {
        $this->_verbose = 1;
    }
   
    public function setWebRoot($path)
    {
        $this->_webroot = $path . '/';
        $this->_webRootWithoutSlash = $path;
    }
   
    private function _mimeHandler($input)
    {
            $fileinfo = pathinfo($input);
            switch ($fileinfo['extension'])
            {
                case 'png':
                    $mime = "text/png";  
                    break;
               
                case 'jpg':
                case 'jpeg':
                    $mime = "text/jpeg";  
                    break;
               
                case 'gif':
                    $mime = "text/gif";  
                    break;
               
                case 'css':
                    $mime = "text/css";  
                    break;
                   
                case 'swf':
                    $mime = "application/x-shockwave-flash";
                    break;
             
                default:
                    $mime = "text/html; charset=UTF-8";
            }
        return $mime;
    }
   
    private function _handleCode($contents)
    {
         //eval() edilecek kodun başında <?php ya da <? varsa çakar. halledelim.
        $contents = trim($contents);
        if(substr($contents , 0 , 5) == '<?php')
        {
            $contents = substr($contents , 5);
        }
        elseif(substr($contents , 0 , 2) == '<?')
        {
            $contents = substr($contents , 2);
        }
       
        return $contents;
    }
   
    private function _parseGet($str)
    {
        $_GET = array();
        $array = explode('&' , $str);
        foreach($array as $requestItem)
        {
            $itemArray = explode('=' , $requestItem);
            if(!empty($itemArray[0])) $_GET[$itemArray[0]] = $itemArray[1];
        }
        unset($_GET['hyperTextServer_php']); //bunu $_GET'e enjekte ediyor. neden, bilmiyorum...
    }
   
    private function _parsePost($str)
    {
        $_POST = array();
        $array = explode('&' , $str);
        foreach($array as $requestItem)
        {
            $itemArray = explode('=' , $requestItem);
            if(!empty($itemArray[0])) $_POST[$itemArray[0]] = $itemArray[1];
        }
    }
   
    private function _parseCookie($str)
    {
       
        $array = explode('; ' , $str);
        foreach($array as $requestItem)
        {
            $itemArray = explode('=' , $requestItem);
            if(!empty($itemArray[0])) $_COOKIE[$itemArray[0]] = $itemArray[1];
        }
    }
   
    private function _parseRequest($str)
    {
       
        $lines = explode("\n" , $str);
        $rawData = explode(' ' , $lines[0]);
        $_SERVER['REQUEST_METHOD'] = $rawData[0];
        if($_SERVER['REQUEST_METHOD'] == 'POST') $this->_parsePost(end($lines));
        $_SERVER['PHP_SELF'] = $this->_webRootWithoutSlash . $rawData[1];
        $_SERVER['HTTP_HOST'] = substr($lines[1] , 6);
        $_SERVER['HTTP_USER_AGENT'] = substr($lines[2] , 12);
        $_SERVER['HTTP_ACCEPT'] = substr($lines[3] , 8);
        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = substr($lines[4] , 17);
        $_SERVER['HTTP_ACCEPT_ENCODING'] = substr($lines[5] , 17);
        $_SERVER['HTTP_ACCEPT_CHARSET'] = substr($lines[6] , 16);
        $_SERVER['HTTP_KEEP_ALIVE'] = substr($lines[7] , 12);
        $_SERVER['HTTP_CONNECTION'] = substr($lines[8] , 12);
        if(strstr($lines[9] , 'Referer'))
        {
            $_SERVER['HTTP_REFERER'] = substr($lines[9] , 9);
            $_SERVER['HTTP_COOKIE'] = substr($lines[10] , 8);
        }
        else $_SERVER['HTTP_COOKIE'] = substr($lines[9] , 8);
       
        if(!empty($_SERVER['HTTP_COOKIE'])) $this->_parseCookie($_SERVER['HTTP_COOKIE']);
       
        $_SERVER['SERVER_SIGNATURE'] = ' <address>Azra/0.0.1 Server at ' . $_SERVER['HTTP_HOST'] . ' Port ' . $this->_port . '</address>';
        $_SERVER['SERVER_SOFTWARE'] = 'Azra/0.0.1';
        $_SERVER['DOCUMENT_ROOT'] = $this->_webroot;
        $_SERVER['SCRIPT_FILENAME'] = $this->_webRootWithoutSlash . str_replace('./' , '/' , $this->_file);
        $_SERVER['SCRIPT_NAME'] = $this->_file;
        $_SERVER['REQUEST_TIME'] = time();
        $_SERVER['REMOTE_ADDR'] = $this->_remoteAddr;
        $_SERVER['REMOTE_PORT'] = $this->_remotePort;
        if(!empty($this->_queryString)) $_SERVER['QUERY_STRING'] = $this->_queryString;
    }
   
    private function _handle404()
    {
        return "<title>UHU 404</title><h2>UHU 404</h2>Iın-ıın-ıın-ıın-cav-cav-cav-cav-oooooo - oooooo - zört - zört - zört -zört (araba alarmı efekti) Çok afedersin müdürüm ama yok öyle bir dosya.";
    }
   
    public function openSocket()
    {
        $this->socket = @socket_create_listen($this->_port);
        if (!$this->socket)
        {
            echo "Soket olamiyor!\n";
            exit;
        }
        $this->_loadConfigHandler();
    }
   
    private function _loadCOnfigHandler()
    {
        $directoryConfigCandidate = $this->_webroot . '/.ConfigHandler.php';
       
        if ($directoryConfigCandidate && is_readable($directoryConfigCandidate))
        {
            require ($directoryConfigCandidate);
        }      
    }
   
    public function serve()
    {

        while (1) //daire-i ilanihaye!
        {
            $client = socket_accept($this->socket);
            socket_getpeername($client , $remoteAddr , $remotePort);
            $this->_remoteAddr = $remoteAddr;
            $this->_remotePort = $remotePort;
            $input = $this->_input = trim(socket_read ($client, 4096));
           
            if($this->_verbose == 1) echo $input;
           
            $input = explode(" " , $input);
            $input = $input[1];

            if(class_exists('ConfigHandler'))
            {
                $configHandler = new ConfigHandler($input , $this->_webroot);
 
                //konvansiyonumuza göre rewrite işi $configHandler'ın url özelliğinde bulunmalı
                if($configHandler->url != NULL) $input = realpath($configHandler->url);
            }
             
            $mime = $this->_mimeHandler($input);
               
            if ($input == "" || $input == '/')
            {
                $input = "/index.html";
            }
            $input = ".$input";
            $input = str_replace('//' , '/' , $input);
            $inputArray = explode('?' , $input);
            $this->_file = $inputArray[0];
           
            $input = $this->_webroot . $this->_file;
            if (file_exists($input) && is_readable($input))
            {
                if($this->_verbose == 1) echo "Dosya: $input\n";
                 
                $contents = file_get_contents($input);
                if(strstr($input , '.php'))
                {
                    if(!empty($inputArray[1])) $this->_queryString = $inputArray[1];
                   
                    $this->_parseGet($this->_queryString);
                    $this->_parseRequest($this->_input);
                   
                    $_REQUEST = array_merge($_GET , $_POST , $_COOKIE);
                   
                    $contents = $this->_handleCode($contents);
                   
                    //PHP çalıştıktan sonra sonucu echo etmesini değil, $contents stringine atmasını istiyoruz.
                    ob_start();
                    eval($contents);
                    //gidip $contents'in üstüne yazmak doğru alışkanlık değil ama yeni değişken register etmek istemiyorum
                    $contents = ob_get_contents();
                    ob_end_clean();
                }
                $output = "HTTP/1.0 200 OK\r\nServer: HyperTextServer\r\nConnection: close\r\nContent-Type: $mime\r\n\r\n$contents";
            }
            else
            {
                $contents = $this->_handle404();
                $output = "HTTP/1.0 404 OBJECT NOT FOUND\r\nServer: HyperTextServer\r\nConnection: close\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n$contents";
            }
            socket_write($client, $output);
            socket_close ($client);
        }
        socket_close ($this->socket);
    }
   
    public function start()
    {
        $pids = array();

        $this->openSocket();
        for($i = 0; $i < 10; $i++)
        {
            $pids[$i] = pcntl_fork();
           
                if(!$pids[$i])
                {
                    // child process
                    $this->serve();
                    exit();
                }
        }
       
        for($i = 0; $i < 10; $i++)
        {
            pcntl_waitpid($pids[$i], $status, WUNTRACED);
        }
    }
}

$server = new webserver();
$server->setWebRoot('/var/www/act');
$server->verbose(); //ayrıntıları stdout'a echo et.
$server->setPort(8115);
$server->start();

Ara-sonuçlar:
- Bir kaç sorun hala devam ediyor.
– Session’lar düzgün halledilemiyor.
– include’larda sorun yaşanıyor zira dirname(__FILE__) Azra’nın çalıştığı dizini döndürüyor.
- log işine çözüm bulmak lazım.
– header() kullanarak 302 yollanırken path düzgün alınamıyor.
Bu sorunlar da halledildikten sonra şaka olarak başlayan denememiz oldukça ilginç hale gelecek ve bu benchmarkları korumayı başarabilirsem 0.0.3 sürümüne Launchpad yolları görünüyor.

Paylaş:
  • Print
  • FriendFeed
  • Twitter
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • DZone
  • LinkedIn
  • MySpace
  • Ping.fm
  • Reddit
  • StumbleUpon
  • Technorati

Etiketler: , ,

Ubuntu’da PHP-PCNTL Desteği

Ubuntu üstünde PHP kullanıyoruz. Günün birince pcntl desteğine ihtiyacımız oluyor ve tüm PHP’yi yeniden derlemek istemiyoruz. Nasıl yapıyoruz? Şu şekilde:
- Önce bir dizin oluşturuyoruz ve o dizine geçiyoruz. Nerede oluşturduğumuz önemli değil

1
2
mkdir php
cd php

Sistemimizde PHP-dev paketi yoksa kuruyoruz:

1
sudo apt-get install php5-dev

- Daha sonra php source paketini indiriyoruz:

1
apt-get source php5

..ve pcntl dizinine geçiyoruz:

1
cd php5-[php sürümü]/ext/pcntl

Akabinde bildiğimiz PHP modül derleme işi:

1
2
3
phpize
./configure
make

Son olarak derlediğimiz paylaşılmış nesneyi ilgili yere kopyalıyoruz

1
2
cp modules/pcntl.so /usr/lib/php5/phpSürümTarihi/
echo "extension=pcntl.so" > /etc/php5/conf.d/pcntl.ini

Sunucuyu yeniden başlatıp phpinfo() çektiğimizde pcntl’i görüp mutlu oluyoruz.

Tahmin edebileceğiniz gibi, gelecek bölüm: “Bir Web Sunucusu Kodlama Denemesi – 4 (Pcntl destekli Azra)
:-)

Paylaş:
  • Print
  • FriendFeed
  • Twitter
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • DZone
  • LinkedIn
  • MySpace
  • Ping.fm
  • Reddit
  • StumbleUpon
  • Technorati

Etiketler: ,

Heyecan devam ediyor:-)

Bu bölümde:

- Bir önceki sürümde eksik kalan $_SERVER['REMOTE_ADDR'] ve $_SERVER['REMOTE_PORT'] halloldu.

- .ConfigHandler.php isimli dosyayı kullanarak Apache’de .htaccess ile çözülen işler saf PHP ile çözülür hale geldi. Bir rewrite örneğini yazının devamında bulabilirsiniz.

- Benchmark sevenler: Bu bölümde istemediğiniz kadar benchmark var;-) Ayrıca, benchmark işleri küçük bir Python kodu yardımıyla otomatik hale getirildi.

Bir önceki yazımda bir web sunucusunda bulunması gereken temel özelliklerin çoğuna sahip, PHP çalıştıran  bir web sunucusunu, yine PHP kullanarak hayata geçirebilmiş ve adını da Azra Erhat’ın anısına “Azra” koymuştum. Yukarıda gördüğünüz logo için ise, bir bakışta anlayabileceğiniz gibi hiç uğraşmadım, çünkü uğraşsam da daha iyisini yapamayacağımı biliyorum! Hayırsever bir arkadaş düzgün bir logo yapabilirse seve seve kullanırım. Şimdiki logo basitçe Göktürk alfabesi kullanarak “Azra” stringinden ibaret.

Bu sürümde yeni ne var?

- Artık supergloballer ($_POST, $_GET, $_REQUEST, $_COOKIE, $_SERVER) tam olarak destekleniyor.

- .ConfigHandler.php diye bir dosya icat ettim. Azra bu dosya var mı diye bakıyor, varsa içeri alıyor ve ConfigHandler sınıfını çağırıyor.  Aşağıdaki dosyada da görebileceğiniz gibi, örneğin “url rewrite” işi çocuk oyuncağı.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
class ConfigHandler
{
    public $url = NULL;
    public function __construct($input)
    {
        $this->azraRewrite($input);
    }
   
    public function azraRewrite($input)
    {
        $candidate = getcwd() . $input;
        if(!is_file($candidate) && !is_dir($candidate)) $this->url = '/router.php?' . $input;
        else $this->url = $input;
    }
}

- Web sunucumuzun yeni sürümü ise şu şekilde:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
<?php
/**
 * Azra Web Server
 *
 * Web Server coded in pure PHP
 *
 * @package     Azra Web Server
 * @author      Can Ince
 * @copyright           Copyright (c) 2010, Logikit / Can Ince.
 * @version             0.0.2
 * @license     http://www.opensource.org/licenses/mit-license.php
 * @link        http://can.logikit.net
 */


set_time_limit(0);

interface server
{
    public function setWebRoot($path);
    public function setPort($port);
    public function serve();
}

final class webserver implements server
{
    private $_port , $_webroot , $_queryString , $_webRootWithoutSlash, $_input , $_file , $_verbose , $_remoteAddr , $_remotePort;
    public function __construct()
    {
        $this->_verbose = 0;
    }
   
    public function setPort($port)
    {
        $this->_port = $port;
    }
   
    public function verbose()
    {
        $this->_verbose = 1;
    }
   
    public function setWebRoot($path)
    {
        $this->_webroot = $path . '/';
        $this->_webRootWithoutSlash = $path;
    }
   
    private function _mimeHandler($input)
    {
            $fileinfo = pathinfo($input);
            switch ($fileinfo['extension'])
            {
                case 'png':
                    $mime = "text/png";  
                    break;
               
                case 'jpg':
                case 'jpeg':
                    $mime = "text/jpeg";  
                    break;
               
                case 'gif':
                    $mime = "text/gif";  
                    break;
               
                case 'css':
                    $mime = "text/css";  
                    break;
                   
                case 'swf':
                    $mime = "application/x-shockwave-flash";
                    break;
             
                default:
                    $mime = "text/html; charset=UTF-8";
            }
        return $mime;
    }
   
    private function _handleCode($contents)
    {
         //eval() edilecek kodun başında <?php ya da <? varsa çakar. halledelim.
        $contents = trim($contents);
        if(substr($contents , 0 , 5) == '<?php')
        {
            $contents = substr($contents , 5);
        }
        elseif(substr($contents , 0 , 2) == '<?')
        {
            $contents = substr($contents , 2);
        }
       
        return $contents;
    }
   
    private function _parseGet($str)
    {
        $_GET = array();
        $array = explode('&' , $str);
        foreach($array as $requestItem)
        {
            $itemArray = explode('=' , $requestItem);
            if(!empty($itemArray[0])) $_GET[$itemArray[0]] = $itemArray[1];
        }
        unset($_GET['hyperTextServer_php']); //bunu $_GET'e enjekte ediyor. neden, bilmiyorum...
    }
   
    private function _parsePost($str)
    {
        $_POST = array();
        $array = explode('&' , $str);
        foreach($array as $requestItem)
        {
            $itemArray = explode('=' , $requestItem);
            if(!empty($itemArray[0])) $_POST[$itemArray[0]] = $itemArray[1];
        }
    }
   
    private function _parseCookie($str)
    {
        $_COOKIE = array();
        $array = explode('; ' , $str);
        foreach($array as $requestItem)
        {
            $itemArray = explode('=' , $requestItem);
            if(!empty($itemArray[0])) $_COOKIE[$itemArray[0]] = $itemArray[1];
        }
    }
   
    private function _parseRequest($str)
    {
        $_SERVER = array();
        $lines = explode("\n" , $str);
        $rawData = explode(' ' , $lines[0]);
        $_SERVER['REQUEST_METHOD'] = $rawData[0];
        if($_SERVER['REQUEST_METHOD'] == 'POST') $this->_parsePost(end($lines));
        $_SERVER['PHP_SELF'] = $this->_webRootWithoutSlash . $rawData[1];
        $_SERVER['HTTP_HOST'] = substr($lines[1] , 6);
        $_SERVER['HTTP_USER_AGENT'] = substr($lines[2] , 12);
        $_SERVER['HTTP_ACCEPT'] = substr($lines[3] , 8);
        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = substr($lines[4] , 17);
        $_SERVER['HTTP_ACCEPT_ENCODING'] = substr($lines[5] , 17);
        $_SERVER['HTTP_ACCEPT_CHARSET'] = substr($lines[6] , 16);
        $_SERVER['HTTP_KEEP_ALIVE'] = substr($lines[7] , 12);
        $_SERVER['HTTP_CONNECTION'] = substr($lines[8] , 12);
        if(strstr($lines[9] , 'Referer'))
        {
            $_SERVER['HTTP_REFERER'] = substr($lines[9] , 9);
            $_SERVER['HTTP_COOKIE'] = substr($lines[10] , 8);
        }
        else $_SERVER['HTTP_COOKIE'] = substr($lines[9] , 8);
       
        if(!empty($_SERVER['HTTP_COOKIE'])) $this->_parseCookie($_SERVER['HTTP_COOKIE']);
       
        $_SERVER['SERVER_SIGNATURE'] = ' <address>Azra/0.0.1 Server at ' . $_SERVER['HTTP_HOST'] . ' Port ' . $this->_port . '</address>';
        $_SERVER['SERVER_SOFTWARE'] = 'Azra/0.0.1';
        $_SERVER['DOCUMENT_ROOT'] = $this->_webroot;
        $_SERVER['SCRIPT_FILENAME'] = $this->_webRootWithoutSlash . str_replace('./' , '/' , $this->_file);
        $_SERVER['REQUEST_TIME'] = time();
        $_SERVER['REMOTE_ADDR'] = $this->_remoteAddr;
        $_SERVER['REMOTE_PORT'] = $this->_remotePort;
        if(!empty($this->_queryString)) $_SERVER['QUERY_STRING'] = $this->_queryString;
    }
   
    private function _handle404()
    {
        return "<title>UHU 404</title><h2>UHU 404</h2>Iın-ıın-ıın-ıın-cav-cav-cav-cav-oooooo - oooooo - zört - zört - zört -zört (araba alarmı efekti) Çok afedersin müdürüm ama yok öyle bir dosya.";
    }
   
    public function serve()
    {
        $socket = @socket_create_listen($this->_port);
        if (!$socket)
        {
            echo "Soket olamiyor!\n";
            exit;
        }
   
        while (1) //daire-i ilanihaye!
        {
            $client = socket_accept($socket);
            socket_getpeername($client , $remoteAddr , $remotePort);
            $this->_remoteAddr = $remoteAddr;
            $this->_remotePort = $remotePort;
            $input = $this->_input = trim(socket_read ($client, 4096));
           
            if($this->_verbose == 1) echo $input;
           

           

               
            $input = explode(" " , $input);
            $input = $input[1];
           
            $dirName = dirname(__FILE__);
     
            $directoryConfigCandidate = $dirName . '/.ConfigHandler.php';
           
            if ($directoryConfigCandidate && is_readable($directoryConfigCandidate))
            {
                require_once ($directoryConfigCandidate);
                if(class_exists('ConfigHandler'))
                {
                    $configHandler = new ConfigHandler($input);
                    //konvansiyonumuza göre rewrite işi $configHandler'ın url özelliğinde bulunmalı
                    if($configHandler->url != NULL) $input = $configHandler->url;
                }
            }
     
            $mime = $this->_mimeHandler($input);
               
            if ($input == "" || $input == '/')
            {
                $input = "/index.html";
            }
            $input = ".$input";
            $inputArray = explode('?' , $input);
            $this->_file = $inputArray[0];
           
            $input = $this->_webroot . $this->_file;
            if (file_exists($input) && is_readable($input))
            {
                if($this->_verbose == 1) echo "Dosya: $input\n";
                 
                $contents = file_get_contents($input);
                if(strstr($input , '.php'))
                {
                    $this->_queryString = $inputArray[1];
                   
                    $this->_parseGet($this->_queryString);
                    $this->_parseRequest($this->_input);
                   
                    $_REQUEST = array_merge($_GET , $_POST , $_COOKIE);
                   
                    $contents = $this->_handleCode($contents);
                   
                    //PHP çalıştıktan sonra sonucu echo etmesini değil, $contents stringine atmasını istiyoruz.
                    ob_start();
                    eval($contents);
                    //gidip $contents'in üstüne yazmak doğru alışkanlık değil ama yeni değişken register etmek istemiyorum
                    $contents = ob_get_contents();
                    ob_end_clean();
                }
                $output = "HTTP/1.0 200 OK\r\nServer: HyperTextServer\r\nConnection: close\r\nContent-Type: $mime\r\n\r\n$contents";
            }
            else
            {
                $contents = $this->_handle404();
                $output = "HTTP/1.0 404 OBJECT NOT FOUND\r\nServer: HyperTextServer\r\nConnection: close\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n$contents";
            }
            socket_write($client, $output);
            socket_close ($client);
        }
        socket_close ($socket);
    }
}
$server = new webserver();
$server->setWebRoot('/var/www/webserver');
//$server->verbose(); //ayrıntıları stdout'a echo et.
$server->setPort(8008);
$server->serve();

konsoldan

1
php-cgi azra.php

şeklinde çağırmak suretiyle çalıştırıyoruz.

- Benchmarklar:

Benchmark işleri için aşağıdaki test.php dosyasını kullandım. Göreceğiniz gibi bir for döngüsüne girip 10001′e kadar saymaktan ve çalışma süresini bir metin dosyasına yeni satır olarak yazmaktan başka bir iş yapmıyor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

$start = microtime(1);

for($n = 0; $n <= 10000; $n++)
{
    //bir şey yapma. yalnızca say...
}
$end = microtime(1);
$elapsed = $end - $start;
echo "<br/>vakit(ms): $elapsed";
$fileHandle = fopen('serverBenchmark.txt' , 'a');
fputs($fileHandle , $elapsed . "\n");
fclose($fileHandle);

Testleri otomatik hale getirebilmek için de, en kolayıma Python geldiği için kısa ve basit bir kod yazdım:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import urllib2
from threading import Thread

class testSuite:
    def testConnection(self , url , thread = 0):
        page = urllib2.urlopen(url)
        data = page.read()
        page.close()
        print("Thread:%d" % thread)
           
    def simpleConnection(self , url , tourNum):
        for i in range(tourNum):
            self.testConnection(url)
       
    def threadedConnection(self , url , tourNum , threadNum):
        for i in range(tourNum):
            myThread = i % threadNum
            t = Thread(target=self.testConnection , args=(url , myThread))
            t.start()

myTestSuite = testSuite()
#myTestSuite.simpleConnection('http://localhost:8008/test.php' , 1000)
#myTestSuite.simpleConnection('http://localhost/webserver/test.php' , 1000)
myTestSuite.threadedConnection('http://localhost:8008/test.php' , 1000 , 10)

Bu kodu ‘benchmark.py’ adıyla kaydedip konsoldan

1
time python benchmark.py

ile çağırıyoruz ve böylece ne kadar sürede çalıştığını ayrıntılarıyla okuyabiliyoruz. Benim apache için webroot’um /var/www. Azra için webroot’um ise /var/www/webserver. localhost:8008′den Azra’ya, localhost:80 (varsayılan port) adresinden Apache’ye ulaşabiliyoruz.

Bunların yanında, bir tür “pseudo-multi-processing” elde edebilmek için aşağıdaki PHP kodunu kullandım:

1
2
3
4
5
6
7
8
9
10
<?php
set_time_limit(0);
include ("thread.php");

$t2 = new Thread("azra.php");
while ($t2->isActive())
{
    echo $t2->listen();
}
$t2->close();

Bu kodu da konsoldan

1
php-cgi server.php

ile çağırıyoruz. Göreceğiniz gibi server.php, yeni bir PID ile bildiğimiz, sevdiğimiz azra.php’yi çağırıyor.

Kullandığımız üçüncü parti PHP sınıfı (thread.php) ise aşağıda

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php

/**
 * original version can be found at http://www.alternateinterior.com/2007/05/multi-threading-strategies-in-php.html
 * This version is slightly modified to run with PHP 5 - Can Ince
 */

class Thread
{
    var $pref ; // process reference
    var $pipes; // stdio
    var $buffer; // output buffer
    public function __construct($file)
    {
        $this->pref = 0;
        $this->buffer = "";
        $this->pipes = (array)NULL;
       
        $descriptor = array (0 => array ("pipe", "r"), 1 => array ("pipe", "w"), 2 => array ("pipe", "w"));
        $this->pref = proc_open ("php $file ", $descriptor, $this->pipes);
        stream_set_blocking ($this->pipes[1], 0);
    }

   
    public function isActive()
    {
        $this->buffer .= $this->listen();
        $f = stream_get_meta_data ($this->pipes[1]);
        return !$f["eof"];
    }
   
    public function close()
    {
        $r = proc_close ($this->pref);
        $this->pref = NULL;
        return $r;
    }
   
    public function tell($thought)
    {
        fwrite ($this->pipes[0], $thought);
    }
   
    public function listen()
    {
        $buffer = $this->buffer;
        $this->buffer = "";
        while ($r = fgets ($this->pipes[1], 1024))
        {
            $buffer .= $r;
        }
        return $buffer;
    }
   
    public function getError()
    {
        $buffer = "";
        while ($r = fgets ($this->pipes[2], 1024))
        {
            $buffer .= $r;
        }
        return $buffer;
    }
}

Benim lokal sistemimde benchmarklar aşağıdaki gibi çıktı:

—-Azra——–

0.00114736318588 – 10 farklı thread – 100 tur
real    0m0.334s
user    0m0.056s
sys    0m0.020s

0.0180547189713 – 10 farklı thread – 1000 tur
real    0m2.982s
user    0m0.192s
sys    0m0.056s

0.00165226125717 – 100 farklı thread – 1000 tur
real    0m5.251s
user    0m0.196s
sys    0m0.056s

0.00191986322403 – 10 farklı thread – 10000 tur
real    0m38.442s
user    0m1.640s
sys    0m0.608s

0.00110848665237 – tek thread – 100 tur
real    0m0.354s
user    0m0.092s
sys    0m0.068s

0.0111782860756 – tek thread – 1000 tur
real    0m3.421s
user    0m0.744s
sys    0m0.424s

0.00116171479225 – tek thread – 1000 tur (pseudo-multiprocess destekli)
real    0m4.293s
user    0m0.792s
sys    0m0.384s

0.00114714858532 – tek thread – 10000 tur
real    0m37.138s
user    0m8.209s
sys    0m4.280s

—-Apache——-

0.00138350725174 – 10 farklı thread – 100 tur
real    0m0.360s
user    0m0.068s
sys    0m0.028s

0.0136778688431 – 10 farklı thread – 1000 tur
real    0m3.524s
user    0m0.176s
sys    0m0.060s

0.00142541861534 – 100 farklı thread – 1000 tur
real    0m4.030s
user    0m0.144s
sys    0m0.040s

0.00147548000813 – 10 farklı thread – 10000 tur
real    0m46.358s
user    0m1.476s
sys    0m0.496s

0.00153880357742 – tek thread – 100 tur
real    0m0.499s
user    0m0.140s
sys    0m0.068s

0.0135918140411 – tek thread – 1000 tur
real    0m3.824s
user    0m0.972s
sys    0m0.504s

0.0135918140411 – tek thread – 10000 tur
real    1m7.090s
user    0m9.149s
sys    0m4.984s

Benchmarklara hızlıca göz attığımızda fark edebileceğimiz gibi, Azra multi-threaded isteklerde yavaş kalıyor. Bu durumu yeni Ubuntu çıktıktan sonra, PHP’yi pcntl ile derleyerek aşabilmeyi umuyorum. Diğer benchmarkların hepsinde Azra, Apache’ye fark atıyor.

Yeni bölümde yeni maceralarla görüşmek üzere:)

Paylaş:
  • Print
  • FriendFeed
  • Twitter
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • DZone
  • LinkedIn
  • MySpace
  • Ping.fm
  • Reddit
  • StumbleUpon
  • Technorati

Etiketler: , ,

« Older entries