Tuesday, March 31, 2009

麦克阿瑟:"我还要回去"

第二次世界大战打到了1944年的6~7月时,艰难爬上诺曼底海滩的100余万盟军已在欧洲大陆上牢牢站住了脚,太平洋战场的盟军也开始向日军发起全面反攻。美国参谋长联席会议认为,盟军已经掌握了战争的主动权,可以大大加速太平洋战争的进程了。

摆在太平洋美军面前的迫切问题只有一个:确定太平洋战场的下一个战略打击目标。

但是,在麦克阿瑟的西南太平洋战区部队完全控制了新几内亚,尼米兹的太平洋战区部队控制了马里亚纳群岛之后,下一个进攻目标指向哪里?恰恰在这个问题上,美军内部存在着严重分歧。

众所周知,美国在太平洋战场上,唱主角的是太平洋舰队兼太平洋战区总司令、海军上将尼米兹和西南太平洋战区盟军总司令、陆军上将麦克阿瑟。

3月11日,参谋长联席会议最终确定的战略计划,再次肯定了从太平洋两个方向对日本发动钳形攻势的战略设想,并明确规定了各路部队的进攻目标和时间表。对于是进攻吕宋还是进攻台湾的问题,留待以后再定。把“再定”的时间期限划在1945年2月15日以前。

在 进攻吕宋还是台湾的问题上,也有两种意见。一方以麦克阿瑟为首,主张夺取吕宋岛,另一方以海军上将金为首,主张夺取台湾岛。金上将一直坚决主张“迂回菲律 宾而攻占台湾”。他建议绕过麦克阿瑟坚持的主攻目标——菲律宾,而由尼米兹指挥部队进攻台湾,并要麦克阿瑟将主力部队移交给尼米兹。

到了1944年6月,参谋长联席会议的其他两位成员马歇尔和阿诺德上将都同意了海军上将金直接进攻台湾的计划。麦克阿瑟对此当然愤愤不平。由于台湾位于中 太平洋战区,接下来在太平洋战争中唱主角的只能是尼米兹,而不是他麦克阿瑟。更重要的是,当年他在日军的强大攻势下几乎是只身逃出菲律宾,那里至今还囚禁 着成千上万的美军战俘,那里有美国在道义上有义务解放的1700万菲律宾人。绕过菲律宾,麦克阿瑟将无法实现自己离开菲律宾时发出的“我还要回来”的誓 言。所以,他态度鲜明地表示,“我认为这一战役是不会成功的”,日军在台湾的防御固若金汤,“没有空中支援,没有充足的军舰和基地来打击重兵防守的堡垒, 直接进攻就是自取灭亡。”他认为,占领菲律宾的吕宋岛,是建立进攻台湾的飞机基地的大前提。

12月22日,本间雅晴陆军中将亲率日军第14集团军主力5万余人,分乘80艘运输舰,在马尼拉西北110英里处的林加延湾登陆。作战仅仅进行两天两夜, 菲律宾守军就全线崩溃了。为避免全军覆没,麦克阿瑟主动撤退到有坚固设防的马尼拉湾西北面的巴丹半岛,准备在那里固守待援。然而,华盛顿当局坚定地奉行“ 欧洲优先”的原则,对这个日本人迟早要夺取的岛国没有派出一兵一卒。

后来在檀香山, 麦克阿瑟和尼米兹在罗斯福总统面前开始了一场精彩的辩论.

罗斯福首先说明此次会面的目的是“决定太平洋战争的下一阶段行动计划”。总统举起竹节教鞭,指向地图上的棉兰老岛——这是大家都同意收复的岛屿。可他问的却是:“道格拉斯,我们从这里再奔向什么地方?”麦克阿瑟回答道:“莱特湾,总统先生,然后是吕宋岛。”

但代表海军方面意见的尼米兹显然不同意这个计划,他端出了金海军上将攻打台湾的计划。为了说明这个计划,有备而来的尼米兹拿出了随身携带的各种地图、计划、手稿、各种统计表及其他形象化的东西。

