Thursday, June 26, 2008

GTA IV

Yes, i have GTA 4. I have been playing on xbox for some time. Halo 3 was good. Awesome visuals - though my TV is not a HDTV and is just 20 inches - around 6 years old cheap one. But still the thrill of playing Halo 3, watching the visuals was good.

Mass Effect was still better. The amount of information associated with each character. How each character reacts to which situation. The power to choose between two different decisions. It was good in its own way.

And now it is GTA 4. I had played the original gta which was a 2d game on my home pc. But that time i was in college and the game was a simple demo. So, though i enjoyed it a lot, but still i wanted more. But, at that time purchasing a game was like a throwing money away. So, i simply enjoyed the 15 minute demo version of GTA.

And then on this sunday, i got the GTA-IV to run on my xbox. I was looking for Gears Of War. But it was not available. The shop keeper instead shoved a GTA-4 under my nose. And i was surprised to see a copy of the most wanted game available so easily. I jumped on it. Checked the seals to ensure that it was orignial and then got it for a hefty 2500/-. That is 2 months salary to my maid. Or 20-25 movies. Or a 80 GB HDD. And instead i spent so much on a single DVD of game.

Anyways, playing GTA is a good experience. In addition to stealing cars and beating up people for money, i could call and fix up meetings and dates with my friend and girl-friend. I could go to strip clubs and play pool. I could go on the internet inside GTA and search for information online. It is like a city where i could do whatever i want.

I have just completed 3-4 missions and am looking forward to more time to spend on it.

Few intersting links:

Missions : http://www.gta4.net/missions/
Official Cheats : http://www.gta4.net/cheats/
Other cheats : http://www.cheatcc.com/xbox360/grandtheftauto4cheatscodes.html

Wednesday, June 18, 2008

QA Tester Versus Developer

How Roshan D'Mello (QA Tester) frustrates developer (Mukesh Thakur)

Roshan D'Mello: Hey Mukesh, there is a bug in your code. Type a text in user name text box and press enter. Beep sound doesn't appear.



Mukesh Thakur: How can that be a bug? There is no requirement that beep sound should come. Anyway, I will assign it to offshore and get it fixed.



After 2 days,

Mukesh Thakur: Roshan, bug is fixed. Please verify.



After another 2 days,

Roshan D'Mello: I have re-opened the bug because sound is not coming in some PCs. Sound is coming in my machine, but my colleague Rajat Choudhry is not getting the sound.



After another 2 days,

Mukesh Thakur: Not a bug. I observed that your friend Rajat Choudhry has old IBM machine. Unlike your DELL machine, IBM machines do not have inbuilt speakers. So, to hear the sound in Rajat Choudhry's machine, please use head phones and then get the bug closed soon.



Another 2 days,

Roshan D'Mello: I have re-opened the bug because sound tone is different across different machines. Sound is coming as 'BEEP' in my machine, but my colleague Rajat Choudhry who is having IBM machine is getting the sound as 'TONG'.

Mukesh Thakur: Not a bug. Get lost man. What can we do for the bug? The two machines are built in such a way that they produce different sounds. Do you expect the developers to rebuild the IBM processors to make them uniform? Please close it.



Another 2 days,

Roshan D'Mello: I have re-opened the bug because intensity of beep sound produced on 2 different DELL machines is different. My machine produces beep sound of intensity 10 decibels whereas my friend's machine produces sound worth 20 decibels. Fix your code to make the sound uniform across all machines.



Another 2 days later,

Mukesh Thakur: Once again it is not a bug. I have noticed that the volume set is different on the two machines. Ensure that volume is same in both the machines before I get mad and then close the bug.



Another 2 days,

Roshan D'Mello: I have re-opened the bug.

Mukesh Thakur: What ?? Why? What more stupid reasons can be there for re-opening?

Roshan D'Mello: Sound intensity is different for machines placed at different locations (different buildings). So, I have re-opened it.



After 2 days,

Mukesh Thakur: I have made some scientists do an acoustical analysis of the two buildings you used for testing. They have observed that the acoustics in the two buildings varies to a large extent. That is why sound intensity is different across the 2 buildings. So, I beg you to please close the bugs.



After 1 year

