2008年8月21日 星期四

JAVA --- Statement與PreparedStatement的差別

首先先分別展示Statement與PrepareStatement兩者用法上的差異.
Statement:
...
String strsql = "insert into mytable(Name, Birthday) values("SHAGIN45","1984/06/07")";
Statement mysta = new Statement();
mysta.executeUpdate(strsql);
...

PreparedStatement:
...
String strsql = "insert into mytable(Name, Birthday) values(?,?)";
PreparedStatement mysta = new PrepareStatement();
mysta.setString(1,"SHAGIN45");
mysta.setString(2,"1984/06/07");
mysta.executeUpdate();

從上面兩個例子,可以很明顯的看出兩者使用上的不同,當你所執行sql不需要設定參數時,你就可以使用Statement.反之,若是你需要自行在適當的時機,設定相對應的參數時,則可以使用PrepareStatement (而且PrepareStatement的sql語法使用上閱讀性比較好).

在網路上有許多人在討論PrepareStatement跟Statement兩者間的效能差異,PreparedStatement在Oracle上的表現比Statement來的好(在MySQL上似乎就看不出兩者的性能優劣),並且當要重複執行同一sql多次時,PreparedStatement也會表現的比Statement來的好.但是,由於PreparedStatement的sql是可以自行設定參數型態,因此當sql要被傳至DB執行時,其還需進行編碼轉換,而Statement只需對已經寫死的sql進行字串轉換,所以以單純的查詢動作來說,Statement的表現可能還會比PreparedStatement表現來的好. 總歸一句,除了看你使用PreparedStatement或是Statement會影響DB的存取效能外,你所使用的JDBC Deiver與SQL語法也都會影響,因此遇到需要重複執行sql或是要自訂參數時,我建議使用PreparedStatement;只需要對DB進行簡單的查詢時,我則建議使用Statement!

reference:
http://ivanl.javaeye.com/blog/49129
http://www.javaeye.com/topic/5631

End~

2008年8月12日 星期二

JAVA --- 連接DataBase

我這次使用MySQL來建立我的DB,在設定好DB的table以及其內容後,接下來就是要讓自己的程式與其相連接嚕~.在JDBC連結DB的時候有幾個動作要做:

註冊驅動程式--->建立連線--->產生Statement--->利用Statement執行sql要求--->得到結果.

Step1. 首先就是註冊MySQL的Driver. 你必須先去MySQL的官網下載其驅動程式 http://dev.mysql.com/downloads/connector/j/5.0.html ,下載下來後解壓縮,並且把解壓縮後的資料夾內,一個名為 "mysql-connector-java-[version]-bin.jar" 的檔案複製到C:\Program Files\Java\jre[version]\lib\ext 內 (要注意一下自己的jre版本,java下可能會有不同版本的jre,要把mysql-connector-java-[version]-bin.jar複製到正確的jre內),接著再重新啟動eclipse,其會自動將MySQL的驅動載入.

Step2. 接著就是要在程式上動手腳了.首先要利用Class.forName()來對DriverManager註冊Driver,例如:
String JD = "com.mysql.jdbc.Driver";
Class.forName(JD);
其主要的作用是讓JVM查找指定的class,並且執行class內某段static程式碼,例如:
static {
DriverManager.registerDriver(Driver driver) ;
}
若是找不到指定的資料庫驅動程式類別,則會丟出java.lang.ClassNotFoundException !!

Step3. 產生Connection object. 利用DriverManager.getConnection()來決定你要連結的資料庫,以及要以什麼身分登入,例如:
try{
String DU = "jdbc:mysql://localhost/brick"; //使用jdbc協定,子協定為mysql,資料庫名稱為//localhost/brick
Connection connection = DriverManager.getConnection(DU,"root", "123");
} catch (ClassNotFoundException e){
System.out.println ("系統找不到connection class!");
}catch(SQLException sqlException){
sqlException.printStackTrace();
System.exit(1);
}
若是DriverManager無法連接到資料庫,getConnection()則會丟出java.sql.SQLException!!

Step4. 利用Statement執行SQL語法. 可以用connection.createStatement()來產生statement object,例如:
Statement statement = connection.createStatement();
產生出來後使用statement使用executeUpdate(),executeQuery()等方法來執行sql語法,並且它們會回傳ResultSet object,例如:
String sql = "select * from tbCusinfo";
ResultSet rs = atement.executeQuery(sql);
另外,executeUpdate()主要是用來執行CREATE TABLE、INSERT、DROP TABLE、ALTER TABLE等會改變資料庫內容的sql語法.

Step5. 利用ResultSetMetaData取得ResultSet object中關於欄位 (Field) 的資訊.例如:
ResultSetMetaData metaData = resultSet.getMetaData();
int noofcolumns = metaData.getColumnCount(); //取得欄位個數

上述主要幾個步驟就是JDBC連接DB時幾個主要的步驟,若是後續還有需要對DB取出的data進行使用的話,則可利用metaData.getXXX()的方式做處理.

reference
http://caterpillar.onlyfun.net/Gossip/JavaGossip-V2/StatementResultSet.htm
http://dslab.ee.ncku.edu.tw/~lok/notes/java/jdbc/jdbc.htm

End~

2008年8月10日 星期日

My SQL---Error message 1366

今天試用MySQL來建立資料庫.安裝好後建立了一個測試資料庫,但是要新增資料的時候卻失敗了,顯示Error message-1366,我上網找了一下有沒有解決的辦法,發現原來是default-character-set設定的問題,在安裝好MySQL後,系統會預設使用default-character-set=latin1,所以當你的資料有中文,日文,韓文...等等語言時,它會無法encode~因此以下為解決此錯誤的方法:

Step1. 先停止MySQL的service. (可以去官網下載其所提供的tools,這些tools可以提供GUI對DB進行管理或監測).

Step2. 找出MySQL安裝目錄下的一個檔案,名為"my.ini".

Step3. 開啟此檔,並且在[mysqld]下加入default-character-set=GBK,並把本來的efault-character-set=latin1註解掉.

Step4. 重新啟動MySQL的service,並且把原先的DB刪掉,重新再建立一個DB~這樣就OK拉!!

Referce
MySQL官網下載:
http://dev.mysql.com/downloads/
MySQL GUI Tools 下載:
http://dev.mysql.com/downloads/gui-tools/5.0.html

End~

2008年7月30日 星期三

JAVA Swing---讓Frame顯示於螢幕中央

要讓Frame顯示於螢幕中央有兩種方式:
Case1.
import java.awt.*;

JFrame f = new JFrame();
Dimension dim = Toolkit().getDefaultToolkit().getScreenSize();
f.setLocation(dim.width/2-f.getWidth()/2, dim.height/2-f.getHeight()/2);

Case2.
import java.awt.*;

JFrame f = new JFrame();
f.setLocationRelativeTo(null);

reference: http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Window.html#setLocationRelativeTo%28java.awt.Component%29

2008年6月23日 星期一

NS2---Segment fault

呼...好一陣子沒寫Blog了,這陣子都在忙著跑模擬.之前在跑模擬,會不時的發生Segment fault這種錯誤,後來利用gdb或是valgrind來debug,會發現程式都停在我們沒有動到的地方,例如: getcid, getBasic...等等地方.這時不要慌張!!(但是我們被這種問題困擾了好久 囧),若是利用gdb來debug的人,當程式遇到錯誤停下後,可以下"bt"的指令,來找出是誰呼叫到這個function,使其產生錯誤~~;在從發生錯誤的地方往回追朔後,會發現原來是tcl的timer沒設好!!
多次的segment fault中發現,要是你拓普點多的時候,使用NIST預設的timer對於node來說是不夠用的,我們推測由於timer會倒數,當點變多的時候,某個node的timer倒數結束前BS沒能即時去抓相對應的資料,後來node的timer倒數結束後,BS才去抓資料,可是此時node已經因timer倒數結束exprice,這樣BS當然就抓不到東西產生segment fault嚕!!因此當你的拓普node數量很多的時候,在run NS2時又產生segment fault,且錯誤是發生在你沒修到程式的地方,那就可以考慮在tcl 裡面增加某些timer的數值!!!這樣應該可以解決你segment fault的問題 ^^ (至少我是這樣解決了不少segment fault~我有把t6,t17,t44這幾個數值加大!)

End~

2008年6月15日 星期日

建立scripts

在跑模擬的時候,有時都要重覆一些執行過的指令~每次都在輸入許多相同的指令,令人覺得既浪費時間又麻煩~這時最好的方法就是建立一個scripts. 以下就直接用範例說明唄!!

假如每次都重複執行:
mkdir test
rm shagin45/BS.log
ns hnss > l
那就可以把上面這些指令建成一個scripts,步驟如下:

Step 1.
建立任一文字檔. "vim shagin45"
Step 2.
將上述的指令鍵入剛剛所建立的文字檔中,輸入後存檔離開.
Step 3.
改變剛剛的文字檔mod. "chmod 755 shagin45"
Step 4.
以後只要執行shagin45,就會執行其內所寫的指令 "./shagin45"

End~~

2008年6月11日 星期三

NS2---Scheduler: Event UID not valid!

