Thứ Bảy, 6 tháng 11, 2010

Thông tin về Hanoi PHP day 2010

Summary :

Where: Bảo Sơn Hotel
When : 18/12/2010
Who : VNG , VNext , Aiti-aptech , oos enthusiasts .. and YOU
What : I don't know .

Detail : Here

Thứ Ba, 26 tháng 10, 2010

Tự viết function cho mysql sử dụng Ansi C

Khi các hàm được cung cấp sắn của mysql là không đủ dùng .

Chúng ta nghĩ đến việc viết function hoặc procedure .

Nếu việc viết procedure hướng đến việc sử lý dữ liệu nội tại của database .

Thì việc viết function lại hướng đến các tiện ích làm việc trên các kiểu dữ liệu cơ bản của mysql .

Trong bài viết này mình sẽ hướng dẫn viết function ( để extends mysql ) .

1.Chuẩn bị thư viện.

sudo apt-get install libmysql++-dev

2.Dùng một Editor để soạn file C

include header :

#include <mysql/mysql.h>

Viết hàm init

int hamming_dist_init(UDF_INIT *initid, UDF_ARGS *args,
char *message)

Trong ví dụ này mình viết hàm hamming_dist nên hàm init cho nó sẽ là hamming_dist_init .

Hàm này sẽ được gọi ngay khi hàm chính được gọi . Thường việc tiền sử lý sẽ được viết ở đây ( ví dụ như việc check param).

int hamming_dist_init(UDF_INIT *initid, UDF_ARGS *args,
char *message)
{
if (args->arg_count != 2)
{
strcpy(message,"hamming_dist() requires two arguments");
return 1;
}
return 0;
}

Kiểm tra xem số tham số có =2 hay không . Nếu khác 2 thì thôgn báo lỗi và kết thúc hàm .

Viết hàm chính

Hàm chính có mẫu như sau :

long long hamming_dist(UDF_INIT *initid, UDF_ARGS *args,char *is_null, char *error)

Đây là mẫ hàm trả về kiểu long64 nếu định trả về String , mẫu sẽ khác . Hay muốn viết các hàm Aggregate sẽ dùng mẫu này :

void xxx_reset(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);


Đầy đủ hàm mình đang viết :
long long hamming_dist(UDF_INIT *initid, UDF_ARGS *args,char *is_null, char *error)
{


uint64_t a1 = *((uint64_t*) args->args[0]);
uint64_t a2 = *((uint64_t*) args->args[1]);


uint32_t v1 = a1^a2;
uint32_t v2 = (a1^a2)>>32;

v1 = v1 - ((v1>>1) & 0x55555555);
v2 = v2 - ((v2>>1) & 0x55555555);
v1 = (v1 & 0x33333333) + ((v1>>2) & 0x33333333);
v2 = (v2 & 0x33333333) + ((v2>>2) & 0x33333333);
int c1 = (((v1 + (v1>>4)) & 0xF0F0F0F) * 0x1010101) >> 24;
int c2 = (((v2 + (v2>>4)) & 0xF0F0F0F) * 0x1010101) >> 24;

return c1+c2;
}

Mình thực hiện một số tính toán rồi trả về kiểu long long (64 bit)

Các bạn có thể viết hàm đơn giản như hàm add
long long add(UDF_INIT *initid, UDF_ARGS *args,char *is_null, char *error)

{

long a = *((long*) args->args[0]);

long b = *((long*) args->args[0]);

return a+b;

}

Nhìn qua 2 hàm trên các bạn có thể hiểu cách lấy tham số .(args <-- nó đấy ).

3.Compile :

gcc -shared -o hamming.so -std=c99 $(mysql_config --cflags) hamming_dist.c  $(mysql_config --libs)

Nhớ sửa tên source file và output file nhé  ( xem lại bài trước về các compile http://i-php.net/2010/10/ket-noi-den-csdl-mysql-su-dung/ )

4.Triển khai .

copy file hamming.so vừa tạo ra được vào thu mục plugin của mysql .
sudo cp hamming.so  /usr/lib/mysql/plugin/

Trên các OS khác thì thư mục này sẽ khác nhau , và cái này có thể config được trong file my.conf ( hoặc mysql.ini )

Thực hiện lệnh tạo function trong mysql
CREATE FUNCTION hamming_dist  RETURNS INT SONAME 'hamming.so';

5.Kiểm tra select hamming_dist(1121234123123,131231313131234);

Chúc các bạn thành công .

Thứ Sáu, 22 tháng 10, 2010

Kết nối đến csdl Mysql sử dụng Ansi C

Kết nối đến csdl Mysql sử dụng Ansi C


Bài viết của mình được thực hiện trên Ubuntu nhé ( và Centos ) các bác sài win đi chỗ khác xem nhé  .

1. Cài đặt thư viện

sudo apt-get install libmysql++-dev

2. Code :

Dùng một Editor để soạn file C .

include header :

#include <mysql/mysql.h>

Kết nối :
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;

char *server ="localhost";
char *user = "root";
char *password = "1";
char *database = "mysql";

MYSQL_STMT    *stmt;
MYSQL_BIND    bind[2];

conn = mysql_init(NULL);
if(!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0))
{
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}

Truy vấn :
if (mysql_query(conn, sql)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(0);
}

res = mysql_use_result(conn);

while ((row = mysql_fetch_row(res)) != NULL)
{

printf("data  %d \n", row[0]));

}

Nhìn chung C API khá giống php API nên cũng không khó nắm bắt lắm .

Vấn đề chủ yêu nằm ở các kiểu dữ liệu giữa C và Mysql :

Để giải quyết vấn đề này nên sử dụng triệt để prepare statement :

ví dụ :
#define UPDATE_SQL "UPDATE articles category_id=? where article_id =? "

