解决 Eclipse SVN 插件(Subversive)内存不足的问题

2010/08/21 | 13:55 | 分类:Linux与开源 | 标签: | 3,821次阅读

  最近的一个项目有点夸张,SVN 上的源代码量超过 1G(事实上是出于种种原因,将很多第三方 jar 之类提交到了 SVN 上)。项目初创到不断壮大的过程中,持续参与的开发人员并没有发现什么问题。但后期新加入的开发人员则发现使用 Eclipse SVN 插件(Subversive)无法完成从无到有的 Check out 操作,Eclipse 总是出现 Java heap space 错误。这很可能是由于 Subversive 实现的问题,在处理庞大的代码库时将堆内存耗尽。根据经验,我们可以修改 eclipse.ini 中的 Java 内存限制,但部分开发人员发现在自己的机器上即使修改到极限,Subversive 仍会报错。于是只能另想办法。
  经测试,在命令行下使用 svn co 是可以正常 Check out 该项目的。但如果把 Check out 出来的项目 Import 到 Eclipse 中,则会发现其缺少 SVN 的相关属性,看不到 Subversive 的上下文菜单。经查,项目的属性并不在项目目录中,而保存在 [WORKSPACE]/.metadata/.plugins/org.eclipse.core.resources/.projects/[PROJECT]/.indexes/properties.index 文件中,这个文件是文本与二进制夹杂的,不便理解与编辑,因此不太容易通过它来添加 SVN 属性。
  最后,我们找到了以下可行的操作路径:
  1、在 Eclipse 中 Check out 项目,Check Out As 对话框的 Depth 选项选择 Only a folder,目标目录为假设 A,完成后关闭 Eclipse;
  2、使用 svn co 命令把项目 Check out 到另一个目录,假设为 B;
  3、把 A 改名为 C;把 B 改名为 A;把 C 中的 .project 复制到 B(因为 .project 通常在 SVN 的 ignore 列表中)。
  4、打开 Eclipse,刷新 A 项目目录。
  这时,带有 SVN 属性的项目就完整地出现在 Eclipse 中了。
  我不是专业 Java 开发人员或专业 Eclipse 用户,因此并不知有没有更好的解决方案。但这也从一个侧面反映了代码管理中存在的问题。另外,负载规模的增长导致 Subversive 内存耗尽,也反映出 Subversive 实现的不周。有兴趣的朋友不妨去帮 Subversive 修正这个 bug。

Btrfs 测试结果简述

2009/12/09 | 22:32 | 分类:Linux与开源 | 标签: | 4,568次阅读

  Btrfs 凭借着其优良的可伸缩性和诸多有用的特性,有望成为 Linux 下一代文件系统。目前它已被纳入主流内核支持,接受用户的实验性(Experimental)使用。
  今年 2 月 hutuworm 给出了一篇《Ext4 ReiserFS Btrfs 等七种文件系统性能比拼》,他是在 2.6.29-rc3 内核上使用 IOZone 3.318 做的测试。Btrfs 官方 Wiki 也给出了一些第三方测试数据,基于的是 4、5 月份的版本。官方 Wiki 同时指出他们在不断解决这些测试中所发现的问题和瓶颈。这几天我也对 Btrfs 进行了一些测试,并针对某些新特性进行了研究。我的测试基于 2.6.32 内核,使用的工具是 IOZone 3.327,对比对象为 ext3 和 ext4,机器配置为 2 * 4Cores Xeon 2.0G / 8G Memory。从测试结果看,性能方面,Btrfs 在 CPU Cache 区和 Buffer Cahce 区较好,在 Disk I/O 区不如 ext3/ext4(所谓三个区的划分参考 IOZone 文档);可靠性方面,Btrfs 仍有待加强。下面简述我的几条观察(详细数据省略)。

Btrfs 测试结果简述
./iozone -Rab output.xls -g 16G

Btrfs 测试结果简述
./iozone -Rab output.xls -s 16G -r 2M

