Monday, November 30, 2009

Camping at YediGöller National Park

Campground near the lake. Autumn leaves every where.


Delicious spring water.

Ladies were responsible for dinner. Gentlemen were responsible for lighting the fire and keeping it burning all night long. The night was freezing.


Warming under the sun.


Breakfast with my cousin Ozan. (I am the man in black on the right side)


Posing on bridge, with my wife Nurten.



Upside down...







Leaving everything behind...

Tranquility..

Saving Nurten :)

View of the lakes from the mountains of Bolu.

And special thanks to Jazz, for keeping us comfortable while passing over mountains...

There are more (high resolution) photos in my public picasa library.

Saturday, September 12, 2009

Python API for Flickr Services - Part I

These days I am working on a facebook application that mashes up servises from Facebook and Flickr. The application is hosted by Google Appengine and I am developing on Django web application framework.

Flickr has an easy to use API which is called Flickr Services. Here are some interesting things you can do with the Flickr Services:


  • You can upload photos from anywhere (web application, desktop application or mobile application)
  • You can search for images. Flickr Services lets you search images by
    - tags
    - geo location
    - photo taken time / photo upload time
    - and more...
  • execute methods that require authentication
    - create, edit, remove tags
    - create, edit, remove photo sets
    - replace, remove photos

There are two Python APIs listed in the Flickr Services page:

  1. http://www.stuvel.eu/projects/flickrapi
  2. http://code.google.com/p/flickrpy/

I have implemented Flickr services in Python. Don't think this as "reinventing the wheel" because it was a coding practice for me. Plus, i have my own, customized, shortcut methods ;)

You can download the library from http://code.google.com/p/ilkinulassandbox/. There are also some other javascript and python code snippets there.

Here is a basic usage of the API:

>>> import flickr
>>> api = flickr.FlickrAPI('API_KEY','SECRET_KEY')
>>> api.search({'tags':'python', 'per_page':'3'})
{'photos': {'page': 1,
'pages': 8326,
'perpage': 3,
'photo': [{'farm': 4,
'id': '3911963732',
'isfamily': 0,
'isfriend': 0,
'ispublic': 1,
'owner': '30041312@N03',
'secret': '44aae23e98',
'server': '3090',
'title': 'Centralian Carpet Python (Apophis)'},
{'farm': 3,
'id': '3911184515',
'isfamily': 0,
'isfriend': 0,
'ispublic': 1,
'owner': '30041312@N03',
'secret': '0aae3c8127',
'server': '2513',
'title': 'Centralian Carpet Python (Apophis)'},
{'farm': 3,
'id': '3911127131',
'isfamily': 0,
'isfriend': 0,
'ispublic': 1,
'owner': '31355375@N02',
'secret': '2921fea364',
'server': '2564',
'title': 'Sendra Python Nails 122 01'}],
'total': '24977'},
'stat': 'ok'}

Methods of the API returns a dictionary instance. Caller must handle the returned result.

>>> result = api.search({'tags':'python', 'per_page':'3'})
>>> result['photos']['photo'][0]['id']
'3911751961'


Flickr photo url construction is described here in details. You can easily get the url of a returned photo search result by using build_photo_url. Default image size is 'm' which means 'normal'

>>> api.build_photo_url(result['photos']['photo'][0])
'http://farm4.static.flickr.com/3462/3911751961_43d409cf7c_m.jpg'
>>> api.build_photo_url(result['photos']['photo'][1], size='s')
'http://farm3.static.flickr.com/2613/3911666353_ac0cc98871_s.jpg'


Lets search for pictures tagged 'fun' around point (lat=41.070293, lon=28.24894)

>>> pictures = api.search({'lat':'41.034046', 'lon':'28.980217', 'radius':'10', 'radius_units':'km','tags':'fun'})
>>> api.build_photo_url(fun_pictures['photos']['photo'][20])
'http://farm1.static.flickr.com/116/293251976_ce5337908d_m.jpg'



