存档

文章标签 ‘svn’

Openfetion近期开发手记(相关功能实现技术)

十月 18th, {2010 29 条评论 8,205 人阅读过  

离上Openfetion上一个版本发布至今过了有将近一个月的时间了,上个版本放出的时候本以为已经解决了很多bug,但发布之后才发现用户遇到的问题还是很多,软件测试还是很重要的,当然有些协议上的问题只能交由用户去测试,我没有那么多飞信号,有些问题有很难遇到的,也很难复现的,所以就在这样不断地与用户沟通中解决问题。

其实做共享软件是件很开心的事情,不管你做得好不好,都会有人支持你,这个是很重要的,因为在最初开发openfetion的时候并没有想过要把它做为一个专业的飞信客户端放出来大家一起使用,可发布之后得到了广大linux用户的支持,即使那时候的bug比现在多得多,仍然有用户乐此不彼地帮我测试,反溃问题,提供建议,当然我也乐此不彼地修改程序,希望有朝一日它能让所有的用户都能稳定地运行,这也是自由软件的优势,如果当初这做为一个商业软件发布,我想毫无疑问,收到的会是一片骂声,然后这个项目也便会匆匆截止,而现在即便很忙也会拿出一些时间来加强它,因为总会有用户支持着它,也会有开源爱好者加入进来做一些贡献。

Openfetion下一个的版本号应该是2.0了,我想2.0应该和之前的1.x版本有所区别,功能上这个不是特别重要,因为之前的版本已经有了几乎所有的基本功能,其它的一些不常用的功能我也没考虑过,因为开发那些功能是一件性价比很低的事情,现在所能想到的2.0和1.x的区别应该是让2.0更加稳定,功能再丰富如果不能稳定运行这个软件就永远成不了优秀的软件,因为我在新版本里面做了大批量的代码修改,甚至包括以前一些很不专业的编码习惯,尽可能将所有潜在的问题都消灭掉,当然也加了一些用户一直以来要求的功能,下面简单地说一下。

首先,是在之前版本中,用户反映登录速度过慢,这个我承认,是因为在之前的版本中没有加入数据的本地缓存,每次用户登录的时候都会需要重新从服务器上请求自己相关的所有数据,包括用户列表和配置文件这样庞大到几个K甚至十几个K的数据,这不可避免地会导致登录过程过慢,甚至网络状况不好的时候,会导致在获取配置文件的时候卡在那里,这些问题都降低了用户体验,解决这些问题的方法毫无疑问是加入本地用户缓存,这也是网络软件所常用的方式,之前我把一些本地配置信息和聊天记录保存在本地所用的方法是直接使用二进制写入dat文件,那种方法灵活性非常差,而且效率也很低,所有就没有对其它的动态数据做缓存,现在在新版本中引用了sqlite3,这个轻量级的数据库无疑是实现这个功能的绝佳选择,使用起来很简单,而且灵活性也很高,基本的SQL语句几乎都支持,之前只是知道有这么个东西,但一直没用过,这次试了一下,发现使用起来也非常简单,于是毫不犹豫就把它给引入了,我想加入了这样一个依赖所带来的用户体验的提高是很大的,希望不会有用户抱怨引赖关系增多。

另外,在将数据进行本地缓存之后便为另一个功能的实现提供了基础,那就是离线登录功能,和IM的离线功能一样,就是在没有网络连接的情况下登录Openfetion,可以查看好友列表,当然这些好友信息都是存储在本地数据中的,通过sqlite3从数据库中提取出来的。

聊天记录改用sqlite3存储之后提取和写入也都方便了很多,而且还添加了删除聊天记录的功能,之前用二进制数据直接写入的方式保存聊天记录所带来的不便就是不能方便地删除聊天记录,如果要删除只能先把整个聊天记录都加载到内存中,然后从中删掉要删除的信息,之后再重新写入磁盘覆盖掉原来的文件,这样效率是非常低的,而用sqlite3直接可以用一条DELETE语句删掉想要删除的信息。

同样这次也加入了本地用户列表删除功能,用户登录完后记录在本地的用户名密码数据也同样都可以删除。

另一个很重要的功能是空闲时间自动离开功能,这个功能之前一直不知道该怎么实现,纠结于当焦点不在Openfetion中时,如何获取全局的鼠标键盘动作,而即便获取到了又如何检测是否空闲,这些问题都非常麻烦,后来查看了一下pidgin的源码,才发现其实IM软件所实现的空闲时间检测功能一般都是通过调用XScreenSaver来实现的,包括之前的evaqq也是之样实现的,过程很简单,下面的几行代码便是获取空闲时间的函数,通过周期性地检测空闲时间便可以判断出IM是否需要进行离开状态。

gint idle_timesec(void)
{
 
#ifdef USE_LIBXSS
	static XScreenSaverInfo *mit_info = NULL;
	static gint has_extension = -1;
	gint event_base, error_base;
 
	if (has_extension == -1)
		has_extension = XScreenSaverQueryExtension(
				GDK_DISPLAY(), &event_base, &error_base);
 
	if(has_extension){
		if (mit_info == NULL)
			mit_info = XScreenSaverAllocInfo();
 
		XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(), mit_info);
		return (mit_info->idle)/1000;
	}
#endif
	return 0;
}