Roshan D'Mello: I am re-opeing the bug. During the year, I requested the clients to arrange architects to build two buildings with same acoustical features, so that I can test it again. Now, when I tested, I found that intensity of sound still varying. So, I am re-opening the defect.

Mukesh Thakur: GROWLLLL.....I am really mad now. I am sure that the sound waves of the two buildings are getting distorted due to some background noise or something. Now I need to waste time to prove that it is because of background noise.



Roshan D'Mello: No need for that. We will put the machines and run them in vacuum and see.

Mukesh Thakur: (not alive)

Friday, June 13, 2008

vim configuration basic

Have you ever thought about configuring vim? The same vim that you use for editing your files (you should be very familiar with vi editor if you are using unix-like systems). Yes, the editor is highly configurable.

Here are some of the basic tips for vim - Vi Improved 7.1

The global configuration file resides at /etc/vim/vimrc. And the local configuration file resides at your home folder. So if you are logged in as jayant and your home folder is /home/jayant, then your local configuration file would be /home/jayant/.vimrc. If you do not see color in your vi editor, you can do the following

syntax on
set background = dark


I have set the following as my default configuration

jayant@jayantbox:~$ cat .vimrc
set autoindent
set cmdheight=2 "command bar is 2 high
set backspace=indent,eol,start "set backspace function
set hlsearch "highlight searched things
set incsearch "incremental search
set ignorecase "ignore case
set textwidth=0
set autoread "auto read when file is changed from outside
set ruler "show current position
" set nu "show line number
set showmatch "show maching braces
set shiftwidth=2
set tabstop=2
set gfn=Courier\ 12
set t_Co=256
colorscheme oceandeep

This sets the tab width to 2 chars instead of the default 8. Color Scheme is changed to oceandeep. You can get Color schemes for vim from http://www.vim.org/scripts/script_search_results.php?keywords=&script_type=color+scheme&order_by=creation_date&direction=descending&search=search. Your color schemes have to be put in <home>/.vim/colors folder. Auto indenting has been turned on, so you dont need to press tab to indent your code.



Check out my vim using the oceandeep color scheme

Wednesday, June 04, 2008

MySQL versus PostgreSQL - part II

My earlier post mysql versus postgresql brought me lots of negative comments - that i did not compare the transactional database of pgsql with the transactional engine (innodb) of mysql. The main reason why i did not do that was because i had found InnoDB to be very slow as compared to MyISAM.

But after all those comments i ran the benchmarks again using the same scripts and the same technology on the same machine (my laptop) and here are the results. I created a new table in both Mysql (using InnoDB engine) and pgsql. And i disabled the binary logging in mysql to speed up insert/update/delete queries. Please refer to the earlier post for the setup information.

Following notification would be used :