The next post of "Python API for Flickr Services" will show how you can call methods that require authentication. For the curious readers the api is ready http://code.google.com/p/ilkinulassandbox/. But it lacks documentation :(


NOTE : I use this python API in my facebook application "Türkiye'yi ne kadar iyi tanıyorsun?". Application is a simple guessing game. You see a geo tagged picture from flickr and you answer which city this picture belongs.

UPDATE : This library returns native Python datatypes rather than XML trees or unparsed JSON, which the other Flickr APIs have a tendency to do. (Thanks martian)

Monday, August 3, 2009

Div Roller : jQuery plugin for rotating html div elements

In this post I want to introduce a jQuery plugin that i have written for one of my projects.
jquery.divroller plugin is written to rotate messages displayed in the home page of www.bahele.com. bahele is a facebook connect site where users can login with their facebook accounts and write messages about what they like or dislike. (Bahele is only available in Turkish for now.)

For the ones who have not heard of this library here's the motto from jquery.com


"jQuery is a fast and concise JavaScript Library that simplifies HTML document
traversing, event handling, animating, and Ajax interactions for rapid web
development. jQuery is designed to change the way that you write JavaScript."

jQuery is a widely used javascript library. There are tons of javascript libraries in the wild, each has its own clever implementations. jQuery differs from other frameworks by its chaining property. Most of the methods in the library returns a jQuery object. You can call a jQuery function on a return value of another jQuery function. Here is what i mean:

$("a[href$='.pdf']")
.addClass("external_link")
.append("<img src="http://www.blogger.com/images/pdf.png" />")
.click(pdfLinkClicked);

One line of javascript is splitted into four lines for better readability.

  1. The first line selects all the links in the page whose 'href' attribute ends with '.pdf'
  2. The second line adds 'external_link' css class to selected link elements.
  3. The third line places an image after the link element in order to specify that is a link to download a pdf file.
  4. The last line binds 'pdfLinkClicked' function to the click event of link element.

Enough for a short introduction, now lets look how we can take advantage of jquery.divroller. Below is a simple usage scenario. Plugin is applied to the html div element whose id attrubute is equal to "divroller_container". There are two configuration parameters:

  • pause : Sleep duration between two rotations. This parameter determines the speed of the rolling divs.
  • visible : Number of visible html elements inside the container. Plugin shows only "visible" number of elements, the others are hidden.


<div id="divroller_container">
<div class="box_dark box_size" id="item1">
<a href="http://ilkinbalkanay.blogspot.com/2007/11/my-favorite-shell-commands.html">
My favorite shell commands</a>
</div>
<div class="box_light box_size" id="item2">
<a href="http://ilkinbalkanay.blogspot.com/2007/10/volatile-variables-in-java.html">
Volatile Variables In JAVA</a>
</div>
<div class="box_dark box_size" id="item3">
<a href="http://ilkinbalkanay.blogspot.com/2007/09/power-off-shell.html">
The power off shell</a>
</div>
<div class="box_light box_size" id="item4">
<a href="http://ilkinbalkanay.blogspot.com/2007/09/seach-java-class-files-in-jars.html">
Search java class files in jars. </a>
</div>
<div class="box_dark box_size" id="item5">
<a href="http://ilkinbalkanay.blogspot.com/2008/01/readwritelock-example-in-java.html">
ReadWriteLock example in Java</a>
</div>
<div class="box_light box_size" id="item6">
<a href="http://ilkinbalkanay.blogspot.com/2008/01/how-to-change-gnome-desktop-wallpaper.html">
How to change GNOME desktop wallpaper programmatically</a>
</div>
</div>

<script type="text/javascript">
$("#divroller_container").divroller({pause:2000, visible:3});
</script>


You can see the plugin in action : Live demonstration
You can also download the javascript source.

Note : There are countless jQuery plugins available on the internet. Before writing your own plugin you should check http://plugins.jquery.com/, you might be reinventing the wheel.

Tuesday, July 28, 2009

Oracle'ın Linux stratejisi Ubuntu mu olmalı?

Bu adresteki haberin Türkçe çevirisini paylaşmak istiyorum. Elimden geldiğince cevirmeye çalıştım. Keyifli okumalar:



Oracle geçtiğimiz yıllarda yaptığı satın almalarla, pazarda önde gelen teknolojileri portföyünde topladı. Fakat tüm bu satın almalara rağmen, hala eksik kalan bir şey var: işletim sistemi. Her ne kadar, yıllardır Red Hat'ı satın alınacaklar listesinde tutsa da, işletim sistemi olarak Ubuntu'yu seçmek Oracle için daha iyi olabilir.

Evet, Oracle Sun'u satın alarak Solaris işletim sistemini de elde etmiş oldu, fakat Red Hat yönetim kurulu başkanı Jim Whitehurst'un Çarşamba günü, finansal raporları açıklarken belirttiği gibi, Solaris'ten Linux'e olan kullanıcı göçü hızla devam ediyor ve Sun'ın Linux'a olan eğilime karşı geliştirdiği OpenSolaris bu göçü durdurmak için etkisiz kaldı.

Red Hat'ın en büyük 25 anlaşmasını, Oracle'a kaptırmadan yenilemesi ile birlikte, bir Red Hat Enterprice (Kurumsal) Linux (RHEL) klonu olan Oracle Enterprise Linux (OEL), Red Hat'ın egemenliğine son vermek yolunda büyük darbe aldı. RHEL'nin piyasadaki egemenliği Oracle'ın herşeyi içinde olan bir kurumsal yazılım paketine sahip olma hedefinin önünde büyük bir engel olarak durmakta. Red Hat'in elinde böyle bir kurumsal yazılım paketinin olması Oracle için gerçek bir tehdit olarak görülüyor.

Oracle satış ekiplerinin Oracle uygulamalarını ve veritabanlarını RHEL platformu üzerinde OEL'e göre daha kolay satması, OEL'in zamanla yok olacağına bir işaret gibi gözüküyor.

The Register'in da belirttiği gibi Oracle, Red Hat'i alabilir fakat sabit ve yüksek gelirleriyle Red Hat, Oracle için pahalı bir satın alma hedefi olarak görülüyor. Bununla birlikte, Red Hat, Redwood Shores'daki (California'da Oracle'in merkezinin bulunduğu yer) ortağı ve rakibi olan Oracle'ın kollarına atlamak için can atmıyor.

Tüm bu bilgiler ışığında, Red Hat ile devam etmek yerine Canonical, ticari Ubuntu sponsoru, ile güçlü bir ortaklık Oracle için doğru bir Linux stratejisi olacaktır.

Açık şekilde görülüyor ki, Masaüstünde egemenliği elinde tutan ve ticari sunucularda da güçlü bir yeri olduğunu iddia eden Ubuntu, Linux dağıtımları içinde en çok tercih edilen dağıtım. OEL, Oracle satış ekibi için pazarlaması zor olan bir ürün olduğu için Ubuntu'yu Oracle teknolojilerini tamamlayan bir ürün olarak pazarlamak daha kolay olacaktır.

OEL'i satmak için istek var fakat derman yok.

Sahibi olduğum, açık kaynak kodlu içerik yönetimi uygulamarı satan şirketin, Alfresco, verilerine bakılacak olursa Ubuntu Kurumsal ürünlerdeki yüzde 37'lik payıyla, yüzde 28 pay alan RHEL ve Fedorayı geride bırakmış durumda.

Bir yıl önce Ubuntu ciddi bir ilerleme içindeydi, bugün ise gerçek kurumsal kurulumlarda tercih edilen dağıtım Ubuntu olmuş gözüküyor.

Özetle, Ubuntu arkasına camianın desteğini almış durumda. Tek eksiğinin bir yazılım devinin desteği olduğunu düşünüyorum. Hala aklına gelmemesine rağmen, Oracle, Ubuntu'yu kurumsal bir marka yapabilecek güçte.

Oracle'ın yıllar önce Red Hat'a elini uzatması tesadüfi değildi. Oracle'ın Red Hat Kurumsal Linux dağıtımına (RHEL) verdiği destek olmasaydı, bugün RHEL'in olduğu yerde Novell'in SUSE'sini ya da diğer Linux dağıtımlarını görebilirdik.

Oracle'ın elinde Ubuntu'yu başlıca tercih edilen kurumsal sunucu yapma gücü var. Fakat akıllardaki soru, Oracle bunu istiyor mu?

"The 451 Group" ile çalışan analist Matt Aslett'in bana dediği gibi, "Oracle'ın Linux stratejisi mevcut müşterilerine hizmet vermek." Ve Oracle RHEL kullanan Oracle müşterileri Ubuntu kullanan müşterilerden fazla. Sean Michael Kerner'in belittiği gibi Oracle ürünlerini Ubuntu üzerinde çalıştırmadan önce hepsinin Ubuntu üzerinde problemsiz çalıştığını belgelendirmek zorunda. Bu yüzden RHEL (ve onun klonu OEL) Oracle için daha güvenli bir seçim gibi gözüküyor.

Pazar RHEL (parasını veren kurumsal müşteriler) ve Ubuntu'dan (para ödemeyen Linux camiası) yanayken, Oracle'ın OEL için neden bir sürü kaynak ayırdığını anlamak zor. Ya git OEL yerine RHEL üzerine yoğunlaş ya da Ubuntu'ya bir fırsat ver.

Oracle Ubuntu'yu seçerek hem bir işletim sistemi sahibine sahip olur hem de Ubuntu'nun populerliğini kazanç kapısına çevirebilir.

Siz ne düşünüyorsunuz? Ubuntu, Oracle için iyi bir hamle olabilir mi? Yoksa Oracle'ın sonradan aklına gelen Linux pazarında, RedHat ile devam etmek Oracle için daha mı iyi olur?

Monday, July 27, 2009

Java LineNumberReader

Bu yazıyı ingilizce yazarım diye düşünüyordum fakat klavyenin başına geçince iş değişti. Bu sefer de işin kolayına kaçıyorum. Bu günlüğe ilk başladığım zamanlarda yazılarım ingilizceydi. Bakınız : Volatile Variables In JAVA. İngilizce yazmanın şöyle bir avantajı oluyor, yazınızı dzone, digg gibi sosyal link paylaşım sitelerine gönderdiğiniz anda tahmin edemeyeceğiniz kadar çok ziyaretçi geliyor sitenize. dzone, reddit, digg benzeri türkçe link paylaşım sitelerini pek bilmiyorum ama araştırıp yazıları oraya eklesem iyi olacak galiba ;) Sonuçta bu yazıları benim gibi yazılım meraklıları okusun diye yazıyorum. Fikirlerimi ve yazılarımı ne kadar çok kişi okursa o kadar çok geribesleme alabilirim diye düşünüyorum. Google'ın satın aldığı feedburner servisinin söylediğine göre ben dahil bu günlüğü takip eden 16 kişi var :D