由於在我的論文中會要設計SS滿足某種條件後,啟動send_scan_request(),但是若直接指定SS啟動scanning的動作,那就有非常大的可能產生: "Scheduler: Event UID not valid!",後來上網查了一下,發現是因為有一個timer物件,還沒有被expire,而我又再一次呼叫它的start function!!
知道原因後,我查看看send_scan_request()中有沒有產生新的timer,發現到原來它會產生一個新的t44timer (也就是因為這原因所以發生錯誤), 因此我再自行啟動send_scan_request()前多加了if判斷:
if (t44timer_ && t44timer_->busy()!=0)
t44timer_->stop();

如此一來就可以解決問題了~^^b

End~

2008年6月9日 星期一

即時增加swap

由於NS2在跑模擬時,總是會遇到一些難以理解的錯誤...所以黃老師幫我們跟江清泉老師約在今天碰個面,希望他能為我們解開疑惑或是給個方向,在一個小時多的討論中,雖然沒有得到真正很明確的解決辦法~但是總算知道問題大概出在哪邊,目前最有可能發生錯誤的原因,是Memory被我們衝爆了(囧),所以江老師提供我們一個方法讓風哥可以即時的增加swap,以下為即時增加swap的方法:
Step1. dd if=/dev/zero of=/tmp/swap bs=1G count=20 (本來才2G的swap,打算多增加20G的swap)

Step2. mkswap /tmp/swap

Step3. swapon /tmp/swap

Step4. 若要在下次開機時能自動執行,則須在/etc/fstab加入下面那一行:
/tmp/swap swap swap defaults 0 0

革命尚未成功~同志仍須努力

End~~

2008年6月6日 星期五

NS2---BS佈建數量限制

當我在寫Tcl的時候,每次最多就只能佈建5個BS,但是我最多要佈建14個BS (囧a), 後來我用gdb來debug,發現每次在建到第六個BS時, 其MAC在 getPhy ()->setFrequency (tmp);的時候都會出錯, 後來我用display看了一下tmp~沒想到居然等於零~~~~,突然想到學長之前mac802_16.cc有一些修改的地方,我就開來比對一下,發現原本NIST預設static const int nbFreq = 5; 學長把它增加到static const int nbFreq = 45; 當然相對的學長也把frequencies的數量增加:
static const double frequencies[] = {3.367e+9,3.374e+9,3.381e+9,3.388e+9,3.395e+9,3.402e+9,3.409e+9,3.416e+9,3.423e+9,3.43e+9,3.437e+9,3.444e+9,3.451e+9,3.458e+9,3.465e+9,3.472e+9,3.479e+9, 3.486e+9, 3.493e+9, 3.5e+9, 3.507e+9, 535e+9,3.542e+9,3.549e+9,3.556e+9,3.563e+9,3.57e+9,3.577e+9,3.584e+9,3.591e+9,3.598e+9,3.605e+9,3.612e+9,3.619e+9,3.626e+9,3.633e+9,3.64e+9,3.647e+9,3.654e+9,3.661e+9,3.668e+9,3.675e+9 };

後來我也把數量增加後,在Tcl就可以成功佈建5個BS以上嚕 ^^,所以要是你需要建5個BS以上,記得要修改nbFreq 與 frequencies[].

End~

2008年6月4日 星期三

NS2---Debug tool

在撰寫NS2的過程中,compiler一定會遇到大大小小的錯誤,最令我厭惡的不外乎就是Segmentation fault (core dumped) 與 Floating point exceptionns, 特別是Segmentation fault 這種錯誤,要是不用tool根本很難找出它錯誤的地方. 為了解決這種錯誤, 就要請 "Valgrind" 出馬嚕(之前有試過gdb但是他回報的錯誤訊息太模糊了囧a,有時根本找不出錯誤真正的地方) !! 但是有個缺點~就是利用Valgrind來debug時會很花時間, 事事無完美嚕~只要找得出bug,就是好tool!!

Debug 指令: valgrind --tool=memcheck --leak-check=full --db-attach=yes ns ***.tcl > *** (valgrind 還有其他的option可以參考下列網址).

reference :
http://kaku26.blogspot.com/2008/06/blog-post_2013.html
http://citynight.blogbus.com/logs/11648949.html

End~

2008年5月31日 星期六

Random walk model

我的論文中使用Random walk model, 在參照其官網的步驟編譯時,會產生幾個錯誤,其中有一個錯誤是必須把statistics.cc中,第66行的grid = new (int*) [x_]; 改為grid = new int* [x_]; 其餘的錯誤比較容易理解我就不在此贅述.

Random walk model 官網:
http://www.cs.rice.edu/~santa/research/mobility/

End~

啟動vsftp指令

在Terminal下: "/etc/init.d/vsftpd start" 即可.

referencr: "http://linux.vbird.org/linux_server/0410vsftpd.php"

End~

模擬時產生的錯誤---Classfier::no-slot{} default handler (tcl/lib/ns-lib.tcl)

今天在試跑模擬時,產生了一個error message :
--- Classfier::no-slot{} default handler (tcl/lib/ns-lib.tcl) ---
_o49: no target for slot 4294967295
_o49 type: Classifier/Portcontent dump:
---------- Finished standard no-slot{} default handler ----------
後來我上網查了一下,看到有人也有類似的問題,所幸友網友知道錯誤發生的原因 "http://www.nabble.com/problem:-Classfier::no-slot{}-default-handler-(tcl-lib-ns-lib.tcl)-to5616757.html" ,我看過後再重新檢查我自己的Tcl,發現原來我產生了一個udp(1) 卻在
" $ns connect $udp(1) $null(1)
$ns connect $udp(1) $null(2) "

重複定義了兩次其connect對象, (我想是因為這種原因,所以會發生這種問題吧!), 後來我將重複定義的connect修正後就解決此問題:) ~

End~

2008年5月29日 星期四

透過封包CID取得SS

void xxx(Packet *p)
{
hdr_mac802_16 *wimaxHdr_req = HDR_MAC802_16(req);
gen_mac_header_t header_req = wimaxHdr_req->header;
....
PeerNode *peer;
peer = mac_->getCManager()->get_connection (header_req.cid, false)->getPeerNode(); //透過CID取出此CID的peer object
int index_ = peer->getPeerNode(); //取出peer object的index (mac)
}

2008年5月19日 星期一

vim自動顯示行號與對齊

在Linux中最普遍的文字編輯器就是vim,依下列的步驟就可讓vim會自動顯示行號,或是撰寫文件時每行會自動對齊. 步驟如下:
Step 1.
在家目錄產生.vimrc檔.

Step 2.
撰寫.vimrc內容為:
set nu (自動顯示行號)
set autoindent (自動對齊)
set smartindent (智能對齊)
set incsearch (逐步查詢)

Step 3.
存檔離開.之後每次使用vim,家目錄下的.vimrc就會被讀取.

End~

2008年5月15日 星期四

ㄧ個Terminal開啟多個分頁