<operation(select/insert/update/delete)> : <no_of_threads> X <operations_per_thread>


  • Firstly i ran single thread with inserts both before and after disabling binary logging in mysql
    Mysql Insert : 1 X 100000
    Time : 65.22 Sec (binary logging enabled)
    Time : 32.62 Sec (binary logging disabled)
    So disabling binary logging in mysql would make your insert/update/delete queries take half the time.
    Pgsql Insert : 1 X 100000
    Time : 53.07 Sec
    Inserts in mysql are very fast.

  • Selects : 2 X 100000
    Mysql time : 30.1 Sec
    Pgsql time : 29.92 Sec
    Both are same

  • Updates : 2 X 50000
    Mysql time : 29.38 Sec
    Pgsql time : 36.98 Sec
    Mysql updates are faster

  • Ran 4 threads with different no_of_operations/thread
    Run 1 [Select : 1 X 100000, Insert : 1 X 50000, Update : 1 X 50000, Delete : 1 X 20000]
    Mysql time : 40.86 Sec
    Pgsql time : 45.03 Sec
    Run 2 [Select : 1 X 100000, Insert : 1 X 100000, Update : 1 X 50000, Delete : 1 X 10000]
    Mysql time : 49.91 Sec
    Pgsql time : 63.38 Sec
    Run 3 [Select : 1 X 100000, Insert : 1 X 20000, Update : 1 X 20000, Delete : 1 X 1000]
    Mysql time : 29.83 Sec
    Pgsql time : 29.3 Sec
    It could be seen that increasing the amount of insert/update/delete queries affects the performance of pgsql. Pgsql would perform better if number of selects are very high. Whereas mysql-innodb performs better in all cases

  • Had 4 runs with different no of threads.
    Run 1: 12 threads [Select : 2X30000 + 3X20000, Insert : 1X20000 + 2X10000, Update : 2X10000, Delete : 2X1000]
    Mysql time : 31.16 Sec
    Pgsql time : 30.46 Sec
    Run 2: 12 threads [Select : 2X50000 + 2X40000 + 1X30000, Insert : 1X20000 + 2X15000, Update : 2X15000, Delete : 2X2000]
    Mysql time : 52.25 Sec
    Pgsql time : 53.03 Sec
    Run 3: 20 Threads [Select : 4X50000 + 4X40000 + 2X30000, Insert : 2X20000 + 3X15000, Update : 2X20000 + 1X15000, Delete : 2X5000]
    Mysql time : 169.81 Sec
    Pgsql time : 136.04 Sec
    Run 4: 30 Threads [Select : 2X50000 + 3X40000 + 3X30000 + 3X20000 + 4X10000, Insert : 1X30000 + 2X20000 + 3X10000, Update : 3X20000 + 3X10000, Delete : 1X10000 + 2X5000]
    Mysql time : 200.25 Sec
    Pgsql time : 156.9 Sec
    So, it can be said that for a small system with less concurrency, mysql would perform better. But as concurrency increases, pgsql would perform better. I also saw that while running the pgsql benchmark, the system load was twice than while running mysql benchmark.


Enabling mysql binary logging for replication would ofcourse add an over head. Similarly enabling trigger based replication in pgsql would be another overhead. The fact that replication in mysql is very closely linked with the database server helps in making a high availability system easier. Whereas creating slaves using replication in pgsql is not that easy. All available products for replication in pgsql are external - 3rd party softwares. Still, for a high concurrency system pgsql would be a better choice.

Tuesday, June 03, 2008

MySQL versus PostgreSQL

I created and ran some simple tests on mysql and postgresql to figure out which one is faster. It is already known that postgresql is more stable and reliable than mysql. pgsql has a rich set of features. It is a complete RDBMS and also supports fulltext search.

All benchmarks were done on my laptop - Intel core 2 duo (2.0 GHz) with 4MB L2 cache & 2 GB ram. I have 64 Bit ubuntu system loaded with MySQL 5.1.24-rc (64 bit binary) and PostgreSQL 8.3.1 (compiled from source).

I used python as a scripting language for writing down my benchmark scripts. I used psycopg2 as a connector from python to postgres and mysql-python as a connector from python to mysql.

The benchmarking was done in phases. Firstly simple Insert, update and select queries were run to check the raw speed of these queries. Then threads were created to run simultaneous insert, update, select and delete queries. I checked the benchmark times for different number of concurrent threads.

I created a simple table on both mysql and pgsql. I used the MyISAM database engine to create table in mysql. :

ABC(id int not null auto_increment primary key, value varchar(250));

Queries that were run are:

