lemon语法分析器模板初探
[| 2012/04/18 00:24]
今天看了一下lighttpd解析http头的过程,之前一直以为是单纯用遍历字符串的形式做的,今天发现除了遍历字符串,还用到了语法分析器来做解析,生成语法分析器模板的就是lemon,语法比较直观,不看文档就能大概看出逻辑,不过深入研究就要借助文档了,文档比较晦涩,需要仔细研究。
大概用法:使用lemon的语法编写一个.y文件,然后调用lemon命令或使用lemon源文件将.y转化成.c和.h,转化后的.c看起来就很晕了,完全看不懂的说。
这个东西还是挺有意思的,lighttpd还用它来解析配置文件。不过配置文件用lua也很不错啊。我准备以后多使用lua作为配置文件,方便灵活。
大概用法:使用lemon的语法编写一个.y文件,然后调用lemon命令或使用lemon源文件将.y转化成.c和.h,转化后的.c看起来就很晕了,完全看不懂的说。
这个东西还是挺有意思的,lighttpd还用它来解析配置文件。不过配置文件用lua也很不错啊。我准备以后多使用lua作为配置文件,方便灵活。
git push中的non-fast-forward问题
[| 2012/04/16 13:50]
今天在回滚一个git操作记录时(使用了git reset --hard)遇到了问题,在push回服务器时提示:
error: failed to push some refs to 'qiuxueda@bb-iis-dev01.vm:code/comlogsvr-proxy'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. 'git pull') before pushing again. See the
'Note about fast-forwards' section of 'git push --help' for details.
看了一下文档:
原文:
NOTE ABOUT FAST-FORWARDS
When an update changes a branch (or more in general, a ref) that used to point at commit A to point at another commit B, it is called a fast-forward update if and only if B is a descendant of A.
In a fast-forward update from A to B, the set of commits that the original commit A built on top of is a subset of the commits the new commit B builds on top of. Hence, it does not lose any
history.
In contrast, a non-fast-forward update will lose history. For example, suppose you and somebody else started at the same commit X, and you built a history leading to commit B while the other
person built a history leading to commit A. The history looks like this:
B
/
---X---A
Further suppose that the other person already pushed changes leading to A back to the original repository you two obtained the original commit X.
The push done by the other person updated the branch that used to point at commit X to point at commit A. It is a fast-forward.
But if you try to push, you will attempt to update the branch (that now points at A) with commit B. This does not fast-forward. If you did so, the changes introduced by commit A will be lost,
because everybody will now start building on top of B.
The command by default does not allow an update that is not a fast-forward to prevent such loss of history.
If you do not want to lose your work (history from X to B) nor the work by the other person (history from X to A), you would need to first fetch the history from the repository, create a history
that contains changes done by both parties, and push the result back.
You can perform "git pull", resolve potential conflicts, and "git push" the result. A "git pull" will create a merge commit C between commits A and B.
B---C
/ /
---X---A
Updating A with the resulting merge commit will fast-forward and your push will be accepted.
Alternatively, you can rebase your change between X and B on top of A, with "git pull --rebase", and push the result back. The rebase will create a new commit D that builds the change between X
and B on top of A.
B D
/ /
---X---A
Again, updating A with this commit will fast-forward and your push will be accepted.
There is another common situation where you may encounter non-fast-forward rejection when you try to push, and it is possible even when you are pushing into a repository nobody else pushes into.
After you push commit A yourself (in the first picture in this section), replace it with "git commit --amend" to produce commit B, and you try to push it out, because forgot that you have pushed
A out already. In such a case, and only if you are certain that nobody in the meantime fetched your earlier commit A (and started building on top of it), you can run "git push --force" to
overwrite it. In other words, "git push --force" is a method reserved for a case where you do mean to lose history.
我的翻译版(不是严格依照原文,按自己理解的意思复述):
关于 FAST-FORWARDS
当修改一个branch(或ref)时,在a是b的直接基线或祖先基线的情况下,将HEAD指针从a移动为b叫做fast-forwards
在这种情况下,因为不会丢失任何历史数据,所以叫做fast-forward
但是,对于non-fast-forward就会丢失历史数据,设想你和另一个人同时以x为基线开发,你开发了一个叫b的commit,而那个人开发了一个叫a的commit:
B
/
---X---A
如果那个人已经将a提交到了服务端,现在服务端的head指向了a,如果你试图去提交b,那么服务端会试图将head从a移动到b上,如此一来,就会丢失a的修改内容,这就是non-fast-forward。
所以默认情况下不允许这种提交,以防止数据丢失
如果你不想丢失你的和别人的工作成果,那么需要先从服务端获取其他人的修改,生成一个包含你的和其他人修改的commit,然后将其提交到服务器。
你可以先运行git pull,然后解决合并冲突,然后git push。git pull会基于a和b生成一个c记录,同时包含两者的修改内容
B---C
/ /
---X---A
这样提交c请求就变成了fast-forward请求,从而被允许。
同样的,你可以在a基础上添加从x到b的这些请求,使用git pull --rebase并push结果到服务器,这样会生成一个commit:d,在a的基础上添加了从x到b的修改
B D
/ /
---X---A
这也是一个fast-forward请求,是被允许的。
(这一段不是特别理解。。像是废话,因为跟上图第一种情况看起来是一回事)还有一种情况,即使没有其他人向版本库推送过数据,你也可能遇到non-fast-forward的情况:
当你推送a到服务端后,又使用了git commit --amend 修改a为b,然后可能忘记已经推送过a,于是试图去推送b到版本库。这样的话,当你确认没有人fetch过a的话,可以使用git push --force去覆盖这个记录。
也就是说,当你确认你确实需要丢失历史数据时,可以使用git push --force来强制推送
在gitolite中,对于每个版本库的授权就有“RW+”字段,其中的“+”权限,就是强制推送的权限,由于可能会导致历史提交丢失,所以是比W更高级的权限,需要单独授予。
error: failed to push some refs to 'qiuxueda@bb-iis-dev01.vm:code/comlogsvr-proxy'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. 'git pull') before pushing again. See the
'Note about fast-forwards' section of 'git push --help' for details.
看了一下文档:
原文:
NOTE ABOUT FAST-FORWARDS
When an update changes a branch (or more in general, a ref) that used to point at commit A to point at another commit B, it is called a fast-forward update if and only if B is a descendant of A.
In a fast-forward update from A to B, the set of commits that the original commit A built on top of is a subset of the commits the new commit B builds on top of. Hence, it does not lose any
history.
In contrast, a non-fast-forward update will lose history. For example, suppose you and somebody else started at the same commit X, and you built a history leading to commit B while the other
person built a history leading to commit A. The history looks like this:
B
/
---X---A
Further suppose that the other person already pushed changes leading to A back to the original repository you two obtained the original commit X.
The push done by the other person updated the branch that used to point at commit X to point at commit A. It is a fast-forward.
But if you try to push, you will attempt to update the branch (that now points at A) with commit B. This does not fast-forward. If you did so, the changes introduced by commit A will be lost,
because everybody will now start building on top of B.
The command by default does not allow an update that is not a fast-forward to prevent such loss of history.
If you do not want to lose your work (history from X to B) nor the work by the other person (history from X to A), you would need to first fetch the history from the repository, create a history
that contains changes done by both parties, and push the result back.
You can perform "git pull", resolve potential conflicts, and "git push" the result. A "git pull" will create a merge commit C between commits A and B.
B---C
/ /
---X---A
Updating A with the resulting merge commit will fast-forward and your push will be accepted.
Alternatively, you can rebase your change between X and B on top of A, with "git pull --rebase", and push the result back. The rebase will create a new commit D that builds the change between X
and B on top of A.
B D
/ /
---X---A
Again, updating A with this commit will fast-forward and your push will be accepted.
There is another common situation where you may encounter non-fast-forward rejection when you try to push, and it is possible even when you are pushing into a repository nobody else pushes into.
After you push commit A yourself (in the first picture in this section), replace it with "git commit --amend" to produce commit B, and you try to push it out, because forgot that you have pushed
A out already. In such a case, and only if you are certain that nobody in the meantime fetched your earlier commit A (and started building on top of it), you can run "git push --force" to
overwrite it. In other words, "git push --force" is a method reserved for a case where you do mean to lose history.
我的翻译版(不是严格依照原文,按自己理解的意思复述):
关于 FAST-FORWARDS
当修改一个branch(或ref)时,在a是b的直接基线或祖先基线的情况下,将HEAD指针从a移动为b叫做fast-forwards
在这种情况下,因为不会丢失任何历史数据,所以叫做fast-forward
但是,对于non-fast-forward就会丢失历史数据,设想你和另一个人同时以x为基线开发,你开发了一个叫b的commit,而那个人开发了一个叫a的commit:
B
/
---X---A
如果那个人已经将a提交到了服务端,现在服务端的head指向了a,如果你试图去提交b,那么服务端会试图将head从a移动到b上,如此一来,就会丢失a的修改内容,这就是non-fast-forward。
所以默认情况下不允许这种提交,以防止数据丢失
如果你不想丢失你的和别人的工作成果,那么需要先从服务端获取其他人的修改,生成一个包含你的和其他人修改的commit,然后将其提交到服务器。
你可以先运行git pull,然后解决合并冲突,然后git push。git pull会基于a和b生成一个c记录,同时包含两者的修改内容
B---C
/ /
---X---A
这样提交c请求就变成了fast-forward请求,从而被允许。
同样的,你可以在a基础上添加从x到b的这些请求,使用git pull --rebase并push结果到服务器,这样会生成一个commit:d,在a的基础上添加了从x到b的修改
B D
/ /
---X---A
这也是一个fast-forward请求,是被允许的。
(这一段不是特别理解。。像是废话,因为跟上图第一种情况看起来是一回事)还有一种情况,即使没有其他人向版本库推送过数据,你也可能遇到non-fast-forward的情况:
当你推送a到服务端后,又使用了git commit --amend 修改a为b,然后可能忘记已经推送过a,于是试图去推送b到版本库。这样的话,当你确认没有人fetch过a的话,可以使用git push --force去覆盖这个记录。
也就是说,当你确认你确实需要丢失历史数据时,可以使用git push --force来强制推送
在gitolite中,对于每个版本库的授权就有“RW+”字段,其中的“+”权限,就是强制推送的权限,由于可能会导致历史提交丢失,所以是比W更高级的权限,需要单独授予。
为blog添加ping插件-自动通知搜索引擎
[| 2012/04/13 22:13]
现在主流搜索引擎都支持ping功能了,每当网站更新时可以主动向搜索引擎发一个xml格式信息,称之为”ping“,通知搜索引擎来抓取,对于收录是非常有好处的。
之前一直懒得搞,今天弄了一下。
参照百度站长工具里提供的格式,搞了一个,试试是否好用呢。
添加了baidu和google的ping地址:
http://ping.baidu.com/ping/RPC2
http://blogsearch.google.com/ping/RPC2
之前一直懒得搞,今天弄了一下。
参照百度站长工具里提供的格式,搞了一个,试试是否好用呢。
添加了baidu和google的ping地址:
http://ping.baidu.com/ping/RPC2
http://blogsearch.google.com/ping/RPC2
OpenVZ VPS内存查看分析工具/超售检查脚本
[| 2012/04/12 02:52]
搞了一个python脚本,用来查看OpenVZ VPS内存情况的,原始数据取自/proc/user_beancounters文件,脚本内做了一个数据简单的分析提取和可视化提高的工作,已经很晚了,先搞几个基本功能出来,增强功能以后再补。
用法: python vz_checker.py /proc/user_beancounters (需要root权限)
输出内容:
filename is:[user_beancounters]
Kernel Mem Info: used:[5.723M] max_used:[35.539M] limit:[2048.000M] fail_count:[0]
Mem already allocated Info: used:[17.621M] max_used:[33.074M] limit:[96.000M] fail_count:[0]
Ram actually used: used:[8.516M] max_used:[67.820M] limit:[96.000M] fail_count:[0]
Mem (Ram + swap) used: used:[9.848M] max_used:[13.219M] limit:[96.000M] fail_count:[0]
Kernel Mem Info:占用的内核内存大小,不可被swap,主要用来存放进程数据等。
Mem already allocated Info:已分配的内存大小,limit即为burst内存大小。
Ram actually used: 实际占用的物理内存大小。
Mem (Ram + swap) used: 占用的物理内存和swap大小。
如果 实际占用的物理内存 == 占用的物理内存和swap大小 那么恭喜你,你的vps里运行的程序都在内存中,主机超售不严重。
如果 实际占用的物理内存 < 占用的物理内存和swap大小 情况不妙,主机已经开始占用swap了,超售比较严重了。
另外我在测试过程中发现有一台vps实际占用物理内存大小显示比物理内存+swap总和还要大,现象很奇怪,查了一些资料没有关于这方面的说明,待后续调查。
脚本功能还比较粗糙,一些数据需要继续打磨,欢迎大家提意见~~
本文地址:http://www.snooda.com/read/263
下载地址:https://github.com/snooda/openvz_checker
用法: python vz_checker.py /proc/user_beancounters (需要root权限)
输出内容:
filename is:[user_beancounters]
Kernel Mem Info: used:[5.723M] max_used:[35.539M] limit:[2048.000M] fail_count:[0]
Mem already allocated Info: used:[17.621M] max_used:[33.074M] limit:[96.000M] fail_count:[0]
Ram actually used: used:[8.516M] max_used:[67.820M] limit:[96.000M] fail_count:[0]
Mem (Ram + swap) used: used:[9.848M] max_used:[13.219M] limit:[96.000M] fail_count:[0]
Kernel Mem Info:占用的内核内存大小,不可被swap,主要用来存放进程数据等。
Mem already allocated Info:已分配的内存大小,limit即为burst内存大小。
Ram actually used: 实际占用的物理内存大小。
Mem (Ram + swap) used: 占用的物理内存和swap大小。
如果 实际占用的物理内存 == 占用的物理内存和swap大小 那么恭喜你,你的vps里运行的程序都在内存中,主机超售不严重。
如果 实际占用的物理内存 < 占用的物理内存和swap大小 情况不妙,主机已经开始占用swap了,超售比较严重了。
另外我在测试过程中发现有一台vps实际占用物理内存大小显示比物理内存+swap总和还要大,现象很奇怪,查了一些资料没有关于这方面的说明,待后续调查。
脚本功能还比较粗糙,一些数据需要继续打磨,欢迎大家提意见~~
本文地址:http://www.snooda.com/read/263
下载地址:https://github.com/snooda/openvz_checker
etag生成规则的配置-lighttpd
[| 2012/04/11 15:20]
最近两天调试一个程序的时候遇到一个问题,发现把一个文件两行对换位置的时候lighttpd不会载入新文件,增加或删除一行就会,考虑到lighttpd有stat cache,怀疑是不是不考虑mtime,只看inode,于是cp了一下,发现还是不行。没办法开gdb调试了一下,囧,原来生成的etag只用到了文件size这一个参数。怪不得。
# 生成ETag的时候是否考虑文件的inode
etag.use-inode = "enable"
# 生成ETag的时候是否考虑文件的mtime
etag.use-mtime = "enable"
# 生成ETag的时候是否考虑文件的size
etag.use-size = "enable"
这是引发困扰的三个参数。平时建议全部开启,或开启后两个。
# 生成ETag的时候是否考虑文件的inode
etag.use-inode = "enable"
# 生成ETag的时候是否考虑文件的mtime
etag.use-mtime = "enable"
# 生成ETag的时候是否考虑文件的size
etag.use-size = "enable"
这是引发困扰的三个参数。平时建议全部开启,或开启后两个。
c程序中变量在循环内部还是外部声明的问题
[| 2012/04/09 15:40]
忘记之前从哪看过的一个文章说不要在for、while等循环内声明变量,因为每次都会重复分配空间,很慢。
今天发现一个模块把变量声明都放到while里面了,看了下代码没有发现必须声明在里面的原因,于是开始怀疑是不是声明在内外是差不多的。
于是测试了一下:
int main() {
int i = 0;
for(;i < 10000000; i++) {
int b;
b++;
}
return 1;
}
使用gcc 编译,把int b放在循环内外试了试,用time ./a.out查看执行时间,发现用时基本相同。
添加-O2优化选项,执行时间均缩减到之前的1/3,内外两种方式时间依然相同。
定义了一个struct实验了下,结果相同
也就是说栈上元素的操作不必纠结于变量声明于何处。
尝试了下堆上元素操作,在预料之内:时间差距巨大,因为重复分配释放内存。
所以对于栈上元素,声明放在循环里和循环外是一样的。堆上元素不同,需注意。
另,仍然需要注意一些计算操作需要放在循环外,比如求大小之类的,避免循环的每个周期重复计算。
原因猜测:1, cpu对栈操作有优化,速度非常快。
2,编译器的基本优化中会优化(gcc没有使用-O参数时仍会优化)
具体原因待深究
今天发现一个模块把变量声明都放到while里面了,看了下代码没有发现必须声明在里面的原因,于是开始怀疑是不是声明在内外是差不多的。
于是测试了一下:
引用
int main() {
int i = 0;
for(;i < 10000000; i++) {
int b;
b++;
}
return 1;
}
使用gcc 编译,把int b放在循环内外试了试,用time ./a.out查看执行时间,发现用时基本相同。
添加-O2优化选项,执行时间均缩减到之前的1/3,内外两种方式时间依然相同。
定义了一个struct实验了下,结果相同
也就是说栈上元素的操作不必纠结于变量声明于何处。
尝试了下堆上元素操作,在预料之内:时间差距巨大,因为重复分配释放内存。
所以对于栈上元素,声明放在循环里和循环外是一样的。堆上元素不同,需注意。
另,仍然需要注意一些计算操作需要放在循环外,比如求大小之类的,避免循环的每个周期重复计算。
原因猜测:1, cpu对栈操作有优化,速度非常快。
2,编译器的基本优化中会优化(gcc没有使用-O参数时仍会优化)
具体原因待深究
静态库和动态库编译链接时的依赖检查
[| 2012/04/05 19:48]
今天编译lua程序时发现总是报缺少dlopen和pow之类的,需要手动加-lm -dl才行。感觉有点奇异,按我的理解来说使用静态库是不需要考虑依赖的。仔细研究了下,发现很多误区。
首先用静态库编译出的可执行文件是不考虑库依赖的,但并不代表用静态库时也不需要考虑。静态库在编译时是不检查函数是否被实现的,也就是说只需要.h即可。
其次,静态库和动态库其实区别很大,静态库只是编译出.o的一个打包的文件,而动态库添加了链接信息。
这样的话静态库还有一个特性,就是在静态库中可以调用一些预留接口,而把这些接口留待以后实现。
首先用静态库编译出的可执行文件是不考虑库依赖的,但并不代表用静态库时也不需要考虑。静态库在编译时是不检查函数是否被实现的,也就是说只需要.h即可。
其次,静态库和动态库其实区别很大,静态库只是编译出.o的一个打包的文件,而动态库添加了链接信息。
这样的话静态库还有一个特性,就是在静态库中可以调用一些预留接口,而把这些接口留待以后实现。