if (mysql_stmt_prepare(stmt, UPDATE_SQL, strlen(UPDATE_SQL)))
{
fprintf(stderr, " mysql_stmt_prepare(), UPDATE failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(0);
}
fprintf(stdout, " prepare, INSERT successful\n");

printf("a");

memset(bind, 0, sizeof(bind));

/* INTEGER PARAM */
/* This is a number type, so there is no need
to specify buffer_length */
bind[0].buffer_type= MYSQL_TYPE_LONGLONG;
bind[0].buffer= (char *)&hash1;
bind[0].is_null= 0;
bind[0].length= 0;
bind[0].is_unsigned=1;

bind[1].buffer_type= MYSQL_TYPE_LONG;
bind[1].buffer= (char *)&article_id;
bind[1].is_null= 0;
bind[1].length= 0;
bind[1].is_unsigned=1;

/* Bind the buffers */
if (mysql_stmt_bind_param(stmt, bind))
{
fprintf(stderr, " mysql_stmt_bind_param() failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(0);
}

/* Execute the INSERT statement - 1*/
if (mysql_stmt_execute(stmt))
{
fprintf(stderr, " mysql_stmt_execute(), 1 failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(0);
}

Nhìn chung code vất vả hơn php gấp 10 lần :( .

Nhưng tốc độ thì khỏi nói .

Dự án của mình sau này chắc  có đển vài trăm ngàn bảng ghi , mà nó chạy như hack ấy :)) .

3.Complile :

gcc -o my.out -std=c99 $(mysql_config --cflags) mycode.c $(mysql_config --libs)

Có 2 tham số hơi lạ mysql_config --cflags <-- để chỉ ra đường dẫn tới mysql header

mysql_config --libs   <-- Để chỉ ra file lib của mysql ( sử dụng khi linking )

Các bạn có thể chạy lệnh này độc lập xem nó sinh ra cái gì .

Happy coding .

Bài viết tiếp theo sẽ là : Tự viến hàm mở rộng cho mysql ( tất nhiên là dùng C )

Thứ Năm, 21 tháng 10, 2010

Tự build extension cho php

Tự build extension cho php


Mình viết tut này trên ubuntu , các distro khác có thể sẽ khác .

1.check out php5 source :

Mình sec check out từ svn vào thư mục /var/lib/php5 nhé .

sudo svn checkout  http://svn.php.net/viewvc/php/php-src/trunk

Nếu ngại sudo nhiều thì có thể dùng sudo su để thành root luôn cho tiện .

2. Cài php5-dev

sudo apt-get install php5-dev

3. Trong thư mục checkout về , trong thư mục ext sẽ có một file ext_skel.sh file này để sinh ra template cho một ext .

Trong ví dụ nay mình đang xây dựng thư viện simhash (http://knol.google.com/k/simple-simhashing#) .

Thư viện này để so sánh văn bản , hiện đã có implement bằng C .

chạy  sudo ./ext_skel --extname=simhash

để tạo thư mục và template cho extension mới .

cd simhash ( để vào thư mục simhash )

4. chạy sudo phpize để sinh ra các file giúp chung ta có thể build extension độc lập , mà không cần build toàn bộ php5 .

5. Viết code:

Có 2 file cần quan tâm là :

php_simhash :

Bạn phải thêm tên các hàm muốn xây dựng trong extension này :

PHP_MINIT_FUNCTION(simhash);
PHP_MSHUTDOWN_FUNCTION(simhash);
PHP_RINIT_FUNCTION(simhash);
PHP_RSHUTDOWN_FUNCTION(simhash);
PHP_MINFO_FUNCTION(simhash);
PHP_FUNCTION(simhash);
PHP_FUNCTION(confirm_simhash_compiled);

Hàm bôi đậm là mình thêm vào nhé .

File Simhash.c

Khai báo các hàm

const zend_function_entry simhash_functions[] = {
PHP_FE(confirm_simhash_compiled,    NULL)        /* For testing, remove later. */
PHP_FE(simhash, NULL)
{NULL, NULL, NULL}    /* Must be the last line in simhash_functions[] */
};

implement hàm  :

tạm thời cứ print ra Hello, world nhé .

PHP_FUNCTION(simhash)
{
php_printf("Hello, world!\n");
}


6. sudo ./configure

7. sudo make

8. ls modules/

kiểm tra xem có file simhash.so chưa .

Nếu có là ok .

Bạn deploy file simhash.so này bằng cách cấu hình lại php.ini rồi kiểm tra lại bằng phpinfo hoặc tự viết script nhé .

Thật ra trong cái ext của mình cũng có sẵn script test rồi (file simhash.php đấy).

Ngoài ra vấn đề parse các param truyền vào từ php và cách để return giá trị lại cho php caller cũng khá phức tạp .

Để parse param các bạn phải dùng hàm

zend_parse_parameters :


if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld|b", &a, &b, &return_long) == FAILURE) {
RETURN_NULL();
}


hàm này hoạt động khá giống scanf chỉ khác formate string "ld|b = long - double - và zend_bool .

Cách return về dữ liệu cũng phải thực hiện qua các macro :

Kiều thế này .

RETURN_LONG(a + b);

Thứ Hai, 18 tháng 10, 2010

Change height cell in tableViewCell in iphone by objective C

Viết hai hàm này vào lớp có tableViewCell

- (CGFloat)heightForTweetCellWithString:(NSString *)text {
//change size
return MAX(85, 80);
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

return [self heightForTweetCellWithString:@"change Height"];

}

Thứ Bảy, 16 tháng 10, 2010

Tự động cập nhật svn trên webserver

Mỗi khi các dev commit code lên svn repository , thường phải có động tác ssh lên webserver gõ một câu lệnh buồn tẻ
: svn update :(

Để tránh điều này có thể sử dụng hook script sau :
( hook vào post-commit nhé )


#!/bin/sh
REPOS="$1"
REV="$2"
cd /var/www/youdir/
svn log -vr $REV /var/www/youdir/;
svnlook dirs-changed "$REPOS" -r "$REV" | xargs svn update --non-recursive --username "www-data" --password "") 2>&1) | mail -s "$REPOS@$REV"ngoc_@aiti.com.vn


script sẽ thực hiện update code và gửi email thông báo cho ngoc_@ aiti.com.vn mới cho webserver khi có event commited . Với script này chỉ thực hiện được với các svn hosting nằm cùng server với webserver .

Với trường hợp khác server , sẽ cần một script khác ở remote server viết bằng php hoặc perl .
Cái này bài viết sau mình sẽ viết .

Cài đặt plugin cho phép trac gửi tin qua IRC , email

Cài đặt plugin cho phép trac gửi tin qua IRC và email .

1.Để gửi email chỉ cần config file /etc/trac.ini :

[notification]
smtp_enabled = true
use_tls = true
mime_encoding = base64
smtp_server = smtp.gmail.com
smtp_port = 587
smtp_user = myusername@gmail.com
smtp_password = mypassword


2. Để cài đặt IRC notice bạn phải cài irccat trước ( xem các bài viết trước ) .

Sau đó build plugin

1. svn co http://irccat-listener-trac-plugin.googlecode.com/svn/trunk/
2. wget http://peak.telecommunity.com/dist/ez_setup.py
3.python ez_setup.py
4.cd trunk
5.python setup.py bdist_egg
Bạn sẽ thu được một file egg trong thu mục dist .
Deploy nó vào trong trac bằng trac admin , hoặc copy vào thư mục trac của dự án .

Done .

Dùng Zend_ACL trong CodeIgniter

Qua tìm hiểu thì : Codeigniter không có thư việc cho ACL
Mặt khác cũng không có ACL plugin nào cho CI đủ tốt .

Vì vậy giải pháp dùng Zend_ACL là khả thi nhất .

Zend ACL là một thư viện nhỏ trong Zend Framework . Chúng chỉ có khoảng 4 file .

Rất thích hợp để dưa vào CI .

  1. Download thư viện Zend framework

  2. Tạo thư mục  Zend trong thư mục   /system/application/libraries của CodeIgniter .

  3. Copy  thư mục  Acl , file  Acl.php và file Exception.php của Zend framework vào thư mục Zend vừa tạo .

  4. Tạo file  Zacl.php trong thư mục libraries .<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
    class Zacl
    {
    // Set the instance variable
    var $CI;


    function __construct()
    {
    // Get the instance
    $this->CI =& get_instance();

    // Set the include path and require the needed files
    set_include_path(get_include_path() . PATH_SEPARATOR . BASEPATH . "application/libraries");
    require_once(APPPATH . '/libraries/Zend/Acl.php');
    require_once(APPPATH . '/libraries/Zend/Acl/Role.php');
    require_once(APPPATH . '/libraries/Zend/Acl/Resource.php');
    $this->acl = new Zend_Acl();

    // Set the default ACL
    $this->acl->addRole(new Zend_Acl_Role('default'));
    $query = $this->CI->db->get('tbl_aclresources');
    foreach($query->result() AS $row){
    $this->acl->add(new Zend_Acl_Resource($row->resource));
    if($row->default_value == 'true'){
    $this->acl->allow('default', $row->resource);
    }
    }
    // Get the ACL for the roles
    $this->CI->db->order_by("roleorder", "ASC");
    $query = $this->CI->db->get('tbl_aclroles');
    foreach($query->result() AS $row){
    $role = (string)$row->name;
    $this->acl->addRole(new Zend_Acl_Role($role), 'default');
    $this->CI->db->from('tbl_acl');
    $this->CI->db->join('tbl_aclresources', 'tbl_acl.resource_id = tbl_aclresources.id');
    $this->CI->db->where('type', 'role');
    $this->CI->db->where('type_id', $row->id);
    $subquery = $this->CI->db->get();
    foreach($subquery->result() AS $subrow){
    if($subrow->action == "allow"){
    $this->acl->allow($role, $subrow->resource);
    } else {
    $this->acl->deny($role, $subrow->resource);
    }
    }
    // Get the ACL for the users
    $this->CI->db->from('tbl_users');
    $this->CI->db->where('roleid', $row->id);
    $userquery = $this->CI->db->get();
    foreach($userquery->result() AS $userrow){
    $this->acl->addRole(new Zend_Acl_Role($userrow->user), $role);
    $this->CI->db->from('tbl_acl');
    $this->CI->db->join('tbl_aclresources', 'tbl_acl.resource_id = tbl_aclresources.id');
    $this->CI->db->where('type', 'user');
    $this->CI->db->where('type_id', $userrow->userid);
    $usersubquery = $this->CI->db->get();
    foreach($usersubquery->result() AS $usersubrow){
    if($usersubrow->action == "allow"){
    $this->acl->allow($userrow->user, $usersubrow->resource);
    } else {
    $this->acl->deny($userrow->user, $usersubrow->resource);
    }
    }
    }
    }
    }

    // Function to check if the current or a preset role has access to a resource
    function check_acl($resource, $role = '')
    {
    if (!$this->acl->has($resource))
    {
    return 1;
    }
    if (empty($role)) {
    if (isset($this->CI->session->userdata['user'])) {
    $role = $this->CI->session->userdata['user'];
    }
    }
    if (empty($role)) {
    return false;
    }
    return $this->acl->isAllowed($role, $resource);
    }
    }

  5. Nếu muốn Zacl tự động load vào CI thì code vào trong file autoload , cái này nên cân nhắc kỹ :D .

  6. Cách dùng : $this->zacl->check_acl gọi hàm này :D


7. DB script
CREATE TABLE IF NOT EXISTS `tbl_acl` (
`id` int(11) NOT NULL auto_increment,
`type` enum('role','user') NOT NULL,
`type_id` int(11) NOT NULL,
`resource_id` int(11) NOT NULL,
`action` enum('allow','deny') NOT NULL,
PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT;

CREATE TABLE IF NOT EXISTS `tbl_aclresources` (
`id` int(11) NOT NULL auto_increment,
`resource` varchar(255) NOT NULL,
`description` longtext NOT NULL,
`aclgroup` varchar(255) NOT NULL,
`aclgrouporder` int(11) NOT NULL,
`default_value` enum('true','false') NOT NULL,
PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT;

CREATE TABLE IF NOT EXISTS `tbl_aclroles` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`roleorder` int(11) NOT NULL,
PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT;

INSERT INTO `tbl_aclroles` (`id`, `name`, `roleorder`) VALUES
(1, 'Admin', 1),
(2, 'User', 2),
(3, 'Guest', 3);

CREATE TABLE IF NOT EXISTS `tbl_users` (
`userid` int(11) NOT NULL auto_increment,
`user` longtext NOT NULL,
`pass` longtext NOT NULL,
`firstname` longtext NOT NULL,
`prefix` longtext NOT NULL,
`lastname` longtext NOT NULL,
`gender` enum('m','f') NOT NULL,
`roleid` int(11) NOT NULL,
`mail` longtext NOT NULL,
PRIMARY KEY  (`userid`)
) ENGINE=MyISAM DEFAULT;

Thứ Năm, 14 tháng 10, 2010

Cài đặt hệ thống tự động gửi tin nhắn qua IRC

Dựa trên một ý tưởng từ last.fm trong việc quản lý dự án .

Ý tưởng có thể tóm tắt như sau :

Các dev của một dự án sẽ tham gia vào một kênh IRC chat http://vi.wikipedia.org/wiki/IRC

Qua kênh này trong đổi các vấn đề liên quan đến quá trình dev và test của dự án .

Khi sử dụng svn , mỗi khi một thành viên thay đổi code , và commit lên thì có một con irc bot sẽ tự động gửi các thông báo liên quan đến sự thay đổi này vào kênh IRC chat để team có thể nhanh chóng cập nhật .

Với cách làm này team có thể kết nối với nhau tốt hơn .

1. Cài IRC server .

trên ubuntu 10.10 ( các bản cũ hơn mình chưa test )

Với các dự án open , thì các bạn có thể dùng một public IRC server (và bỏ qua bước này ).
sudo apt-get install  ircd-hybrid

2.Cài đặt irccat
wget http://static.last.fm/rj/irccat.tar.bz2

tar -xvf  irccat.tar.bz2

cd irccat

build

Yêu cầu phài cài đặt sẵn java và ant nhé ( build mà ).

chạy .

sh irccat.sh

sửa lại svn để hook các update mới nhất

sửa file /svn/ten_du_an/hook/post-commit

để bắt thời điểm dev commit , thì irccat tự gửi vào kênh
REPOS="$1"
REV="$2"

#"$REPOS"/hooks/mailer.py commit "$REPOS" $REV "$REPOS"/mailer.conf
LOG=`/usr/bin/svnlook log -r $REV $REPOS`
AUTHOR=`/usr/bin/svnlook author -r $REV $REPOS`
echo "SVN commit by $AUTHOR (r$REV) '$LOG' http://183.91.2.104/trac/bantin.com/changeset/$REV" | netcat -q0 localhost 9999

Cài đặt Apache+Trac+Svn trên ubuntu

Cài đặt Apache+Trac+Svn trên ubuntu

Bản ubuntu mình dùng là 10.10

1. Cài đặt các module cần thiết , bao gồm cả apache bằng apt-get.
sudo apt-get install apache2 libapache2-mod-python libapache2-svn python-setuptools subversion python-subversion

2.

Dùng easy_install của python để cài trac
sudo easy_install http://ftp.edgewall.com/pub/trac/Trac-0.12.tar.gz

Ở  thời điểm này thì bản 0.12 là bản stable .

3. Tạo các thư mục , cấu hình , add user :

sudo mkdir /svn
sudo mkdir /trac
sudo htpasswd -cm /etc/svnauth yourusername
sudo htpasswd -m /etc/svnauth nextusername


+Tạo file /etc/svnaccess
sudo vim /etc/svnaccess

các bạn dùng vi vim nano gì cũng được , localhost thì dùng gedit cũng chả sao .

Nội dung của nó kiểu thế này .
[groups]
developers = yourusername, nextusername
[ / ]
@developers = rw
* = r

mục đích là tạo group và gán quyền
developer thì đọc và ghi
còn * thì chỉ có thể đọc .

+ cấu hình apache
sudo vim /etc/apache2/sites-available/default

thêm vào

   


<Location /svn>

DAV svn
SVNParentPath /svn

AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/svnauth
Require valid-user

AuthzSVNAccessFile /etc/svnaccess
</Location>

<Location /trac>

SetHandler mod_python
PythonHandler trac.web.modpython_frontend
PythonOption TracEnvParentDir /trac
PythonOption TracUriRoot /trac

AuthType Basic
AuthName "Trac"
AuthUserFile /etc/svnauth
Require valid-user

</Location>


Nhớ là trong thẻ nhé .

tạo file trac.ini trong /etc/ nội dung :

/etc/trac.ini
[header_logo]
alt = Logo
height = -1
link =
src = /logo.gif
width = -1

Cái file logo là 1 file bất kỳ để làm logo hiển thị phía trên tay trái cảu trac . cái này cũng không cần thiết lắm .
Nhưng muốn đệp thì phải làm :D .

Viết script để add project mới cho nhanh
#!/usr/bin/perl
$sName = $ARGV[0];
$lName = $ARGV[1];
if ($lName eq "") {
$lName = $sName;
}
$sName =~ tr/A-Z/a-z/;
$path = "sudo svnadmin create /svn/$sName";
system ($path);
$path = "sudo chown -R www-data /svn/$sName";
system ($path);
$path = "sudo trac-admin /trac/$sName initenv '$lName' 'sqlite:db/trac.db' 'svn' '/svn/$sName' --inherit=/etc/trac.ini";
system ($path);
$path = "sudo chown -R www-data /trac/$sName";
system ($path);
$path = "sudo trac-admin /trac/$sName permission add yourusername TRAC_ADMIN permission list yourusername";
system ($path);
print "Done!\n\n";

script này các bạn có thể để thẳng vào /trac
đặt tên là create.pl

chạy

perl /trac/create.pl "ProjectName" "ProjectDESC"

nhớ thay các tham số nhé .

truy cập vào dự án :
- trac : http://localhost/trac/ProjectName
- svn : http://localhost/svn/ProjectName

Done .

Thứ Ba, 28 tháng 9, 2010

Anonymous Inner Class in Java

Hôm nay, mình vừa thi đề về java, làm 1 câu về Anonymous Inner Class, làm bị sai toét tòe toe :D.
Sau khi tìm hiểu, mình xin trình bày lại, hi vọng giúp được một số bạn quan tâm đến Anonymous Inner Class, và cũng để mình note lại luôn :D(xem lại khi đã quên :P)

1. Định nghĩa về Anonymous Inner Class:
- Là một class không có tên, được định nghĩa trong 1 method của 1 class xác định. Nó chỉ được dùng 1 lần tại nơi mà nó đã được định nghĩa ra.

Nghe có vẻ hơi trừu tượng nhỉ:D Để mình làm ví dụ nhé :


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

// Outer.java
public class Abstract3 extends JFrame{

JButton btnHello = new JButton("aaaaaaaaaaa");

public Abstract3()
{

this.add (btnHello);

this.btnHello.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("bogay xao");

}
});
this.setSize(100,100);
this.setVisible(true);
}

public static void main(String args[])
{
Abstract3 abs3 = new Abstract3();

}
}

