lemon语法分析器模板初探

[| 不指定 2012/04/18 00:24]
    今天看了一下lighttpd解析http头的过程,之前一直以为是单纯用遍历字符串的形式做的,今天发现除了遍历字符串,还用到了语法分析器来做解析,生成语法分析器模板的就是lemon,语法比较直观,不看文档就能大概看出逻辑,不过深入研究就要借助文档了,文档比较晦涩,需要仔细研究。

    大概用法:使用lemon的语法编写一个.y文件,然后调用lemon命令或使用lemon源文件将.y转化成.c和.h,转化后的.c看起来就很晕了,完全看不懂的说。
    这个东西还是挺有意思的,lighttpd还用它来解析配置文件。不过配置文件用lua也很不错啊。我准备以后多使用lua作为配置文件,方便灵活。
Tags: ,
    今天在回滚一个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更高级的权限,需要单独授予。




    现在主流搜索引擎都支持ping功能了,每当网站更新时可以主动向搜索引擎发一个xml格式信息,称之为”ping“,通知搜索引擎来抓取,对于收录是非常有好处的。
    之前一直懒得搞,今天弄了一下。
    参照百度站长工具里提供的格式,搞了一个,试试是否好用呢。

    添加了baidu和google的ping地址:

    http://ping.baidu.com/ping/RPC2
    http://blogsearch.google.com/ping/RPC2
Tags:
    搞了一个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










Tags: , ,

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"


    这是引发困扰的三个参数。平时建议全部开启,或开启后两个。
Tags: ,
    忘记之前从哪看过的一个文章说不要在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参数时仍会优化)
具体原因待深究
    今天编译lua程序时发现总是报缺少dlopen和pow之类的,需要手动加-lm -dl才行。感觉有点奇异,按我的理解来说使用静态库是不需要考虑依赖的。仔细研究了下,发现很多误区。
    首先用静态库编译出的可执行文件是不考虑库依赖的,但并不代表用静态库时也不需要考虑。静态库在编译时是不检查函数是否被实现的,也就是说只需要.h即可。
    其次,静态库和动态库其实区别很大,静态库只是编译出.o的一个打包的文件,而动态库添加了链接信息。

    这样的话静态库还有一个特性,就是在静态库中可以调用一些预留接口,而把这些接口留待以后实现。
Tags:
分页: 2/2 第一页 上页 1 2 最后页 [ 显示模式: 摘要 | 列表 ]