Btrfs 测试结果简述
tar cf *.tar *; tar jcf *.tar.bz2 *

  性能方面:
  1.CPU Cache 区和 Buffer Cahce 区的 read 吞吐率,Btrfs、ext3、ext4 相差不大。
  2.CPU Cache 区和 Buffer Cahce 区的 write 吞吐率,明显地 Btrfs 优于 ext4 优于 ext3(tar 测试检验了这个结果)。
  3.Disk I/O 区的 read 吞吐率 ext3 占优,write 吞吐率 ext4 占优,而 Btrfs 两方面均劣于 ext3、ext4(与 hutuworm 的结论类似)。
  4.三个文件系统对于小于 CPU Cache 区的小文件,都有“文件或记录过小时读写性能变差”的问题。其负面影响程度 BtrFS 大于 ext4 大于 ext3。
  而可靠性方面,常规的读写校验并没有出现问题,但在测试 Copy on write(COW)特性时,先后遇到两个错误:
  1.最初使用 2.6.31-15 内核测试,出现了克隆文件与原始文件计算 MD5 有可能不一致的问题。开发人员回复说这个 bug 已经在 2.6.32-rc 以后的内核中修复。升级内核后此问题得以解决。
  2.目前使用 2.6.32 内核测试,发现同时读写原始文件和克隆文件,有可能致使 syslogd 出错、文件系统没有响应。现在我还没有得到可靠的答复,但相关回复者基本怀疑是竞态问题。
  有关 Btrfs 其它的高级特性我还没有详细测试。正在使用或打算使用 Btrfs 的朋友,也欢迎与我交流。

在 Dell PowerEdge 1950 上安装 Linux 2.6.32-rc8 内核的问题与解决

2009/12/03 | 19:26 | 分类:Linux与开源 | 标签: | 6,221次阅读

  出于实验和使用 Linux 内核某些新特性的需要,我要在 Dell PowerEdge 1950 服务器上安装最新的内核,而且必须是 2.6.32-rc 以后的版本。由于服务器硬件的特殊性,这一过程费了一番周折,最终在 @Sisyphusliu 师兄的帮助下搞定,记录如下。
  服务器上已安装的操作系统是 CentOS 5.3,软件栈的需求使之不能用别的发行版替代。保守的 RHEL/CentOS 5 系列的软件源上最新的内核是 2.6.18-164,因此只能从 Linux Kernel 官方获得我们所需的内核,自行编译安装。
  在 Kernel.org 下载当前最新的 2.6.32-rc8 内核,将原有内核的 config 文件复制过来,重新 make menuconfig,加入我们需要测试的新特性,然后编译、安装,这一过程顺利。但在系统重启之后,initrd 中的 init 脚本却报出“mount: could not find filesystem '/dev/root'”的错误。看来新内核没有成功挂载本地根文件系统,所以我们仍改用旧内核启动,开始排查原因。
  PowerEdge 1950 服务器安装了 RAID 卡,即使只使用一块硬盘,它也会走 RAID 的 Virtual Drive。因此 RAID 卡成了最大的嫌疑。检查新内核配置,与 RAID 相关的选项都已经选中,编译出来的 modules 目录中也存在诸如 raid456.ko 之类的模块,那么是什么地方有所缺失呢?对比旧内核与新内核的 initrd 中的 init 脚本,发现 raid456.ko 之类并没有在启动时加载;新旧内核不同的地方在于:旧内核加载了 dm-raid45.ko 模块,而新内核则没有。对比两个内核的配置文件,发现 dm-raid45 相关的内容只在旧内核中出现,新内核没有相应的选项,也没有对应的源代码。
  于是我们需要核查 dm-raid45 的身份。google 发现 dm- 系列模块不是 Linux Kernel 官方组件,而是 RedHat 开发的 Device-mapper 模块,是以 patch 方式添加到内核中的。CentOS 5 软件源提供的修改版内核中,已经附带了包含 dm-raid45 在内的 3000 多个 patch,这些在我们下载的标准内核中当然没有。在 dm-raid45 的作者 Heinz Mauelshagen(傻根?)的主页上,提供了 dm-raid45 patch 下载,但均针对的是较旧版本的内核,打在新内核上编译屡屡出错。进一步的 google 使我们惊喜地发现,Mauelshagen 一周之前在 Kernel Patchworkβ 上发布了针对 2.6.32-rc8 的 dm-raid45 patch——尽管他这个 patch 的主要目的是提供一个 xor 算法,但这个版本恰好能为我们实验所使用。下载并运行这个 patch 之后,内核编译通过并生成了 dm-raid45.ko 模块,init 脚本中也自动增加了相应的 insmod 语句。
  然而重新启动系统后,除了多了几句 insmod 的输出,mount 语句照样出错。难道我们找错了原因?这次不猜了,直接深入 initrd 内部分析吧。我们将 initrd 解包,在 /bin 目录中放一个静态编译的 busybox,并在 init 脚本的 mkrootdev 语句(这一语句创建了 /dev/root 节点)之前插入 busybox sh 命令。将这个 initrd 重新打包后重启系统,即可对 initrd 阶段的执行进行调试。调试时,我们发现 initrd 的 /sys/devices 目录下已经出现了一系列 PCI 设备,用 find 查找,其中有一个正是包含了 sda、sda1 等磁盘和分区的节点。看来硬盘是正常工作的。而在 /dev/ 目录下,却没有出现 /dev/sda、/dev/sda1 等设备节点。看来是 mkrootdev 之前的 mkblkdevs 语句没有生效。我们进入 nash,再次执行 mkblkdevs,发现仍然没有效果。于是试图采用 mknod 命令手工建立设备节点。mknod 所需的主、从设备号可以在类似于“/sys/devices/pci0000:00/.../block/sda/sda1/dev”的文件中找到,其语法也可以参考 init 脚本中的其它几条 mknod 语句。在 nash 中手工 mknod 之后,运行 mkrootdev、mount 仍然没能将本地根文件系统挂载。但改用 busybox 中的 mount,挂载则是成功的,可以访问磁盘文件。
  于是我们推测,可能是 CentOS 5 中较旧版本的 mkinitrd 及其包含的 nash 与新版本的内核出现了不兼容。因为使用新版内核的 Fedora 中的 mkinitrd 和 nash 早已进化到了 6.0.X 版,而 CentOS 5 中的还是 5.1.19.6 版。CentOS 5 的软件源上并没有更新版本的 mkinitrd,在分析了 mkinitrd 包的依赖关系之后,我们认为 6.0.X 有太多的、较为关键的依赖项(而 5.1.19.6 版的 nash 是静态编译的单个文件)。贸然使用 Fedora 源更新 mkinitrd 有可能造成较大范围的影响,不利于我们软件栈的稳定移植。我们需要的只是 initrd 中的 nash,因此可以从更容易的途径获得。我们从一台安装了 Fedora 10 的机器中复制出 initrd,将 nash 6.0.71 及其依赖的库覆盖到 CentOS 5 的 initrd 中。使用这个 initrd 启动,调试 mkblkdevs、mkrootdev 和 mount 顺利通过,最终 Linux 成功启动,文件系统访问正常。
  不过仔细观察启动时输出的信息,我们还是发现了两个小问题。一是 init 脚本中 stabilized 语句报错:“Could not detect stabilization, waiting 10 seconds”,经查这是 Fedora 10 上 mkinitrd 的一个 bug,在 switchroot 之后并不影响根文件系统的使用,可以忽略。再者是在执行 /etc/rc.d 下的脚本时,udevd-event 报错:“udevd-event[XXXX]: wait_for_sysfs: waiting for '/sys/devices/pci0000:00/.../ioerr_cnt' failed”。估计这也是旧版工具与新版内核不兼容的问题,udevd 主要用于监听设备的热插拨等事件,在我们的实验环境中一般不会涉及。毕竟这只是一个使用 rc 版内核的实验环境,这个问题暂不予理睬。我们最终需要测试的程序在新版内核上运行通过,效果良好。