按照金海军上将的计划,麦克阿瑟应当在棉兰老岛上建立强大的作战基地,以削弱日军在菲律宾的空中力量,但菲律宾的其余部分应该绕过,为在1945年的夏季 前做好进攻台湾的准备,只能把西南太平洋的美军“象征性”地留给麦克阿瑟两个师和几个飞行中队,其余部队都交给尼米兹指挥。

而麦克则开始了他各个方面的辩论:---------

“你不能把1700万虔诚的菲律宾基督教徒留给日本人。”麦克阿瑟首先从政治的角度说服罗斯福。他知道,总统对政治问题远比军事问题更感兴趣,尤其 是罗斯福刚刚接受民主党的提名,准备进行美国历史上破天荒的第四次总统竞选。他强调说:“总统先生,那时如果美国公众舆论谴责你,那也是有道理的。”

麦克阿瑟接着说,把菲律宾丢下不管,在远东人民的心目中也会引起强烈反响。他们会相信日本人的宣传,认为美国人不会为拯救他们的东方朋友而自己去流血。他还 谈到了被拘押在吕宋岛上的3700名美国战俘,并且说,如果在北面攻打台湾,在南面攻打棉兰老岛,就会使菲律宾中断外界的全部供应。到那时候,日本占领军 自己都没有吃的,大批菲律宾人和美国战俘就会活活饿死。

至于军事上的理由,麦克阿瑟也颇为理直气壮。他指出,攻占菲律宾后,在日本和荷属东印度之间设立封锁线,将切断日军继续作战所需的石油和金属等资源 供给。这将会卡得日本天皇喘不过气来,迫使他因此而投降。对于下一步首先进攻的目标,麦克阿瑟表示,不赞成为了配合攻台作战而攻占棉兰老岛,而是出于占领 菲律宾群岛的需要,必须首先攻占莱特岛、民都洛岛,将其作为上岸的踏脚石,或者在两个岛上同时修建机场,一旦机场修好,他的部队就可以在林加延湾登陆,并 在5周内进入菲律宾首都马尼拉。

“但是,道格拉斯,”总统想起不久前关于日军在马尼拉加强地面部队和航空兵力量的报告,而且那里聚集着50万日军部队,就打断了麦克阿瑟滔滔不绝的话头,“攻占吕宋岛需要付出惨重的代价,我们恐怕承受不了。我们似乎应当绕过它。”

麦克阿瑟在回答总统提问之前,脑海里浮想出尼米兹的海军陆战队前不久攻打日军弹丸之地塔拉瓦时付出重大牺牲的情景,便话中带刺地说 :“总统先生,我的损失不会大,决不会比过去大。正面进攻的时代过去了。现代化的步兵武器是致命的,正面进攻不合时宜了。只有平庸的指挥官才会那么干,优 秀的指挥官打仗是不会招致重大伤亡的。”他还补充说,“盟军可以从仇恨日本占领军的菲律宾人民那里得到一切可能的帮助。在有些地区,强大的菲律宾游击队在 驱逐日本占领者的战斗中已经取得了重大的进展。

午餐后,麦克阿瑟准备做最后的努力,他问能否单独同总统谈10分钟。总统顾问塞缪尔·罗森曼和埃尔默·戴维斯对麦克阿瑟摇了摇头,说总统还有其他安排,但罗斯福总统在短暂的沉默之后,还是答应了麦克阿瑟的这一要求。

“ 总统先生,”在别人都退出去之后,麦克阿瑟直截了当地把话题拉到政治层面上,他知道眼下罗斯福最关心的也就是这个,“美国人民对昔日巴丹发生的事已经原谅 了你。你希望能够连任下一届美国总统,但是如果你批准一项让菲律宾处于侵略者铁蹄之下、直到签署和平条约时才能让他们获得解放的计划,会令1700万忠于 美国的基督徒因此而感到屈辱,美国人民也将永远不会原谅你的。你这样做也许有军事上的战略战术原因,但这样做,将毁了你的政治前途。现在,总统先生,司令 部里还有很多事情等着我,我要告辞了。”麦克阿瑟握了握总统的手,扭头要走,但罗斯福还是把他叫了回来,让他陪自己去做最后一次视察。