İstanbul'da 3 büyük GSM operatöründen birisinde yazılım geliştirme departmanında çalışıyorum. (Hangi operatorde çalıştığımı merak edenler için ipucu: "Fark var!!!"). İçinde milyonlarca satır olan bir text dosyasını işleyecek bir java uygulaması yazmam gerekti. Uygulamanın yapacağı iş çok basit, satır satır tüm dosyayı okuyup her satır için belirli işleri çalıştıracak.

İşlenecek dosya içinde çok fazla satır olduğu için uygulamanın çalışma süresi de yarım saatten fazla oluyor. Uygulamayı başlattıktan sonra işin yüzde kaçının tamamlandığını ekrana yazdırmak için başlangıçta dosya içinde kaç satır olduğunu bilmek yeterli. Bunun için iki yöntem var.


  • Birinci yöntem dosyayı açıp satır satır taramak ve her satırda satır sayısı sayacını bir artırmak.
  • İkinci yöntem java.util.LineNumberReader sınıfını kullanmak.

Aşağıdaki kod parçası iki yöntemin çalışma sürelerini karşılaştırmak için yazıldı. 10 milyon satırlı bir deneme dosyası ile 100 iterasyonun ortalamasını alarak elde ettiğim sonuç:

LineNumberReader average : 388 miliseconds.
FileScanner average : 839 miliseconds.