Thứ Hai, 27 tháng 9, 2010

Anonymous Inner Class in Java

Hôm nay, mình vừa thi đề về java, có 1 câu về Anonymous Inner Class, làm bị sai toét tòe toe :D.
Sau khi tìm hiểu, mình xin trình bày lại, hi vọng giúp được một số bạn quan tâm đến Anonymous Inner Class, và cũng để mình note lại luôn :D(xem lại khi đã quên :P)

1. Định nghĩa về Anonymous Inner Class:
- Là một class không có tên, được định nghĩa trong 1 method của 1 class xác định. Nó chỉ được dùng 1 lần tại nơi mà nó đã được định nghĩa ra.


Nghe có vẻ hơi trừu tượng nhỉ:D Để mình làm ví dụ nhé :


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

// Outer.java
public class Abstract3 extends JFrame{

JButton btnHello = new JButton("aaaaaaaaaaa");

public Abstract3()
{

this.add (btnHello);

this.btnHello.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("Hi! bogay");

}
});
this.setSize(100,100);
this.setVisible(true);
}

public static void main(String args[])
{
Abstract3 abs3 = new Abstract3();

}
}



Ở đây, khi tớ bắt sự kiện cho nút, tớ dùng interface ActionListener, nhưng tớ không implements trực tiếp, mà tớ gián tiếp sử dụng nó và override lại phương thức ActionPerformed tại method AddActionListener.