更新于 2009-12-06:
  在我们刚刚取得基本成功的时刻,恰逢 Linux 2.6.32 正式版内核发布,要不在正式版内核上也实验一下吧。既然上面是因为升级 nash 而最终成功的,那么 dm-raid45 有可能不是核心问题所在。因此在编译正式版内核时,我们没有加入 dm-raid45,而只替换了 nash 版本。结果一次就启动成功!看来这个问题真是 nash 引起的。至于 dm-raid45,这个机器使用的是硬件 RAID 卡,对操作系统透明,一般不需要内核支持;而 dm-raid45 是软 RAID 模块(感谢网友指正),对我们的系统来说安装不安装无所谓。

更新于 2009-12-07:
  今天 google 到了另一种解决方案:编译内核前,在 .config 中设置“CONFIG_SYSFS_DEPRECATED_V2=y”即可。经我们实验,果然如此。究其原因,google 到的答案[1][2]大约是说旧版的 mkinitrd 及其 nash 在内核没有 CONFIG_SYSFS_DEPRECATED_V2 参数时默认使用旧版 sysfs 路径格式,从而在新内核下无法正确访问 /sys 内的硬盘信息节点。

让 Dropbear 更好地支持 PAM

2009/10/22 | 14:45 | 分类:Linux与开源 | 标签: | 3,923次阅读

  Dropbear 是一套来自澳大利亚的 *nix SSH 工具集,以体积微小著称,因此在嵌入式环境被广泛中使用。Dropbear 支持 Linux PAM,但直到目前最新的 0.52 版本,它对 PAM 的支持仍极其有限,只能做基本的身份认证(auth、account),不支持会话与密码管理(session、password)。在使用时,我发现即使是 Dropbear 已实现的 PAM 特性也存在一些不大不小的问题,需要自己动手解决。不过作者在 configure 的帮助中已经说明了现在只是“Try to include PAM support”,并且在与 PAM 相关的源代码注释中多次告知用户可以在什么地方 add、edit、hack 一些代码来满足自己特定的需求。我在编译部署 Dropbear 时,为了正常使用 PAM 认证,做了如下工作(基于 0.52 版本):
  1.开启 PAM 支持
  不要以为 configure 时加入 --enable-pam 参数就开启了 PAM 支持,仔细看 configure 输出的最后一句:Now edit options.h to choose features。我们需要自行修改 options.h,定义 ENABLE_SVR_PAM_AUTH 宏,同时将与其冲突的 ENABLE_SVR_PASSWORD_AUTH 宏注释掉,这样 PAM 相关的代码才会被启用。
  2.修正每次 PAM 会话(conversation)之后立即销毁密码的 bug
  svr-authpam.c 中的 pamConvFunc 函数实现了将客户端消息传递给服务端 PAM 的会话。为安全起见,第 119 行使用 m_burn 函数将用完的消息中的密码销毁(使用 0x66 字符覆盖)。但我们知道,在一次 pam_authenticate 调用中有可能配置了多个 PAM(pam_unix.so、pam_ldap.so……)陆续调用应用程序提供的会话函数来取用户名、密码,如果在第一次会话之后立即销毁密码,后续的会话就无法正常工作了。因此,需要等待所有 PAM 会话结束之后再销毁密码。我们可以注释掉 119 行;而 pam_authenticate 之后销毁密码的工作在 svr_auth_pam 函数中已经实现,不用新增。
  3.去除 PAM 会话函数只识别“password:”提示符为密码消息的限制
  svr-authpam.c 的第 101 行限制了密码消息的提示符为“password:”,但一些 PAM 有可能使用其它自定义的提示符,这使得 Dropbear 拒绝传送密码。事实上像 OpenSSH 等软件只是通过消息的类型为 PAM_PROMPT_ECHO_OFF 来认定其内容为密码,而不在意提示符是什么。因此,我们可以去除此处对提示符的判断,让使用自定义提示符的 PAM 也能与之兼容。
  4.解决 PAM 和基于 NSS 的用户映射无法同时工作的问题
  有的应用系统结合使用 PAM 以及 GNU C Library 提供的 NSS 特性实现应用级的用户到本地系统用户的映射。在这类系统中,用户提供给 PAM 的应用级用户名在 NSS 中被映射为本地系统级用户名,用户只持有应用级的密码而不用知道本地系统级的密码。login、OpenSSH、vsftp 等程序对此种需求的支持良好,但 Dropbear 的实现却是首先调用 getpwnam 获得本地系统级用户名(已经由 NSS 映射过的),再用这个用户名去调用 PAM 认证,这就使得 PAM 得到的是“本地系统级用户名+应用级密码”的组件,自然验证失败。我们可以修改 Dropbear 的实现,在 svr-authpam.c 的 recv_msg_userauth_request 函数中保存客户端输入的用户名,在 svr-authpam.c 的 svr_auth_pam 函数中读取前面保存的用户名,而不要使用 NSS 输出在 ses.authstate.pw_name 的本地用户名。
  所有修改如下,如果你也需要在 Dropbear 中支持 PAM 认证,可以直接打上这些 patch。我有空向 Dropbear 的作者反馈一下吧。

  1. dropbear-0.52$ cat options.h.diff
  2. 152c152
  3. < #define ENABLE_SVR_PASSWORD_AUTH
  4. ---
  5. > /*#define ENABLE_SVR_PASSWORD_AUTH*/
  6. 154c154
  7. < /*#define ENABLE_SVR_PAM_AUTH*/
  8. ---
  9. > #define ENABLE_SVR_PAM_AUTH
  1. dropbear-0.52$ cat svr-auth.c.diff
  2. 36a37,38
  3. > char client_login_username[256];
  4. >
  5. 142a145,146
  6. >     strncpy(client_login_username, username, 256);
  7. >
  1. dropbear-0.52$ cat svr-authpam.c.diff
  2. 41a42,43
  3. > extern char client_login_username[256];
  4. >
  5. 101c103
  6. <             if (!(strcmp(compare_message, "password:") == 0)) {
  7. ---
  8. >             if (/*!(strcmp(compare_message, "password:") == 0)*/ 0) {
  9. 119c121
  10. <             m_burn(userDatap->passwd, strlen(userDatap->passwd));
  11. ---
  12. >             /*m_burn(userDatap->passwd, strlen(userDatap->passwd));*/
  13. 198c200
  14. <     userData.user = ses.authstate.pw_name;
  15. ---
  16. >     userData.user = m_strdup(client_login_username);
  17. 247a250,252
  18. >     if (userData.user != NULL) {
  19. >         m_free(userData.user);
  20. >     }

vCard Assistant:将 vCard 导入 Nokia S60v2 手机的辅助工具

2009/09/02 | 00:17 | 分类:手机与移动平台 | 标签: | 8,323次阅读

  晚上为 Nokia S60v2 老机型用户写了一个 PC 端的小工具——vCard Assistant,用于将含有中文姓名的 vCard 文件(可以是 GB、UTF-8 或 UTF-16LE 编码的)转换成 ASCII 字节编码 UTF-8 形式;并可将 vCard 3.0 格式转为 2.1 格式,便于在某些对 vCard 中文姓名或 3.0 标签支持不好的手机中导入联系人。效果如下:
  输入:

BEGIN:VCARD
VERSION:3.0
N:;张三
FN:张三
TEL;TYPE=CELL;TYPE=VOICE:13811112222
EMAIL;TYPE=PREF;TYPE=INTERNET:foo@bit.edu.cn
REV:20090901T035836Z
END:VCARD
BEGIN:VCARD
VERSION:3.0
N:;李四
FN:李四
EMAIL;TYPE=PREF;TYPE=INTERNET:bar@gmail.com
REV:20090901T035835Z
END:VCARD
...

  输出:

BEGIN:VCARD
VERSION:2.1
N;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:;=E5=BC=A0=E4=B8=89
FN;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:=E5=BC=A0=E4=B8=89
TEL;CELL;VOICE:13811112222
EMAIL;PREF;INTERNET:foo@bit.edu.cn
REV:20090901T035836Z
END:VCARD
BEGIN:VCARD
VERSION:2.1
N;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:;=E6=9D=8E=E5=9B=9B
FN;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:=E6=9D=8E=E5=9B=9B
EMAIL;PREF;INTERNET:bar@gmail.com
REV:20090901T035835Z
END:VCARD
...

  这种格式可以被 Best vCard for S60 等软件读取,导入手机通信录。
  vCard Assistant 下载地址(包含源代码):
  http://files.linjian.org/dotNet/VCardAssistant.zip
  (需要 .Net Framework 3.5 平台支持)


  我为什么要写这个东西呢?主要还是自己的需求。我使用的 Nokia 6600 的 PC Suite 只支持从 IBM Lotus Notes、Microsoft Outlook 这类庞大的程序或 Windows Address Book 这种已被放弃的格式中导入联系人。我没有使用这两个商业软件,也不愿使用已经失去官方支持的 WAB 格式,而选择使用跨平台的、广为各类软件支持的 vCard 格式管理联系人,以便在多个系统、软件中直接共享。以前同步联系人时,先将 vCard 导出为 CSV,再使用虚拟机中的 Windows XP 通信录将 CSV 转换成 WAB 格式,然后通过 PC Suite 同步,比较折腾。现在只需要将 vCard 转换一次,通过蓝牙或 Email 发到手机上,用手机端的软件做同步,简便不少。
  事实上我以前也尝试过用 Google Sync 服务在线同步联系人(Gmail 也支持 vCard 导入导出),但同步过程总是异常停止。换用其它一些 SyncML 同步服务问题依旧。最终我在 mobical 网站发现一句话:“Nokia 6600: This device has a known issue where the synchronization may stop working at any time. As far as we can tell this is a bug in the Nokia software.”原来这是 Nokia 6600 的 bug……我也没有找到其它免费的 SyncML for S60v2 客户端,只能作罢。

页面: 上页(较新) 1 2 下页(较旧)