Kupfer可作为Gnome-Do的替代品,对于不喜欢安装mono或者不喜欢Gnome-Do 臃肿的dock功能的同学来说,是个绝佳的选择。基于Python,但是速度非常快,插件扩展也相当丰富,使用体验上毫不逊色于Gnome-Do.
需要说明的一点,本地的配置文件夹默认位于~/.config/kupfer下,当然你也可以通过gnome-panel applet进行设置。
Kupfer可作为Gnome-Do的替代品,对于不喜欢安装mono或者不喜欢Gnome-Do 臃肿的dock功能的同学来说,是个绝佳的选择。基于Python,但是速度非常快,插件扩展也相当丰富,使用体验上毫不逊色于Gnome-Do.
需要说明的一点,本地的配置文件夹默认位于~/.config/kupfer下,当然你也可以通过gnome-panel applet进行设置。
SourceForge组织的2009社区选择奖评选完毕,今日在其官方网站公布了获奖的开源软件项目。名单(奖项、项目、投票率)如下:
最佳系统管理工具:Mysql管理工具 PhpMyAdmin 18.82%;
最佳学术项目:思维导图软件 Xmind 21.54;
最可能改变做事方式的项目:PortableApps.com: Portable Software/USB 20.21%;
最佳多媒体项目:多轨音频编辑器 Audacity 32.09%;
最佳开发者工具:代码编辑器 Notepad++ 19.21%;
最佳视觉设计:Best Visual Design 27.87%;
最佳游戏项目:游戏模拟器ScummVM 20.38%;
最佳企业项目: 数据库服务器 Firebird 18.05%;
最佳政府项目:办公套件 OpenOffice.org 48.27%;
最佳商业开源项目:PortableApps.com: Portable Software/USB 41.74%;
最佳新项目:迷你电脑操作系统 eeebuntu 27.52%;
最佳项目:PortableApps.com: Portable Software/USB 16.45;
其中PortableApps.com:Portable Software/USB无疑是大赢家,获得了最佳项目、最可能改变做事方式的项目、最佳商业开源项目三项大奖。
用户通过PortableApps.com: Portable Software/USB可以将自己喜爱的应用程序装到USB闪盘或外部硬盘。安装后,应用程序就可以在任何Windows计算机上运行。任何个人的数据随身携带,十分方便。
GnuCash 看名字就知道来头不小,是 GNU 开发的记帐工具,支持多账号和层次化的账号。在 GnuCash 里面所有的收入支出都看成是”传输“,即一笔资金不会凭空而来,都会有一个来源和一个目的。比如从银行卡流到钱包。因此在 GnuCash 里面每笔资金流动都会有 2 条记录。称为”double entry”,也叫复式记帐。
Debian 和 Ubuntu 自带。可方便安装。启动后会提示建立一个初始账号。另外还提供强大的资金分析功能。总之很专业。
GnuCash原是UNIX/LINUX下的个人财务管理软件下的个人财务管理软件,后来增加了Windows下的版本,现在已经更新到2.2.7,portableapps.com提供了Portable版本的下载,方便随身携带使用。
为了方便观看整理成了PDF文件,《Gnucash入門使用教學》PDF版本下载:
下载(1.48MB): Skydrive | UUShare | MediaFire | RayFile | BRSBOX | 纳米盘 | 猪八戒
推荐一款很好玩的经典开源游戏 – xmoto
你所要做的就是利用方向键控制摩托车的平衡,吃掉所有红色果实后,到达地图的终点(花形标志)就算过关。左右键控制前后平衡,上方向键为加速(注意,只有后轮驱动),下方向键刹车。空格键掉头。
此游戏基于ODE 这个很棒的开源虚拟物理引擎。游戏中,可以自动在线上传你的分数,看看你是不是排在第一。
另外,值得一提的是,您可以直接使用inkscape开发矢量的游戏地图,打包成你自己的level让大家一起玩。非常强悍。
早上搜索了下 清华大学开源软件俱乐部的网站,找到这点关于Ccnet的资料,分享下。
Ccnet 是 common creative network 的简称,它的目标是给 Linux 桌面提供一个面向于 group 的通用的 P2P 服务,使得人们没有中心服务器的情况下也能协同工作。
使用上来说,与大部分现有的 P2P 系统相比,Ccnet 有两个主要的不同点。 首先,Ccnet 并不试图将所有的人连接成一个全球性的网络,而是从协作的视角出发,为个人桌面环境提供 P2P 服务,使得一个桌面系统可以和一个或多个 group 中所有的其他成员的桌面系统能联通起来。其次,Ccnet 本身是一个守护进程,为桌面上的其他程序提供服务,比如通过 Ccnet 提供的消息传输服务,一个桌面应用程序可以向一个或多个 peer 发送一条消息;这种简单易用的 P2P 服务将极大地扩展目前桌面应用程序的所能实现的功能。
技术上来说,Ccnet 包含了一个目前大多数 P2P 系统都没有的功能,即请求的延迟满足。 举个例子,如果主机 A 需要向一个不在线的主机 B 发送一个消息,而且主机 A 自己马上要下线,怎么来保证该请求得到满足? 该功能对于一个节点在线时间不确定的 P2P 系统是至关重要的。Ccnet 通过 Requirement 机制来实现该功能。
程序结构上来说,Ccnet 是极易扩展的。Ccnet 包含提供了两套机制: Processor 和 Requirement。 Processor 用于实现两个在线 peer 的交互功能,比如传文件、传消息。 Ccnet 框架提供了一个 Processor 基类,通过书写一个子类,我们就能实现一个新的交互功能。Requirement 也是如此,通过书写一个子类,我们就能实现一个新的种类的请求的延迟满足。
目录[显示] |
代码页面
为什么使用 C 和 GObject
功能模块 | 文件 | 说明 |
---|---|---|
工具模块 | ||
事件管理 | trevent.c | |
log | log.c | |
底层 | ||
peer 信息管理(本地) | peer.c peer-mgr.c | 建立和维护 peer 数据库 (内存和磁盘) |
peer 互连 | peer.c peer-mgr.c handshake.c listen.c peer-io.c | |
packet IO | peer.c packet.h | |
group(本地) | ||
routing | routing-mgr.c getpeerinfo-proc.c | |
processor | processor.c session.c peer.c proc-factory.c | |
requirement | requirement.c response.c req-manager.c sendreq-proc.c receivereq-proc.c | |
中层 | ||
message 管理 | message.c message-manager.c sendmsg-proc rcvmsg-proc getmsg-proc putmsg-proc sendmsg-req | |
文件管理 | file-manager.c sendfile-proc receivefile-proc getfile-proc sendfile-proc | |
git db 管理 | ||
高层 | ||
peer 信息管理(网络化) | 依赖于 message 管理和文件管理 | |
group(网络化) | 依赖于 message 管理和 git db 管理 |
相关的类: CcnetPeer ccnet_peerMgr
信息存储: peer-db/peer-info.txt peer-db/<id>
每个节点用自己的公钥的 SHA1 值作为 ID。
采用 RSA 公钥算法认证。
添加一个 peer 有两种方式
auth-request 工作流程如下 (A 请求 B 的认证):
路由模块依赖于 peer 模块和 getpeerinfo-proc.c 。
主动操作
被动操作
权限列表
几个问题
基于 libevent 库中的 bufferevent 和 evbuffer 实现,涉及的文件:
上层应用应该调用 peer.h 提供的 IO 函数,以便自动选择是否需要启动中转服务。
每隔时间间隔 LISTEN_INTERVAL (listen.c),incomingPeersPulse() 函数回被调用,以检测是否有 TCP 连接请求到达。注意,由于是非阻塞 IO, 所以 ccnet_netAccept() 函数总会立即返回。 ccnet_peerMgrAddIncoming() 生成 peerIo 对象和 handshake 对象,前者是对 socket IO 的封装,后者负责连接的初始化,比如认证。初始化完成后, myHandshakeDoneCB() 会被调用。
static void
incomingPeersPulse (ccnet_handle * h)
{
for ( ;; ) /* check for new incoming peer connections */
{
int socket;
struct sockaddr_storage cliaddr;
size_t len = sizeof (struct sockaddr_storage);
if ((socket = ccnet_netAccept (h->bindSocket, &cliaddr, &len)) < 0)
break;
ccnet_peerMgrAddIncoming (h->peerMgr, &cliaddr, len, socket);
}
}
void
ccnet_peerMgrAddIncoming (ccnet_peerMgr *manager,
struct sockaddr_storage *cliaddr,
size_t addrlen,
int socket)
{
ccnet_peerIo *io;
ccnet_handshake *handshake;
managerLock (manager);
io = ccnet_peerIoNewIncoming (manager->handle, cliaddr, socket);
handshake = ccnet_handshakeNew (io, myHandshakeDoneCB, manager);
g_ptr_array_add (manager->incomingHandshakes, handshake);
managerUnlock( manager );
}
见 handshake.c。 完成 Hankshake 后,双方都知道了对方的 ID。 接下去要采取的行为,比如是否要认证对方,各自决定,采用“请求-响应”语义进行。比如,A 发起认证 B 的过程,而 B 可以决定不去认证 A。
Client 将所有已经认证的 peer 放到 peer-db/peer-info.txt 中。 启动时读取该文件。
Client 在与一个未认证的 peer 完成 Handshake 后, 将该 peer 放到未认证 peer 池中。 用户调用 processor-getpeerinfo 来从该 peer 得到更多的信息。 调用 ccnet_peerMgrAuthPeer(peer) 来将该 peer 放入到已认证 peer 池中。
用户可以决定是否把未认证 peer 池保存到磁盘文件中 (peer-db/peer-unauth.txt)。
相关函数
void ccnet_peerMgrAddUnauthPeer (ccnet_peerMgr *mgr, const char *peer_id, ccnet_peerIo *io);
void ccnet_peerMgrAcceptPeer (ccnet_peerMgr *mgr, const char *peer_id);
void ccnet_peerMgrRejectPeer (ccnet_peerMgr *mgr, const char *peer_id);
Client 自身处于三种状态之一:
Client 用 CcnetPeerAtom 结构来保存 peer 的地址信息。 为了保持地址信息的有效性,需要
Processor 生命周期的管理并不使用 GObject 引用计数机制,而是通过下面的规范
ccnet_processor_done () 只能由 processor 自己调用。 其他模块如果要关闭一个 processor, 使用 ccnet_processor_shutdown()
Requirement 是一种可靠的对象传输机制,它可以在两个节点不同时在线的情况下可靠地将一个节点上的对象(消息、文件、认证请求等)传输到另一个节点上,Requirement 本身并不负责对象的处理,对象的处理交由上层负责。
Requirement 的生命周期分为内存生命周期和状态生命周期,前者由引用计数机制管理,后者由自身管理。
在源节点和中继节点, Requirement 存在于 pending_reqrs 列表中。在目的节点,它存在于 check_reqrs 列表中。(在状态生命周期结束后,Requirement 有没有必要保存在一个特殊列表中以便查询?)
Requirement 由事件驱动其运转。 函数 try_satisfy() 用于其他模块给 Requirement 一个初始的触发。 在发生以下事件的时候该函数被调用:
初始触发后,Requirement 自我运转,对其他模块封闭。
目前只考虑与消息传送有关的 Requirement。这里有两类 Requirement
源节点
INIT:
WAITING: 只在源节点存在,reqr 已经发给足够的中继节点。
SENDING: 只在源节点存在,reqr 尚未发给足够的中继节点。
FINISH 状态: 由 ack-reqr 设置
中继节点
INIT:
MSG_RECV:
FINISH:
目的节点
INIT:
FINISH:
当一个 requirement 到达目的节点之后,会自己根据 check_reqrs 列表自己判断是否是重复的 reqr(详细见 sendmsg-reqr 的状态机),不管是否重复,都需要回复一个 ack-reqr,这是因为重复的 reqr 有可能是源节点超时重传的结果,必须回复一个 ack。这里防止重复是对上层而言的,防止将重复的数据传给上层,而不是防止接收到重复的 reqr。
Requirement 只能发给直接相连的邻居路由器。 路由采用泊松分布模型。每个节点估计一个到目的节点的 mu 值。对源节点来说,一个 requirement 在 SENDING 状态下,
union_lambda = union_lambda + (1/mu)。 (超时设为 1/union_lambda * 2)
中继节点的的超时设为 mu * 2
目的节点的的超时(保留在 check_reqrs 列表的时间)设置为一个较大的值,目前取 6 天。
如果进一步考虑文件对象的传输,还需要设计一个 getfile-reqr,这个 requirement 只是发送一个获取文件的请求,当目的节点收到请求之后,会发送两个 requirement, 一个是 sendfile-reqr,另一个是 ack-reqr,之所以要将数据和 ack 分开是因为如果目的节点收到多个重复的 getfile-reqr,就需要回复多个 ack,如果数据和 ack 是绑定 在一起的话,数据也会被重复发送多次。
(是否能够将各种对象的传输统一起来,只用一套 requirement 来传输?)
中转的消息只有 server 程序内对其有引用计数,可以用引用计数来管理其生命期。 非中转的消息由于本地 server 无法知道哪些本地 client 需要或正在使用它,所以不能用引用计数来管理。现在的方案是全部保存。
先考虑如何处理中转消息。
Ccnet 提供以下服务
put (key, value)
get (key)
见 http://www.thoss.org.cn/trac/ccnet/report/1
A Universally Unique IDentifier (UUID) URN Namespace rfc4122
Pastry http://freepastry.rice.edu
http://en.wikipedia.org/wiki/Collanos
http://www.thoss.org.cn/mediawiki/index.php/Ccnet