Birinci yöntem ile 10 milyon satırlı bir dosyanın satır sayısını bulmak 839 milisaniye sürerken ikinci yöntem ile 388 milisaniye sürmüş.


package util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;


public class LineNumberReaderTest {

public static void main(String[] args) throws IOException {
LineNumberReaderTest test = new LineNumberReaderTest();
String filePath = args[0];
File textFile = new File(filePath);
int numberOfIterations = 100;
int result_1 = test.testByLineNumberReader(numberOfIterations, textFile);
int result_2 = test.testByFileScan(numberOfIterations, textFile);
assert result_1 == result_2;
}


private int testByLineNumberReader(int numberOfIterations, File textFile) throws IOException {
int numberOfLines = 0;
long start = System.currentTimeMillis();
for (int i = 0; i < numberOfIterations; i++) {
numberOfLines = this.numberOfLinesByLineNumberReader(textFile);
}
long diff = System.currentTimeMillis() - start;
System.out.println("LineNumberReader average : " + diff/numberOfIterations + " miliseconds.");
return numberOfLines;
}


public int testByFileScan(int numberOfIterations, File textFile) throws IOException {
int numberOfLines = 0;
long start = System.currentTimeMillis();
for (int i = 0; i < numberOfIterations; i++) {
numberOfLines = this.numberOfLinesByScanningFile(textFile);
}
long diff = System.currentTimeMillis() - start;
System.out.println("FileScanner average : " + diff/numberOfIterations + " miliseconds.");
return numberOfLines;
}

/**
* Dosyayı satir satir gezerek satir sayisini bulmaya yarar
* @param textFile
* @return dosyadaki satir sayisi
* @throws IOException
*/
public int numberOfLinesByScanningFile(File textFile) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new FileReader(textFile));
int numberOfLines = 0;
while(bufferedReader.readLine() != null) {
numberOfLines++;
}
return numberOfLines;
}

/**
* LineNumberReader sinifini kullanarak satir sayisini verir.
* @param textFile
* @return dosyadaki satir sayisi
* @throws IOException
*/
public int numberOfLinesByLineNumberReader(File textFile) throws IOException {
LineNumberReader lineNumberReader = new LineNumberReader(new FileReader(textFile));
lineNumberReader.skip(textFile.length());
return lineNumberReader.getLineNumber();
}
}


Merak ettiğim bir konu var. Ben bu LineNumberReader sınıfına ilk defa iki gün önce rastladım. Siz böyle bir sınıfın varlığını biliyor muydunuz?

Son olarak aklımdayken söyleyeyim. 10 milyon satırlık test dosyasını aşağıdaki komut ile oluşturdum:

ilkinulas@tututil:/tmp$ seq 10000000 > deneme.txt
ilkinulas@tututil:/tmp$ wc -l deneme.txt
10000000 deneme.txt

Sunday, July 26, 2009

Bahele. Artık mesajlara yorum yazabilirsin