Insert(I) : Insert ignore into ABC (id, value) ...(For pgsql, a rule has to be created to ignore duplicate inserts)
Update(U) : Update ABC set value=<something> where id=<random_id>
Select(S) : Select * from ABC where id=<random_id>
Delete(D) : Delete from ABC where id=<random_id>



  • Insert - 100000 rows in 1 thread
    Time taken for Mysql : 20.8 seconds
    Time taken for Pgsql : 58.1 seconds
    So, raw insert speed of mysql is much better as compared to pgsql

  • 100000 selects in 1 thread
    Time taken for Mysql : 21.76 seconds
    Time taken for Pgsql : 20.15 seconds
    Raw selects are better in pgsql as compared to mysql

  • Selects - 2 threads of 100000 selects
    Time taken for Mysql : 40.46 seconds
    Time taken for Pgsql : 27.38 seconds
    So, if i increase the concurrency of selects, pgsql perfors much than mysql

  • Update - 2 threads of 50000
    Time taken for Mysql : 23.97 seconds
    Time taken for Pgsql : 34.03 seconds
    Mysql looks better in handling updates here.

  • 4 Threads
    Run 1 : [100000 Selects, 50000 Inserts, 50000 Updates, 20000 Deletes]
    Time taken for Mysql : 45.25 seconds
    Time taken for Pgsql : 54.58 seconds
    Run 2 : [100000 Selects, 100000 Inserts, 50000 Updates, 10000 Deletes]
    Time taken for Mysql : 59.05 seconds
    Time taken for Pgsql : 69.38 seconds
    Run 3 : [100000 Selects, 20000 Inserts, 20000 Updates, 1000 Deletes]
    Time taken for Mysql : 35.54 seconds
    Time taken for Pgsql : 31.23 seconds
    These runs show that Mysql is good when you have very large no of inserts/updates/deletes as compared to selects. But pgsql's performance surpasses that of mysql when the number of selects are much higher.

  • Finally, lets approach the real life scenario where generally the number of selects are much more than the number of inserts and there are multiple threads performing selects and inserts.
    I will use the following notification here - <no_of_threads> X <no_of_operations(select/insert/update/delete)_per_thread>
    So, for example 3 X 20 Selects = 3 threads of 20 Selects in each thread

    Run 1 : [2 X 30000 selects, 3 X 20000 selects, 1 X 20000 inserts, 2 X 10000 inserts, 2 X 100000 updates, 2 X 1000 deletes] Total - 12 threads
    Time taken for Mysql : 42.28 seconds
    Time taken for Pgsql : 44.28 seconds
    Both Mysql and Pgsql are almost at par.

    Run 2 : [2 X 50000 selects, 2 X 40000 selects, 1 X 30000 selects, 1 X 20000 inserts, 2 X 15000 inserts, 2 X 15000 updates, 2 X 2000 deletes] Total - 12 threads but number of selects are quite high
    Time taken for Mysql : 61.02 seconds
    Time taken for Pgsql : 48.60 seconds
    So, as we increase the number of operations (specially selects) mysql's performance degrades, whereas pgsql's performance remains almost the same

    Run 3 : [4 X 50000 selects, 4 X 40000 selects, 2 X 30000 selects, 2 X 20000 inserts, 3 X 15000 inserts, 3 X 15000 updates, 2 X 3000 deletes] Total - 20 threads (10 threads for select, 5 for insert, 3 for update and 2 for delete) Which is the normal trend in database servers.
    Time taken for Mysql : 169.31 seconds
    Time taken for Pgsql : 128.7 seconds
    Bingo, so as concurrency increases pgsql becomes faster than mysql.



My earlier benchmarks with pgsql 7.x was not as good as this one. With postgresql 8.3.1, the speed of serving concurrent requests has increased a lot. So, in a high concurrency environment, i would generally recommend to go ahead with using postgresql rather than mysql.

Please check the comments section. We have some really interesting comments there...

Saturday, May 31, 2008

From MySQL to PostgreSQL

Why? In brief, it is said that mysql is not as stable as postgresql. Postgresql or pgsql focuses on a single database engine as compared to mysql which has a pluggable engine architecture and has multiple engines. Also postgresql is well designed as compared to mysql. psql console is much better than mysql console (you will realize it when you use it). It is supposed to be much more scalable and have better performance than mysql. Pgsql uses a more standard sql language as compared to mysql.

Both have fulltext search capabilities. Though it is said that the fulltext search of pgsql is better than mysql, but i still have to look into it. And the most important of all - pgsql is a full fledged RDBMS, whereas mysql (using the default MyISAM engine) is a DBMS. Data integrity is better in pgsql as compared to mysql. Also i have seen lots of corrupt tables in mysql(might be because i have used mysql throughout my career), and have heard(on the web) that mysql is more crash prone than pgsql.

The final question then comes down to speed. Which one is faster? Logically, since mysql is a DBMS and it does not maintain foreign key relations, it should be faster than pgsql. I will benchmark and blog the results sometime later.

Basically, pgsql is more stable & reliable than mysql. Pgsql has a rich set of features and data integrity is well maintained in pgsql.