这需要XScreenSaver的支持才行,于是加入了条件编译,在ubuntu或者debian中可以通过下面的命令安装XScreenSaver开发包:

sudo apt-get install libxss-dev

另外一个很重要的功能是断线自动离开功能,这个用tcp的相关特性来检测链路状态灵敏性太低,参考了一下pidgin和empathy,它们用的方法都是调用NetworkManager的相关API来实现的,NetworkManager是基于dbus的,之前在slackware13.1上因为安装NetworkManager失败,而导致之前同学写的基于nm和dbus的程序在我这里不能跑,从而对这个一直留有某种恐惧感,当然现在也意识到要让程序在网络状态改变的时候即刻感知到,最佳方法还是使用libnm,下面的函数便是初始化libnm的函数,它为网络状态改变的事件注册了回调函数nm_state_change()

void fx_conn_init(FxMain *fxmain)
{
#ifdef USE_NETWORKMANAGER
	GError *error = NULL;
        DBusGConnection *nm_conn = NULL;
        DBusGProxy *nm_proxy = NULL;
 
	nm_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
	if (!nm_conn) {
		debug_error("Error connecting to DBus System service: %s.\n", error->message);
	} else {
		nm_proxy = dbus_g_proxy_new_for_name(nm_conn,
		                                     NM_DBUS_SERVICE,
		                                     NM_DBUS_PATH,
		                                     NM_DBUS_INTERFACE);
		dbus_g_proxy_add_signal(nm_proxy, "StateChange", G_TYPE_UINT, G_TYPE_INVALID);
		dbus_g_proxy_connect_signal(nm_proxy, "StateChange",
		                        G_CALLBACK(nm_state_change), fxmain, NULL);
	}
#endif
}

下面的代码是回调函数的代码,在它里面能过检测各种网络状态而做出相应的动作:

static void
nm_state_change(DBusGProxy *proxy, NMState state, gpointer data)
{
	switch(state)
	{
		case NM_STATE_CONNECTED:
			debug_info("network is connected");
			break;
		case NM_STATE_ASLEEP:
			debug_info("network is sleeping...");
			break;
		case NM_STATE_CONNECTING:
			debug_info("network is connecting...");
			break;
		case NM_STATE_DISCONNECTED:
			debug_info("network is disconnected");
			break;
		case NM_STATE_UNKNOWN:
			debug_info("unknown network state");
		default:
			break;
	}
}

ubuntu或debian中NetworkManager开发包的安装方法如下:

sudo apt-get install libnm-glib-deb

要说的是,XScreenSaver和NetworkManager的使用都是可选项,为了避免不愿意引入这些库的用户抱怨,可以在configure的时候用–disable-screensaver和–disable-nm将其禁用。

另外也解决几个崩溃的bug,比如添加好友时崩溃,这个纯粹是我编码过程中出现的失误,还有群发短信时崩溃的问题,这个也是我编码的失误,都已经修改过来了,有时候收到的信息会显示发送失败,这个也修改好了,一个比较重要的bug是多人同时聊天在窗口切换的时候可能会崩溃的问题,这个问题现在也已经解决了。

有时候程序会出现 ”Program received signal SIGPIPE, Broken pipe.“这样的错误,这个信号一般是在服务器端主动关闭连接时客户端会收到的来自操作系统的信号,理论上服务器端主动关闭连接这个可能性不大,但它有时候确实会出现,之前没有对这个信号进行处理,这次把这个信号直接忽略了,然后在send和recv的时候就会返回-1,通过返回值就可以检测连接状态。

 struct sigaction sa;
 sa.sa_handler = SIG_IGN;
 sigaction( SIGPIPE, &sa, 0 );

还有用户提到在登录时登录按钮状态不变,这个之前没怎么在意,这次也修改过来了,不过没有加取消登录的功能,这个也考虑过,不过没想到实现的方法,因为登录线程用的是gthread库,而它没有像pthread一样提供取消线程的方法,一时间也不知道该怎么去实现,这个先暂时一放,希望有了解这个的朋友可以提供些帮助,现在的实现方法是像官方飞信一样在点击登录后改变登录界面,自己还用GIMP做了个登录正在进行的gif,就是让Openfetion的图标一直在转,哈哈,很有成就感,上两个登录界面的图吧。

image image

图片里面没有打码,这个飞信号是我测试用的小号,无所谓了,反正也不用。

这次新版本想多测试一段时间再发,肯定还存在问题,尽可能在发布之前能解决更多的问题,能让2.0正式版更稳定,能让用户更满意,同时也欢迎大家到svn上co最新的版本试用,并帮忙测试,如果你有问题,请向我反溃,这样我才能帮你解决问题。svn :

svn checkout http://ofetion.googlecode.com/svn/trunk/ ofetion-read-only

分类: C/C++ 标签: , , ,

SVN使用小结(在google code上管理代码)