Sau khi bạn chạy xong, bạn vào thư mục chứa class này, bạn sẽ thấy nó sinh ra một class khác(chỉ sinh ra sau khi đã run), có tên là : Abstract3$1.java .
Đây chính là Anonymous Innner Class :D

Còn cách viết thông thường :


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

// Outer.java
public class Abstract3 extends JFrame implements ActionListener{

JButton btnHello = new JButton("aaaaaaaaaaa");
public void actionPerformed(ActionEvent arg0) {
System.out.println("Hi ! bogay");

}
public Abstract3()
{

this.add (btnHello);
this.setSize(100,100);
this.btnHello.addActionListener(this);
this.setVisible(true);
}

public static void main(String args[])
{
Abstract3 abs3 = new Abstract3();

}
}



Trong cách này, thì tớ implements ActionListener theo cách thông thường, sau đó tớ overide lại phương thức ActionPerformed.

Tổng kết lại nhé :

1. Tác dụng : như nhau, không có sự khác biệt

2. Độ sướng : cách code anonymous ngắn gọn hơn, pro hơn :D

Thứ Năm, 5 tháng 8, 2010

problem with width of 'ul' when 'ul' float left and 'li' float right


<html>
<head>
<style>
#ex {
width: 700px;
background: red;
float: left;
}
a, span {
display: block;
}
ul, li {
margin: 0;
padding: 0;
}
.ex_1 {
float: left;
background: yellow;
list-style: none;
}
.ex_2 {
float: right;
}
</style>
</head>

<body>
<div id="ex">
<ul class="ex_1">
<li class="ex_2"><a href="#"><span>example 1</span></a></li>
<li class="ex_2"><a href="#"><span>example 2 - </span></a></li>
<li class="ex_2"><a href="#"><span>example 3 - </span></a></li>
<li class="ex_2"><a href="#"><span>example 4 - </span></a></li>
</ul>
</div>
</body>
</html>

IN IE7 when 'ul' float: left and 'li' float:left, the width of 'ul' is ok. but when 'ul' float:left and 'li' float: right, the width of 'ul' is 100%(the background yellow). What should i do to make the width of ul when 'li' float:right is look like 'li' float:left. i can't set width of ul because it's must depends on 'li'. width of 'ul' = total width of 'li'.

because both <a>  and <span>  are default display:block, so i can't set display:inline for <li>.

NOTE : only use CSS, not JAVASCRIPT.

Please help me !!!


Chủ Nhật, 11 tháng 7, 2010

Senior programmer, anh là ai?



Senior programmer/developer hay gọi là lập trình viên cao cấp được cho là người có khả năng, nhiều kinh nghiệm, có những đóng góp nhất định cho các công ty họ làm việc và cho xã hội. Đi kèm với sự công nhận đó, họ sẽ được hưởng những mức đãi ngộ tốt hơn, vị trí cao và công việc nhiều thách thức, sáng tạo hơn so với những người mới.

Nếu các bạn có từ 4 thứ dưới đây trở lên, bạn có thể coi mình là senior programmer :)

  1. Biết nhiều hơn một ngôn ngữ lập trình. Cái này sẽ mở ra nhiều hướng tư duy mới cho bạn.

  2. Thường xuyên code ngoài giờ. Đó có thể là sản phẩm của riêng bạn, những đoạn mã nguồn mở cho phần mềm miễn phí hay sửa lỗi nhỏ, trả lời các thắc mắc của cộng đồng trên diễn đàn hay làm freelancer :D

  3. Thường xuyên đổi mới. Giống như tìm nhiều cách khác nhau để giải quyết vấn đề, cách sau tối ưu hơn cách trước, nôm na là code càng ngày càng ít ... ngu :D (ngắn gọn, bớt rườm ra, đẹp, hiệu quả...)

  4. Tham gia xây dựng phần mềm từ khâu ý tưởng, thiết kế, viết mã, triển khai và hỗ trợ. Có nghĩa là, bạn kinh qua hầu hết các bước phát triển phần mềm. Nó cũng sẽ yêu cầu bạn phải quen thuộc với nhiều tư duy, kỹ thuật thiết kế và làm việc nhóm.

  5. Viết những phần mềm hữu ích. Đơn giản hơn, phần mềm/sản phẩm bạn làm ra giúp giải quyết một vấn đề thực tế trong cuộc sống, như bán hàng hay quản lý sản phẩm chẳng hạn.


------

Câu hỏi là: thành senior programmer rổi thì sao?

Trả lời: tức là giá trị & khả năng của bạn đã được công nhận, ít nhất là công ty chủ quản. Duy trì công việc đó thì bạn sẽ đảm bảo được một mức sống trung lưu. Từ đây, phấn đấu đạt mức cuối cùng là principle programmer/developer, tức là ngang hàng chuyên gia rồi đó.

Nếu thành công theo hướng này, con đường sự nghiệp của bạn sẽ là

the career path of software engineer




-----

Nếu nhìn sang hướng quản lý, senior dev ngang cấp với junior project manager, priciple dev ngang cấp với principle project manager và technical director tương đương deliverable manager/program manager. Như vậy có nghĩa là gì? nghĩa là nếu bạn thực sự là senior programmer thì mức lương của bạn sẽ tương đương với một project manager. Dĩ nhiên, đặc thù công việc khác nhau, càng lên cao thì sự khác nhau càng phân hóa rõ rệt nhưng lương vẫn tăng cùng mức :P

-----

Có chút động viên là: tại thị trường Việt Nam lúc này, nếu bạn được công nhận là senior programmer, sẽ có nhiều công ty mời bạn vào làm việc với mức đãi ngộ không tồi :)

Chúc may mắn :)

Thứ Hai, 28 tháng 6, 2010

Thứ Sáu, 25 tháng 6, 2010

Struts 2 helloWorld

:D Bài viết là tổng hợp những gì đã đọc, thấy hay post lại, nên nhiều chỗ chưa dịch :D

I. Struts:

Trước tiên nhắc lại JSP và Servlet:

Một servlet là một chương trình viết bằng java chạy trên máy ảo Java (JVM) ở phía máy chủ (Web Server). các Servlet nhận và phản hồi từ Web client, thường thường sử dụng giao thức HTTP- Hyper Text Transfer Protocol. Để hiển thị một trang web với định dạng html, nếu chỉ dùng Servlet thì sẽ phải println() các mã html về client.

Khi có một request đến, servlet container sẽ kiểm tra xem có servlet nào đã đăng ký cho request đó chưa. Nếu có, request sẽ chuyển tới servlet. Nếu không, request sẽ trả về HTTP server.

Filter nằm ở giữa client và servlet. Request gửi lên và response trả về sẽ phải đi qua filter . Tương tự như một servlet phụ, filter không thực thi một chức năng điều khiển riêng biệt, mà nó chỉ cùng tham gia vào quá trình xử lý các request.

