電影流水帳(2012/1/20~2012/1/26)

2011_rise_of_the_planet_of_the_apes-wide

  • Rise of The Planet of The Apes(IMDB, Wikipedia),中譯:猩球崛起。很好看的電影,是多年前決戰猩球的前傳,描述為什麼地球會演變成猩猩變成高等人類的星球。其實就是Will為了解決父親老人癡呆症的問題,而去研發出一種新的病毒作為新藥,經過實驗,猩猩的智力的確有驚人的成長。後來,因為某些變故,使實驗室主持人下令將這批猩猩銷毀,但是有一隻小猩猩,Robert不忍心下手,就交給了Will。小猩猩Caesar繼承了媽媽的血,也有高等智慧。經過數年之後,小猩猩越發聰明了,而Will偷偷把還沒人體試驗的藥物用在自己的父親身上,也得到了很好的成效。但是,隨著時間過去,Will發現父親的免疫系統已經開始可以抵抗病毒,老人癡呆症也愈來愈嚴重。Will決定冒險開發新的藥物,以解決父親的病症,於是他告訴實驗室主持人說自己已經拿父親試驗過,希望可以開發新的藥物。實驗室主持人在知道藥物有效之後,就決定繼續進行研發計劃。就在藥物快要完成的時候,出現了實驗室意外,Robert不小心吸入了病毒。而Will的父親老人癡呆症也越發嚴重,讓猩猩Caesar為了救他而讓鄰居嚇到,並因此被關到動物管制中心。Caesar在管制中心裡並不愉快,很想要離開,但是受限於法律,Will沒辦法。過了一段時間,聰明的Caesar偷到了小刀,並且收買了中心裡最強壯的猩猩,對抗欺負他的猩猩,然後成為中心裡領袖的角色,為了讓同伴更加聰明,他去Will的實驗室偷到新藥物給猩猩,讓所有的猩猩變得非常聰明。某天,這些猩猩就發難逃了出去,引起軒然大波,並逃到了舊金山北邊的Redwood。而Robert去Will家裡找不到Will的情況下,讓Will的鄰居感染了病毒,而Will的鄰居剛好又是機長,要飛到全世界,於是病毒擴散到整個世界,剛好這個時候又有太空人飛到太空去。飾演Caesar的角色其實是Andy Serkis,之前曾經飾演過Gollum,也難怪在講猩猩的時候,讓人真的以為他是人。
  • Attack of the 50 Foot Woman(IMDB, Wikipedia),中譯:巨型女的襲擊。自己笨,被簡介跟海報騙了,特技效果不突出(1993年的電影)、故事普普,而且還看了國語配音的,才看了沒幾分鐘,就沒耐心地開始亂跳著看完。主角Nancy被丈夫背叛,被父親操控,整個很不爽。有一天被飛碟的光照到,然後就變大了。變大以後,心智也慢慢改變,所以後來就愈來愈不爽,就開始發飆。後面被直昇機打到,就昏倒,被飛碟救走,被救走的時候,她花心的老公也被帶走,片尾是3個巨型女在飛碟裏面看3個花心男在那邊吵架的畫面。

 

參考資料:

電影流水帳(2012/1/9~2012/1/19)