Vakit buldukça Bahele.com'a yeni özellikler eklemeyi sürdürüyorum. Site çok fazla kullanılmasa da motivasyonum yüksek. Önceleri yabancı olduğum web teknolojilerini deneyebilmem için iyi fırsat oldu. Ve işte Bahele'deki son değişiklikler:


  1. Mesajlara yorum yazılabiliyor. Yazılan bu yorumlar yorumu yapanın facebook feed'leri arasına gönderiliyor.

  2. Yeni facebook feed şablonları ekledim. Facebook'ta ana sayfayada gözüken feed'ler arasına birşeyler göndermek isterseniz facebook feed şablonlarını kullanmanız gerekiyor. Şablonları biraz daha göze batacak hale getirdim.



İnternette dolanırken programmableweb diye bir siteye rastladım. Aklınıza gelebilecek her türlü mashup ile ilgili bilgi bulabileceğiniz bir site. Bu aralar flickr, google, yahoo, twitter ve facebook api'lerini inceliyorum. Bu devlerin servislerini kullanarak geliştirilebilecek yeni uygulamalar, servisler üzerine kafa yormaya başladım.

Hemen bir örnek site tanıtayım: nearbytweets.com. Google Maps ve Twitter API'lerini kullanarak geliştirilmiş bu site sizin yerinizi buluyor (google sağolsun) sonra da twitter API'si ile arama yaparak yakınlarınızdan yazılan twitter mesajlarını listeliyor. Bence çok başarılı bir mashup örneği.

Nereden nereye geldik. Bahele ile başladık mashup ile bitiriyoruz. Haydi görüşmek üzere...

Monday, June 15, 2009

www.bahele.com beta versiyonu yayında

Günlük yazmak gerçekten zor bir iş. Düzenli olarak kaliteli yazılar yazan blog yazarlarını çok kıskanıyorum. Notlarım arasında yazılmayı bekleyen 20-25 tane yazı var. Ne zaman bilgisayarın başına oturup birisini yazayım desem hemen dikkatim dağılıyor. Google Reader içindeki yazılara dalıp gidiyorum. İnternetten bugüne kadar çok şey öğrendim. Hep al hep al olmuyor, biraz da benim internete birşeyler katmam lazım diye düşünüyorum.

Bu günlükteki 41. yazımda (41 kere maşallah :) ) son 4 aydır uğraştığım bir web sitesini tanıtmak istiyorum. Liseden arkadaşlarım Sefa ve Taylan ile beraber hayata geçirdiğimiz bu eğlenceli web sitesinin adresi http://www.bahele.com. Eğlenceli diyorum çünkü biz yaparken çok eğlendik umarım sizler de kullanırken çok eğlenirsiniz.

Bahele.com nedir?

Bahele.com, insanların sevdiklerini ve sevmediklerini tüm internet ile paylaşabilecekleri bir sosyal ortamdır. Sevdiklerinize, onları sevdiğinizi söylemek size de zor geliyorsa bahele.com tam size göre. Bahele.com'u benzer diğer web sitelerinden ayıran en önemli özelliği facebook-connect alt yapısını kullanmasıdır. Facebook-connect sayesinde bahele.com'u mevcut facebook hesaplarınız ile kullanabilirsiz. Bahele.com'da yazdığınız mesajlar isterseniz facebook profilinizde yayınlanır. Bahele.com ile ilgili detaylı bilgiyi yardım sayfalarında bulabilirsiniz.

Ben bu yazıda bahele.com'u yaparken hangi teknolojileri kullandık ondan bahsetmek istiyorum.


  • Siteyi django web framework kullanarak kodladık. Daha önceden java ile web uygulaması geliştirme tecrübelerim olmuştu. Java ne kadar güçlü bir dil olsa da konu kısa sürede çalışır projeler ortaya koymak olunca python'un eline su dökemez.
  • Veritabanı olarak sizin de tahmin edebileceğiniz gibi mysql kullanıyoruz.
  • Veritabanı işlemlerini biraz da olsa rahatlatmak için memcached kullandık. Şimdilik çok fazla trafik gelmiyor ama ileride trafik arttığında veritabanı sorgularını azaltacağı için önbellek çok işimize yarayacak biliyorum.
  • Facebook ile entegrasyonu pyfacebook API ile yaptık.
  • Siteyi webfaction'da barındırıyoruz. İnternette yaptığım araştırmalar sonucunda webfaction'ı seçtim. Şimdiye kadar ki gözlemlerim seçimimde hata yapmadığımı gösteriyor.