Công nghệ JSP là một phần mở rộng của công nghệ Java Servlet. Tập tin .jsp có cấu trúc giống như tập tin .html truyền thống, nhưng khác ở chỗ là tập tin .jsp có xen lẫn mã Java. Mã Java được tách biệt với phần HTML thông thường bằng cặp dấu <% và %>. Trang JSP khi chạy, mã Java sẽ được được tách ra khỏi nội dung bình thường của trang JSP biên dịch thành Java Servlet . Kết quả xử lý của Servlet được thay vào chỗ biểu thức JSP trong trang Web ban đầu. Trang Web mà trình duyệt nhận được là trang HTML thuần túy.

Struts:
Nếu tất cả mọi thứ đều gói gọi trong servlet hoặc JSP thì sẽ không phù hợp cho việc phát triển các ứng dụng quy mô lớn do:
- Do các tính năng bị lặp lại -> code lặp lại
- Code mỗi người có một phong cách riêng, không biết đâu mà lần...
...
--> MVC (Model-View-Control) giải quyết các vấn đề trên do có sự phân tách rõ ràng trong ứng dụng.
Struts là một framework sử dụng mẫu thiết kế MVC, nó có các thư viện tiện ích để làm cho việc phát triển MVC được nhanh hơn và dễ dàng hơn.
Struts2 có nhiều tính năng nổi trội hơn Struts1 (nghe nói vậy :D)
MVC thể hiện trong Struts như thế nào?
View component: presentation logic. Ví dụ như các trang jsp hay html đơn giản....
Model component: business logic và data. Các model component cung cấp một giao diện với dữ liệu và/hoặc các dịch vụ được sử dụng bởi ứng dụng. Theo cách này, các controller component không cần phải chứa code để thao tác với dữ liệu của ứng dụng. Thay vào đó, chúng giao tiếp với các model component để thực hiện truy cập và thao tác dữ liệu. Các model component có thể ở nhiều dạng từ các Java bean đến các EJB hay các Web service.
Controller component: Struts 2 sử dụng filter làm nền tảng cho controller, thay vì dùng servlet. Chúng  nằm trong gói thư viện struts2-core. Controller quản lý sự tương tác giữa Model và View.

II. Struts 2 HelloWorld

HelloWorld exaple:
Vào nguồn link sau để xem hướng dẫn dầy đủ, download source + lib:  http://www.vaannila.com/struts-2/struts-2-example/struts-2-hello-world-example-1.html

Ngó qua ví dụ:

Người dùng ở trang index.jsp, nhập username, nhấn submit, sẽ chuyển đến trang success.jsp hiện ra dòng  "Hello [username]".

Để làm ví dụ trên, phải có 3 thứ:

  1. Có một trang để hiện message

  2. Tạo Action class để sinh message

  3. Mapping giữa action và message page.


1. Trang hiển thị message: success.jsp


<%@taglib uri="/struts-tags" prefix="s" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello World</title>
</head>
<body>
<h1><s:property value="message" /></h1>
</body>
</html>


2. Action class sinh message: HelloWorld.java
package vaannila;

public class HelloWorld {
private String message;

private String userName;

public HelloWorld() {
}

public String execute() {
setMessage("Hello " + getUserName());
return "SUCCESS";
}
.......
// các hàm get, set cho các thuộc tính message, userName
.......
}

3. Mapping giữa action và message page.
<struts>
<package name="test" extends="struts-default">
<action name="HelloWorld">
<result name="SUCCESS">/success.jsp</result>
</action>
</package>
</struts>

Sau khi nhập username và submit từ trang "/index.jsp" , sẽ gửi request đến URL "/HellWorld.action" và message "Hello [username]" hiện ra.

Code trên hoạt động thế nào?

(Trích nguyên văn trong bài hướng dẫn, mọi người tự dịch :D)

  1. The container receives from the web server a request for the resource HelloWorld.action. According to the settings loaded from the web.xml, the container finds that all requests are being routed to org.apache.struts2.dispatcher.FilterDispatcher, including the *.action requests. The FilterDispatcher is the entry point into the framework.

  2. The framework looks for an action mapping named "HelloWorld", and it finds that this mapping corresponds to the class "HelloWorld". The framework instantiates the Action and calls the Action's execute method.

  3. The execute method sets the message and returns SUCCESS. The framework checks the action mapping to see what page to load if SUCCESS is returned. The framework tells the container to render as the response to the request, the resource HelloWorld.jsp.

  4. As the page HelloWorld.jsp is being processed, the <s:property value="message" /> tag calls the getter getMessage of the HelloWorld Action, and the tag merges into the response the value of the message.

  5. A pure HMTL response is sent back to the browser.


III. Các thành phần config:

Vào đây để xem tài liệu đẩy đủ.

Một web application sử dụng deployment descriptor để khởi tạo các  resources như servlets, taglibs. Deployment descriptor có dạng xml được đặt tên là "web.xml".

Cũng như vậy, framework struts sử dụng file config để khởi tạo các resources của nó. bao gồm:

  • Interceptors that can preprocess and postprocess a request

  • Action classes that can call business logic and data access code

  • Results that can prepare views, like JavaServer Pages and FreeMarker templates


Trước lúc runtime, configuration được định nghĩa từ 1 hoặc nhiều XML document, bao gồm cả struts.xml. Khi runtime sẽ có một configuration duy nhất cho một application. Có nhiểu element được configure bao gồm packages, namespaces, includes, actions, results, interceptors, and exceptions.

1. web.xml

Trong ví dụ HelloWorld trên:



web.xml :
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher </filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Filter và filter-mapping dùng để  setup filter. Ở đây dùng FilterDispatcher. Ở đây filter được map tới URL pattern "/*" . Có nghĩa tất cả các request tới Struts 2 action sẽ được xử lý bởi FilterDispatcher class.


2. struts.xml

Trong ví dụ HelloWorld trên:


struts.xml :
<struts>
<package name="test" extends="struts-default">
<action name="HelloWorld">
<result name="SUCCESS">/success.jsp</result>
</action>
</package>
</struts>


a. Administrative Elements

Bean Configuration:



<struts>
<bean type="com.opensymphony.xwork2.ObjectFactory" name="myfactory" class="com.company.myapp.MyObjectFactory" />
...
</struts>

Constant Configuration: có thể được khai báo ở nhiều file:


struts.xml



<struts>
<constant name="struts.devMode" value="true" />
...
</struts>

struts.properties



struts.devMode = true

web.xml



<web-app id="WebApp_9" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>struts.devMode</param-name>
<param-value>true</param-value>
</init-param>
</filter>
...
</web-app>

Package Configuration
Namespace Configuration



<package name="default">
<action name="foo" class="mypackage.simpleAction">
<result name="success" type="dispatcher">greeting.jsp</result>
</action>

<action name="bar" class="mypackage.simpleAction">
<result name="success" type="dispatcher">bar1.jsp</result>
</action>
</package>

<package name="mypackage1" namespace="/">
<action name="moo" class="mypackage.simpleAction">
<result name="success" type="dispatcher">moo.jsp</result>
</action>
</package>

<package name="mypackage2" namespace="/barspace">
<action name="bar" class="mypackage.simpleAction">
<result name="success" type="dispatcher">bar2.jsp</result>
</action>
</package>

Namespace are not hierarchical like a file system path. There is one namespace level. For example if the URL /barspace/myspace/bar.action is requested, the framework will first look for namespace /barspace/myspace. If the action does not exist at /barspace/myspace, the search will immediately fall back to the default namespace "".


Include Configuration:



<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<include file="Home.xml"/>
<include file="Hello.xml"/>
<include file="Simple.xml"/>
<include file="/util/POJO.xml"/>
<include file="/com/initech/admin/admin-struts.xml"/>
</struts>


b.Request Handling Elements

Interceptor Configuration:


Interceptors allow you to define code to be executed before and/or after the execution of an Action method. (The "Filter" pattern.) Interceptors can be a powerful tool when developing applications. There are many, many use cases for Interceptors, including validation, property population, security, logging, and profiling.



Registering Interceptors

<interceptors>
<interceptor name="security" class="com.company.security.SecurityInterceptor"/>
<interceptor-stack name="secureStack">
<interceptor-ref name="security"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>

Action Configuration



<package name="Hello" extends="action-default">