在整个会议期间,罗斯福并没有说过一句明显有倾向性的话。但麦克阿瑟心里明白,总统内心的天平已倒向了他一边。当飞机从希卡姆机场呼啸着腾空而起的时候,机舱内的麦克阿瑟收回俯视珍珠港港区的目光,转身向他的副官高兴地说:“我们的意见被采纳了。”

但罗斯福并不打算直接说服参谋长联席会议的成员们。这使将星闪耀的高级军官们陷入举棋不定的困惑之中。马歇尔受到总统的影响,转到了麦克阿瑟的立场 上;阿诺德空军上将和参谋长联席会议主席莱希知道了总统的意向后则为菲律宾群岛上的日军飞机和坚固的陆上防御而忧心忡忡;一贯十分固执的金海军上将不为所 动,仍然坚持进攻台湾。

在接下来的一段时间里,上百万的太平洋战场上的盟军官兵似乎失去了下一个作战的大目标,位于布里斯班的西南太平洋战 区司令部和位于珍珠港的太平洋战区司令部的参谋们,各自忙乎着自己顶头上司让他们干的事情,前者重新审定了不包括棉兰老岛在内的菲律宾作战计划,后者则按 照金海军上将的指示,忙着研究如何进攻中国台湾和厦门.

这里发生了戏剧性的一幕......

1944年9月29日至10月1日,美军海军总司令兼作战部长欧内斯特·金海军上将与美军太平洋战区高级指挥官们在旧金山召开了一次高级会议。

参 加这次旧金山会议的人员有:太平洋舰队司令官尼米兹上将、第5舰队司令官斯普鲁恩斯上将、陆军航空部队司令官哈蒙中将、第10集团军司令官巴克纳中将,此 外还有一位尼米兹手下负责作战的谢尔曼少将。会议的主要议题就是统一思想,确定美海军对太平洋战场下一个战略进攻目标的看法。众所周知,金上将一直坚决主 张“迂回菲律宾而攻占台湾”。由于7月26日罗斯福总统亲临太平洋战区召开檀香山军事会议,在会上会下,麦克阿瑟从政治和军事两个方面成功地说动了罗斯福 总统。参谋长联席会议受总统的影响,转到了麦克阿瑟的立场上,固执的金上将成了孤家寡人。

尼米兹当着作战部长金上将的面发表自己的看法。他说:“我认为,迅速攻占日本本土乃是美国的最高目的。为了达到这个最高目的,美军完全可以不经过台湾和中 国沿岸,而从吕宋岛、冲绳和马里亚纳、小笠原两个方向实施进攻。这样做,对美军更为有利。因为美军如果攻占了吕宋岛,美军就可以在菲律宾建立一些海空基 地,封锁中国海海域的海上交通,与此同时还可以削弱台湾的威胁,进而达到攻占冲绳的目的。如果美军攻占了冲绳、小笠原,美军就可以更加容易地对日本本土发 动进攻。从而,可以更快地结束这场战争。如果仅仅是为了获取海空基地而向台湾发动进攻的话,那么美军付出的代价可就太大了。”

[尾声]

1944年10月3日,美军参谋长联席会议对麦克阿瑟和尼米兹下达了命令。命令麦克阿瑟在1944年12月20日攻占吕宋岛,并为尔后尼米兹的军队占领琉球群岛提供支援。

10月5日,麦克阿瑟终于等到了从1943年春天以来一直苦苦期盼的那句话:“I shall return.”


The essence of all good strategy is simplicity. 一切优秀战略的精髓是简单。

战略千变万化中,有一条是永恒不变的,那就是 "目的".