Lets look at some of the steps you need to follow if you decide to switch to pgsql from mysql:


  • First of all, down the database engine from www.postgresql.org. Untar it and compile it.

    $ tar -xvjf postgresql-8.3.1.tar.bz2
    $ cd postgresql-8.3.1
    $ ./configure --with-openssl --enable-thread-safety --with-libxml
    (check out the options that you need using ./configure --help)
    $ make
    $ sudo make install

    By default this will install pgsql in /usr/local directory

  • Next, create a user postgres and the database directory for pgsql
    $ adduser postgres
    $ mkdir /usr/local/pgsql/data
    $ chown postgres.postgres /usr/local/pgsql/data

  • Create the pgsql database:
    Firstly, log into mysql and do
    mysql> show variables like '%character';
    +--------------------------+-----------------------------------------------------------------+
    | Variable_name | Value |
    +--------------------------+-----------------------------------------------------------------+
    | character_set_client | latin1 |
    | character_set_connection | latin1 |
    | character_set_database | latin1 |
    | character_set_filesystem | binary |
    | character_set_results | latin1 |
    | character_set_server | latin1 |
    | character_set_system | utf8 |
    | character_sets_dir | /usr/local/mysql-5.1.24-rc-linux-x86_64-glibc23/share/charsets/ |
    +--------------------------+-----------------------------------------------------------------+

    You will see here that the character set for the database & server is latin1. Even though the default database is utf8. If you create the pgsql database using the default command, it will create a utf8 database and you will face problems importing your data into it.

    So, create a latin1 database for pgsql
    $ su - postgres
    $ initdb -D /usr/local/pgsql/data -E latin1 --locale=C

  • Now you have postgresql installed and you can create your own databases and tables. But before proceeding forward, do psql from user postgres's shell.

    start pgsql:

    $ /usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data >~/logfile 2>&1 &

    $ psql
    Welcome to psql 8.3.1, the PostgreSQL interactive terminal.

    Type: \copyright for distribution terms
    \h for help with SQL commands
    \? for help with psql commands
    \g or terminate with semicolon to execute query
    \q to quit

    postgres=#


    The =# says that you are logged in as a super user. To login as another user, create another user and give him required privileges. And then su to the user and login to pgsql from that user.

    postgres=# CREATE USER jayant WITH CREATEDB INHERIT LOGIN;
    postgres=# \q
    $ su - jayant
    $ createdb test
    $ psql test
    test=>


    Here => says that i am not a super user. Now i can create my tables in the test database or create more databases.

    For help on how to create users do

    test=> \h CREATE USER

    And it will give you the syntax for creating a user in postgres

  • To convert your table from mysql format to pgsql format, just dump the table and data separately from mysql using the mysqldump --no-data and mysqldump --no-create-info respectively.

    And you will get two files <mysql_table>.sql & <mysql_table_data>.sql

    download a perl script mysql2pgsql.perl which will be able to convert the sql for your table into appropriate format for pgsql.

  • Now load the table and data into pgsql

    $ psql -f <mysql_table>.sql
    $ psql -f <mysql_table_data>.sql



It looks simple, but it is not that simple. Some points that need to be remembered while using pgsql


  • auto_increment column is defined using the SERIAL word. So, to create an auto_increment primary key column the syntax would be

    CREATE TABLE MYTABLE(ID SERIAL NOT NULL PRIMARY KEY, ....);

    This would also create a sequence mytable_id_seq.

  • While importing data from the mysql dump you may get some warning about backslash escapes in your sql. To remove this warning you will have to set the escape_string_warning to off.

    edit your postgresql.conf file which can be found in the /usr/local/pgsql/data directory and change the variable to off. Now restart pgsql.

  • To start and stop pgsql following commands can be used

    start pgsql
    $ /usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data >~/logfile 2>&1 &

    stop pgsql
    $ /usr/local/pgsql/bin/pg_ctl stop -D /usr/local/pgsql/data

  • Another thing to note is that you dont have custom queries like 'insert ignore into', 'replace into' or 'insert into ... on duplicate key...' in pgsql. You will need to create rules on the table to handle these cases.

    test=> \h create rule
    Command: CREATE RULE
    Description: define a new rewrite rule
    Syntax:
    CREATE [ OR REPLACE ] RULE name AS ON event
    TO table [ WHERE condition ]
    DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) }


    So for exampe to create an insert ignore into type of rule, the following rule needs to be created.

    test=> CREATE OR REPLACE RULE "insert_ignore_mytable" AS ON INSERT TO "mytable" WHERE EXISTS (SELECT 1 FROM "mytable" WHERE id = NEW.id) DO INSTEAD NOTHING;

  • Remember SHOW PROCESSLIST of mysql which used to list down all the processes.

    To list down all the processes for pgsql following command needs to be run

    test=> select * from pg_stat_activity;