<default-action-ref name="UnderConstruction">

<action name="UnderConstruction">
<result>/UnderConstruction.jsp</result>
</action>

...


Wildcard Mappings


"action=Crud_input"
"action=Crud_delete"



<action name="Crud_*" class="example.Crud" method="{1}">

<action name="*">
<result>/{1}.jsp</result>
</action>

Result Configuration:


Most often, results are nested with the action element. But some results apply to multiple actions. In a secure application, a client might try to access a page without being authorized, and many actions may need access to a "logon" result.



<global-results>
<result name="error">/Error.jsp</result>
<result name="invalid.token">/Error.jsp</result>
<result name="login" type="redirectAction">Logon!input</result>
</global-results>


c. Error Handling

Exception Configuration:

Interceptor is needed to activate the exception mapping functionality. Điểu này đã được làm mặc định trong struts-default.xml
<struts>
<package name="default">
...
<global-results>
<result name="login" type="redirect">/Login.action</result>
<result name="Exception">/Exception.jsp</result>
</global-results>

<global-exception-mappings>
<exception-mapping exception="java.sql.SQLException" result="SQLException"/>
<exception-mapping exception="java.lang.Exception" result="Exception"/>
</global-exception-mappings>
...
<action name="DataAccess" class="com.company.DataAccess">
<exception-mapping exception="com.company.SecurityException" result="login"/>
<result name="SQLException" type="chain">SQLExceptionAction</result>
<result>/DataAccess.jsp</result>
</action>
...
</package>
</struts>



By default, the ExceptionMappingInterceptor adds the following values to the Value Stack:











exceptionThe exception object itself
exceptionStackThe value from the stack trace


Sample JSP using Error and Exception Values

<h2>An unexpected error has occurred</h2>
<p>
Please report this error to your system administrator
or appropriate technical support personnel.
Thank you for your cooperation.
</p>
<hr/>
<h3>Error Message</h3>
<s:actionerror/>
<p>
<s:property value="%{exception.message}"/>
</p>
<hr/>
<h3>Technical Details</h3>
<p>
<s:property value="%{exceptionStack}"/>
</p>

III. Tài liệu đã dùng trong bài:

http://www.vaannila.com/struts/struts-tutorial/struts-tutorial.html

http://www.humg.edu.vn/cntt/forum?func=view&id=437&catid=21

http://struts.apache.org/2.0.14/docs/configuration-elements.html

Thứ Ba, 22 tháng 6, 2010

Khám phá những kỹ thuật đằng sau facebook

Một thử thách rất lớn dành cho các kỹ sư tại Facebook là phải giữ cho website hoạt động ổn định, nhẹ nhàng, và nhanh chóng cho nửa tỷ active users. Bài này sẽ điểm qua một số phần mềm, kỹ thuật được sử dụng để đạt được mục tiêu đó.


Các thách thức của Facebook

Các dữ liệu dưới đây cho bạn cái nhìn tổng quan về mức độ ổn định và hoạt động của website

  • Facebook phục vụ 570 tỷ page views mỗi tháng (Google Ad Planner)

  • Số lượng ảnh có trên Facebook lớn hơn tổng số lượng ảnh của tất cả các trang chia sẻ/hosting ảnh khác (bao gồm cả những site như Flickr)

  • Hơn 3 tỷ ảnh được tải lên hàng tháng.

  • Facebook xử lý 1.2 triệu ảnh mỗi giây.

  • Hơn 25 tỷ mẩu tin/status/links/comments được chia sẻ hàng tháng.

  • Facebook có hơn 30,000 servers (năm 2009).


Phần mềm sử dụng



Ở khía cạnh nào đó, ta vẫn có thể coi Facebook là LAMP, nhưng nó đã phải thay đổi, nâng cấp những chức năng, dịch vụ sẵn có ở nhiều mức độ.

Ví dụ:

  • Facebook vẫn sử dụng PHP, nhưng nó đã xây dựng một compiler để có thể chuyển đổi mã nguồn thành native code chạy trên webserver -> tăng hiệu năng.

  • Facebook sử dụng Linux, nhưng đã tối ưu hệ thống cho mục địch sử dụng cụ thể của site (đặc biệt là giao tiếp mạng).

  • Facebook sử dụng MySQL, nhưng phần lớn lưu giữ kiểu key-value, đưa các logic trong câu lệnh join lên web servers sao cho việc tối ưu có thể được thực hiện hiệu quả nhất ở đây.


Tiếp theo đó là một loạt các hệ thống được viết và tích hợp thêm như Haystack, Scribe.

Và bây giờ ta sẽ lượt qua một số phần mềm được sử dụng bởi trang mạng xã hội lớn nhất thế giới hiện nay

Memcached

Memcached là một hệ thống bộ nhớ phân tán mà Facebook đã sử dụng như một caching layer giữa web servers và MySQL server. Facebook đã tối ưu hóa Memcached và các phần liên quan và xây dựng một hệ thống bao gồm hàng ngàn servers với hàng chục terabytes dữ liệu được cached tại mỗi thời điểm. Có thể coi đây là hệ thống Memcached lớn nhất thế giới tại thời điểm này.

HipHop




PHP bản chất là scripting language, như vậy sẽ chậm hơn so với code chạy native trên servers. Một số kỹ sư của Facebook đã dành 18 tháng để xây dựng HipHop nhằm mục đích chuyển đổi PHP sang mã nguồn của C++ , có thể biên dịch để chạy nhằm tăng hiệu năng.

Haystack

Là hệ thống lưu giữ và xử lý ảnh với hiệu năng cao của Facebook.

BigPipe

Cũng là một hệ thống do Facebook phát triển, nhằm phục vụ những trang web động, pagelet như cửa sổ chat, notification. Những pagelets này có thể được lấy & xử lý song song để đảm báo hiệu năng, giảm thiểu những rủi ro hay làm ngắt quãng hoạt động của users.

Cassandra

Là một hệ thống lưu giữ phân tán hoàn hảo, sử dụng những lý thuyết truy xuất của NoSQL.

Scribe

Là hệ thống logging linh hoạt được Facebook sử dụng cho nhiều mục đích khác nhau.

Hadoop and Hive

Mã nguồn mở và có vai trò tiên quyết trong việc xử lý các phép tính với lượng dữ liệu khổng lồ. Facebook sử dụng cho việc phân tích dữ liệu. Ngoài ra, Yahoo & Twitter cũng sử dụng hệ thống này.

Thrift

Facebook sử dụng những ngôn ngữ khác nhau cho từng services của họ. PHP cho front-end, Erlang cho Chat, Java và C++ cũng được sử dụng ở nhiều nơi. Như vậy, Thrift là cross-language platform được phát triển để kết hợp chặt chẽ các ngôn ngữ lập trình lại với nhau, làm cho chúng có thể giao tiếp được.

Varnish

Là hệ thống tăng tốc trong giao thức HTTP, hoạt động giống như load-balancer và cũng có khả năng cache nội dung để giảm tải truy xuất. Varnish được sử dụng rộng rãi trong việc quản lý ảnh, profile và xử lý hàng tỷ requests mỗi ngày.

Những thứ cũng quan trọng khác


Phần trên thì chúng ta đã điểm qua một số software đã giúp Facebook đạt được sử ổn định và hiệu năng cao. Tuy nhiên, quản lý một hệ thống lớn và phức tạp cần nhiều hơn thế. Dưới đây là một số yếu tố khác

Thường xuyên release, nhưng vẫn có độ trễ

Facebook vẫn hàng ngày cập nhật, nâng cấp những tính năng của mình, họ sử dụng hệ thống gọi là Gatekeeper cho phép chạy những phiên bản mã nguồn khác nhau cho những nhóm users khác nhau. Như vậy, những chức năng sẽ được active từ từ trước khi được sử dụng phổ biến.

Quản lý hệ thống rất tốt

Facebook theo dõi, chăm chút hệ thống của họ vô cùng cẩn trọng, đến từng PHP function. Họ sử dụng XHProf cho việc này.

Tạm thời vô hiệu hóa một số chức năng để tăng hiệu năng

Nếu có vấn đề với hiệu năng, Facebook sẽ có những mức độ xử lý khác nhau bao gồm vô hiệu hóa các chức năng ít quan trọng để tăng hiệu năng trong những core features.

Những thông tin khác