little mermaid
三部片。

  • The adjustment Bureau(IMDB, Wikipedia),中譯:命運規劃局。這應該算是一部頗揪心的愛情片。男主角David參加眾議員競選,投票前被爆了醜聞,結果沒上。要發表落選演說時,遇到女主角Elise,一見鍾情又一見傾心,還沒來的及留下電話,就分開了,David因此發表了一篇不凡的落選演說。後來,David要上班時,竟然在公車上巧遇Elise,兩人超happy,互留了電話。David到了辦公室,發現好奇怪,一堆人都被停住了,他遇到了The adjustment team正在調整眾人的思維,他就拼命逃,可是還是沒能逃過The adjustment team的魔掌。他被警告說,不可以洩漏我們的存在,在Elise的電話號碼被撕掉以後,David被放走。之後,The adjustment team裡的Thompson出來偷偷告訴David一些事情,David只好放棄。隔了3年之後,David上班途中竟然再次看到Elise,重新邂逅,The adjustment team出來強制干預,並要脅David,跟Elise分開的話,你會變成總統,Elise會變成知名舞者,如果不從,Elise的腿可能就不只是扭傷而已。於是David為了Elise好,就把Elise丟在醫院,忍痛走了。又隔了好一陣子,David在報上看到Elise要結婚了,他真的不能忍受,而Elise也很猶豫,透過Thompson的幫助下,David成功的阻婚,並在The adjustment team的阻撓下,逃到了某大樓上。最後的結局是,The adjustment team其實是天使,而命運則是由上帝寫的,因為上帝很感動,就改寫了他們兩人的命運,然後就沒了。
  • Detroit Metal City(IMDB, Wikipedia),中譯:重金搖滾雙面人。根岸熱愛音樂,在大學畢業後,卻誤進了重金屬搖滾的唱片公司,組成了Detroit Metal City,非常的紅。某天,他遇到了大學時代心儀的舊識由利,開心的聊了起來。之後發生了一連串的誤會,並且又不小心成了日本最紅的樂團,成了美國重金屬搖滾樂團的目標。就在這個時候,他被由利很深的誤會,非常灰心,回去老家。在老家,他扮為克勞薩二世,教訓了弟弟,並且,也接受母親的開導而想開,決定回到東京接受挑戰。最後就以戰勝美國重金屬樂團而告終。裏面蠻多好笑的片斷,像是社長弄息煙的方式跟克勞薩二世在老家開割草車等等,蠻好看的片。
  • Pirates of the Caribbean: On Stranger Tides(IMDB, Wikipedia),中譯:神鬼奇航-幽靈海。還算可以的續集片,沒什麼特別的亮點。就一堆人陰錯陽差去找不老泉,有人是為了報仇,有人是為了生命,有人是去看熱鬧,有人是去搞破壞。Sparrow跟Gibbs有地圖,是知道路的人,主要是去看熱鬧順便把黑珍珠號拿回來的,Barbossa去報Black beard的仇,Black beard是為了生命,他快死了,豈知後來因此而死,西班牙國王去搞破壞,他不允許有東西超越上帝賜與人的生命。最後就是泉水被西班牙破壞,Barbossa得償所願,Black beard掛掉,Angelica被放逐,Sparrow跟Gibbs拿到黑珍珠號跟其他一堆船,看起來是還會有續集的樣子。

ping in Android(續)

後來發現裏面有包ping這指令,而且有設置setgid權限,那麼應該是可以執行。只是試了之後,卻不行,然後我就以為不行。之後不死心,把stderr接出來看,才知道我下錯指令,於是修正以後,就可以了。

[java]
final class Helper {
private final String TAG=”Helper”;
private void pingInExec(String host) {
Runtime runtime = Runtime.getRuntime();
String command = String.format(“/system/bin/ping -c 2 %s”, host);
Process proc;
try {
proc = runtime.exec( command );
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

String inputLine;
while ((inputLine = in.readLine()) != null) {
Log.d(TAG, inputLine );
}
in.close();
while ((inputLine = err.readLine()) != null) {
Log.e(TAG, inputLine );
}
err.close();
proc.waitFor();
int exit = proc.exitValue();
Log.d(TAG, String.format(“exitcode=%d”, exit) );
if (exit == 0) { // normal exit
Log.d(TAG, “RESPONSE_OK”);
} else { // abnormal exit, so decide that the server is not reachable
Log.d(TAG, “RESPONSE_TIMEOUT” );
}
} catch (IOException e) {
Log.e( TAG, e.getMessage() );
} catch (InterruptedException e) {
Log.e( TAG, e.getMessage() );
}
}
}
[/java]

ping in Android

上網找了一下,一般對於ping的建議是直接利用java內建的InetAddress.isReachable()來做,實際上在ping內部網路的伺服器時,是沒問題的,但是如果要ping位於外部網路的伺服器時,就會失敗而回傳False。

Android內部的實作是在libcore/luni/src/main/java/java/net/InetAddress.java裡,這裡就很簡單的建立socket,然後試著連到指定位址的port 7,如果可以連,或者是伺服器明確地拒絕,就視為伺服器存在,可以連線。這就解釋了為什麼無法ping位於外部網路的伺服器,因為ISP為了安全或是其他考量,而不允許。我分別以python與java寫了與Android實作相似的程式去實驗,的確都不行。