Geçen 4 ay içinde akşamları ya da haftasonları vakit buldukça kodladığım bu web sitesi beni çok heyecanlandırıyor. 9 milyonu aşkın Türk abonesi olan bir platform (facebook) ile entegre çalışabilen bahele.com django kullanarak yaptığım ilk web uygulaması. Bakalım bahele.com'un geleceği nasıl olacak? İnternetin karanlık sularında kayıp mı olacak yoksa hatırı sayılır bir ziyaretçi kitlesine mi sahip olacak. Bunları zamanla göreceğiz.

Sunday, January 18, 2009

Java IntegerCache

Şirkette yazdığımız bir kodu Eclipse FindBugs plugini ile incelerken kodun sarı renkli böcekler tarafından istila edildiğini gördük. Integer sınıfını kullandığımız hemen hemen her sınıf içinde FindBugs bize aşağıdaki uyarıyı veriyordu:
Method invokes inefficient Number constructor; use static valueOf instead

"Yav bırak allah aşkına, alt tarafı bir Integer yaratacaksın" deyip FindBugs uyarısını görmezden gelme varsayılan davranışımdır fakat bugün can sıkıntısının da etkisi ile Java SDK içindeki Integer sınıfının koduna baktım. "new Integer(5)" ile "Integer.valueOf(5)" arasında ne gibi bir fark olabilir çok merak ediyordum. Integer.java sınıfı içerisinde fark yaratan kod aşağıdaki IntegerCache sınıfıymış. JVM sizin için 256 adet tam sayıyı önbelleğe alıyor. -128'den +127'ye kadar olan tam sayılar için Integer.valueOf size hep aynı Integer instance'ını veriyor.
private static class IntegerCache {
private IntegerCache(){}

static final Integer cache[] = new Integer[-(-128) + 127 + 1];

static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}

/**
* Returns a Integer instance representing the specified
* int value.
* If a new Integer instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Integer(int)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* @param  i an int value.
* @return a Integer instance representing i.
* @since  1.5
*/
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache 
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
Küçük bir örnekle konuya nokta koymak istiyorum. Bğyle ufak tefek performans optimizasyonları ile işim olmaz fakat java 1.5'ten beri aktif olan bu özelliği daha yeni öğrendiğim için ilgimi çekti sizinle de paylaşmak istedim.
public class IntegerCacheTest {
public static void main(String[] args) {
Integer int1 = Integer.valueOf(5);
Integer int2 = Integer.valueOf(5);
Integer int3 = new Integer(5);
Integer int4 = 5; 
if ( int1 == int2) {
System.out.println("int1 ve int2 ayni instance.");
} 
if( int1!= int3) {
System.out.println("Fakat int1 ve int3 farkli instance'lar");
} 
if (int1 == int4) {
System.out.println("int1 ve int4 de aynı instance");
} 
if (int1.equals(int2) && int2.equals(int3) && int3.equals(int4)) {
System.out.println("ve son olarak hepsinin değeri aynı :)");
}
}
}
Yukarıdaki kod parçasını çalıştırırsanız aşağıdaki gibi bir çıktı alırsınız.
int1 ve int2 ayni instance.
Fakat int1 ve int3 farkli instance'lar
int1 ve int4 de aynı instance
ve son olarak hepsinin değeri aynı :)
Fakat bu sonuç sizi beni şaşırttığı kadar şaşırtmayabilir :)

Friday, January 9, 2009

Akış Diyagramı

http://xkcd.com/518/ adresinden :

Thursday, January 8, 2009

Web uygulamasını deploy ederken python yardımı