We will looking more and more into pgsql.

Friday, May 30, 2008

python programming - threading

There are a few options for threading in python. I wont be exploring all the options here. I would simply try to make this blog entry simple, sweet and short.

There are two modules in python which provide threading capabilities - "thread" module and "threading" module. The thread module is very basic. So lets focus on the threading module

To use the threading module, all you have to do is

import threading

class mythread(threading.Thread):
  def run(self):
    <your code>

mythread().start()
mythread().start()


This will create 2 threads running <your code>

That was quick right. Now lets see some basic stuff like Thread Naming, Thread isAlive and join which is used in most threading environments...

Naming a thread:

import threading

class mythread(threading.Thread):
  def run(self):
    print 'my name is ', self.getName()

foo = mythread()
foo.setName('Foo')
foo.start()

bar = mythread()
bar.setName('Bar')
bar.start()

mythread().start()


Run the program:

$ python threadname.py

And see the output

my name is Foo
my name is Bar
my name is Thread-3


Checking if the thread is still alive:

import threading
import time

class mythread(threading.Thread):
  def run(self):
    print 'my name is ', self.getName()

class aliveth(threading.Thread):
  def run(self):
    time.sleep(10)
    print 'my name is ', self.getName()

myt = mythread()
myt.setName('mythread')
myt.start()
if myt.isAlive():
  print 'myt is alive'
else:
  print 'myt is dead'

alt = aliveth()
alt.setName('aliveth')
alt.start()
if alt.isAlive():
  print 'alt is alive'
else:
  print 'alt is dead'

And check the output

my name is mythread
myt is dead
alt is alive
my name is aliveth


Joining threads:

You can use the thread.join() method to make a thread wait for another thread

import threading
import time

class ThreadOne ( threading.Thread ):
  def run ( self ):
    print 'Thread', self.getName(), 'started.'
    print self.getName(), ': sleeping '
    time.sleep ( 5 )
    print 'Thread', self.getName(), 'ended.'

class ThreadTwo ( threading.Thread ):
  def run ( self ):
    print 'Thread', self.getName(), 'started.'
    print self.getName(), ': waiting for ', thingOne.getName()
    thingOne.join()
    print 'Thread', self.getName(), 'ended.'

class ThreadThree (threading.Thread):
  def run(self):
    print 'Thread', self.getName(), 'started'
    print self.getName(),': Not waiting for any other thread'
    print 'Thread', self.getName(), 'ended.'

thingOne = ThreadOne()
thingOne.start()
thingTwo = ThreadTwo()
thingTwo.start()
thingThree = ThreadThree()
thingThree.start()


And check the output

Thread Thread-1 started.
Thread-1 : sleeping
Thread Thread-2 started.
Thread-2 : waiting for Thread-1
Thread Thread-3 started
Thread-3 : Not waiting for any other thread
Thread Thread-3 ended.
Thread Thread-1 ended.
Thread Thread-2 ended.


This covers most of the stuff for programming threads in python. We will look into thread synchronization issues some other time.

Friday, May 23, 2008

python postgresql connectivity