Đây có thể coi là thông tin ít được public từ Facebook. Tất nhiên là họ có sử dụng CDN để xử lý static content, hay một trung tâm dữ liệu lớn với nhiều servers.

Ngoài ra, hàng chục phần mềm khác đang được sử dụng mà chúng ta chưa đề cập đến trong bài này.

Facebook ứng dụng mã nguồn mỡ mạnh mẽ

Hầu hết các software đều là mã nguồn mở, từ những software đã tồn tại cho đến những hệ thống do Facebook viết ra. Danh sách các software mã nguồn mở của Facebook có thể tìm ở Facebook's Open Source page

Những thử thách lớn hơn


Facebook vẫn đang phát triển rất nhanh với hơn 100 triệu users mỗi 6 tháng, đội ngũ Facebook cũng ngày càng mở rộng để có thể xử lý những vấn đề đó.

Sự phát triển nhanh cũng đồng nghĩa với việc Facebook phải đối mặt với hàng loạt vấn đề về hiệu năng, bảo mật. Các kỹ sư ở đó hẳn có rất nhiều việc để làm.

Tham khảo

Bài viết gốc bằng tiếng Anh http://royal.pingdom.com/2010/06/18/the-software-behind-facebook

Trang web liệt kê các phần mềm mã mở của Facebook http://facebook.comopensource

Blog của các kỹ sư Facebook http://facebook.com/eblog

Các bài presentation của các kỹ sư Facebook http://www.infoq.com/presentations/Scale-at-Facebook

Thứ Hai, 21 tháng 6, 2010

Social media đang quá 'nóng'


Khó có thể dịch từ “social media” sang tiếng Việt một cách sát nghĩa và rõ ràng nhất, thế nên sự lựa chọn là giữ nguyên thuật ngữ tiếng Anh khi lại dễ hiểu hơn cả.



Cũng theo với xu hướng chung của thế giới, social media đang ngày càng tiêu tốn nhiều giấy báo + thời gian gõ phím + tài nguyên internet ở Việt Nam. Liên tục có những bài viết, những thảo luận trên các báo, diễn đàn

xoay quanh chủ đề này.

Bên cạnh đó là sự ra đời của một loạt các dịch vụ mang tính social hoặc chứa đựng các đặc điểm (ý là features) của social media. Phần lớn các dịch vụ này là học theo những sản phẩm đã thành danh trên làng internet. Nội dung chủ yếu xoay quanh

  • Người dùng đăng nội dung.

  • Chia sẻ.

  • Kết nối với nhau.

  • Gợi ý các thông tin.


Và không thể thiếu các bàn luận về các thuật ngữ (chả biết có đúng là thuật ngữ không nữa) bay bướm như social graphcore values, platform, branding

Nữa là, trong các vấn đề thảo luận thì số lượng người làm sản phẩm tham gia chiếm tỷ lệ áp đảo so với số lượng người dùng sản phẩm. Chất lượng thì miễn bàn nha.

Cùng với nó là sự “ra đi” trong mong đợi của dịch vụ blog Yahoo! 360, kéo theo sự tò mò cũng như nhu cầu chuyển dịch nơi … “tâm sự” của bộ phận lớn người dùng. Một vài trong số đó sẽ thay đổi thói quen blog, có thể họ sẽ thấy các dịch vụ cung cấp của social network thú vị và cuốn hút hơn và dành thời gian (thậm chí là nhiều hơn blog) cho nó. Một vài người khác sẽ phải coi trọng hơn nội dung bài blog của mình, sự phân hóa sẽ hiện hữu dần dần.

Quiz và những game nho nhỏ vui vui trên facebook chiếm một lượng lớn truy cập trong số các bạn ở Việt Nam. Cùng với việc cập nhật những câu status ngắn gọn cộng bình luận là đủ để tạo nên một luồng thảo luận chiếm không ít visits. Lác đác đâu đó có các hội nhóm, cả tạo cho vui lẫn thường xuyên gửi tin nhắn để giữ liên lạc + thông báo. Cũng có các bác chuyên nghiệp sử dụng facebook cho mục đích phát triển cá nhân.



“Content is king” (trích của một ai đó – không nhớ), nội dung bạn chia sẻ đôi khi tạo nên những giá trị rất lớn. Thế nhưng, với đặc điểm là truyền bá + lan tỏa, nội dung đó đôi khi chỉ để giải trí hoặc tham khảo, hãy tìm sự chuyên biệt ở nơi khác. Tuy nhiên, không gì là tuyệt đối.

Các dịch vụ của chúng ta rồi sẽ đi về đâu? Không ai biết. Ít nhất là từ những dịch vụ online đã có được những giá trị offline hữu hình, như những buổi hội thảo chẳng hạn.

Ở chừng mực nào đó, có lẽ cái được nhất của những dịch vụ “social media” ở Việt Nam chính là giá trị nhận thức mà những người tham gia đạt được. Thế nên, chúng ta chờ đợi giai đoạn tiếp theo, khi mà các dịch vụ “social” thực sự mang lại lợi nhuận cho người/tổ chức sở hữu và vận hành nó.

Tự động sinh dữ liệu cho một trường DB

Tự động sinh dữ liệu cho một trường DB


Rất nhiều trường hợp chúng ta cần tự sinh mã , chuỗi cho một số trường khi dữ liệu được insert vào database .

Ví dụ mỗi sinh viên Aptech sẽ có mã kiểu như A000856 , 856 đơn giản là ID của sinh viên , nhưng toàn bộ hệ thống aptech toàn cầu chỉ quản lý thông qua code chứ không phải ID . Chính vì vậy code trên tự sinh ra từ ID là ngon nhất .

Cách làm :

1.Dùng table


CREATE TABLE Aptech_Student
(
sname varchar(15),
ID int identity(1,1),
code AS 'A' + RIGHT('0000'+CAST(ID AS varchar(4)),4)
)
Test:
insert into test (sname) values (1)
--
select *from test
--
sname ID student_ID
1 1 A00001


2.Dùng function

create function CustomerNumber (@id int)
returns char(5)
as
begin
return 'C' + right('0000' + convert(varchar(10), @id), 4)
end
--

Gán hàm trên vào cột:

alter table Customers add CustomerNumber as dbo.CustomerNumber(dbID)

hoặc gán vào trigger

Dùng trigger

alter Customers add CustomerNumber varchar(10)


create trigger Customers_insert
on Customers after insert
as
update Customers
set Customers.customerNumber = dbo.CustomerNumber(Customers.dbID)
from Customers inner join inserted
on Customers.dbID= inserted.dbID

3.Dùng procedure

create procedure prcGenCode
@codeno char(6) OUTPUT
as
select @codeno = Max(Ccodeno) from testtable
select @codeno =
case
when @codeno >=0 and @codeno < 9 then '00000' + convert(char,@codeno + 1) when @codeno >=9 and @codeno < 99 then '0000' + convert(char,@codeno + 1) when @codeno >=99 and @codeno < 999 then '000' + convert(char,@codeno + 1) when @codeno >=999 and @codeno < 9999 then '00' + convert(char,@codeno + 1) when @codeno >=9999 and @codeno < 99999 then '0' + convert(char,@codeno + 1) when @codeno >=99999 then convert(char,@codeno + 1)
end
return


Như vậy có thể thấy cách gen dùng trực tiếp trên bảng văn minh hơn .
Cách làm này dễ nhất , nhưng ít người biết , mà thường sử dụng các giải pháp Trigger , hoặc procedure ..

Thứ Bảy, 19 tháng 6, 2010

Tối ưu hóa website theo chuẩn Yslow part 2

4.Compress components with gzip
Phần này đã được đề cập ở phần 1 :D

Tạo address book đơn giản với photoshop - html / css

Hi mọi người, lâu lắm không vào i-php thấy có nhiều bài viết mới nên hôm nay em cũng "đú đởn" xin phép viết 1 bài :D. Trong bài viết này mình sẽ tạo 1 address book với photoshop và html/css. (Bắt chước theo address book trong hđh MAC - có chỉnh sửa đôi chút).
Đầu tiên là với photoshop :
Bước 1 : Tạo một file mới


Bước 2 : Tạo một group mới (Group 1):



Bước 3 : Tạo layer mới trong group đó. Dùng công cụ  Rounded Rectangle Tool , chỉnh độ radius là 10px và vẽ hình như sau. Ấn Ctrl + enter để tạo vùng lựa chọn rồi dùng công cụ Paint Bucket tool và đổ mầu bất kỳ cho nó sau đó ấn Ctrl+D