Yazdığım bir web uygulamasının dosyalarını web sunucusuna ftp ile göndermeye çalışırken çektiğim eziyet yüzünden aşağıdaki özellikleri içeren bir script yazmaya karar verdim.
    Script;
  1. Benim seçeceğim bir klasör altındaki tüm dosyaları tarayacak.

  2. Benim belirteceğim süre içerisinde güncellenmiş dosyaları bulacak.

  3. Bulduğu dosyalar CVS (.cvs) ya da SVN (.svn) tarafından kullanılan dosyalar olmayacak

  4. Seçilen dosyaları belirteceğim bir sunucunun belirteceğim bir klasörüne secure ftp ile kopyalacak.

Python standart library içerisisinda ftp istemcisi için ftplib modülü bulunuyor. Fakat bu modül güvenli bağlantıyı (SSH2) desteklemiyor. Bu devirde de ssh haricinde bağlantı kabul eden hosting firması yoktur diye tahmin ediyorum. Google'a arama yaparken Paramiko adındaki modülü buldum. Eğer easy_install kurulu ise paramiko'yu kurmak çok kolay. Burada paramiko kurulumundan bahsetmeye gerek yok zaten README dosyasında detaylı bir şekilde anlatmış adam. Bir hayırsever de paramiko modulünü almış ve üzerine basitleştirilmiş, http://media.commandline.org.uk/code/ssh.txt adresinden indirebileceğiniz python kodunu yazmış. Ben de bu kadar hazır yazılmış kodun üzerine asağıdaki satırları yazdım.

import subprocess
import sys
from ssh import Connection

if len(sys.argv)<4:
print 'usage : python ' + sys.argv[0] + ' source_dir destination_dir hour(s)'
sys.exit()

source_dir = sys.argv[1]
destination_dir = sys.argv[2]
minutes = 60 * int(sys.argv[3])

findCommand = 'find ' + source_dir + ' -type f -mmin -' + str(minutes)
process1 = subprocess.Popen(findCommand.split(), stdout=subprocess.PIPE)
process2 = subprocess.Popen('grep -v .svn'.split(), stdin=process1.stdout, stdout=subprocess.PIPE)

files = process2.stdout.read().strip().split('\n')
host = 'HOST'
username = 'USER'
password = 'PASSWORD'
print 'connecting to ', host
ftp = Connection(host, username=username, password=password)
print 'connected.'
for file in files:
local = file
remote = destination_dir + file.split(source_dir)[1]
print 'sending file ', local, ' to ', remote
ftp.put(local, remote)
ftp.close()
print 'connection closed.'

Yeni güncellenmiş dosyaları bulup bunlar arasından SVN(subversion) dosyaları ayıklamak için linux find ve grep komutlarından yararlandım. Örneğin:
find . -type f -mmin -60 |grep -v 'svn'

komutu bulunduğun dizindeki dosyalardan (klasörler hariç) son 60 dakika içinde güncellenenleri bulur. (subversion dosyalari hariç)
Python ile sistem komutlarını çalıştırmak için subprocess modülünü kullandım. Subprocess modülü ile
  • Sistem komutları çalıştırılabilir.
  • Bir process'in çıktısı başka bir process'e girdi olarak yönlendirilebilir(pipe)
  • Çalıştırılan process'in çıktısı python script'i içinden okunabilir.

Yukarıdaki script'te find komutu çıktısı subprocess modulu yardımı ile grep komutuna veriliyor ve sonuç grep process'inin stdout alanından okunuyor. Yukarıdaki script'i ftp.py olarak kaydettim. /home/ilkinulas/projects/webapps/test dizini altındaki son 5 saat içinde güncellenmiş dosyaları ftp ile web sunucusundaki /home/ilkinulas/webapps/ dizinine atmak için aşağıdaki komutu yazmak yeterli oluyor.
python ftp.py /home/ilkinulas/projects/webapps/test /home/ilkinulas/webapps 5