It is sweet and simple. Got it running in 2 minutes...


  • Download psycopg 2.0 (yup that's the name) from http://www.initd.org

  • Extract the library
    $ tar -xvzf psycopg2-2.0.7.tar.gz

  • Build the extension
    $ cd psycopg2-2.0.7/
    $ python setup.py build

  • And install the extension
    $ sudo python setup.py install

  • Create a simple script
    $ vim pypgsql.py


    import psycopg2

    try:
        conn = psycopg2.connect("dbname='test' user='jayant' host='localhost' password='secret'")
    except:
        print "unable to connect to db"

    cur = conn.cursor()
    cur.execute("""select datname from pg_database""")
    rows = cur.fetchall()

    print "\nShow me the databases\n"
    for row in rows:
        print " ", row[0]


    Save the pypgsql.py file.

  • And finally run the script
    $ python pypgsql.py

    Output:

    Show me the databases

      template1
      template0
      postgres
      test

Monday, May 19, 2008

The forbidden kingdom


Another jackie chan movie. And this time jet li is in it too. And then there is this sweet girl Liu Yifei (difficult to spell though). Jackie chan movies are always full of fun and kung-fu.

The story revolves around a young american kid who is a fan of kung-fu and watches tons of chinese kung-fu movies. He sees a golden staff in the pawn shop w
here he gets his movies from and is drawn to ancient china where he is the saviour who has to return the staff to the monkey king to save the kingdom from t
he evil warlord. The ancient chinese world is full of immortals. And he sees this sweet girl and falls for her. Jackie chan plays the part of a drunk and jet li the part of a silent monk.

A totally imaginary story. If you would have followed the recent movies from jackie chan - the Myth and some others (i dont remember the names). But in all
these movies there is this stuff about ancient chinese civilizations, transportation of other worlds and a relic of huge importance and power that has to be saved from evil.

Though it does make the stories interesting but they still tend to be repetative. I liked the movie. I generally like movies with kung-fu and sweet girls. It is worth a watch

Thursday, May 15, 2008

python on web - getting started : building your first app

I would be focusing here on the following tasks.


  • install pylons.

  • create a helloworld app using pylons.

  • install genshi.

  • change template engine.

  • deploy on apache using mod_wsgi.



Install Pylons

Run the following:

$ easy_install Pylons==0.9.6.1
OR
$ easy_install -f http://pylonshq.com/download/ Pylons==0.9.6.1

More details at http://wiki.pylonshq.com/display/pylonsdocs/Installing+Pylons


Create helloworld app

$ paster create -t pylons helloworld

A directory helloworld with the following structure is created

jayant@jayantbox:~/myprogs/python/helloworld$ ls -lh
total 44K
drwxr-xr-x 4 jayant jayant 4.0K 2008-04-25 17:47 data
-rwxr-xr-x 1 jayant jayant 1.5K 2008-05-15 10:41 development.ini
drwxr-xr-x 2 jayant jayant 4.0K 2008-04-25 17:47 docs
drwxr-xr-x 2 jayant jayant 4.0K 2008-04-25 17:47 ez_setup
drwxr-xr-x 9 jayant jayant 4.0K 2008-05-14 19:52 helloworld
drwxr-xr-x 2 jayant jayant 4.0K 2008-04-25 17:47 helloworld.egg-info
-rwxr-xr-x 1 jayant jayant 79 2008-04-25 17:47 MANIFEST.in
-rwxr-xr-x 1 jayant jayant 463 2008-04-25 17:47 README.txt
-rwxr-xr-x 1 jayant jayant 1.2K 2008-04-25 17:47 setup.cfg
-rwxr-xr-x 1 jayant jayant 865 2008-04-25 17:47 setup.py
-rwxr-xr-x 1 jayant jayant 507 2008-04-25 17:47 test.ini

To run the app, from within the helloworld directory do

jayant@jayantbox:~/myprogs/python/helloworld$ paster serve --reload development.ini
Starting subprocess with file monitor
Starting server in PID 15555.
serving on 0.0.0.0:5000 view at http://127.0.0.1:5000

Create a test.html in the <path_to_helloworld>helloworld/helloworld/public directory

<html>
<body>
Hello World!!
</body>
</html>


And point your browser to http://127.0.0.1:5000/test.html to see the "Hello World!!" page.

Now lets create a controller and try printing info through a template.

jayant@jayantbox:~/myprogs/python/helloworld$ paster controller hello
Creating /home/jayant/myprogs/python/helloworld/helloworld/controllers/hello.py
Creating /home/jayant/myprogs/python/helloworld/helloworld/tests/functional/test_hello.py

Edit the <path_to_helloworld>/helloworld/helloworld/controllers/hello.py file and put in some python code

import logging

from helloworld.lib.base import *

log = logging.getLogger(__name__)

class HelloController(BaseController):

    def index(self):
        # Return a rendered template
        # return render('/some/template.mako')
        # or, Return a response
        return 'Hello World'
    def serverinfo(self):
        import cgi
        import pprint
        c.pretty_environ = cgi.escape(pprint.pformat(request.environ))
        c.name = 'Jayant Kumar'
        return render('serverinfo.mako')

Now create a template serverinfo.mako in <path_to_helloworld>/helloworld/helloworld/templates

<h2>
Server info for ${request.host}
</h2>

<p>
The URL you called: ${h.url_for()}
</p>

<p>Hi there ${c.name or c.full_name or "Joe Smith"}</p>

<p>
The name you set: ${c.name}
</p>

<p>The WSGI environ:<br>
<pre>${c.pretty_environ}</pre>
</p>

Edit the <path_to_helloworld>/helloworld/helloworld/config/routing.py file and check if the following code there in the "CUSTOM ROUTES" section

map.connect('', controller='hello', action='index')
map.connect(':controller/:action/:id')
map.connect('*url', controller='template', action='view')

This means that an empty URL is matched to the index action of the hello controller. Otherwise, the route mapper looks for URLs in the form controller/action/id, but if action or controller are not specified the request is routed to the view action of the templates controller (created by the Pylons template). This raises a 404 error by default

Now go to http://localhost:5000/hello/hello and http://localhost:5000/hello/serverinfo and check out the output.

Installing genshi and switching the template engine

$ easy_install Genshi

To enable genshi in your project edit the <path_to_helloworld>/helloworld/helloworld/config/environment.py file and change the template engine from mako to genshi

    config.init_app(global_conf, app_conf, package='helloworld',
        template_engine='genshi', paths=paths)


Now create a new template in <path_to_helloworld>/helloworld/helloworld/templates, say serverinfo.html and put in the following code

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
lang="en">
<h2>
Testing...
</h2>

<p>Hi there ${c.name}</p>

<p>
The name you set: ${c.name}
</p>

<p>The WSGI environ:<br/>
<div py:content="c.pretty_environ">Pretty Environ</div>
</p>
</html>

And change your <path_to_helloworld>/helloworld/helloworld/controllers/hello.py to render the new template

        return render('serverinfo')

And check the output at http://localhost:5000/hello/hello and http://localhost:5000/hello/serverinfo

Deploy using mod_wsgi

For those who have not yet configured mod_wsgi, you can get mod_wsgi from http://code.google.com/p/modwsgi/.

Simply untar it and do a

./configure --with-apxs=/path/to/apache/bin/apxs
make
sudo make install


Bingo and you have the mod_wsgi.so file in your apache/modules directory

Change the httpd.conf and add the following

LoadModule wsgi_module modules/mod_wsgi.so

to load the wsgi module and then deploy the hello world application

WSGIDaemonProcess hello thread=25
WSGIScriptAlias /hello "/path/to/apache/anydirectory/hello.wsgi
<Location /hello>
        WSGIProcessGroup hello
        WSGIReloadMechanism Process
</Location>


This says that the application helloworld would run as a separate process with 25 threads. And since we have also enabled process reload mechanism available with mod_wsgi-2.0, all that is needed to restart/reload the application is to touch/change the wsgi script modification time.

Wait a minute, we did not create the hello.wsgi script. Create a directory in /path/to/apache or anywhere where apache has read access and where you want to keep your application startup scripts. So what i did was.

$ mkdir /path/to/apache/wsgi

And create a hello.wsgi inside it

cd /path/to/apache/wsgi
vim hello.wsgi


Add the following code here

import os, sys
sys.path.append('/path/to/python/application/helloworld')

from paste.deploy import loadapp

application = loadapp('config:/path/to/python/application/helloworld/development.ini')


And we are done. Please note that the /path/to/python/application should be readable and executable by apache. Or you can do (very unsafe - not recommended on production servers)

chmod -R a+rx /path

Now simply restart apache and point your browser to

http://localhost/hello/
and
http://localhost/hello/hello/serverinfo

To see the output.

Source:
http://wiki.pylonshq.com/display/pylonsdocs/Installing+Pylons
http://wiki.pylonshq.com/display/pylonsdocs/Getting+Started
http://wiki.pylonshq.com/display/pylonsdocs/Using+Other+Template+Languages
http://code.google.com/p/modwsgi/wiki/InstallationInstructions
http://code.google.com/p/modwsgi/wiki/IntegrationWithPylons