[python]
import sys
import socket

if len(sys.argv)<2:
print( “Need at least 1 parameters.” )
print( “Usage: {0} host”.format( sys.argv[0] ) )
sys.exit(-1)

r = False
try:
s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
s.settimeout(5)
s.connect( (sys.argv[1], 7) )
r = True
except socket.error, ex:
if ex.errno==111:
r = True
else:
print( ex )

if r:
print( “{0} is reachable.”.format( sys.argv[1] ) )
else:
print( “{0} is NOT reachable.”.format( sys.argv[1] ) )
[/python]

[java]
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.io.IOException;

class Ping {
public static void main(String[] args) {
InetAddress in;

try {
in = InetAddress.getByName(args[0]);
boolean result = in.isReachable(5000);
if (result) {
System.out.println(“Response OK”);
}
else {
System.out.println(“Response fail”);
}
} catch (UnknownHostException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
[/java]

Java裡只能建立 stream(TCP) 或 dgram(UDP) 的socket,那麼只能用JNI,用C寫ping了,但經過實驗結果,發現會因為權限的關係而無法建立socket,原來要建立raw與IPPROTO_ICMP的socket,需要root權限。一般linux裡,非root使用者可以使用ping,是因為ping加上了setuid權限,才能使用。在Android裡,要不就是建立service,要不就是設法為ping加上setuid,否則是都無法使用的。

Get IP Address in Android

這篇Get the ip address of your device on Android Development其實就講的很清楚了,就是用NetworkInterface.getNetworkInterfaces()去取得所有網路介面,然後再用網路介面的getInetAddresses()去看該網路卡上的所有IP位址,然後把Loopback位址排除掉,就可以取得了。該開的權限有android.permission.INTERNET與android.permission.ACCESS_WIFI_STATE。

我工作上的需求,是要拿到3G那邊的IP,經過實驗,發現在WiFi開啟的情況下,只會拿到WiFi網路介面的IP位址,而非3G網路介面的。如果把WiFi網路介面關閉,就可以拿到3G網路介面的IP。我以為是程式邏輯的關係,可是在確認過NetworkInterface.getNetworkInterfaces()傳回的網路介面數量以後,發現都是取得兩個網路介面,而非我預期的三個。好,那我不使用NetworkInterface.getNetworkInterfaces()改用NetworkInterface.getForName()去取的話,在WiFi開啟的情況下,取得的結果會是null,也就是說該網路介面被關掉了。

直接去看底層,在 mydroid/libcore 下NetworkInterface的JNI函式,那邊是使用netlink去跟kernel問所有的網路介面,然後解析之後傳回。那麼底層應該是沒有問題,看來是中間層為了能取得較快的網路速度,而自動把3G網路介面給關閉了。看來也只能在程式執行前,先把WiFi給關閉,才能取得3G網路介面的IP位址了。

參考資料:

[ExcelVBA]刪掉所有sheet,只留下指定的sheet

上星期的某天花了一個小時在寫這個Script來幫我刪sheet,程式邏輯很簡單,很快就搞定了,只是另存新檔,打開以後,卻什麼東西都沒看到。存為 .csv 的話,的確是有資料,那就奇怪了,百思不得其解。一放就又放了一個星期,這次終於解開秘密了。另存新檔以後,不知道為什麼,打開以後視窗會被隱藏,所以什麼都看不到。只要取消隱藏視窗就可以看到了。程式的話,就是要這樣寫: Application.Windows(1).Visible=True,下面就是整個程式:

電影流水帳(2012/1/1~2012/1/8)

轉眼又是新的一年。

  • Cowboys & Aliens(IMDB, Wikipedia),中譯:星際飆客。中文翻譯還蠻能唬人的,算了。這是一部西部片,只是對抗的人變成了外星人。故事很簡單,男主角一開始是喪失記憶的,手上帶了一個莫名其妙的手環,然後他到了小鎮。小鎮旋即被外星人襲擊,一堆人被擄走要解剖用。然後男主角就跟小鎮上最硬的人組隊去救人,在途中,男主角慢慢想起以前的事情,也跟女主角等人慢慢熟起來。然後終於找到外星人的飛船,就決定先把外星人引出來打,男主角跟女主角趁機進去救人。外面真的幾乎是一場一面倒的戰役,那個時代的槍沒打到要害的話,基本上是打不死人的,就子彈卡在肌肉裡這樣,所以外星人根本是所向披靡。不過在電影的加持之下,還是幹掉了不少外星人。題外話,其實外星人的設定不是很合理,為什麼身體還會打開,把要害攤給別人看還會伸出另外兩隻手呢?不過反正是外星人,我想我就別在意了。在硬撐了許久之後,終於把人救了出來,女主角其實也是外星人,是要來報仇的外星人,所以就拿了男主角的手環下來,轉成炸彈,進去核心。男主角趁機會趕緊逃了出來,女主角最後就把外星人的船炸掉,就這樣。大致上不難看啦,最可惜的一幕是女主角死而復生的那一段,她從火裡走出來,衣服都被燒光光,我蠻想加入那些圍觀的人說,想知道為什麼他們那麼驚訝。(你劃錯重點了好嗎?驚訝是因為她死了又再復活,不是沒穿衣服的問題!!)
  • Iron Man 2(IMDB, Wikipedia),中譯:鋼鐵人2。Tony因為控制不住palladium的關係,生命不長久了,所以就開始亂搞,並且讓Pepper當CEO。在西班牙遇到他老爸朋友的兒子Ivan Vanko,一陣亂打讓鋼鐵人跟Starks工業的名聲大為降低,讓對手Hammers工業趁機而入。一整個low到谷底,一具鋼鐵人又被美國國防部拿走的情況下,神盾局的人跑出來跟他說palladium不是最好的元素,給他打了抑制Palladium的藥物並給了他他老爸的遺物,說有更好的元素可以用,他摸索一陣子之後,找到了製造新元素的方法,然後噹噹噹,新的core誕生了,arc reactor更為強大。Ivan被Hammers吸收以後,幫他們研發,但不聽他們的話,而是搞自己的,所以在Expo時,他遙控一堆機器人跟Iron Man打,這堆機器人真的很酷啊,但Iron Man跟他的朋友聯手把這堆機器人幹掉,Ivan大魔王現身,最後以解決掉大魔王告終。這一集Pepper的戲份不多,好可惜,我很喜歡她說。然後飾演Natalie的Scarlett Johansson是一個亮點,她的武術動作真的好酷,然後她真的很適合演這種酷酷的角色,The Spirit裡是這樣(有多一點搞笑),這裡也是這樣。

http://en.wikipedia.org/wiki/Whiplash_(comics)#Film

skydrive+FUSE的read

這幾天弄skydrive+fuse的時候,一直在想,這到底適不適合用FUSE來實作?

  1. 以網路程式來說,讀取的時候,要可以告訴伺服器端,客戶端要下載那一段,要下載多少,以HTTP來說,這可以用Range這個header來達成,只要在發request的時候,加上Range header就可以指定。那麼skydrive伺服器端有支援續傳嗎?這個我還沒去確定。
  2. 那麼FUSE的read裡可以使用續傳嗎?在read裡會指定要讀取多少,從哪裡開始讀取,看來是可以使用續傳,可是使用續傳的話,就要考慮一下客戶端的情況,一般在做這種read的時候,是使用一個回圈,然後一次只讀取一部份到緩衝區裡,並不是一次讀完,因此,只讀取一部份的結果,等於會送出許多次的request給伺服器端。
  3. 可以不要送出許多次的request嗎?這樣網路會折返很多次。一次下載完,先放到硬碟的話,就要面對同步的問題。首先第一次read時,就要可以傳回一部份值,並且要把這個下載的動作放到thread去執行,繼續下載,並放到某個暫存的地方,直到下載完成。那接下來第二次要read時,再去讀取已經下載的部份並傳回。這樣會少掉比較多的request,效率也會比較高一點。可是thread在寫的時候,另外一個thread可以去讀取正在寫入的檔案嗎?會不會有什麼奇怪的事情發生呢?這個是需要實驗的地方。
  4. 延續前面的討論,現在已經放到暫存的地方,存取會快很多,可是該怎麼知道伺服器端的檔案被更改了?這應該可以在一開始要read的時候,去判斷檔案大小跟屬性來判斷是不是要重新下載。另外也要考慮到伺服器端檔案被頻繁更動的情況。
  5. 既然會放到暫存的地方的話,是不是乾脆像dropbox那樣用sync的方式來做會比較好?

 

家裡server升級

先從昨天講起,昨天早上本想在今天下午請特別假的,卻發現沒辦法請特別假了。仔細看,才發現原來可以請特別假的期間是到職日到隔年到職日的前一天,啊啊啊!!我還以為跟前公司一樣說,一整個晴天霹靂。所以我去年短短的6個半月時間,就把所有特別假都請完了,今年要撐半年以後才能放特別假啊~
好吧,去年最後一天有請特別假,也是最後一個特別假,然後在家裡升級伺服器,中午有出去吃火鍋,載太座大人回家。去年我弟換NB時,就把他的桌機給我了,一直有打算要幫家裡伺服器升級,但一直沒動手。這次的升級遇到的問題是,機器按了電源開關以後,電源燈一閃即逝,猜想是短路的問題,所以就整個拆掉,看有沒有裝上墊片。拆開一看,發現沒裝墊片,然後機版不是用銅柱去鎖主機板,而是靠凸起跟主機板接觸去鎖。這下可就傷腦筋,就上網查了一下,說這種的比較容易短路,所以他是用透明膠帶去貼凸起,然後戳洞以後再鎖。我就如法泡製,再把主機板…等等的東西都再裝上。裝上、按前面的電源以後,怎麼還是閃了一下就滅掉,於是確定後面的電源開關以後,再去按前面的電源開關,這下就可以了。所以或許不用整個拆掉,可能只是自己耍白痴,後面的電源開關搞錯開跟關了?!算了,反正已經都弄好,硬碟也裝上,可以順利開機就好。
可是,事情往往不是這麼簡單就可以解決。原本有一顆SATA硬碟,我加裝兩顆原來伺服器的IDE硬碟上去,主要的那顆用IDE轉SATA接,另外一個次要的用IDE接。我是想說用原來伺服器主要的那顆硬碟來開機,可是怎麼弄都不行,經過兩個多小時,無數次的試驗之後,發現是因為CentOS做出來的initrd沒有載入SATA的驅動模組,那接下來就無法找到硬碟去掛載主要硬碟上的分割區。本來是想為initrd補上SATA驅動模組的,後來放棄了,就把主要硬碟改用IDE接,次要的則用IDE轉SATA接,這樣,就順利開機了,拜Linux所賜,也不需要重灌,就稍微調整了一下設定、日期時間就收工了。
升級以後的確是爽,原本的伺服器是Celeron 566MHz加384MB的RAM,新的伺服器是AMD Sempron 3000+加1G RAM,雖然規格還是跟現在的電腦差很多,速度快了好多啊!!

UnicodeDecodeError when logging utf-8 string

我的python有使用logging library,可是卻出現下面的錯誤訊息:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 56: ordinal not in range(128)

百思不得其解,明明我的字串就是utf-8,可是卻會出現這個錯誤訊息。查了Python的Unicode How-To好幾次,覺得問題應該是出在檔案上,開檔案時應該要用codecs,那,會不會是logging開啟檔案時,沒有用codecs去開檔案然後處理encoding啊??發現好像也不是,因為使用FileHandler時有指定編碼啊。
上網找了之後,才發現logging的確已經使用codecs來開啟檔案了,那為什麼呢??又再找了幾篇當參考:UTF-8 In Python logging, how?UnicodeEncodeErrors with celery built-in console logging,也有人直接自訂formatter來解決,看著看著,就想到,原來logging裡面已經有處理了啊,再次對utf-8字串作utf-8 encode的結果就是出錯,那就表示不必特別丟utf-8字串,只要丟給他unicode字串,logging就會自動幫我轉了啊~
於是我就不特別再作字串的轉換,直接使用unicode字串,這樣就解決這問題了。