四月 6th, {2010 3 条评论 11,455 人阅读过  

前几天发布了openfetion的新协议版本,在Ubuntu中文论坛上发了个贴子宣传了一下,Ubuntu在中国果然不愧是拥有最状大的用户群,以前在其它的开源社区发的时候点击率都很低(当然也可能是大家觉得这个很没意思),不过这次Ubuntu论坛里面的网友们让我很感动,大家回馈了丰富的修改意思,也提交了各种现存的bug,还有的网友帮我打了deb包和rpm包,甚是感动,在这里先谢一下,由于bug太多,一个多星期的时候更新了两个版本,本来这个东西就是做出来玩玩的,看来还是有很多人喜欢的,所以我也决定用继续用我的休息时间把它做下去,之后考虑加上文件传输和非移动号码登陆这些有用的功能。

OK,扯远了,这篇文章是要总结一下svn的用法的,很多人发邮件问我关于飞信相关协议的问题,我也都给一一回复了,可也着实花费了不少的时间,后来就写了几篇相关的文章,仍然有人对一些细节不解,没办法,后来我也管不了那么多了,就把飞信给完全开源了,希望我的行为能对祖国的开源事业做一点小小的贡献吧。

突然觉得sourceforge和google code的svn代码管理很有用,以前在服务器上搭过cvs,后来嫌麻烦就一直没用,看了看svn的一些介绍,发现用起来着实简单方便了不少,于是就想用一用了,本来想在实验室服务器上搭一个的,后来想既然开源了就放到网上跟大家共享吧,gg去香港后在实验室上就很不稳定了,偶尔上得去偶尔上不去,于是想放到sf上去,结果sf的svn服务器教育网不加代理访问不了,抓包看了下svn的协议是TCP承载的TLS,只有http的代理,也不知道行不行,懒得研究就用gg了。

又扯了一大堆费话,总结一下svn的基本命令吧。

svn checkout :简写是svn co
example:

$svn checkout https://ofetion.googlecode.com/svn/trunk/ ofetion –username levin108

这个没什么好说的,跟cvs的checkout一个意思,从版本库中取出一个项目的拷贝,输入后会提示输入验证码,验证通过后会提示是否以保存在本地,保存的话以后就不用输入了。

svn commit :简写是svn ci
example:

$svn commit -m “modified some bugs”

将本地项目拷由的修改提交到版本库藏, 不加-m会的话提示一些乱七八糟的东西,没细看。

svn copy :简写svn cp

复制本地项目副本到版本库

svn move (mv), svn delete (rm,del),svn mkdir

故名思义吧,跟copy差不多,懒得说细地写了。这些操作所做的修改都会保存到本地缓存中,执行svn ci后才会同步到版本库。

svn import
example:

$svn import -m “initial import” https://ofetion.googlecode.com/svn/trunk/ ofetion –username levin108

递归地把一个目录下的文件提交到版本库,这个目录提交上去后它里面并没有版本库信息,我觉得应该在执行完这条命令后就应该在所有的目录中创建.svn文件夹,以保存版本库信息的。

所以就只能再把版本库中的项目checkout下来,这样的话各目录中就有了版本控制信息了,就可以进行版本控制操作了。

svn blame
example:

$svn blame Makefile.am

2 levin108 SUBDIRS = src include skin resource
2 levin108
2 levin108 EXTRA_DIST = LICENSE LICENSE.OpenSSL
2 levin108
2 levin108 install: install-recursive
2 levin108 @echo “———————————————————-”;
2 levin108 @echo “| |”;
2 levin108 @echo “| OpenFetion 1.2 by lwp(levin108@gmail.com) |”;
2 levin108 @echo “| |”;
2 levin108 @echo “| OpenFetion a fetion client for linux based on GTK+2.0,|”;
2 levin108 @echo “| using Fetion Protocol Version 4. It supports most |”;
2 levin108 @echo “| useful functions of Mobile Fetion,more important. |”;
2 levin108 @echo “| It\`s small and fast,and is better in look. |”;
2 levin108 @echo “| More information at http://basiccoder.com/openfetion |”;
2 levin108 @echo “———————————————————-”;

显示指定文件(本地的或者远程版本库中的)作者和修订版本信息。 当然看到这个命令的输出的时候才发现原来版本控制软件真的很强大。

svn log
example

$ svn log
————————————————————————
r11 | levin108 | 2010-04-06 19:31:11 +0800 | 1 行
4.5
————————————————————————
r10 | levin108 | 2010-04-06 18:49:41 +0800 | 1 行
test
————————————————————————
r9 | levin108 | 2010-04-06 18:49:18 +0800 | 1 行

显示提交日志信息。

svn status

打印工作拷贝文件和目录的状态,如A,D,U…详细如下:

A 添加
D 删除
U 更新
C 冲突
G 合并

svn list
example:

$ svn list https://ofetion.googlecode.com/svn/trunk/ –username levin108
AUTHORS
COPYING
ChangeLog
INSTALL
LICENSE

列出版本库目录的条目

svn update
example:

$svn update -r7

用版本号为7的版本库项目更新你的本地项目副本,不加-r就默认用最新的版本更新,这个命令很重要。

常用的命令差不多就这些了,其它不常用的我也记不住了,写一下以后自己忘了可以过来查

分类: Linux 标签: ,