Douglas MacArthur 独身反对美军高层到最后力挽狂澜的历史已成为经典进入了战争史诗的殿堂,作为西太平洋战区盟军总司令,他向我们展示一名战略家所独有的气质和人格.他对"战略"的理解,完全清晰而简明的浮现在每个读者的面前. 就单凭这点,MacArthur是我至今最欣赏的美军元帅.



Wednesday, March 25, 2009

代理配置记录

这篇文章的技术含量不会太高. 不过是简单记录点东西.

最近是用公司的网络搭建了一个代理,这样访问国际网会比较快. 用到的技术是2个, Squid服务器 和 Pac 代理管理. 这2个的相关问题 google 可以得到一大堆, 我就不介绍了.

然后在 Linux,MacOSX,Windows上进行浏览器配置. 这个都好说,我直接导入pac,然后重启浏览器OK .
接着的问题是在Linux 和 Mac 的命令行. 我以前笨的以为命令行是不能用代理的 O_0 ...
要解决问题很简单配置 ~/.bashrc (有的是bash_profile) 简单加n条

export http_proxy = http://username:password@adress:port
export ftp_proxy = http://username:password@adress:port
export https_proxy = http://username:password@adress:port

随后 source .bashrc(或者 source .bash_profile). 问题就可以解决了.

结果svn又遇到了问题 我开始想svn不是支持http协议么,结果又重新看了下文档. 编辑 /etc/subversion 或 ~/.subversion 中的

[global]
http-proxy-exceptions = *.
http-proxy-host = 211.112.86.213
http-proxy-port = 3305
http-proxy-username = freefis
http-proxy-password = xxxxxx

* 这里注意 要加在 [global] 下面.





Tuesday, March 24, 2009

erlang和python交互

最近开发 Erlang ,对其字符串处理能力无言至极,于是决定把它和python联合起来,打造一个强力的分布式系统,等将来需要系统级开发时,我再把 C++/C组合进来.

首先参考了 Erlang 官方文档和 http://blog.developers.api.sina.com.cn/?tag=erlang 以及 http://kazmier.net/computer/port-howto/ .

研读了将近24个小时, 才终于完全把问题解决. 开始 python 一直是broken pipe.后来才知道是管道中断导致的问题.

接着我排除了python的问题, 在erlang上面发现了Timeout, 感谢litaocheng的提醒,翻看了文档,把gen_server:call 的超时控制为infinity, 这样完全排除了超时的错误.

后来发现执行combin()之后,系统一直在等待. 我重新参考了下前面的2个成功案例,数据流的结尾应该
加上"\n"(windows为"\t\n"),并且erlang需要转换二进制,于是就是

String = list_to_binary("combine|"++_String++"\n"),

python端就成功收到了Stream.
这里combine只是我自己定的一个通信协议 合成请求|String1,String2 => string1+string2.








%%%-------------------------------------------------------------------  

%%% File    : gen_server_template.full  

%%% Designer  : free.Won <freefis@Gmail.com>  

%%% Description :  

%%%     Communication between Python and Erlang via Stdio.  

%%% Archieved :  Mar 24 2009 by  free.Wang <freefis@Gmail.com>  

%%%-------------------------------------------------------------------  

-module(comm).  

-behaviour(gen_server).  

%% API  

-export([start/0,combine/1]).  

%% gen_server callbacks  

-export([init/1, handle_call/3, handle_cast/2, handle_info/2,  

     terminate/2, code_change/3]).  

-record(state, {port}).

  

start() ->  

    gen_server:start_link({global, ?MODULE}, ?MODULE, [], []).