Chon công cụ Rounded Rectangle Tool



Để radius là 10px



Vẽ hình rồi ấn Ctrl + enter để tạo vùng lựa chọn



chọn công cụ Paint Bucket Tool



Đổ mầu rồi ấn Ctrl + D


Bước 4 : Trỏ phải vào layer đang dùng , chọn Blending option và thiết lập thông số Drop shadow , Gradient Overlay , Stroke như sau :


Drop shadow



Gradient Overlay - Nhấn vào Gradient



Chọn mã mầu như trên



Stroke



Kết quả


Bước 5 : Dùng công cụ Rectangular Marquee Tool, tạo vùng lựa chọn sau đó xóa đi


Rectangular Marquee Tool



Tạo vùng lựa chọn và xóa



Kết quả


Bước 6 : Tạo layer mới, dùng công cụ Rounded Rectangle Tool, để radius là 20px và vẽ hình, đổ mầu cho hình là mầu trắng, sau đó chọn blending options rồi thiết lập thông số như sau :


Vẽ hình và đổ mầu trắng



Thiết lập thông số Inner Shadow



Thiết lập thông số Stroke



Kết quả



Tìm 1 icon sau đó đưa vào trong hình, viết chữ ‘Address Book’.


Bước 7 : Tạo Group mới (Group 2), tạo layer mới trong đó, Dùng công cụ Rounded Rectangle Tool và vẽ hình. Làm theo từ bước 3 đến bước 5 ta được hình mới.


Rounded Rectangle Tool và vẽ hình + thiết lập thông số



Kết quả


Bước 8 : Tạo layer mới. Dùng công cụ Pencil Tool , chọn mã mầu là : #6f6464 , giữ Shift và kẻ một vài đường thẳng. Sau đó viết chữ ‘Group’ và ‘Name’ :


Chọn công cụ Pencil Tool



Giữ shift và kẻ đường thẳng + viết chữ


Bước 9 : Tạo Group mới nẳm trong Group 2 và đặt tên là left. Tạo layer mới trong đó. dùng công cụ Rectangular Marquee Tool tạo vùng lựa chọn sau đó đổ mầu với mã mầu là : #ffffff


Dùng Rectangular Marquee Tool tạo vùng lựa chọn + đổ mầu


Bước 10 : Dùng công cụ Rounded Rectangle Tool vẽ hình sau đó đổ mầu với mã mầu : #adadad rồi dùng công cụ Rectangular Marquee Tool tạo vùng lựa chọn rồi xóa đi phần thừa.



Vẽ hình rồi xóa đi phần thừa


Bước 11 : Thêm chữ, dùng công cụ Pencial Tool kẻ đường thẳng và chèn thêm một số Icon vào.
Thêm chữ + kẻ đường thẳng + chèn icon


Thêm chữ + kẻ đường thẳng + chèn icon


Bước 12 : Tạo Group mới ngang hàng với Group left , đặt tên là center. và làm như bước 8 + 10


Kết quả


Làm tương tự như vậy :




Tiếp đến là HTML / CSS


Chia làm 3 phần chính :


header



main



footer


Trong từng phần các bạn chia thẻ div tùy theo ý thích để tạo định dạng cho trang web. Đây là cách của mình :




	Address Book






























Mobile :



0912.345.678






Home :



0912.345.678






Office :



0912.345.678






Other :



0912.345.678






Fax :



0912.345.678






Address :



262 Nguyen Huy Tuong - Thanh Xuan - HN






Company :



BITJSC - 262 Nguyen Huy Tuong - Thanh Xuan - HN








Yahoo :



thuynguyen






Skype :



thuy.nguyen






Email :



thuy.nguyen@gmail.com






Website :



www.i-php.net






Follow me on :



























Note :





Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elementum accumsan mi. Maecenas id dui a magna tempor pretium. Quisque id enim. Proin id tortor. Curabitur sit amet enim vitae quam pharetra imperdiet. Nulla diam ante, pellentesque eu, vestibulum non, adipiscing nec, eros. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis a nunc. Donec non dui a velit pulvinar gravida. Nunc rutrum libero vel tortor. Duis sed mi eu metus tincidunt ullamcorper. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In purus lorem, aliquam ac, congue ac, vestibulum quis, felis. Aliquam non sapien.











Name






































































































































Chạy file .html sẽ hiển thị ra như sau

Css chung :
body {
font-family:arial;
color:#6f6464;
}

.page {
background:white;
margin:auto;
width:1167px;
}

hr {
margin:10px 0 10px 0;
padding:0;
color:#d2d2d2;
}

h3 {
color:#457EDA;
}

.clear {
clear:both;
}

Style css cho các class phần header :
.header {
background:url('img/header.png') no-repeat;
height:79px;
clear:both;
}

.space {
height:30px;
}

.address_search {

}

.address_search span {
margin-left:500px;
font-size:22px;
}

.search {
float:right;
margin-right:15px;
width:220px;
height:26px;
background:url('img/search.png') no-repeat;
position:relative;
}

.search input {
position:absolute;
width:160px;
left:45px;
top:5px;
border:none;
}


kết quả

Phần main mình chia làm 4 phần : left - center - right - config
Style css (class : main - left - center - right) :
.main {
background:url('img/background_main.png') repeat-y;
}

.left {
float:left;
width:240px;
border-right:solid 1px #d2d2d2;
position:relative;
}

.right {
float:right;
width:539px;
position:relative;
}

.center {
background:#d2d2d2;
min-width:250px;
padding:0;
width:auto;
margin:0 541px 0 241px;
border-right:solid 1px #d2d2d2;
position:relative;
}


kết quả


Css cho các class trong phần left :
.title {
border-bottom:solid 1px #d2d2d2;
width:100%;
padding:2px 0 2px 0;
text-align:center;
}

.group {
margin:30px 0 0 30px;
text-transform:uppercase;
}

.group_name {
margin-top:10px;
padding:10px 0 10px 5px;
}

.group_name a {
color:#6f6464;
text-decoration:none;
}

.group_name:Hover {
background:url(img/group_name_hover.png) no-repeat;
}

.group_name:Hover a{
color:#f0f7f6;
}


Kết quả


Css cho các class trong phần center :
.contentfloat {
float:left;
width:100%;
}

.contentdetail {
background:#ebeaeb;
}

.list_name {
width:100%;
color:#457eda;
font-size:12px;
}

.name_item {
margin-bottom:15px;
}

.name_item:Hover {
background:#78bbda;
color:#f0f7f6;
}

.user_image {
float:left;
margin-left:10px;
width:20%;
}

.user_image img {
width:55px;
height:55px;
}

.user_common {
margin-bottom:3px;
}

.button {
float:right;
margin-left:5px;
}

.button img {
width:15px;
border:none;
}

.name_selected {
background:#667ed8;
color:#f0f7f6;
}


Kết quả


Css cho các class trong phần right :
.allinfo {
width:90%;
margin:5%;
font-size:13px;
}

.group_selected {
background:url(img/group_name_hover.png) no-repeat;
}

.group .group_selected a {
color:#f0f7f6;
}

.social {
float:left;
margin-left:18px;
text-align:center;
}

.social_image img {
border:none;
}

.social_name {
margin-top:3px;
color:#457EDA;
}

.float_left_common {
float:left;
width:20%;
font-weight:bold;
margin-right:15px;
text-align:right;
}

.float_right_common {
float:left;
width:75%;
}

.user_image_big {
float:left;
}

.user_image_big img {
width:100px;
}

.user_info {
float:left;
margin-left:10px;
width:70%;
}


Kết quả


Css cho các class trong phần config + footer
.config {
text-align:right;
}

.float_right {
float:right;
margin-left:10px;
}

.float_right img {
border:none;
}

.config .left {
border:none;
}

.config_common {
width:90%;
margin:auto;
text-align:right;
border-top:solid 1px gray;
padding:5px 0 3px 0;
}

/**************** footer ****************/
.footer {
background:url('img/footer.png') no-repeat;
height:44px;
}


Do máy mình không có IE nên mình không test được CSS. Nếu có bị vỡ thì sửa hộ mình nhé :D

DOWNLOAD file psd & ảnh dùng cho css

DOWNLOAD SOURCE