在ㄧ般來說,要是針對不同資料夾或是檔案夾,同時進行修改或比對等動作,有可能會要同時開啟多個Terminal來work,但是現在只需開啟一個Terminal,並且下"screen",就可以在同一個Terminal下開啟多個分頁,就不用東開一個新的Terminal,西開一個Terminal了. 在啟動screen前先記得在家目錄產生一個名為".screenrc"的檔案,內容為:
caption always "%{= wk} %{= KY} [%n]%t @ %H %{-} %= %{= KR} %l %{-} %{= KG} %Y-%m-%d %{-} "hardstatus alwayslastline " %-Lw%{= Bw}%n%f %t%{-}%+Lw %= %0c:%s "bindkey ^[z prevbindkey ^[x next.

以下為啟動screen後的一些基本指令 (在下指令之前記得先按Ctrl+a喔~):
1. c: 新增一個新的分頁.
2. exit: 關閉當下分頁.
3. d:離開screen.
4. Alt+z/x: 開啟前一/後ㄧ的分頁.
5. 1~9: 直接切到指定的分頁.
6. Ctrl+a + Ctrl+g: 切換錯誤的提示的方式 (螢幕閃爍<->發出B聲)

若是做事做到一半離開screen,下次要登入screen時,在Terminal下"screen -r",登入screen後,則會延續上次登出時的狀態!!

End~

2008年5月14日 星期三

C#---數字轉國字

由於在仁耀的系統中,需要將阿拉伯數字轉成國字的大寫,因此研究了一下這種功能,後來在網路上發現有高手寫好類似的程式碼 (嘿嘿~當然不客氣的拿來使用嚕,在此謝謝Q_282898034大大的開發嚕^^),以下為Q_282898034大所開發的程式:
using System;using System.Collections.Generic;static class RMB{ private static readonly string DigitText = "零壹貳參肆伍陸柒捌玖"; private static readonly string PositionText = "圓拾佰仟萬億兆京垓秭穰"; private static readonly string OtherText = "分角整負"; private static void GetFractionStack(int num, Stack stack) { int fen, jiao = Math.DivRem(num, 10, out fen); if (fen != 0) { stack.Push(OtherText[0]); stack.Push(DigitText[fen]); } if (jiao != 0) { stack.Push(OtherText[1]); stack.Push(DigitText[jiao]); } } private static void GetIntegerStack(decimal num, int position, Stack stack) { if (num < _num =" Decimal.ToInt32(num);" i =" 0," mod_10 =" 0;" behindzero =" mod_10" _num =" Math.DivRem(_num," mod_10 ="="" _num ="=""> 0) stack.Push(PositionText[i]); stack.Push(DigitText[mod_10]); } } else { GetIntegerStack(Decimal.Remainder(num, 10000M), position, stack); int mask = -1, offset = 4; while ((position & (0x1 << ++mask)) == 0) ; mask += offset; while (stack.Peek() == PositionText[offset++]) stack.Pop(); stack.Push(PositionText[mask]); GetIntegerStack(Decimal.Divide(num, 10000M), position + 1, stack); } } public static string DecimalFormatter(Decimal input) { Stack stack = new Stack(60); bool isNegate = input < Decimal.Zero; input = Decimal.Add(isNegate ? Decimal.Negate(input) : input, 0.005M); decimal integer = Decimal.Truncate(input); int fraction = Decimal.ToInt32(Decimal.Multiply(Decimal.Subtract(input, integer), 100M)); if (fraction == 0) stack.Push(OtherText[2]); else GetFractionStack(fraction, stack); if (integer != Decimal.Zero) { stack.Push(PositionText[0]); GetIntegerStack(integer, 1, stack); if (stack.Peek() == DigitText[0]) stack.Pop(); } else if (fraction == 0) { stack.Push(PositionText[0]); stack.Push(DigitText[0]); } if (isNegate) stack.Push(OtherText[3]); return new string(stack.ToArray()); }}class Program{ static void Main() { decimal input = decimal.MaxValue; Console.WriteLine(input /= 1000M); // 国内银行通用上法转换:万万为亿,亿亿为兆 Console.WriteLine(RMB.DecimalFormatter(input)); Console.ReadKey(); }}

套到仁耀的系統上,我進行了小幅度的修改.

reference: http://topic.csdn.net/u/20080125/09/04c65875-4f50-42cd-bd63-d7b1429e42e1.html

End~

2008年5月6日 星期二

nam 編譯出錯

柏鋒發現修正nam編譯錯誤的方法!!由於風哥是用的是64 bit的OS, 所以在nam一開始編譯時會發生錯誤,如下所示:
netmodel.cc: In member function ‘int NetModel::addr2id(int) const’:
netmodel.cc:311: error: cast from ‘void*’ to ‘int’ loses precision
netmodel.cc: In member function ‘int NetModel::lookupObjname(const char*)’:
netmodel.cc:2764: error: cast from ‘void*’ to ‘int’ loses precision
解決辦法:
把return (int)Tcl_GetHashValue(he);改為return (long)Tcl_GetHashValue(he);

後續會在遇到數個類似的問題,依樣畫葫蘆~把int改成long即可!!

End~

2008年5月1日 星期四

tar壓縮解壓縮指令

壓縮檔案:
tar -czvf 壓縮封裝檔名稱.tar.gz 資料夾名稱--- 將 「資料夾名稱」 壓縮成為 「壓縮封裝檔名稱.tar.gz」壓縮檔.
tar -cjvf 壓縮封裝檔名稱.tar.bz2 資料夾名稱--- 將 「資料夾名稱」 壓縮成為 「壓縮封裝檔名稱.tar.bz2」壓縮檔.

解壓縮檔案:
tar -xzvf 欲解壓縮的檔名.tar.gz--- 解開 「檔名.tar.gz」壓縮封裝檔.
tar -xjvf 欲解壓縮的檔名.tar.bz2--- 解開 「檔名.tar.bz2」壓縮封裝檔.

各參數所代表的意思:
-c :建立一個壓縮檔案的參數指令(create 的意思);
-x :解開一個壓縮檔案的參數指令!
-t :查看 tarfile 裡面的檔案! 特別注意,在參數的下達中, c/x/t 僅能存在一個!不可同時存在! 因為不可能同時壓縮與解壓縮。
-z :是否同時具有 gzip 的屬性?亦即是否需要用 gzip 壓縮?
-j :是否同時具有 bzip2 的屬性?亦即是否需要用 bzip2 壓縮?
-v :壓縮的過程中顯示檔案!這個常用,但不建議用在背景執行過程!
-f :使用檔名,請留意,在 f 之後要立即接檔名喔!不要再加參數!   例如使用『 tar -zcvfP tfile sfile』就是錯誤的寫法,要寫成   『 tar -zcvPf tfile sfile』才對喔!
-p :使用原檔案的原來屬性(屬性不會依據使用者而變)
-P :可以使用絕對路徑來壓縮!
-N :比後面接的日期(yyyy/mm/dd)還要新的才會被打包進新建的檔案中!
--exclude FILE:在壓縮的過程中,不要將 FILE 打包!

reference: http://linux.vbird.org/linux_basic/0240tarcompress.php#tar

sftp 連線指令

若要利用sftp連至ip為XXX.XXX.XXX.XXX時,且對方的port設為YYYY. 則此時在terminal所下的指令為 "sftp -o PORT=YYYY 自己的帳號名稱@XXX.XXX.XXX.XXX" 即可.

以下為比較常用的指令:
1. 結束 SFTP: exit/quit
2. 變換遠方端伺服器的目錄: cd.
3. 更改檔案或目錄的權限: chmod.
4. 刪除檔案: del.
5. 刪除檔案: rm.
6. 列出遠方端伺服器目錄下的檔案名稱: dir/ls.
7. 下載檔案: get.
8. 上傳檔案: put.
9. 新增一個遠方端伺服器的目錄: mkdir.
10. 刪除遠方端伺服器的目錄: rmdir.

2008年4月17日 星期四

Error message: jump to case label

因為有修改NS2其本來的code,在compile時,跳出"jump to case label"的錯誤訊息,後來在網路上看到解決的方法,原來是使用switch/case的時候,若是case內部有宣告區域變數,則必須用大括號將case內的code刮起來,如下範例:

未使用區域變數:
switch (S){
case 'A':
...
break;

case 'B':
...
break;

default:
...
break;
}

若有使用區域變數:
switch (S){
case 'A':
{int counter;
...
break;}

case 'B':
...
break;

default:
...
break;
}

編譯器: gcc
End~~

2008年4月12日 星期六

Error message: multiple types in one declaration

今天在增加NS2-mac802_16pkt.h的struct時,在編譯的時候發生了問題"multiple types in one declaration",一開始我還以為是根本來的NS2裡面內部所宣告的變數衝到,花了一下時間才發現...原來是自己所加的struct最後的大括號沒加到一個分號~~囧, 應該要這樣:struct XXX {...}; 以後一定要記得加分號阿阿阿阿阿阿阿~~~

2008年4月10日 星期四

SS的Scheduler12---process_bsho_rsp()

當SS收到BS傳來的handoff respond後,會利用此memeber function執行相對應的程序,以下將會敘述member function的流程---

Step1. 首先會取出n_rec[].neighbor_bsid的值,並且與SS目前連線的BS做比對,要是相同則不執行後續動作;若是不同,就會把target BS的資訊取出來存至scan_info_的nbr內,

Step2. 再來就產生mac802_16_mob_ho_ind_frame frame,把frame的type設為MAC_MOB_HO_IND,以及設定一些參數,再將target_bsid設定為targetBS,在來就把packet enqueue.

Step3. 最後就設定scan_info_的handoff_timeout與substate(設為HANDOVER_PENDING).

End~

BS的Scheduler7---process_msho_req(Packet *req)

當BS收到SS所送來的packet時,將會執行此member function,以下將敘述此function流程---

Step1. 依序將req frame中的bs_full內的bs_rssi_mean相互比較,後可得到最大rssi的BS index.取得最大rssi的BS後,BS會執行send_nbr_adv().

Step2. 產生mac802_16_mob_bsho_rsp_frame frame,並且設定其相對應的參數,把frame type設為MAC_MOB_BSHO_RSP,並且把target BS的id存進n_rec[].neighbor_bsid.後續在設定一些數值後,就把packet enqueue.

End~

SS的Scheduler11---send_msho_req ()

根據文件上的敘述,當SS收到MOB_SCN_RSP後會跟其他neighbor BS進行Scanning並且接收其DL MAP, UL MAP, DCD, UCD(進行同步的動作),並且會送MOB_SCN_REP給BS(但是我找不到這段程式碼在哪),接著SS會送出MOB_MSHO_REQ給BS,以下將敘述SS的send_msho_req ()流程---


Step1. 先取得peer node的head,在依序產生WimaxNeighborEntry,其內儲存neighbor的資訊.在判斷此node是否為發現過的neighbor,若是新的neighbor則nbrPref就加1.


Step2.若是nbrPref不為0的話,那SS就必須產生出request用的packet.產生packet,並且透過packet建立起一個frame,初始frame,並且把frame的type設為MAC_MOB_MSHO_REQ.接著設定report_metric, n_new_bs_index, n_new_bs_full...等等利用getStatWatch()取得訊號強度在利用average()算出rssi,再利用rssi算出bs_rssi_mean,並將其儲存至struct bs_current[]中,也把當下的peer node存進temp bsid內.

Step3. 開始收集neighor BS的rssi.根據neighbor 的數量產生WimaxNeighborEntry,在判斷此entry是否為已發現且跟目前的BS不同,若是的話,將會取出此BS的id,並且計算rssi跟rssi_mean,在將這些值存入至bs_full[]中.

Step4. 取出peer node的connection id並且存入至wimaxHdr的header.cid中,最後將packet enqueue.

End~

2008年4月9日 星期三

BS的Scheduler6---process_scan_request (Packet *req)

當BS收到SS所發出的MAC_MOB_SCN_REQ packet時,會執行process_scan_request (p),但是此member function主要是在wimaxctrlagent.cc內(不知道為何要把它寫在別的file~),以下將會敘述此function的流程---

Step1. 首先產生Scan_req物件entry,並且設定一些哩哩摳摳的參數,例如:delay, cid...等等.接著把scan_req的表頭加到list中.

Step2. 利用switch/case來判斷目前的default_association_level_為何.level主要有分成三種: (1) Scan without association, (2) Association without coordination, (3) Association with coordination.若是level為case1則透過entry來設定mac802_16_mob_scn_rsp_frame的相關參數;接著再根據nbmapentry_,依序將maptable_[i][0]內的值(第一row,紀錄node的mac address)放入rec_bs_full[]的recommended_bs_id(這個值似乎是紀錄被推薦的BS id),以及把scanning_type設為SCAN_WITHOUT_ASSOC,把被推薦的BS id都記錄好後,利用send_scan_response()把response傳回去.送回去後把entry remove~~.

Step2-2. 若是level為case2,跟Step2一樣設定mac802_16_mob_scn_rsp_frame的相關參數,把maptable_[][] 內的值放入rec_bs_full[]的recommended_bs_id,不同的是把scanning_type設為SCAN_ASSOC_LVL0,後續的動作則相同於Step2.

Step2-3. 若是level為case2,則會先將n_recommended_bs_index, n_recommended_bs_full, pending_rsp ()歸零,再根據nbmapentry_依序設定許多參數.先將wimax bs的type設為WIMAX_BS_SYNCH_REQ,將maptable_[][]設為目的地的address,接著利用port()取出目的端的port(應該是這樣XD),再經由getPeerNode取的設定Mac address.再來設定cid, scanning type, rdvt, rendezvous_time (不知道rdvt, rendezvous_time是作啥用的 囧),然後執行sned() (不知道是不是用這個function把packet送給SS).接著設定n_recommended_bs_full, recommended_bs_id,scanning_type以及rdv_time.最後,在初始化response()下的各參數.

2008年4月7日 星期一

SS的Scheduler10---process_ranging_rsp (mac802_16_rng_rsp_frame *frame)

當SS從MAC收到packet後,檢查其type若是為MAC_RNG_RSP,就會執行這個member function,以下將會敘述此member function流程---

Step1. 先判斷所收到的frame其所包含的SS address是否跟自己的address一樣,是的話就進行後續動作,不是的話就把frame drop掉.

Step2. 判斷frame內的ranging status為何種型態,在code裡面有分四種型態: (1) RNG_SUCCESS, (2) RNG_ABORT, (3) RNG_CONTINUE以及(4) RNG_RERANGE這四種,但是在code中主要只有針對第一種進行相對應的procedure.

Step3. 若是frame內的ranging status為RNG_SUCCESS,則把先前產生的request移除,並且判斷sub state是否為SCANNING,是的話將取出Mac backup的state (Mac備份的資訊包含BS id, frameduration, frame_number......等等)存回state_info中,並且把此neighber當為detected.接著把frame的資訊複製到另一mac802_16_rng_rsp_frame frame中,以及在scanning期間設定UCD message,並且變更到另一channel.

Step4. 若是sub state不是為SCANNING,則分別取出basic/primary connect.判斷basic connect是否為null以及其connection id是否跟傳回的frame basic id一樣,若是一樣則表示收到同一BS所回傳的frame,則不進行後續動作.若是不同且basic connect不為null,則把舊的basic/primary/secondary/outdate/indata connect刪除.利用所收到的mac802_16_rng_rsp_frame frame內其包含的basic/primary cid產生新的basic/parmary/upbasic/upprimary connection.並且透過這些connection把BS新增為peer node,並且將這些cid紀錄起來.

Step5. 把Mac state設為MAC802_16_REGISTER,並且執行send_registration().

End~~

SS的Scheduler9---send_scan_request ()

當SS移動時發生需要handoff的時候,SS就必須執行此member function, 以下將敘述此function的流程---

Step1. 首先會先判斷Mac的state是否為MAC802_16_CONNECTED,若是的話就往下進行後續動作.反之,則不進行後續動作.判斷是否有連線後,產生一packet,並且配給其n byte data buffer,再產生一mac802_16_mob_scn_req_frame的frame,並將frame的type設為MAC_MOB_SCN_REQ,後續設定其相關參數scan_duration, interleaving_interval......等等.

Step2. 設定好frame後,產生一peer node,利用此peer node取得connection id,並且將packet enqueue,準備送出去.

End~

2008年4月6日 星期日

發現需修改處!!??

恩...這陣子花了不少的時間在看BS & SS之間是如何運作,會這麼做的原因是因為~我需要在new call剛起來的時候,"BS會執行HNSS幫其選擇出一個最佳的BS給SS",但是目前SS在啟動init_rang()後,BS收到其RANG_REQ會無條件的同意其connect,建立起BS與SS間最初的連線.由此看來,要是我想實現HNSS for new call,那我應該在BS收到RAND_REQ的時候,進行某種判斷來啟動HNSS的運作.不要像目前NIST所預設的一樣,讓任何SS都可以直接connect!!
另外,HNSS要利用不同的criteria,因此有兩種想法來決定SS的target BS是誰:
Case 1. HNSS在SS上執行.
Case 2. HNSS在BS上執行.
目前我是偏向Case 2., 但是Case 2的話~那某個BS必須先取得,其他幾個BS對於SS的傳輸相關參數,Ex. transmission data rate, vaild symbole. 但是重點來了~BS該如何取得其餘的BS對SS這些相關參數呢??這一部份就要仔細去思考了...

BS的Scheduler5---process_ranging_req (Packet *p)

當BS收到packet其型態為MAC_RNG_REQ,則BS就會呼叫此member function.以下將敘述此member function流程---

Step1. 判斷packet的header.cid是否為INITIAL_RANGING_CID,若是的話BS則會取出peer node (以SS的address作為參數),接著判斷peer node是否為null, 若是的話則利用CONN_BASIC與CONN_PRIMARY 建立出basic, upbasic, primary以及upprimary connection.

Step2. 增加connection CID後,開始增加Peer node的information. 先利用SS的address新增一個peer node,再來分別使用connection basic, primary設定peer node的Basic connection與Primary connection,設定好後再為connection設定peer node.最後利用SS的address新增的peer node,再mac上實際新增一個peer node,並且把basic與primary加到down_con_list_中, upbasic與upprimary 加到up_con_list_中.

Step3. 取得一個新的Packet,並且替他分配n byte data buffer. 將packet的data存至一ranging request frame中,並且設定此frame的type為MAC_RNG_RSP, ranging status為RNG_SUCCESS,frame的SS address為傳入此packet的address, 並將basic_cid, primary_cid...等等其他的參數一併封裝至frame中.來就是取得一burst,並且利用此burst為frame設定txtime,最後再將frame enqueue.

Step4. 若在step1.中peer不為null,則分別利用delay-intolerant message/delay-tolerant message取得basic/primary conneciton.後續就與step3.相同.

End~~

SS的Scheduler8---init_ragning()

當SS成功的收到UL MAP,並且正確的處裡它後,SS會執行init_ranging().以下將會敘述init_ranging()的流程---

Step1. 產生ulsubframe & dlsubframe,接著判斷substate是否為HANDOVER且判斷是否有收到DCD message, 若是符合條件則執行process_ranging_rsp().

Step2. 若是沒有符合step1.的條件,則會依序取得UL的各pdu,並且經由pdu取得burst.再判斷burst的IUC, ExtendedIUC以及FastRangingMacAddr是否分別為UIUC_EXT_UIUC, UIUC_FAST_RANGING與mac_->addr(),若是的話,則會取出一packet,並且設其id為INITIAL_RANGING_CID (預設為BROADCAST_CID),並產生一ranging frame,設定它的type為 MAC_RNG_REQ, Channel ID存入dc_id, ss_mac_address為SS的address, 設定傳輸時間,最後將Mac的state設為MAC802_16_WAIT_RNG_RSP.

Step3. 依序取得UL的各pud,並且經由pdu取得burst.再判斷burst的IUC是否為UIUC_INITIAL_RANGING, 若是的話取packet,並將其id設為INITIAL_RANGING_CID,後續的動作與Step2後半段相同. (觀察TCL所run出來的結果,一開始SS都是執行Step3.)

End~~

2008年4月5日 星期六

SS的Scheduler7---process_ucd (mac802_16_dcd_frame *frame)

process_ucd()的procedure與process_ucu類似,所以我在這邊就不詳述每個流程,就點出不一樣的地方就好.在SS剛收到UCD時,會判斷Mac的state是否為MAC802_16_WAIT_DL_SYNCH或MAC802_16_WAIT_DL_SYNCH_DCD,若是得話則會丟棄此封包.繼續等待DL MAP或DCD.若Mac的state是MAC802_16_UL_PARAM則會進行封包複製的動作(類似於process_dcd (mac802_16_dcd_frame *frame),可參考"Scheduler6"),並且將Mac的state設為MAC802_16_RANGING以及重新設定t12timer.

End~~

SS的Scheduler6---process_dcd (mac802_16_dcd_frame *frame)

此member function主要是處裡當SS收到DCD的時候,該進行何種相對應的程序,以下將敘述此member funciton的流程---

Step1. 收到DCD後,首先會判斷Mac的state是否為MAC802_16_WAIT_DL_SYNCH,若是的話則不進行後續的動作,把封包丟棄.SS會繼續等DL MAP,等SS收到DL MAP後會將Mac state改為MAC802_16_WAIT_DL_SYNCH_DCD (可參照"SS的Scheduler5"),這樣後來收到DCD才會進行後續的動作.

Step2. 若受到DCD的時候,Mac的state為MAC802_16_WAIT_DL_SYNCH_DCD,則會設定Start time,並且判斷sub state是否為SCANNING.若是的話,則會將所收到的frame複製一份存到mac802_16_dcd_frame中,以備給handoff時使用.

Step3. 將Mac的state設為MAC802_16_UL_PARAM,並且設定T1timer.

End~~

SS的Scheduler5---process_dl_map (mac802_16_dl_map_frame *frame)

當SS收到packet時,若是其型態為DL MAP則就會呼叫到此function,以下將敘述此funciton的流程---
Step1. 當收到DL MAP後,SS則會先透過getPeerNode(frame->bsid)判斷是否為null,若是null則表示此BS是第一次接觸到,因此利用addPeerNode為此BS增加紀錄.

Step2. SS會先判斷Mac目前的state,若是為MAC802_16_WAIT_DL_SYNCH,則會進行一連串timer的設定,接著將Mac目前的state設為MAC802_16_WAIT_DL_SYNCH_DCD,並且判斷substate是否為HANDOVER或SCANNING,接著再判斷一次substate是否為SCANNING,若是會再判斷nbr是否為null,或是nbr list內有沒有目前送packet來的BS id,若是的話則會將此BS id存至nbr內(增加此BS為Peer node),接著再判斷若nbr是否為null,若是的話則利用此BS id新增成WimaxNeighborEntry並且將此BS新增為neighbor.否則會判斷此BS是否曾經發現過,是的話SS則會跳到下一個channel,並且執行lost_synch().

Step3. 在step2中第二次判斷是否為SCANNING時,若不是的話就不會進行後續增加nbr的動作. SS會取出DCD,接著判斷是否為null,若不是null則依序取得burst,並且判斷其IUC為何.若IUC為DIUC_END_OF_MAP,則將found設為false.

Step4. 若一開始判斷Mac目前的state,若不是MAC802_16_WAIT_DL_SYNCH,則會再判斷Mac State是否不為MAC802_16_WAIT_DL_SYNCH_DCD與MAC802_16_UL_PARAM,若能滿足這三個條件,將會重新設定reschedule的時間.

End~~

SS的Scheduler4---process (Packet *p)

process (Packet *P)主要是針對從MAC所收到的封包,判斷此封包的種類後進行相對應的procedure,以下將敘述process(Packet *p)的流程---

Step1. 將所收到的packet利用accessdata()存至mac802_16_dl_map_frame *frame,接著判斷此frame的type為何.

Step2. 若是frame的type為MAC_DL_MAP,則會先設定Start time,然後執行process_dl_map (frame); 若type為MAC_DCD, 則執行process_dcd ((mac802_16_dcd_frame*)frame); 若type為MAC_UL_MAP, 則執行process_ul_map ((mac802_16_ul_map_frame*)frame); 若type為MAC_UCD, 則執行process_ucd ((mac802_16_ucd_frame*)frame); 若type為MAC_RNG_RSP, 則執行process_ranging_rsp ((mac802_16_rng_rsp_frame*) frame); 若type為MAC_REG_RSP, 則執行process_reg_rsp ((mac802_16_reg_rsp_frame*) frame); 若type為MAC_MOB_SCN_RSP, 則執行process_scan_rsp ((mac802_16_mob_scn_rsp_frame *) frame); 若type為MAC_MOB_BSHO_RSP, 則執行process_bsho_rsp ((mac802_16_mob_bsho_rsp_frame *) frame); 若type為MAC_MOB_NBR_ADV, 則執行process_nbr_adv ((mac802_16_mob_nbr_adv_frame *) frame);

後續有機會的話我將會描述各個sub procedure的作用為何!!

End~

SS的Scheduler3---start_ulsubframe()

此篇文章將敘述start_ulsubframe() 的流程---

Step1. 先將PHY的state變成OFDM_SEND.

Step2. 取出目前的peer node head (意即取得BS), 再逐一取出Burst,然後判斷Burst的IUC是否為UIUC_INITIAL_RANGING或是UIUC_REQ_REGION_FULL,若是的話則利用Burst的cid取得此connection, 接著就會利用不同方式(by delay-intolerant messages, delay-tolerant messages, standard-based messages, data messages)取得connection,並且判斷conneciton是否為null, 若不是null則利用transfer_packets()算出duration.

Step3. 處裡完每個Burst後,再利用各種方式(by delay-intolerant messages, delay-tolerant messages, standard-based messages, data messages)取得connection, 並且為其增加request.

End~

2008年4月4日 星期五

SS的Scheduler2---start_dlsubframe()

在此member function中主要是判斷scan_info_的substate為何,並且進行相對應的程序,以下將敘述start_dlsubframe()之流程---

Step1. 先將frame number加一,接著判斷scan_info_為何.在此主要考慮兩種state: (1) SCAN_PENDING, (2) HANDOVER_PENDING, 若state為SCAN_PENDING(與process_scan_rsp()相互呼應,在process_scan_rep()中會將scan_info_->state設為SCAN_PENDING),則會再判斷state轉為scanning前,frame的數量,若為0 則會執行resume_scanning() ;若是state為HANDOVER_PENDING, 則會判斷在執行handoff之前frame的數量,若是為0則會將state設定成HANDOVER, 並且設定Channel (相對的會設定到Frequency,Frequency包含3.486e+9, 3.493e+9, 3.5e+9, 3.507e+9, 3.514e+9),設定完後會呼叫lost_synch() function (主要是移除本來的peer node,取得新的peer node), 接著會增加peer node.

Step2. 設定new frame的Start time為NOW, 並啟動dlsubframe的handler,最後則位下一個frame重新排程.

End~

SS的Scheduler1--init()

現在開始將敘述ssscheduler.cc內一些比較重要的member funciton,首先是init()---

Step1. 設定MacState為MAC802_16_WAIT_DL_SYNCH,並且設定PHY的mode為OFDM_RECV.

Step2. 設定各種Timer. 設定的種類有T21 (time the station searches for DL-MAP on a channel), T1 (wait for DCD timeout), T12(wait for UCD descriptor), T2(wait for broadcast ranging timeout), lostDLMAPtimer (Timer for Lost DL-MAP interval), lostULMAPtimer (Timer for Lost UL-MAP interval).

Step3. 利用scanning _structure (reference ssscheduler.h)產生scan_info_,並且初始化其內部各值.scanning_structure包含response for BS, current scanning state, backup of normal, current iteration, timer to notify end of scanning period, number of frame before switching to scanning, ss的schdule state, current neighbor during scanning or handover, arrays of rdv timers, nb_rdv_timer, serving_bsid, number frame to wait before executing handoff.

End~~

2008年4月3日 星期四

BS的scheduler4-start_dlsubframe ()

正所謂逃的了一時~~逃不了一世XDDD,終於到關鍵的地方了"DL Subframe".呼...這一段真是不好k,一些外部的member funciton呼叫來呼叫去的,雖然有搭配文件在看,但是有時真被搞的昏頭轉向 囧,好了...廢話不多說~進入主題吧!!以下為start_dlsubframe () 的流程---

Step1. 先判斷哪些peer node很久沒有傳送packet,並與這些很久沒傳packet的peer node中斷連線.

Step2. 計算出nbPS (一個Frame內總Phy slot的數量), nbPS_left (Remain slot = nbPS - 從receving轉成transmission state所花費的slot -從transmission轉成receving state所花費的slot) , nbSymbols (在nbPS_left中, Symbol的數量,記得還要扣除INIT_DL_DURATION+DL_PREAMBLE所佔據的Symbol喔~), dlduration (INIT_DL_DURATION+DL_PREAMBLE) 以及 ulduration.

Step3. 取得outgoing connection list,再判斷此connection的peer是否沒有在scanning,若是的話則取得此connection的queue size,並且將packet傳輸時間換算成Symbol數 (tmp).若是tmp小於Symbol數,則dlduration (單位應為symbol)加上tmp, Symbol數減去tmp;反之,dlduration加上Symbol數, Symbol數減去Symbol數(此處針對dlduration加Symbol數的真正含意我不暸~要在研究研究).

Step4. 已OFDM Symbol為單位產生DL Subframe的duration以及Burst. 另外再設定Ul Subframe的start time (dlduration*每個Symbol所會佔用的PS數+receving轉成transmission state所花費的slot)以及resched的時間.

Step5. 重新取得Burst(1) (在init()中有設定Burst(1)為End_of_map)更新其Start time.並且逐一將UL Subframe的PDU刪去.

Step6. 先計算出contention slots,再判斷nbSymbols是否大於contention slots,若是大於則間接求出ranging slot, bw slot以及nbSymbols. 透過算出的數值在求得ranging duration與bw duration.接著產生一Burst,並設定其IUC為UIUC_INITIAL_RANGING, Duration為rangingduration, Start time為ulduration. 再產生一Burst, 並設定其IUC為UIUC_REQ_REGION_FULL, Duration為bwduration, Start time為ulduration. 最後會判斷是否有Fast Rangin allocation,若是有則會進行相對應的動作(此段code我沒有深入研究,就先跳過嚕~).

Step7. 判斷是否有peer node在Scanning,若是有則將其加到list中. 若是nbSymbols大於0,且peer node沒有在進行scanning,則產生Burst,並設定其IUC為UIUC_PROFILE_1, Cid, Duration為nbSymbols, Start time為ulduration. 接著取得UIUC_PROFILE_1的profile *p,若是p為Null則為它增加一profile,並設定其IUC為UIUC_PROFILE_1.最後,產生一Burst,設定其IUC為UIUC_END_OF_MAP,Start time為rangingduration+bwduration+nbSymbols.

Step8. 重頭戲要豋場了~首先依序取得先所設定的眾多Burst,在判斷所取出的burst其Index是否為0(第一個Burst),若是則會分別設定DL_MAP, UL_MAP, DCD以及UCD相關數據;首先抓出DL_MAP,設定其傳輸時間,並將傳輸時間轉為Symbols數 (txtime_s),並將此DL_MAP放至queue中,並且把duration加上txtime_s,同理於UL_MAP. 設定好DL/UL MAP後,接著設定DCD/UCD,首先抓出DCD,設定其傳輸時間,並將傳輸時間轉為Symbols數 (txtime_s),並將此DCD放至queue中,並且把duration加上txtime_s,接著把sendDCD設為false,以及重新設定DCD的時間,同理於UCD. 再來就是取出outgoing connection list的head嚕,並且會計算其數量多少.再來就是將這些connection隨機取出一個~並且判斷是否在scanning,若是的話就執行transfer_packets (c, b, duration).

Step9. 改變PHY的State為Send,並且啟動dlsubframe的hander與重新schedule下一個frame的起始時間.

接下來就要k ssscheduler.cc~看SS是如何進行運作的,以及了解一下transfer_packets (c, b, duration).

End~~

BS的scheduler3-start_ulsubframe ()

在一個Frame中主要是由兩個Subframe所組合而成,分別為DL Subframe以及UL Subframe.此篇文章先敘述UL Subframe的流程吧~以下為NS2為利用start_ulsubframe ()產生UL Subframe的流程---
Step1. 首先設定PHY layer的Mode (至於是哪些Mode我就不清楚了 :P).

Step2. 啟動UL Subframe的handler

Step3. 為下一個Frame重新排程(主要是利用一個Frame的duration time來做排程).

End~~

BS的scheduler2-process (Packet *p)

這篇文主要是敘述,當BS從MAC layer收到packet後會有何種反應.當BS從MAC收到packet後,會執行process (Packet *p),流程如下---
Step1. 首先利用傳入的packet產生wimaxHdr. 取出object wimaHdr的header,放到gen_mac_header_t header內,再判斷此header是否為bw request,若是則執行prcess_bw_req(p) (以後有空在談吧 ^^).

Step2. 取出傳入packet的accessdata. 將accessdata放入 mac802_16_dl_map_frame *frame.接著利用switch判斷此frame的type為何,若是為MAC_RNG_REQ, 則執行process_ranging_req (p); 若是為MAC_REG_REQ, 則執行process_reg_req (p); 若是為MAC_MOB_SCN_REQ, 則執行ctrlagent_->process_scan_request (p); 若是為MAC_MOB_MSHO_REQ, 則執行process_msho_req (p); 若是為MAC_MOB_HO_IND, 則執行process_ho_ind (p).

以後有機會在敘述各個process吧~~
End~~

BS的scheduler1-init()

這幾天想了解BS是如何形成frame,因此就去k了bssscheduler.cc 囧(呼...真難吃),在bsscheduler.cc中,我覺得它比較重要的有幾個部份: 1. init(), 2. process(Packet *p), 3. start_ulsubframe(), 4. star_dlsubframe(). 以下將敘述init()這個member function (若是有錯就麻煩糾正一下嚕^^)---

Step1. 首先會利用Frameduration time / PS (number fo Phy Slot)的duration time來得到PS的數量.

Step2. 產生用來broadcast的Profile,設定Interval Usage Code (IUC),以及設定Preamble的大小(單位為symbols).

Step3. 產生Burst(0)來carry broadcast message,並設定Cid為(BROADCAST_CID), IUC, Starttime, INIT_DL_DURATION, Preamble等等參數.另外產生Burst(1),也設定其IUC (DIUC_END_OF_MAP)以及其start time (INIT_DL_DURATION).

Step4. Create initial ranging. 先計算starttime, slotleft, rangingslot (slotleft/2), rangingduration, bwduration (duration的單位都是symbols),計算好後產生一個Profile,並將其IUC設為UIUC_INITIAL_RANGING, 接著為BW requset取得contention slots,並透過InitRangingopportunity得到nbPS,並將其設為contention slots的大小,再分別設定Backoff_star/stop.設定好這些參數後,實際產生Burst(0),並在Subframe第0的位置增加PDU,其IUC設為UIUC_INITIAL_RANGING,start time設為0.到此以完整產生出一uplink burst接收initial ranging request.

Step5. 產生一bw request配給相對應的burst與PDU.先產生一profile並將其IUC設為UIUC_REQ_REGION_FULL,利用getBw_req()取得BW request的contention slot,取回slot後分別設定slot的Size, Backoff_star/stop,接著產生Burst(0),並在Subframe第1的位置增加PDU,設定IUC為UIUC_REQ_REGION_FULL,以及設定相對應的Duration與Starttime.(start after the ranging slot)

Step6. 設定End of map. 產生Burst(0),並在Subframe第2的位置增加PDU,以及設定IUC為UIUC_END_OF_MAP,start time則為ranginnduration+bwduration.

Step7. Schedule the first frame by using a random & start the DCD, UCD and NBRADV timer (DCD=Downlink Channel Descriptor UCD=Uplink Channel Descriptor)

End~

2008年3月30日 星期日

NS2---Scanning procedure

由於我的研究領域主要先從network selection著手,因此就必須先了解NS2中,SS與BS是如何進行scanning procedure來達到handoff的目的. 在NS2中scanning procedure分成幾個步驟:
Step 1. SS會監測incoming packet其singal level,若是singal level超過某一threshold,MS則會傳送MOB_SCN_REQ給serving BS.
Step 2. BS收到後會回傳MOB_SCN_RSP給SS,告知SS是否可進行scanning,若是可以則SS會開始進行scanning

Continue......

2008年3月29日 星期六

C的內建function與macro

由於NS2是由OTcl與C所架構出來的,在NS2底層的code大部分都是用C所完成.在我研究其.16底層的code時,有時都會看到一些C內建的function或macro,例如strcmp(),assert()...等等,以下我將簡述這些function與macro的基本功能:
1. int strcmp(string s, string t)---
功用: 字串之間的比較.此function主要是判斷s與t之間的大小,若是s = t則傳回整數0;若s大於t則傳回任一正數;若s小於t則傳回任意負數.

2. assert(condition)---
功用: 防止程式因某些condition而出現嚴重錯誤. assert()主要是判斷condition是否滿足開發者所設定的要求,若是滿足則可繼續執行後續的程式,反之,終止整個程序.另外ASSERT()與assert()兩者主要差別是前者只在Debug模式中才有效,後者則是在Debug與Release兩種模式中都有效.

3. atof(const char *sc)---
功用: 字元轉型. atof()主要會先scan參數sc,將其面空白符號先跳過,直到遇上數字或是正負號才開始進行轉換.遇到非數字或是參數sc結束時才會停止轉換,並將結果傳回.除此之外,類似的function還有: atoi(), atol(), strtod(), strtol(), strtoul().

4. memset(void *s, char ch, unsigned n)---
功用: 將s中的字元取代成ch,取代長度為n. memset()可應用於字元陣列的清空...等等,目的在於將A,依自己所需取代成B.以下為一範例: #include
#include
void main( void )
{
char buffer[] = "This is a test of the memset function";
printf( "Before: %s\n", buffer );
memset( buffer, '*', 4 );
printf( "After: %s\n", buffer );
}

結果:
Before: This is a test of the memset function
After: **** is a test of the memset function

5.malloc/free ---
功用:動態配置/釋放記憶體. malloc與new的用法類似,不一樣的地方在於使用malloc時不能同時給予初值.以下為malloc格式與範例:
格式:
變數型態* point = (變數型態*) malloc (記憶體空間大小);
範例:
int* p = (int*) malloc (sizeof(int));
free主要是將一配置的記憶體空間,經由所輸入的記憶體空間之起始指標來加以釋放.以下為其格式與範例
格式:
free(point);
範例:
free(*p);

6. sqrt()---
功用: 將傳入之參數開根號.

7. int abs()---
功用: 將傳入的參數取絕對值. 另外還有應付回傳各種型態的abs, 如: double cabs(), double fabs(), long labs()等.

若是還有遇到其他的function或macro我會繼續更新此篇文章~
Continue......

2008年3月27日 星期四

.Net農民曆改版V2.0

前篇文章所提到的國曆轉農曆小程式,後來經測試發現有Bug,沒有做到檢查閏月的程序,因此有時候會造成13月,或是某些月份與正常的月份多一個月,因此就進行些許的修改,以下為完整程式碼 (此程式在線上跑時還是有做些許修改,但是此程式的轉換功能算是已經完整):
using System;
using System.Collections.Generic;
using System.Text;using System.Globalization;
namespace TimeTran{
class Program {
static int Main(string[] args) {
string s = "91 / 2 / 9";
int L_ly,ly,lm,y,ny,nm=0,iToken1,iToken2;
string strny,tT,S;
string[] dateFormats = { "yyyy/MM/dd", "yyy/MM/dd", "yy/MM/dd", "y/MM/dd", "yyyy-MM-dd", "yyy-MM-dd", "yy-MM-dd", "y-MM-dd", "yyyy/M/dd","yyy/M/dd","yy/M/dd","y/M/dd", "yyyy-M-dd","yyy-M-dd","yy-M-dd","y-M-dd", "yyyy/MM/d","yyy/MM/d","yy/MM/d","y/MM/d", "yyyy-MM-d","yyy-MM-d","yy-MM-d","y-MM-d", "yyyy/M/d","yyy/M/d","yy/M/d","y/M/d", "yyyy-M-d","yyy-M-d","yy-M-d","y-M-d"};
ChineseLunisolarCalendar tl = new ChineseLunisolarCalendar();
S = s.Replace(" ", "");
iToken1 = S.IndexOf("/", 0);
iToken2 = S.IndexOf("/", iToken1 + 1);
string iYear = S.Substring(0, iToken1).Trim();
string iMonth = S.Substring(iToken1+1, iToken2-iToken1-1).Trim();
string iDay = S.Substring(iToken2+1).Trim();
ny = int.Parse(iYear) + 1911;
strny = ny.ToString();
tT = strny + "/" + iMonth + "/" + iDay;
DateTime dy = DateTime.ParseExact(tT, dateFormats, null, DateTimeStyles.AllowWhiteSpaces);
ly = tl.GetYear(dy);
lm = tl.GetMonth(dy);
if (tl.IsLeapYear(ly)) //判斷此農曆年是否為閏年
{
L_ly = tl.GetLeapMonth(ly); //抓出此閏年閏何月
switch(L_ly)
{
case 1:
if (lm >= 1)
lm--;
break;
case 2:
if (lm >= 2)
lm--;
break;
case 3:
if (lm >= 3)
lm--;
break;
case 4:
if (lm >= 4)
lm--;
break;
case 5:
if (lm >= 5)
lm--;
break;
case 6:
if (lm >= 6)
lm--;
break;
case 7:
if (lm >= 7)
lm--;
break;
case 8:
if (lm >= 8)
lm--;
break;
case 9:
if (lm >= 9)
lm--;
break;
case 10:
if (lm >= 10)
lm--;
break;
case 11:
if (lm >= 11)
lm--;
break;
case 12:
if (lm >= 12)
lm--;
break;
default:
if (lm >= 13)
lm--;
break;
}
}
else
lm = tl.GetMonth(dy);
Console.WriteLine(DateTime.Now);
Console.WriteLine("國曆:" + tT);
Console.WriteLine("陰曆:" + tl.GetYear(dy) + "/" + lm + "/" + tl.GetDayOfMonth(dy));
return 0;
}
}
}

2008年3月22日 星期六

.Net之農民曆轉換

由於在仁耀的系統中需要做到陽曆轉陰曆的功能,所以嘗試用.Net所開發的System.Globalizatoin (namespace) -- http://msdn2.microsoft.com/zh-tw/library/system.globalization(VS.80).aspx 來達到此目的.
因為需要用到台灣陽曆轉陰曆的功能,因此我使用了TaiwanLunisolarCalendar 類別 -- http://msdn2.microsoft.com/zh-tw/library/system.globalization.taiwanlunisolarcalendar(VS.80).aspx ,此類別是專門針對台灣的曆法所發展出來的類別,透過其已開發好的method便可將所輸入的陰曆轉換成農曆!!以下為我所寫的C#範例:

using System;using System.Collections.Generic;
using System.Text;
using System.Globalization;
namespace TimeTran
{
class Program
{
static int Main(string[] args)
{
string s = "58 / 12 / 23";
int y,ny,sToken1,sToken2;
string ly,strny,tT,S;
string[] dateFormats = { "yyyy/MM/dd", "yyy/MM/dd", "yy/MM/dd", "y/MM/dd", "yyyy-MM-dd", "yyy-MM-dd", "yy-MM-dd", "y-MM-dd", "yyyy/M/dd","yyy/M/dd","yy/M/dd","y/M/dd", "yyyy-M-dd","yyy-M-dd","yy-M-dd","y-M-dd", "yyyy/MM/d","yyy/MM/d","yy/MM/d","y/MM/d", "yyyy-MM-d","yyy-MM-d","yy-MM-d","y-MM-d", "yyyy/M/d","yyy/M/d","yy/M/d","y/M/d", "yyyy-M-d","yyy-M-d","yy-M-d","y-M-d"};
TaiwanLunisolarCalendar tl = new TaiwanLunisolarCalendar();
S = s.Replace(" ", ""); //將字串內的空白消去
sToken1 = S.IndexOf("/", 0); //抓出字串內第一個/的位置
sToken2 = S.IndexOf("/", iToken1 + 1);
string nYear = S.Substring(0, iToken1).Trim(); //抓出字串中的新曆年
string nMonth = S.Substring(iToken1+1, iToken2-iToken1-1).Trim();
string nDay = S.Substring(iToken2+1).Trim();

ny = int.Parse(iYear) + 1911; //將民國轉成西元
strny = ny.ToString();
tT = strny +"/"+ iMonth +"/"+ iDay;
DateTime dy = DateTime.ParseExact(tT, dateFormats, null, DateTimeStyles.AllowWhiteSpaces); //須先將字串轉成DataTime的型態,以供TaiwanLunisolarCalendar的物件tl使用
Console.WriteLine(DateTime.Now);
Console.WriteLine("國曆:" + tT);
Console.WriteLine("陰曆:" + tl.GetYear(dy) + "/" + tl.GetMonth(dy) + "/" + tl.GetDayOfMonth(dy)); //將欲轉換的日期傳進.Net以寫好的方法內,接著再傳回轉換好的農曆
return 0;
}
}
}

End~

2008年3月13日 星期四

[C++]的argc & argv

在coding的時候,有時main會需要傳入參數,而寫成 int main(int argc, char *argv[]),那argc與argv又分別代表什麼意思呢??以下將用例子說明讓大家快速的了解這兩個變數的用處!!
Ex.
若是你寫好一隻程式叫Hell.cc並且已經將其編譯成Hello.exe,當你在Terminal要執行Hello.exe的時候,你則又可能執行以下的command:
$Hello.exe hello all
那這時你的argc則為3,argv[0]=Hello.exe,argv[1]=hello,argv[2]=all.
由此看來,argc則為你在command line所下的參數個數,argv[]則分別存放你所下的每個參數.

End~~

2008年3月10日 星期一

設定BS的覆蓋範圍

由於我的論文主要是考慮two-tier架構,所以需要調整節點的接收threshold(RXThresh_),可偵測其他網路活動的範圍(CSThresh_)...等等參數.在/ns-2.29/tcl/lib/ns-default.tcl內有預設相對應數值:
# Initialize the SharedMedia interface with parameters to make
# it work like the 914MHz Lucent WaveLAN DSSS radio interface
Phy/WirelessPhy set CPThresh_ 10.0
Phy/WirelessPhy set CSThresh_ 1.559e-11
Phy/WirelessPhy set RXThresh_ 3.652e-10
Phy/WirelessPhy set bandwidth_ 2e6
Phy/WirelessPhy set Pt_ 0.28183815
Phy/WirelessPhy set freq_ 914e+6
Phy/WirelessPhy set L_ 1.0
Phy/WiredPhy set bandwidth_ 10e6


在ns-2.29/indep-utils/propagation/threshold.cc內可以得知,FreeSpace與TwoRayGround兩種model計算Pr的方式:

double TwoRay(double Pt, double Gt, double Gr, double ht, double hr, double L, double d, double lambda)
{
/*
* if d <>= crossover_dist, use two ray model
*
* Two-ray ground reflection model.
*
* Pt * Gt * Gr * (ht^2 * hr^2)
* Pr = ----------------------------
* d^4 * L
*
* The original equation in Rappaport's book assumes L = 1.
* To be consistant with the free space equation, L is added here.
*/

double Pr; // received power
double crossover_dist = (4 * M_PI * ht * hr) / lambda;

if (d < pr =" Friis(Pt," pr =" Pt">

Pr:在程式中即為RXThresh_也就是要在tcl所設定的數值
Pt = transmit power
Gt = transmit antenna gain
Gr = receive antenna gain
ht = transmit antenna height
hr = receive antenna height
d = distance (例如250m)

根據網路上鎖參考的資料,我們可以透過編譯threshold.cc來產生一個執行檔,再經由輸入相對應的參數至所產生的執行檔,即可得到RXThresh_,以下敘述如何產生出RXThresh_:

Step1.
ns-2.29/indep-utils/propagation/ 執行以下的編譯指令:
$g++ threshold.cc -o calculate

Step2.
若要執行計算某distance其相對應的RXThresh_,則執行以下指令:

$./calculate -m TwoRayGround -fr 3.5e+9 250

(計算model為TwoRayGround,且frequency為3.5MHz,距離250M)
如此即可計算出RXThresh_ .


reference:

http://hi.baidu.com/vvfang/blog/item/bf834c0fc3b4ab296159f344.html
http://blog.pixnet.net/NS2lab/post/10050300


End~



2008年3月9日 星期日

Grey Prediction!!

前幾天利用C#終於把Grey Prediction的第一階段寫完了~~在撰寫的這段期間內,遇到唯一較大的問題居然是反矩陣XDDDD,太久沒用數學忘記反矩陣怎麼求了(囧rz),問問同學拜拜google大神後,終於有點印象了...呼~為了避免日後又忘或是要再次用到,我今天就把例子寫在網誌上!!

假設有Array A[2,2]
Step1.
計算det(A) = (A[0,0]*A[1,1]) - (A[0,1]*A[1,0])

Step2.
A反矩陣之[0,0]= 1/(-det(A)) * A[1,1]
A反矩陣之[0,1]= 1/(-det(A)) * -A[0,1]
A反矩陣之[1,0]= 1/(-det(A)) * -A[1,0]
A反矩陣之[1,1]= 1/(-det(A)) * A[0,0]

End~

2008年2月24日 星期日

為NIST新增traffic type

昨天晚上嘗試將長庚根據Std. IEEE 802.16e所開發的五種traffic type,加入NIST所release支援mobility的ns-2.29中,其加入步驟如下:
Step 1.
將長庚所開發的traffic type檔案複製到ns-2.29/tools內.

Step 2.
修改ns-allinone-2.29/ns-2.29/common/packet.h
在enum packet_t {} 裡加
PT_UGS,
PT_rtPS,
PT_ertPS,
PT_nrtPS,
PT_BE,
在p_info() {} 裡加
name_[PT_UGS]="UGS";
name_[PT_rtPS]="rtPS";
name_[PT_ertPS]="ertPS";
name_[PT_nrtPS]="nrtPS";
name_[PT_BE]="BE";

Step 3.
修改ns-allinone-2.29/ns-2.29/Makefile.in, 由於我是將各個traffic type放在ns-2.29/tools下,所以在Makefile.in的OBJ_CC加入:
tools/UGS_traffic.o \
tools/rtPS_traffic.o \
tools/ertPS_traffic.o \
tools/nrtPS_traffic.o \
tools/BE_traffic.o \

Step 4.
在ns-2.29下重新再下一次指令"make clean; ./configure; make"即可.

End~

2008年2月23日 星期六

重新安裝gcc

在上篇文章中提到對於NIST 其所release能支援mobility的ns-2.29,在編譯時所會遭遇的問題以及解決方法,但是整體來說大部分的問題是因為gcc版本的關係,所以這篇文章將描述如何安裝自己想要的gcc版本.
#gcc -v (可得到目前所用的gcc版本)
然後可以去ftp://ftp.ntu.edu.tw/pub/gnu/gnu/ (GCC在台灣的mirror)下載所想要的gcc版本.
下載完後,分別載console執行下列指令:
# tar -zxvf gcc-x.x.x.tar.gz
# mkdir gcc-build
# cd gcc-build
# ../gcc-x.x.x/configure --prefix=/usr/local/gcc-x.x.x --enable-threads=posix --host=i386-redhat-linux --with-system-zlib --enable-languages=c,c++,java
# make
# make install
# which gcc (查看原來的gcc所在的路徑)
# cd /usr/bin
# ln -s /usr/local/gcc-x.x.x/bin/gcc gccxx (gccxx是自己取的名子)
# ln -s /usr/local/gcc-x.x.x/bin/g++ g++xx
# ln -s /usr/local/gcc-x.x.x/bin/gcj gcjxx
(利用連結的方式,就可以分別使用gccxx, g++xx, gcjxx對C, C++, JAVA程式進行編譯,除此之外由於是利用連結的方式去取得gcc-x.x.x的gcc, g++, gcj, 所以還是可以使用本來舊版的gcc, g++等命令)
最後在.bashrc中的LD_LIBRARY_PATH加入/usr/local/gcc-x.x.x/lib

End~

2008年2月22日 星期五

編譯NS2-NIST_mobility時遇到的問題與解決方法

今天在安裝NIST所release支援mobility的ns-2.29版本http://www.antd.nist.gov/seamlessandsecure/download.html,在編譯時遇到以下幾個問題:

問題1:
./sctp/sctp.h:705: error: extra qualification 'SctpAgent::' on member 'DumpSendBuffer'
make: *** [trace/trace.o] Error 1
解決方法:
將sctp.h裡面第705行DumpSendBuffer function前面的'SctpAgent::'去掉.

問題2:
./mobile/god.h:88: error:extra qualification ‘vector::’ on member ‘operator=’
./mobile/god.h:93: error:extra qualification ‘vector::’ on member ‘operator+=’
./mobile/god.h:98: error:extra qualification ‘vector::’ on member ‘operator==’
./mobile/god.h:101: error:extra qualification ‘vector::’ on member ‘operator!=’
解決方法:
分別將mobile/god.h內相對應的‘vector::’刪去.

問題3:
./mac/mac-802_11.h:620: error: extra qualification 'Mac802_11::' on member 'calFreq'
make: *** [mac/mac-802_11.o] Error 1
解決方法:
將mac/mac-802_11.h內相對應的'Mac802_11::'刪去.

會有以上三種類似的問題是因為gcc版本的關係!!

問題4:
dsr/dsragent.cc: In member function ‘void DSRAgent::handleFlowForwarding(SRPacket&, int)’:
dsr/dsragent.cc:828: error: ‘XmitFlowFailureCallback’ was not declared in this scope
dsr/dsragent.cc: In member function ‘void DSRAgent::sendOutPacketWithRoute(SRPacket&, bool, Time)’:
dsr/dsragent.cc:1385: error: ‘XmitFailureCallback’ was not declared in this scope
dsr/dsragent.cc:1386: error: ‘XmitFlowFailureCallback’ was not declared in this scope
dsr/dsragent.cc:1403: error: ‘XmitFailureCallback’ was not declared in this scope
make: *** [dsr/dsragent.o] Error 1
解決方法:
voidXmitFailureCallback(Packet *pkt, void *data){ DSRAgent *agent = (DSRAgent *)data; // cast of trust agent->xmitFailed(pkt);}
voidXmitFlowFailureCallback(Packet *pkt, void *data){ DSRAgent *agent = (DSRAgent *)data; agent->xmitFlowFailed(pkt);}
這兩個function移到218行左右,或是在218行加上
void XmitFlowFailureCallback(Packet *pkt, void *data);
void XmitFailureCallback(Packet *pkt, void *data);

問題5:
diffusion/diffusion.cc: In member function 'void DiffusionAgent::MACprepare(Packet*, nsaddr_t, int, bool)':
diffusion/diffusion.cc:429: error: 'XmitFailedCallback' was not declared in this scope
make: *** [diffusion/diffusion.o] Error 1
解決方法:
參考問題4.

問題6:
diffusion/omni_mcast.cc: In member function 'void OmniMcastAgent::MACprepare(Packet*, nsaddr_t, unsigned int, bool)':
diffusion/omni_mcast.cc:388: error: 'OmniMcastXmitFailedCallback'was not de clared in this scope
make: *** [diffusion/omni_mcast.o] Error 1
解決方法:
參考問題4.

問題7:
tcp/tcp-sack-rh.cc:68: error: extra qualification 'SackRHTcpAgent::' on member 'newack'
make: *** [tcp/tcp-sack-rh.o] Error 1
解決方法:
將tcp/tcp-sack-rh.cc內相對應位置的SackRHTcpAgent::刪去.

問題8:
pgm/pgm-agent.cc:307: error: extra qualification 'PgmAgent::'on member 'trace_event'
make: *** [pgm/pgm-agent.o] Error 1
解決方法:
將pgm/pgm-agent.cc內相對應位置的PgmAgent::刪去.

問題9:
pgm/pgm-sender.cc:189: error: extra qualification 'PgmSender::' on member 'trace_event'
make: *** [pgm/pgm-sender.o] Error 1
解決方法:
將pgm/pgm-sender.cc內相對應位置的PgmSender::刪去.

問題10:
pgm/pgm-receiver.cc:186: error: extra qualification 'PgmReceiver::' on member 'trace_event'
make: *** [pgm/pgm-receiver.o] Error 1
解決方法:
將pgm/pgm-receiver.cc內相對應位置的PgmReceiver::刪去.

問題11:
bluetooth/lmp-link.h:296: error: extra qualification 'LMPLink::' on member 'LMPLink'
bluetooth/bt-node.h:100: error: extra qualification 'BTNode::' on member 'setup'
make: *** [bluetooth/baseband.o] Error 1
解決方法:
將bluetooth/lmp-link.h與bluetooth/bt-node.h內相對應位置的LMPLink::和BTNode::刪去.

開張大吉~^^

大家好~這個網誌是我放有關於軟體方面的東東~包括linux, C++, C#, JAVA等等,一些平常會用到的指令或是程式編輯概念,我都會放到我自己的網誌上~~一方面讓我自己有時忘記某個指令或是程式設計的概念時~可以較快速的找到我想要的東西,另一方面可以跟大家分享分享心得^^,請大家多多指教嚕!!