init([]) ->  

    process_flag(trap_exit, true),

    Port = open_port({spawn, "python -u /home/freefis/Desktop/comm.py"},[stream,{line, 1024}]),

    {ok, #state{port = Port}}.

handle_call({combine,String}, _From, #state{port = Port} = State) ->  

    port_command(Port,String),

    receive

        {Port,{data,{_Flag,Data}}} -> 

            io:format("receiving:~p~n",[Data]),

            sleep(2000),

            {reply, Data, Port}

    end.

handle_cast(_Msg, State) ->  

    {noreply, State}.  

handle_info(Info, State) ->

    {noreply,State}.

%    {stop, {port_terminated, Reason}, Port}.

terminate(_Reason, Port) ->  

    ok.

code_change(_OldVsn, State, _Extra) ->  

    {ok, State}.  

  

%%--------------------------------------------------------------------  

%%% Internal functions  

%%--------------------------------------------------------------------

sleep(T) ->

    receive

        after T ->

            true

    end.

combine(_String) ->

    String = list_to_binary("combine|"++_String++"\n"),

    gen_server:call({global,?MODULE},{combine,String},infinity).








#!/usr/bin/env python

# -*- coding:utf-8 -*-

#-------------------------------------------

# Designer  : Free.Wang

# E-mail    : freefis@Gmail.com

# Licence   : License on GPL Licence

# Archieved : Dec 27 2008

#-------------------------------------------







import sys



def handle(_string):

    if _string.startswith("combine|"):

        string = "".join( _string[8:].split(","))

    return string







"""waiting for input """

while 1:

    # Recv. Binary Stream as Standard IN

    _stream = sys.stdin.readline()

    if not _stream: break

    # Scheme, Turn into  Formal String

    inString  = _stream.strip("\r\n")

    # handle String

    outString = handle(inString)

    # send to port as Standart OUT

    sys.stdout.write("%s\n" % (outString,))

    sys.exit(0)


Saturday, March 14, 2009

python发送post保存cookie封装

近期刚写完某SNS的一个刷人气机器人(仅仅做技术测试),然后封装了这个功能。

socket = Httpsocket()
创建一个请求实例,并初始化 cookie容器

socket.connect(url,param)
请求处理post的url和post 参数 执行完后 会返回该socket

socket.openurl(url)
通过持有上一步中得到的cookie来访问接下来的网络地址。


# auther: free.Wang<freefis@gmail.com>

import urllib
import urllib2

class Httpsocket:
 """ Build for Make a full HttpRequest via POST/GET """
 def __init__(self):
# login url to recieve param , Post/Get param
# opener will be used to open Url with cookie.
# build the cookie container.
  self.cookies = urllib2.HTTPCookieProcessor()
  self.opener = urllib2.build_opener(self.cookies)
  urllib2.install_opener(self.opener)

 def connect(self,loginurl,param):
 """make a Container for Cookie"""
  self.loginurl = loginurl
  self.param = param
  self.encodeparam = urllib.urlencode(self.param)
  try:
   urllib2.urlopen(urllib2.Request(self.loginurl,self.encodeparam))
  except:
   pass

 def openurl(self,url):
 """ get Response. """
# serialize the Param
# Login to Get Cookie ,Which will be Push into self.opener.
# get request with Cookie.
  return self.opener.open(url)

Sunday, February 8, 2009

Erlang 分布式爬虫

下面这个是主模块,后面2段代码分别是数据库模块,和一个附属功能模块.

%%%-------------------------------------------------------------------
%%% File : Distributed-Crawler
%%% Designer : free.Wang
%%% Description :
%%% Archieved : Jan 28, 2009
%%%-------------------------------------------------------------------
-module(crawler_server).
-behaviour(gen_server).
%% API
-export([start/1,login/0,crawl/0,check/0]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).


-define(MasterNode,'aaa@219.141.12.84').
-define(Downloadpath,'/Users/winfree/Project/distriawler/urlsea').
%-define(Mastername,).
%if this node is master.node , comment delow row.
%-define(Selfname,changjiangyihao).

%=====================================================================
% gen_server : {global,node()}
% send : mnesia:lookup(pid_table,node)
%=====================================================================

%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
%% Description: Starts the server
%%--------------------------------------------------------------------

globalname(Mode) ->
if
Mode =:= 'slave' ->
[Name,_] = string:tokens(atom_to_list(node()),"@");
Mode =:= 'master' ->
[Name,_] = string:tokens(atom_to_list(?MasterNode),"@")
end,
list_to_atom(Name).




start(Mode) ->
if
Mode =:= 'master' ->
gen_server:start_link({global, globalname(master)}, ?MODULE, [], []);
Mode =:= 'slave' ->
net_adm:ping(?MasterNode),
gen_server:start_link({global, globalname(slave)}, ?MODULE, [], []),
login()
end.




%%====================================================================
%% gen_server callbacks
%%====================================================================

%%--------------------------------------------------------------------
%% Function: init(Args) -> {ok, State} |
%% {ok, State, Timeout} |
%% ignore |
%% {stop, Reason}
%% Description: Initiates the server
%%--------------------------------------------------------------------
init([]) ->
database:start(),
{ok,["success"]}.

%%--------------------------------------------------------------------
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
%% {reply, Reply, State, Timeout} |
%% {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, Reply, State} |
%% {stop, Reason, State}
%% Description: Handling call messages
%%--------------------------------------------------------------------

%handle_call(_Request, _From, State) ->
% Reply = term(),
% {reply,ok,State};

login() ->
gen_server:call({global,globalname(master)},{login,{globalname(slave),node()}}).


handle_call({login,{Globalname,Node}},_From,State) ->
io:format("starting handling form ~p~n",[_From]),
[Id,Hostname] = string:tokens(atom_to_list(Node),"@"),
database:insert_address(Id,Hostname,Globalname),
% database exe. in MasterNode.
Reply = database:select_all(address),
{reply,Reply,State};

% this will be executed by Slave Node.
handle_call({crawl,Urls},_From,State) ->
lists:foreach(fun(Url) ->
io:format("~p~n",[Url]),
spawn(fun() ->
Command = " curl " ++ Url ++ " > " ++ lists:nth(2,string:tokens(Url,"//")),
% os:cmd("cd"++?Downloadpath),
os:cmd(Command),
io:format(" downloading :~p~n",[Command])
end)
end,Urls),
{reply,ok,State}.


%%--------------------------------------------------------------------
%% Function: handle_cast(Msg, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% Description: Handling cast messages
%%--------------------------------------------------------------------
handle_cast(_Msg, State) ->
{noreply, State}.

%%--------------------------------------------------------------------
%% Function: handle_info(Info, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
handle_info(_Info, State) ->
{noreply, State}.

%%--------------------------------------------------------------------
%% Function: terminate(Reason, State) -> void()
%% Description: This function is called by a gen_server when it is about to
%% terminate. It should be the opposite of Module:init/1 and do any necessary
%% cleaning up. When it returns, the gen_server terminates with Reason.
%% The return value is ignored.
%%--------------------------------------------------------------------
terminate(_Reason, _State) ->
ok.

%%--------------------------------------------------------------------
%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
%% Description: Convert process state when code is changed
%%--------------------------------------------------------------------
code_change(_OldVsn, State, _Extra) ->
{ok, State}.

%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------


allurls() ->
["http://www.g.cn","http://www.sina.com.cn","http://www.xiaonei.com",
"http://www.erlang.org","http://www.microsoft.com","http://www.yahoo.com",
"http://www.google.com","http://www.dell.com","http://www.doban.com"].

% communication with others.





check() ->
Nodes = database:select_all(address),
LoopNum = length(Nodes),
UrlGroups = tools:seperate_list(allurls(),LoopNum,[]),
io:format("~p~n------~p~n",[Nodes,UrlGroups]).

% this will deploy the CrawlerDuty by MasterNode.
crawl() ->
Nodes = database:select_all(address),
LoopNum = length(Nodes),
AIG = length(allurls()) div LoopNum,
UrlGroups = tools:seperate_list(allurls(),AIG,[]),
Final = lists:zip(Nodes,UrlGroups),
lists:foreach(fun(One) ->
{Node,UrlGroup} = One,
{_ ,_ ,_ , Globalname} = Node,
io:format("executed by ~p~n",[Globalname]),
spawn(fun() ->
gen_server:call({global,Globalname},{crawl,UrlGroup})
end)
end,Final).


下面是数据库模块:


-module(database).
-import(lists, [foreach/2]).
-compile(export_all).
-include_lib("stdlib/include/qlc.hrl").

%% API
-export([start/0,select_all/1,delete/2,insert_address/3,
insert_urltable/2]).



% address: {Globalname,id@hostname} to send Message.
% urltable:{"http://www.freeis.cn/new/year/","freeis.cn"}
-record(address, {id,hostname,globalname}).
-record(urltable, {url,domain}).



ready() ->
mnesia:create_schema([node()]),
mnesia:start(),
mnesia:create_table(address, [{attributes, record_info(fields, address )}]),
mnesia:create_table(urltable, [{attributes, record_info(fields, urltable)}]),
mnesia:stop().


start() ->
ready(),
mnesia:start(),
mnesia:wait_for_tables([address,urltable], 20000).

select_all(Table) ->
do(qlc:q([X || X <- mnesia:table(Table)])).

do(Q) ->
F = fun() -> qlc:e(Q) end,
{atomic, Val} = mnesia:transaction(F),
Val.

example_tables() ->
[%% The address table
{address, "jack", "10.1.225.117", "<0.33>"},
{address, "allen", "abc.example.com", "<7.313>"},
{address, "Foy", "chat.gogogo.com", "<1.214>"},
%% The urltable table
{urltable, "http://gogogo.sina.com", "sina.com"},
{urltable, "http://A.sohu.com", "sohu.com"},
{urltable, "http://B.avial.com", "avial.com"},
{urltable, "http://C.wgi.com", "wgi.com"}
].

insert_address(Id, Hostname, Globalname) ->
Row = #address{id=Id, hostname=Hostname, globalname=Globalname},
F = fun() ->
mnesia:write(Row)
end,
mnesia:transaction(F).

insert_urltable(Url,Domain) ->
Row = #urltable{url=Url,domain=Domain},
F = fun() ->
mnesia:write(Row)
end,
mnesia:transaction(F).

delete_address(Item) ->
Oid = {adress, Item},
F = fun() ->
mnesia:delete(Oid)
end,
mnesia:transaction(F).

delete_urltable(Item) ->
Oid = {urltable, Item},
F = fun() ->
mnesia:delete(Oid)
end,
mnesia:transaction(F).

delete(Table,Item) ->
if
Table =:= urltable ->
Oid = {urltable,Item};
Table =:= address ->
Oid = {address,Item}
end,
F = fun() ->
mnesia:delete(Oid)
end,
mnesia:transaction(F).

reset_tables() ->
mnesia:clear_table(urltable),
mnesia:clear_table(address),
F = fun() ->
foreach(fun mnesia:write/1, example_tables())
end,
mnesia:transaction(F).

get_plan(PlanId) ->
F = fun() -> mnesia:read({design, PlanId}) end,
mnesia:transaction(F)




这段是附加功能模块:

-module(tools).
-export([seperate_list/3,check/0]).

allurls() ->
["http://www.g.cn","http://www.sina.com.cn","http://www.xiaonei.com",
"http://www.erlang.org","http://www.microsoft.com","http://www.yahoo.com",
"http://www.google.com","http://www.dell.com","http://www.doban.com"].

% seperate_list([1,2,3,4,5],2,[]) ---> [ [1,2],[3,4],[5] ].
% seperate_list([1,2,3,4,5,6],2,[]) ---> [ [1,2],[3,4],[5,6] ].
seperate_list(List,NOP,LatestList) ->
% NOP = Number of One Page.
Rem = length(List) rem NOP,
Grp = lists:sublist(List,NOP+Rem),
Ext = lists:subtract(List,Grp),
if
length(Grp) > 0 ->
seperate_list(Ext,NOP,[Grp|LatestList]);
length(Grp) =:= 0 ->
LatestList
end.


check() ->
Allurl = allurls(),
seperate_list(Allurl,2,[]).

Followers