Author: 芳草苑主

  • When does php apc refresh cache data?

    I did this experiment with php apc:

    In php.ini I set include_path = /first/include/path:/second/include/path, but do not put a file in /first/include/path or /second/include/path, create test.php as simple as this

    <?php
    require 'tobeincluded.php';
    

    It will run into a fatal error. This error is obvious.

    Then I create the file tobeincluded.php in /second/include/path, test.php now runs all right.

    Then I create another file with same file name as tobeincluded.php but different content and put it in /first/include/path, test.php keeps running as if /first/include/path/tobeincluded.php does not exist. This is because php apc has cached /second/include/path/tobeincluded.php and ignored /first/include/path/tobeincluded.php. Apc will refresh its cache when it is restarted or original cached file is updated in the file system. I assume apc is checking file timestamp.

    Then I copy test.php to test2.php and put test2.php in the same folder as test.php, run test2.php. It renders the same result as test.php – include /second/include/path/tobeincluded.php but ignore the existence of /first/include/path/tobeincluded.php.

    Then I copy test.php to test3.php and put test3.php in a different folder (no matter parent folder or child folder or irrelevant folder), run test3.php. Now it is aware of the existence of /first/include/path/tobeincluded.php so /first/include/path/tobeincluded.php is included in test3.php.

    Even I trigger to run test2.php in a different virtual host (but same document root), it still renders the same result. I assume php file on the file system is identical to apc. In other words, apc loads cache data by realpath regardless virtual host.

  • Magento does not remove storeview data when scope changes

    今天我做了个有趣的实验:

    1. 首先 Manage Attributes,设置某 product attribute ‘my_attr’ scope 为 Store view
    2. 然后 Manage Products,为 my_attr 设置 default value ‘aaa’,再设置 store view (假设 storeId = 2) value ‘bbb’
    3. 然后 Manage Attributes, 把 my_attr scope 改为 Global
    4. 然后 Manage Products,Choose Store View (storeId = 2),这时仍可见 my_attr 显示值 ‘bbb’。It means although my_attr scope is changed to ‘Global’, but old store view specific values are not removed.
    5. 这时 (my_attr scope is Global) 如果在 Store View (storeId = 2) 状态把 my_attr 的值改为 ‘ccc’,then Save Product。my_attr default value 被改为 ‘ccc’,store view (storeId = 2) value 仍为 ‘bbb’。It means when my_attr scope is ‘Global’, it is not possible using Manage Products GUI to change or remove existing store view value.

    摸清 Magento 的规律后就容易理解 Manage Products GUI 在 scope 改变或 store view 切换时的行为。另文有提及 change product default value and store view view by programming.

  • Skype banned Fring

    不久前注意到我的 fring addon 里 skype 突然就不见了,我没上心去究其原因。今天在 fring 官网看到:

    Skype no longer on fring
    Skype no longer on fring

    我搜了几则关于 fring skype 的消息,就明白了——skype 把 fring 给禁了。

    我用 fring 就是因为手机上用不了 skype:在 iphone 上装 fring 是因为无需 jail break 就能通过 fring 中转的 skype 支持 voip over 3g;在 android 上装是因为 skype 的开发速度太慢,刚用 android 时 skype 根本没有 skype for android。今天我又重新上 skype 去看,倒是开始支持某些 android 手机,可惜我的 g1 仍不支持。所以,在我看来,skype 禁了 fring 有点损人不利己。

    这让我对 skype 再次失望:一个公司技术力量有限情有可原,但如果它的经营哲学是用技术限制去阻止用户享受更好的服务,那就没有救了,一切营销手段在这种哲学的指导下都是缘木求鱼。

    I am lucky because skype is not my main voip service provider. Whatever restrictions skype put on to its users won’t affect my life, but get away from skype quicker.

  • What is Google Wave?

    董总问我,什么是 Google Wave?

    这问题问得好,我一时不晓得怎么回答,我知道他问这个问题不是问 Google Wave 的定义。要泛泛了解 Google Wave,何必问我,去看看 Google Wave Help 或者上 YouTube 看几个入门的 video 就可以。

    那么换句话问,在各种交流方式层出不穷的今天,Google Wave 有什么独到的地方?我们已经有了 email (of course I refer to Gmail), IM, SNS;Google 通讯产品也出了不少,gmail, gtalk, orkut, voice, buzz, 现在又出了 wave。很多产品,比如 facebook, twitter 据称很火爆的产品我都没来得及用。这也说明一个问题,大部分产品都有独到的地方,即便火爆,但它们无法象 email 一样不可或缺,从而改变世界。

    Google Wave logo
    Google Wave logo

    就功能而言,Google Wave 高出 gmail 很多,比如即时、自主、互动,等等特性,在 Google Wave introduction 里都有提及,不用我多说。我自己在使用 gmail 时碰到的问题是:尽管gmail很智能,但无法按自定义的、更多的线索归类。我想 Google Wave 更灵活,能弥补 gmail 的不足。但现在使用 Google Wave 的缺陷是必须拉对方进入 wave 才能共同享受 wave。我想如果能把 gmail 作为 wave object,发起人能单方面 wave by email,即使对方不加入 wave,发起人也能 enjoy wave,这样 wave 就完美了。

    要不然,在还没有人手一个 wave 的今天,wave 就无法取代 gmail。要是我们还得开一个 tab 用 Google Wave,另一个 tab 用 gmail,那么反过来也会影响 Google Wave 的普及。我期盼着一个能把 gmail 取而代之的 Google Wave。

  • Class Mage_Sales_Model_Entity is deprecated

    今天终于搞清楚了一件困扰我已久的问题:在 Magento Sales Module 下有两个分支 Mage_Sales_Model_Entity 和 class Mage_Sales_Model_Mysql4,看上去文件结构比较相似,Sales 和其他模块一时用 Mage_Sales_Model_Entity,一时又用 Mage_Sales_Model_Mysql4。它们有什么区别?为什么要同时存在?有必要同时存在吗?如要删除一个,该删哪个保留哪个?

    以前有个任务,想要给 order 等 entity 添加一些自定义属性,因为搞不清楚哪个在起作用,我把两个类都 extends 了,即 class Mage_Sales_Model_Entity_Setup 和 class Mage_Sales_Model_Mysql4_Setup。而因为其他一些原因,自定义属性并不能完全按照我的意愿工作,所以我也没办法再用替换法去测试哪个类在起作用。

    今天重新回顾了这个问题,摸清 Mage_Sales_Model_Entity is deprecated。When extending sales entity, only need to extend classes in Mage_Sales_Model_Mysql4.

    但是简单地删除 magento/app/code/core/Mage/Sales/Model/Entity 目录则会导致程序找不到必要的文件而出错。我的建议是了解 Mage_Sales_Model_Entity is deprecated 这个事实就可以了,如果一定想割了这个阑尾目录,得做一些调整:

    • 搜索一下哪些 class extends Entity 下的类 (search for Mage_Sales_Model_Entity under magento folder),把它们改成 extends Mysql4 下对应的类。据我搜索结果,只有 Mage_Reports 一些 class extends Entity 下的类,或许 Mage_Sales 在 Mage_Reports 成形之后进行 Entity to Mysql4 的调整,而为了省事,保留 Entity 下的类,就不用去修改 Mage_Reports 了。
    • 搜索一下哪些地方用到了 getModel(‘sales_entity/entity_name’) 的方式,把它们改成 getModel(‘sales_mysql4/entity_name’)。这需要同时搜索文件和数据库(数据库里 eav_attribute 有几个 backend models 是这样被引用的)。如果嫌这么替换比较麻烦,也可以修改 magento/app/code/core/Mage/Sales/etc/config.xml,把 <sales_entity><class>Mage_Sales_Model_Entity</class></sales_entity> 修改成 <sales_entity><class>Mage_Sales_Model_Mysql4</class></sales_entity>,这样就把 sales_entity model 与 sales_mysql4 model 等价起来了。
  • Android pdf viewer

    为了在 Android 打开 pdf 文档,我曾从 Android Market 里找了一个 PDF Viewer,幸好有免费的版本,安装也不困难。

    最近发现 Android G1 随即自带的 QuickOffice 就支持 pdf 阅读,速度还比 PDF Viewer 快,我当初怎么就没想到它?真是糊涂!

    回想一下,我糊涂也是有原因的:在 Android 到手前我还研究过怎么在 iphone 上看 pdf,花了一晚上时间也没找到一个可行的办法,忿忿地放弃(其实也没什么好忿忿的,iphone 本来就不好用,apple app store 里也没几个好软件是免费的)。Android 到手之后我就沿袭了 iphone 的研究方法,在 Android Market 很快找到了一个应用,很快地解决问题,再也没去想原来 Android 还有更现成的方案。

  • Google Contacts synchronisation fails on my Android after Google Mail became Gmail

    Google announced Google Mail is becoming Gmail in the UK in May. Then some day I decided to swap over my Google Account primary email address from @googlemail.com to @gmail.com. Everything continues to work as before. It should be working because I assume googlemail.com or gmail.com is alias to the other.

    After quite a long time (at least 2 weeks), I noticed Google Contacts stopped synchronisation from 28 May, 2008. Because Google Mail and Google Calendar continued to work all right, so I did not think it was problem of my Google Account change. I did not regard the domain name swap was a change. I thought it was merely Google was updating Google Contacts programme or server something.

    I have been waiting for Google Contacts synchronisation back to normal for a month. During the month I googled quite often if someone else encountered the same problem, but I did not find a case like mine.

    I could not live up with a situation that I had to enter a new contact twice any longer, so I started investigating harder. And only by change I realised it might be a problem caused by domain name swap. Then how to change Google Account information stored on my Android? I find it is not straight forward.

    First there is no interface for change the Google Account on Android. Someone mentioned a tricky method by changing the Google Account password then reboot Android. But it did not work on my Android G1. After reboot, it only pop up a box to enter password, not for account username.

    I manage to change Google Account by clicking Setup -> Applications -> Manage applications -> Google Apps -> Clear data, then reboot. Clear Google Apps data clear all contacts on Android as well, but it is not a problem for me because I have all contacts in google cloud anyway.

    A by-product of my investigation is I find Android support Google Apps Account as normal Google Account, which makes me very happy because I use Google Apps Account much more than Google Account.

  • Upgrade zend server php 5.2 to 5.3

    The correct command to remove php 5.2 before upgrade zend server to 5.3 is

    yum -y remove zend-server-php-5.2 && yum -y remove `rpm -qa|grep zend|xargs`

    Use yum -y remove zend-server-php-5.2 is not enough.

    After removal, run

    yum install zend-server-ce-php-5.3

    Of course, zend repository must be add to /etc/yum.repos.d before. (If not, where you got zend server php 5.2?)

    The most recent /etc/yum.repos.d/zend.repo is

    [Zend]
    name=Zend Server
    baseurl=http://repos.zend.com/zend-server/rpm/$basearch
    enabled=1
    gpgcheck=0

    [Zend_noarch]
    name=Zend Server – noarch
    baseurl=http://repos.zend.com/zend-server/rpm/noarch
    enabled=1
    gpgcheck=0

    I notice it was changed since my first copy. It was

    [Zend]
    name=Zend CE $releasever – $basearch – Released Updates
    baseurl=http://repos.zend.com/rpm/ce/$basearch/
    enabled=1
    gpgcheck=0
    [Zendce-noarch]
    name=Zend CE – noarch
    baseurl=http://repos.zend.com/rpm/ce/noarch
    enabled=1
    gpgcheck=0

    Old copy no long work with command
    yum install zend-server-ce-php-5.3

  • 1and1 cloud server datasheet

    从 1&1 新订了一个合同,cloud server,就是为了让 magento 跑快一些。那 1and1 的 cloud server 究竟能有多快呢?

    先看看 cat /proc/cpuinfo 的情况
    processor : 0
    vendor_id : AuthenticAMD
    cpu family : 16
    model : 2
    model name : Quad-Core AMD Opteron(tm) Processor 2352
    stepping : 3
    cpu MHz : 2109.718
    cache size : 512 KB
    fpu : yes
    fpu_exception : yes
    cpuid level : 4
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush mmx fxsr sse sse2 syscall mmxext fxsr_opt lm 3dnowext 3dnow pni cx16 popcnt lahf_lm cr8_legacy altmovcr8 abm sse4a misalignsse
    bogomips : 4219.43
    TLB size : 1024 4K pages
    clflush size : 64
    cache_alignment : 64
    address sizes : 48 bits physical, 48 bits virtual
    power management:

    processor : 1
    vendor_id : AuthenticAMD
    cpu family : 16
    model : 2
    model name : Quad-Core AMD Opteron(tm) Processor 2352
    stepping : 3
    cpu MHz : 2109.718
    cache size : 512 KB
    fpu : yes
    fpu_exception : yes
    cpuid level : 4
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush mmx fxsr sse sse2 syscall mmxext fxsr_opt lm 3dnowext 3dnow pni cx16 popcnt lahf_lm cr8_legacy altmovcr8 abm sse4a misalignsse
    bogomips : 4220.53
    TLB size : 1024 4K pages
    clflush size : 64
    cache_alignment : 64
    address sizes : 48 bits physical, 48 bits virtual
    power management:

    processor : 2
    vendor_id : AuthenticAMD
    cpu family : 16
    model : 2
    model name : Quad-Core AMD Opteron(tm) Processor 2352
    stepping : 3
    cpu MHz : 2109.718
    cache size : 512 KB
    fpu : yes
    fpu_exception : yes
    cpuid level : 4
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush mmx fxsr sse sse2 syscall mmxext fxsr_opt lm 3dnowext 3dnow pni cx16 popcnt lahf_lm cr8_legacy altmovcr8 abm sse4a misalignsse
    bogomips : 4223.97
    TLB size : 1024 4K pages
    clflush size : 64
    cache_alignment : 64
    address sizes : 48 bits physical, 48 bits virtual
    power management:

    processor : 3
    vendor_id : AuthenticAMD
    cpu family : 16
    model : 2
    model name : Quad-Core AMD Opteron(tm) Processor 2352
    stepping : 3
    cpu MHz : 2109.718
    cache size : 512 KB
    fpu : yes
    fpu_exception : yes
    cpuid level : 4
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush mmx fxsr sse sse2 syscall mmxext fxsr_opt lm 3dnowext 3dnow pni cx16 popcnt lahf_lm cr8_legacy altmovcr8 abm sse4a misalignsse
    bogomips : 4219.25
    TLB size : 1024 4K pages
    clflush size : 64
    cache_alignment : 64
    address sizes : 48 bits physical, 48 bits virtual
    power management:

    在 cloud server 上我使用 zend server。我特意从 1 Virtual processor core 1GB Ram 一步步往上加,使用 ab -c 5 -n 500 对比测试,客户端是 10 Mb down stream / 1Mb up stream adsl 连接。

    在 1 Virtual processor core 1GB Ram 时,Requests per second: 5.31 [#/sec]
    在 2 Virtual processor cores 1GB Ram 时,Requests per second: 8.34 [#/sec]
    在 2 Virtual processor cores 2GB Ram 时,Requests per second: 8.26 [#/sec]
    在 3 Virtual processor cores 1GB Ram 时,Requests per second: 10.57 [#/sec]
    在 4 Virtual processor cores 1GB Ram 时,Requests per second: 11.33 [#/sec]

    在 shopping cart 里有 7 条不同商品时,checkout/cart/index 页面时间为 10 秒左右。

    回头看看老 server
    # cat /proc/cpuinfo
    processor : 0
    vendor_id : AuthenticAMD
    cpu family : 15
    model : 67
    model name : Dual-Core AMD Opteron(tm) Processor 1216 HE
    stepping : 3
    cpu MHz : 1000.000
    cache size : 1024 KB
    physical id : 0
    siblings : 2
    core id : 0
    cpu cores : 2
    apicid : 0
    initial apicid : 0
    fpu : yes
    fpu_exception : yes
    cpuid level : 1
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow rep_good nopl pni cx16 lahf_lm cmp_legacy svm extapic cr8_legacy
    bogomips : 1999.96
    TLB size : 1024 4K pages
    clflush size : 64
    cache_alignment : 64
    address sizes : 40 bits physical, 48 bits virtual
    power management: ts fid vid ttp tm stc

    processor : 1
    vendor_id : AuthenticAMD
    cpu family : 15
    model : 67
    model name : Dual-Core AMD Opteron(tm) Processor 1216 HE
    stepping : 3
    cpu MHz : 1000.000
    cache size : 1024 KB
    physical id : 0
    siblings : 2
    core id : 1
    cpu cores : 2
    apicid : 1
    initial apicid : 1
    fpu : yes
    fpu_exception : yes
    cpuid level : 1
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow rep_good nopl pni cx16 lahf_lm cmp_legacy svm extapic cr8_legacy
    bogomips : 1999.96
    TLB size : 1024 4K pages
    clflush size : 64
    cache_alignment : 64
    address sizes : 40 bits physical, 48 bits virtual
    power management: ts fid vid ttp tm stc

    运行的是 nginx,同等条件下,Requests per second: 8.12 [#/sec],checkout/cart/index 页面生成时间也是 10 秒左右。

    虽 zend server 和 nginx 不同,靠不是完全对等的对比结果,我还是可以得出两个结论:

    1. 瓶颈仍是 cpu 速度;
    2. cloud server 并未显著提高速度,我对它预期过高,略有失望。
  • How to detect current connection is secure using Php?

    Over a long time I had believed there was a function or an environment variable I could use in Php to tell whether the current connection secure or not, i.e. a page requested via http or https protocol. Unfortunately I could not find a good solution. I can not find it does not mean it does not exist.

    Recently I intend to believe the perfect solution does not exist, i.e. I can not write something in Php safely to tell whether the current connection is secure unless I know the server setting.

    Look at the code snippet Magento use for isSecure function:

    $secure = (!empty($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!='off')) || $_SERVER['SERVER_PORT']=='443';
    

    This code is not perfect because it assumes the server is not listening http on 443 AND server is listening HTTPS on 443.

    Unfortunately I can not do more than that. I am wondering whether the situation is the same in Python or Java.