顯示文章

這裡允許您檢視這個會員的所有文章。請注意, 您只能看見您有權限閱讀的文章。


主題 - FIEND

頁: [1] 2
1
PHP程式設計討論區 / ZF2 終於在 0905 推出了
« 於: 2012-09-21 08:56 »
ZF2 終於推出了.

早期我常告訴別人 ZF1  是玩具 , 為什麼?

http://leftblank.nl/php-framework-benchmark-zend-codeigniter-cakephp-481.html

這裡有篇 Benchmark 的比較表.

 Requests per second (5 run avg)
Baseline PHP    2237,05
Cake 1.2.1    101,03
Cake 1.2.3    103,68
CodeIgniter 1.6.2    221,86
CodeIgniter 1.7.1    229,50
Zend 1.7.5    126,90
Zend 1.8.1    128,85


這是效能差異~~~
代碼: [選擇]
Baseline PHP 2237,05
Zend 1.7.5    126,90
Zend 1.8.1    128,85

我實驗的結果也差不多.

差了快20倍.

後來 查到 IO 時發現 ZF1 本身邏輯運算沒什麼問題.

主要是 INIT OBJECT 時 IO 佔掉太多伺服器的資源了.

我之前的公司在全世界有五千多萬個用戶 , 早期那些天材全部都用 ZF1 , 我接手這個技術處後每天都在調它的效能也沒什麼用 , 主要是 IO 的問題 , 害的我們後來又採購了三百多台伺服器 @@"

還花了很多時間說服 元老級的工程師們放棄它 , 開發新的系統.

我很期待 ZEND FRAMEWORK 可以全部編譯成 zend_framework.so 讓 PHP DL 可以 直接用.

這樣就沒這問題了它將會是很好的工具.

###########

http://packages.zendframework.com/

最近比較忙 , 有空再替大家測試它的性能....

看看還是不是玩具 ^^.





2
工作機會 / 誠徵一名 PHP 程式設計師
« 於: 2012-09-07 08:04 »
誠徵 一名 PHP 程式設計師 :

工作內容 : 網路遊戲開發 .

公司業務 , 主要是生產 網路遊戲 並且銷售到全世界.

這個職務主要負責編寫 後台 及 分析報表 , 有半年的密月期 , 半年內不會讓你參與核心產品的開發.


1. 十月份 開始上班.
2. 專案獎金跟員工分紅.
3. 勞健保.
4. 三節獎金.
5. 不需要筆試跟智力測驗.
6. 員工旅遊.
7. 採責任制 , 上班時間彈性.
8. 薪資面議.
9. 工作地點 台北市.

求材資格 :
1. 工作年資 不限 , 接受剛畢業的學生.
2. 中英打每分最少 60~150 字. ( 必要 ) 如無法證明 打字速度 , 現場測試打字速度.
3. 懂一點 PHP 程式語法即可.
4. 有畫過 UML , 看的懂一點點即可.
5. 對自己的 物理 數學 能力有信心.
6. 年齡 22~29 之間.
7. 男生要有當過兵 , 抗壓性高 , 肯接受各種關於技術成長的訓練和磨練. (非必要)
8. 對 LINUX , 網路 , 程式語言 有高度興趣 , 喜歡自己實驗.


備註 :

我們很要求打字速度 , 如果打字速度不夠快 , 就好像一個 NBA 選手身高只有 150 公分一樣.

請見諒.




若有興趣 請 投履歷表 到 :

EMAIL : howard@108es.com
聯絡人 : 楊先生.




3
看起來 jsoncpp 的穩定性也沒很好.

送了 100000000 組 搞了 幾十個併發攻擊 請求後 , 直接把它給弄死了.....

繼續研究~~


[root@FIEND wge_server]# gdb sbin/wge core.30747
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-56.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/cpp/wge_server/sbin/wge...done.
[New Thread 30749]
[New Thread 30750]
[New Thread 30748]
[New Thread 30747]
Missing separate debuginfo for /usr/local/wge/server/boost/lib/libboost_system.so.1.51.0
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/43/e38b856af532331942a23fd0cfd05c3a7eb6b2
Missing separate debuginfo for /usr/local/wge/server/wge/lib/libPhpFpm.so
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/7b/cb561cb29f74b1fd8f6121b1ef8b24babe5890
Missing separate debuginfo for /usr/local/wge/server/wge/lib/libWgeBase64.so
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/1b/1cd9c7370849727662953e57da8d4e5c0e7c78
Missing separate debuginfo for /usr/local/wge/server/wge/lib/libWgeJsoncpp.so
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/b8/1f4d99f40ef14d4dbb56900669dad627d4f09d
Missing separate debuginfo for /usr/local/wge/server/wge/lib/libZlib.so
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/6f/50ef6e38d3cb1e25ba8b37d6bce700e6ee6d0f
Missing separate debuginfo for /usr/local/wge/server/wge/lib/libWgeOpenssl.so
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/a1/6668595410ed1f78e46ce2b00168c58107f102
Missing separate debuginfo for /usr/local/wge/server/poco/lib/libPocoFoundation.so.12
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/9b/d1532f5e378a14a2cd3d2ba460fd79ebae579b
Missing separate debuginfo for
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/74/22987f6cfa699f465b0327139aac3fdac4a838
Reading symbols from /usr/local/wge/server/boost/lib/libboost_system.so.1.51.0...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/boost/lib/libboost_system.so.1.51.0
Reading symbols from /usr/local/wge/server/wge/lib/libPhpFpm.so...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/wge/lib/libPhpFpm.so
Reading symbols from /usr/local/wge/server/wge/lib/libWgeBase64.so...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/wge/lib/libWgeBase64.so
Reading symbols from /usr/local/wge/server/wge/lib/libWgeJsoncpp.so...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/wge/lib/libWgeJsoncpp.so
Reading symbols from /usr/local/wge/server/wge/lib/libZlib.so...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/wge/lib/libZlib.so
Reading symbols from /usr/local/wge/server/wge/lib/libWgeOpenssl.so...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/wge/lib/libWgeOpenssl.so
Reading symbols from /usr/lib64/libstdc++.so.6...(no debugging symbols found)...done.
Loaded symbols for /usr/lib64/libstdc++.so.6
Reading symbols from /lib64/libm.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libm.so.6
Reading symbols from /lib64/libgcc_s.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libgcc_s.so.1
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
Loaded symbols for /lib64/libpthread.so.0
Reading symbols from /lib64/librt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/librt.so.1
Reading symbols from /usr/local/wge/server/poco/lib/libPocoFoundation.so.12...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/poco/lib/libPocoFoundation.so.12
Reading symbols from /usr/lib64/libcrypto.so.10...(no debugging symbols found)...done.
Loaded symbols for /usr/lib64/libcrypto.so.10
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Reading symbols from /lib64/libdl.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/libdl.so.2
Reading symbols from /lib64/libz.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libz.so.1
Core was generated by `./sbin/wge'.
Program terminated with signal 6, Aborted.
#0  0x000000342b6328a5 in raise () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.80.el6_3.3.x86_64 libgcc-4.4.6-4.el6.x86_64 libstdc++-4.4.6-4.el6.x86_64 openssl-1.0.0-25.el6_3.1.x86_64 zlib-1.2.3-27.el6.x86_64
(gdb) bt
#0  0x000000342b6328a5 in raise () from /lib64/libc.so.6
#1  0x000000342b634085 in abort () from /lib64/libc.so.6
#2  0x000000342b62ba1e in __assert_fail_base () from /lib64/libc.so.6
#3  0x000000342b62bae0 in __assert_fail () from /lib64/libc.so.6
#4  0x00002abae62a2e16 in Json::Value::resolveReference(char const*, bool) () from /usr/local/wge/server/wge/lib/libWgeJsoncpp.so
#5  0x00002abae6298217 in wgeJsoncpp::wgeJsoncpp::getUID() () from /usr/local/wge/server/wge/lib/libWgeJsoncpp.so
#6  0x0000000000416d47 in session::readClientRequest (this=0x2abaec008790) at ./src/wge.cpp:613
#7  0x000000000041701d in session::handle_read (this=0x2abaec008790, error=<value optimized out>, bytes_transferred=<value optimized out>) at ./src/wge.cpp:655
#8  0x0000000000409065 in call<boost::shared_ptr<session>, boost::system::error_code const, unsigned long> (owner=<value optimized out>, base=<value optimized out>)
    at /usr/local/wge/server/boost/include/boost/bind/mem_fn_template.hpp:271
#9  operator()<boost::shared_ptr<session> > (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/bind/mem_fn_template.hpp:286
#10 operator()<boost::_mfi::mf2<void, session, const boost::system::error_code&, long unsigned int>, boost::_bi::list2<const boost::system::error_code&, const long unsigned int&> > (owner=<value optimized out>,
    base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/bind/bind.hpp:392
#11 operator()<boost::system::error_code, long unsigned int> (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/bind/bind_template.hpp:102
#12 operator() (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/detail/bind_handler.hpp:118
#13 asio_handler_invoke<boost::asio::detail::binder2<boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> >, boost::system::error_code, unsigned long> > (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/handler_invoke_hook.hpp:64
#14 invoke<boost::asio::detail::binder2<boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> >, boost::system::error_code, unsigned long>, boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> > > (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/detail/handler_invoke_helpers.hpp:39
#15 boost::asio::detail::reactive_socket_recv_op<boost::asio::mutable_buffers_1, boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> > >::do_complete (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/detail/reactive_socket_recv_op.hpp:110
#16 0x0000000000411c75 in complete (this=0x2abaec000910, ec=...) at /usr/local/wge/server/boost/include/boost/asio/detail/task_io_service_operation.hpp:37
#17 do_run_one (this=0x2abaec000910, ec=...) at /usr/local/wge/server/boost/include/boost/asio/detail/impl/task_io_service.ipp:419
#18 boost::asio::detail::task_io_service::run (this=0x2abaec000910, ec=...) at /usr/local/wge/server/boost/include/boost/asio/detail/impl/task_io_service.ipp:160
#19 0x0000000000404d2e in run () at /usr/local/wge/server/boost/include/boost/asio/impl/io_service.ipp:59
#20 startServer () at ./src/wge.cpp:888
#21 0x0000003e978b6470 in ?? () from /usr/lib64/libstdc++.so.6
#22 0x000000342be07851 in start_thread () from /lib64/libpthread.so.0
#23 0x000000342b6e76dd in clone () from /lib64/libc.so.6
(gdb) up
#1  0x000000342b634085 in abort () from /lib64/libc.so.6
(gdb)
#2  0x000000342b62ba1e in __assert_fail_base () from /lib64/libc.so.6
(gdb)
#3  0x000000342b62bae0 in __assert_fail () from /lib64/libc.so.6
(gdb)
#4  0x00002abae62a2e16 in Json::Value::resolveReference(char const*, bool) () from /usr/local/wge/server/wge/lib/libWgeJsoncpp.so
(gdb)
#5  0x00002abae6298217 in wgeJsoncpp::wgeJsoncpp::getUID() () from /usr/local/wge/server/wge/lib/libWgeJsoncpp.so
(gdb)
#6  0x0000000000416d47 in session::readClientRequest (this=0x2abaec008790) at ./src/wge.cpp:613
613                                     uid = wgejson.getUID() ;
(gdb)
#7  0x000000000041701d in session::handle_read (this=0x2abaec008790, error=<value optimized out>, bytes_transferred=<value optimized out>) at ./src/wge.cpp:655
655                            readClientRequest() ; // call readClientRequest()  , and use async_write
(gdb)
#8  0x0000000000409065 in call<boost::shared_ptr<session>, boost::system::error_code const, unsigned long> (owner=<value optimized out>, base=<value optimized out>)
    at /usr/local/wge/server/boost/include/boost/bind/mem_fn_template.hpp:271
271             BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2);
(gdb)
#9  operator()<boost::shared_ptr<session> > (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/bind/mem_fn_template.hpp:286
286             BOOST_MEM_FN_RETURN call(u, p, a1, a2);
(gdb)
#10 operator()<boost::_mfi::mf2<void, session, const boost::system::error_code&, long unsigned int>, boost::_bi::list2<const boost::system::error_code&, const long unsigned int&> > (owner=<value optimized out>,
    base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/bind/bind.hpp:392
392             unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]);
(gdb)
#11 operator()<boost::system::error_code, long unsigned int> (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/bind/bind_template.hpp:102
102             BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
(gdb)
#12 operator() (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/detail/bind_handler.hpp:118
118         handler_(static_cast<const Arg1&>(arg1_),
(gdb)
#13 asio_handler_invoke<boost::asio::detail::binder2<boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> >, boost::system::error_code, unsigned long> > (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/handler_invoke_hook.hpp:64
64        function();
(gdb)
#14 invoke<boost::asio::detail::binder2<boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> >, boost::system::error_code, unsigned long>, boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> > > (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/detail/handler_invoke_helpers.hpp:39
39        asio_handler_invoke(function, boost::addressof(context));
(gdb)
#15 boost::asio::detail::reactive_socket_recv_op<boost::asio::mutable_buffers_1, boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> > >::do_complete (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/detail/reactive_socket_recv_op.hpp:110
110           boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
(gdb)
#16 0x0000000000411c75 in complete (this=0x2abaec000910, ec=...) at /usr/local/wge/server/boost/include/boost/asio/detail/task_io_service_operation.hpp:37
37          func_(&owner, this, ec, bytes_transferred);
(gdb)
#17 do_run_one (this=0x2abaec000910, ec=...) at /usr/local/wge/server/boost/include/boost/asio/detail/impl/task_io_service.ipp:419
419             o->complete(*this, ec, task_result);
(gdb)
#18 boost::asio::detail::task_io_service::run (this=0x2abaec000910, ec=...) at /usr/local/wge/server/boost/include/boost/asio/detail/impl/task_io_service.ipp:160
160       for (; do_run_one(lock, this_thread, ec); lock.lock())
(gdb)
#19 0x0000000000404d2e in run () at /usr/local/wge/server/boost/include/boost/asio/impl/io_service.ipp:59
59        std::size_t s = impl_.run(ec);
(gdb)
#20 startServer () at ./src/wge.cpp:888
888                     io_service.run();
(gdb)
#21 0x0000003e978b6470 in ?? () from /usr/lib64/libstdc++.so.6
(gdb)
#22 0x000000342be07851 in start_thread () from /lib64/libpthread.so.0
(gdb)
#23 0x000000342b6e76dd in clone () from /lib64/libc.so.6
(gdb)
Initial frame selected; you cannot go up.

4

http://www.boost.org/doc/libs/1_51_0/libs/smart_ptr/smart_ptr.htm


http://67.223.234.84/boost_doc/libs/smart_ptr/shared_ptr.htm


Introduction 簡介

shared_ptr 類模板存儲一個指向動態分配對像(一般是用 C++ new-expression 生成的)的指針。在最後一個 shared_ptr 所指向的對象被銷毀或重置時,要保證它所指向的對象被刪除。參見示例。

每一個 shared_ptr 都符合 C++ 標準庫的 CopyConstructible 和 Assignable 的必要條件,並因此能夠用於標準庫容器。因為提供了比較操作,因此 shared_ptr 可以和標準庫中的關聯式容器一起工作。

通常,一個 shared_ptr 不能正確地持有一個指向動態分配的數組的指針。關於那種用法請參見 shared_array。

因為在實現中使用了引用計數,shared_ptr實例的循環引用不會被回收。例如,如果 main() 持有一個指向 A 的 shared_ptr, A 又直接或間接持有一個指回 A 的 shared_ptr,A 的使用計數是 2。最初的 shared_ptr 析構後將導致一個使用計數為 1 的 A 被懸掛。使用 weak_ptr 以「打破循環」。

這個類模板被 T 參數化,T 是被指向的對象的類型。shared_ptr 和它的大多數成員函數對於 T 沒什麼要求,允許它是一個不完整類型,或者為 void。對 T 有附加要求的成員函數 (constructors, reset) 都明確地記錄在下面。

只要 T* 能被隱式地轉換到 U*,則 shared_ptr<T> 就能被隱式地轉換到 shared_ptr<U>。特別是,shared_ptr<T> 隱式轉換到 shared_ptr<T const>,當 U 是 T 的一個可訪問基類的時候,還能轉換到 shared_ptr<U>,以及轉換到 shared_ptr<void>。

shared_ptr 現在是 TR1(第一個 C++ 庫技術報告)的一部分。TR1 的最新草案可以在下述位置找到:

http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf (1.36Mb PDF)

這個實現與 TR1 規範一致,僅有的例外是它依然存在於名字空間 boost 中,而不是 std::tr1。
Best Practices 最佳實踐

一個簡單的近乎完全消滅內存洩露的方針是:總是使用一個已命名的智能指針變量接收 new 的結果。代碼中每一次出現 new 關鍵字都應該是如下形式:

shared_ptr<T> p(new Y);

當然,也可以用其它智能指針代替上面的 shared_ptr;T 是和 Y 相同的類型,或者是可作為參數傳遞給 Y 的構造函數即可。

如果你遵守這個方針,自然導致你不再需要顯式 deletes,try/catch 結構也將非常罕見。

避免使用匿名 shared_ptr 臨時變量去存儲內容,為了看到這樣做是如何的危險,請考慮下面的例子:

void f(shared_ptr<int>, int);
int g();

void ok()
{
    shared_ptr<int> p(new int(2));
    f(p, g());
}

void bad()
{
    f(shared_ptr<int>(new int(2)), g());
}

函數 ok 亦步亦趨地遵循了方針,相反 bad 構造了臨時的 shared_ptr 來代替,這就為內存洩漏留下了可乘之機。因為函數參數的求值順序是不確定的,new int(2) 首先被求值,g() 第二個是有可能的,如果 g 拋出一個異常,我們永遠也不可能到達 shared_ptr 的構造函數。關於這個問題的更多信息請參見 Herb Sutter 的對策(還有 這裡)。
Synopsis 概要

namespace boost {

  class bad_weak_ptr: public std::exception;

  template<class T> class weak_ptr;

  template<class T> class shared_ptr {

    public:

      typedef T element_type;

      shared_ptr(); // never throws
      template<class Y> explicit shared_ptr(Y * p);
      template<class Y, class D> shared_ptr(Y * p, D d);
      template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
      ~shared_ptr(); // never throws

      shared_ptr(shared_ptr const & r); // never throws
      template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
      template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
      template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);

      shared_ptr & operator=(shared_ptr const & r); // never throws 
      template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
      template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);

      void reset(); // never throws
      template<class Y> void reset(Y * p);
      template<class Y, class D> void reset(Y * p, D d);
      template<class Y, class D, class A> void reset(Y * p, D d, A a);
      template<class Y> void reset(shared_ptr<Y> const & r, T * p); // never throws

      T & operator*() const; // never throws
      T * operator->() const; // never throws
      T * get() const; // never throws

      bool unique() const; // never throws
      long use_count() const; // never throws

      operator unspecified-bool-type() const; // never throws

      void swap(shared_ptr & b); // never throws
  };

  template<class T, class U>
    bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

  template<class T, class U>
    bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

  template<class T, class U>
    bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

  template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws

  template<class T> T * get_pointer(shared_ptr<T> const & p); // never throws

  template<class T, class U>
    shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws

  template<class T, class U>
    shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws

  template<class T, class U>
    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws

  template<class E, class T, class Y>
    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);

  template<class D, class T>
    D * get_deleter(shared_ptr<T> const & p);
}

Members 成員
element_type 元素類型

typedef T element_type;

    提供模板參數 T 的類型。

constructors 構造函數

shared_ptr(); // never throws

    作用:構造一個 empty 的 shared_ptr。

    後置條件:use_count() == 0 && get() == 0。

    拋出:無。

【這裡保證不拋出異常非常重要,因為 reset() 被指定使用缺省構造函數,這就意味著構造函數不必分配內存。】

template<class Y> explicit shared_ptr(Y * p);

    條件:p 必須可以被轉換到 T *。Y 必須是一個完整類型。表達式 delete p 必須是正常可用的,不能發生未定義行為,也不能拋出異常。

    作用:構造一個擁有指針 p 的 shared_ptr。

    後置條件:use_count() == 1 && get() == p。

    拋出:std::bad_alloc,或者一個由實現定義的當內存之外的某個資源無法獲得時的異常。

    異常安全:如果拋出一個異常,則調用 delete p。

    注意:p 必須是一個指向由 C++ new 表達式分配的對象的指針或者是 0。即使 p 是 0,後置條件中的 use count 也是 1,在一個值為 0 的指針上調用 delete 是無害的。

【這個構造函數被變成模板是為了記住被傳遞的實際的指針類型。析構函數可以針對同樣的指針,連同它的原始類型調用 delete,即使 T 沒有虛擬析構函數,或者是 void。

可選的侵入式的計數支持暴露了太多的實現細節,而且無法和 weak_ptr 很好地結合。當前實現使用了一個不同的機制,enable_shared_from_this 以解決 "shared_ptr from this" 問題。】

template<class Y, class D> shared_ptr(Y * p, D d);
template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);

    條件:p 必須可變換為 T *。D 必須是 CopyConstructible(可拷貝構造)的。D 的拷貝構造函數和析構函數不能拋出異常。表達式 d(p) 必須是正常可用的,不能發生未定義行為,也不能拋出異常。A 必須是一個 Allocator(分配器),關於分配器的描述可參見 C++ 標準 20.1.5 (Allocator requirements)。

    作用:構造一個擁有指針 p 和刪除器 d 的 shared_ptr。第二個構造函數用 a 的一個拷貝分配內存。

    後置條件:use_count() == 1 && get() == p。

    拋出:std::bad_alloc,或者一個由實現定義的當內存之外的某個資源無法獲得時的異常。

    異常安全:如果拋出一個異常,則調用 d(p)。

    注意:在 p 指向的對象被刪除時,所存儲的 d 的拷貝被調用,並以所存儲的 p 的拷貝作為參數。

【custom deallocators(定制化釋放器)准許一個返回 shared_ptr 的工廠函數以將用戶隔離在它的內存分配策略之外。因為這個 deallocator(釋放器)不是類型的一部分,改變其分配策略不會破壞源代碼級或二進制級兼容性,也不需要客戶端重新編譯。例如,一個 "no-op" 釋放器返回一個指向靜態分配對象的 shared_ptr 是有用的,而其它變種卻允許用一個 shared_ptr 來包裝其它智能指針,以方便互操作性。

對 custom deallocators(定制化釋放器)的支持不會強加很大的負擔。其它 shared_ptr 特性依然需要 deallocator(釋放器)提供支持。

對 D 的拷貝構造函數不能拋出異常的需求來自於以值傳遞。如果拷貝構造函數拋出異常,指針就會洩漏。排除這一需求需要使用以 (const) reference((常)引用)傳遞。

以引用傳遞的主要問題在於它和 rvalues(右值)的相互影響。一個 const reference(常引用)可能還是會引起一次拷貝,並需要一個 const operator()。而一個 non-const reference(非常引用)根本不會綁定在一個右值上。解決這個問題的一個好的方案是 N1377/N1385 提案中的 rvalue reference(右值引用)。】

shared_ptr(shared_ptr const & r); // never throws
template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws

    作用:如果 r 為 empty,構造一個 empty shared_ptr,否則,構造一個帶有 r 的 shares ownership(共享所有權)的 shared_ptr。

    後置條件: get() == r.get() && use_count() == r.use_count()。

    拋出:無。

template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);

    作用:構造一個帶有 r 的 shares ownership(共享所有權)的 shared_ptr,並存儲 r 中所存儲指針的一個拷貝。

    後置條件:use_count() == r.use_count()。

    拋出:當 r.use_count() == 0 時,拋出 bad_weak_ptr。

    異常安全:如果拋出一個異常,構造函數將不起作用。

template<class Y> shared_ptr(std::auto_ptr<Y> & r);

    作用:構造一個 shared_ptr,就像存儲了一個 r.release() 的返回值的拷貝。

    後置條件:use_count() == 1。

    拋出:std::bad_alloc,或者一個由實現定義的當內存之外的某個資源無法獲得時的異常。

    異常安全:如果拋出一個異常,構造函數將不起作用。

【這個構造函數所得到的源 auto_ptr 是以引用傳遞的,而非以值傳遞,而且不能接收 auto_ptr 臨時變量。這是故意的,作為構造函數提出的強制保證,一個右值引用也可以解決這個問題。】
destructor 析構函數

~shared_ptr(); // never throws

    作用:

        如果 *this 為 empty,或者和其他 shared_ptr 實例共享所有權 (use_count() > 1),沒有副作用。
        否則,如果 *this 擁有一個指針 p 和一個刪除器 d,則調用 d(p)。
        否則,*this 擁有一個指針 p,則調用 delete p。

    拋出:無。

assignment 賦值

shared_ptr & operator=(shared_ptr const & r); // never throws
template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);

    作用:等價於 shared_ptr(r).swap(*this)。

    返回:*this。

    注意:由臨時對象的構造和析構造成的使用計數的更新不被認為是可察覺的副作用,而實現可以自由地經由不同的手段達到其效果(以及隱含的保證),而不創建臨時變量。特別是,在下例中:

    shared_ptr<int> p(new int);
    shared_ptr<void> q(p);
    p = p;
    q = p;

    兩個賦值可能都是 no-op(什麼都不做)。

reset 重置

void reset(); // never throws

    作用:等價於 shared_ptr().swap(*this)。

template<class Y> void reset(Y * p);

    作用:等價於 shared_ptr(p).swap(*this)。

template<class Y, class D> void reset(Y * p, D d);

    作用:等價於 shared_ptr(p, d).swap(*this)。

template<class Y, class D, class A> void reset(Y * p, D d, A a);

    作用:等價於 shared_ptr(p, d, a).swap(*this)。

template<class Y> void reset(shared_ptr<Y> const & r, T * p); // 不拋出

    作用:等價於 shared_ptr(r, p).swap(*this).

indirection 間接引用

T & operator*() const; // never throws

    條件:所存儲的指針不能為 0。

    返回:一個引向所存儲的指針所指向的對象的引用。

    拋出:無。

T * operator->() const; // never throws

    條件:所存儲的指針不能為 0。

    返回:所存儲的指針。

    拋出:無。

get 取得

T * get() const; // never throws

    返回:所存儲的指針。

    拋出:無。

unique 唯一性

bool unique() const; // never throws

    返回:use_count() == 1。

    拋出:無。

    注意:unique() 可能比 use_count() 更快。如果你用 unique() 實現 copy on write(寫時拷貝),當所存儲的指針為 0 是,不要依賴於一個特定的值。

use_count 使用計數

long use_count() const; // never throws

    返回:與 *this 共享所有權的 shared_ptr 對像(包括 *this 在內)的數量,或者當 *this 為空時,一個不特定的非負值。

    拋出:無。

    注意:use_count() 達不到必要的效率。只用於調試和測試的目的。而不要用於產品代碼。

conversions 轉換

operator unspecified-bool-type () const; // never throws

    返回:一個未確定的值,在需要布爾值的上下文中,它等價於 get() != 0。

    拋出:無。

    注意:這一轉換操作符允許將 shared_ptr 對像用於需要布爾值的上下文中,就像 if (p && p->valid()) {}。實際目標類型通常是一個指向成員函數的指針,消除了很多隱式轉換的陷阱。

【到 bool 的轉換不僅僅是語法糖。它允許在使用 dynamic_pointer_cast 或 weak_ptr::lock 時,在條件中聲明 shared_ptrs。】
swap 交換

void swap(shared_ptr & b); // never throws

    作用:交換兩個智能指針中的內容。

    拋出:無。

Free Functions 自由函數
comparison 比較

template<class T, class U>
  bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

    返回:a.get() == b.get()。

    拋出:無。

template<class T, class U>
  bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

    返回:a.get() != b.get()。

    拋出:無。

template<class T, class U>
  bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

    返回:一個未確定值,以致於

        operator< 是一個嚴格意義上的 C++ 標準 25.3 [lib.alg.sorting] 中描述的 weak ordering(弱順序);
        等值關係通過 operator< 來定義,!(a < b) && !(b < a),在這種情況下,當且僅當兩個 shared_ptr 實例共享所有權或者都為空時,兩個 shared_ptr 相等。

    拋出:無。

    注意:允許 shared_ptr 對像在關聯式容器中作為鍵值使用。

【因為兼容性和合法性的原因,Operator< 比 std::less 的特化版本更優先被選用,因為 std::less 需要返回一個 operator< 的結果,而當沒有提供謂詞時,許多標準算法在比較中使用 operator< 來代替 std::less。組合對象,比如 std::pair,也根據它們所包含的子對象的 operator< 來實現它們的 operator<。

其餘的比較操作符被故意省略。】
swap 交換

template<class T>
  void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws

    作用:等價於 a.swap(b)。

    拋出:無。

    注意:與 std::swap 的接口匹配。為泛型編程提供幫助。

【swap 被定義在和 shared_ptr 同樣的名字空間中,這是當前提供一個讓標準庫有機會使用的 swap 函數的僅有的合法方法。】
get_pointer 取得指針

template<class T>
  T * get_pointer(shared_ptr<T> const & p); // never throws

    返回:p.get()。

    拋出:無。

    注意:為泛型編程提供幫助,用於 mem_fn。

static_pointer_cast

template<class T, class U>
  shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws

    條件:表達式 static_cast<T*>(r.get()) 必須正常可用。

    返回:如果 r 為 empty,返回一個 empty shared_ptr<T>;否則,返回一個存儲 static_cast<T*>(r.get()) 的拷貝並和 r 共享所有權的 shared_ptr<T> 對象。

    拋出:無。

    注意:表面上看似乎等價的表達式

    shared_ptr<T>(static_cast<T*>(r.get()))

    因為試圖刪除同樣的對象兩次,而最終陷入未定義行為。

const_pointer_cast

template<class T, class U>
  shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws

    條件:表達式 const_cast<T*>(r.get()) 必須正常可用。

    返回:如果 r 為 empty,返回一個 empty shared_ptr<T>;否則,返回一個存儲 const_cast<T*>(r.get()) 的拷貝並和 r 共享所有權的 shared_ptr<T> 對象。

    拋出:無。

    注意:表面上看似乎等價的表達式

    shared_ptr<T>(const_cast<T*>(r.get()))

    因為試圖刪除同樣的對象兩次,而最終陷入未定義行為。

dynamic_pointer_cast

template<class T, class U>
  shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);

    條件:表達式 dynamic_cast<T*>(r.get()) 必須正常可用,而且它的行為已被定義。

    返回:

        當 dynamic_cast<T*>(r.get()) 返回一個非 0 值,則返回一個存儲它的拷貝並和 r 共享所有權的 shared_ptr<T> 對像;
        否則,返回一個 empty shared_ptr<T> 對象。

    拋出:無。

    注意:表面上看似乎等價的表達式

    shared_ptr<T>(dynamic_cast<T*>(r.get()))

    因為試圖刪除同樣的對象兩次,而最終陷入未定義行為。

operator<<

template<class E, class T, class Y>
    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);

    作用:os << p.get();。

    返回:os。

get_deleter

template<class D, class T>
    D * get_deleter(shared_ptr<T> const & p);

    返回:如果 *this 擁有一個類型為 D 的刪除器 d,則返回 &d;否則返回 0。

Example 示例

來看一個完整的示例程序 shared_ptr_example.cpp。這個程序創建了一個 shared_ptr 對象的 std::vector 和 std::set。

注意,在容器被填充之後,一些 shared_ptr 對象的使用計數為 1,而不是 2,這是因為 set 是一個 std::set 而不是 std::multiset,而這樣就不能包含重複的條目。此外,當 push_back 和 insert 容器操作執行的次數不同,使用計數可能會更高。還有更複雜的,容器操作在多種情況下都可能拋出異常。在這個示例程序中的內存管理和異常處理都很正常,而沒有讓智能指針成為一場噩夢。
Handle/Body Idiom Handle/Body 慣用法

shared_ptr 的一個慣常用法是實現 handle/body(也稱為 pimpl)慣用法,以避免在頭文件中暴露身體(實現)。

shared_ptr_example2_test.cpp 示例程序包含一個頭文件 shared_ptr_example2.hpp,其中使用了一個指向一個完整類型的 shared_ptr<> 來隱藏實現。成員函數的實例化要求在 shared_ptr_example2.cpp 實現文件中存在完整類型。注意這裡不需要顯示的析構函數。不像 ~scoped_ptr,~shared_ptr 不需要 T 是一個完整類型。
Thread Safety 線程安全

shared_ptr 對像提供與內建類型一樣的線程安全級別。一個 shared_ptr 實例可以同時被多個線程「讀」(僅使用不變操作進行訪問)。不同的 shared_ptr 實例可以同時被多個線程「寫入」(使用類似 operator= 或 reset 這樣的可變操作進行訪問)(即使這些實例是拷貝,而且共享下層的引用計數)。

任何其它的同時訪問的結果會導致未定義行為。

示例:

shared_ptr<int> p(new int(42));

//--- Example 1 ---

// thread A
shared_ptr<int> p2(p); // reads p

// thread B
shared_ptr<int> p3(p); // OK, multiple reads are safe

//--- Example 2 ---

// thread A
p.reset(new int(1912)); // writes p

// thread B
p2.reset(); // OK, writes p2

//--- Example 3 ---

// thread A
p = p3; // reads p3, writes p

// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write

//--- Example 4 ---

// thread A
p3 = p2; // reads p2, writes p3

// thread B
// p2 goes out of scope: undefined, the destructor is considered a "write access"

//--- Example 5 ---

// thread A
p3.reset(new int(1));

// thread B
p3.reset(new int(2)); // undefined, multiple writes



從 Boost 版本 1.33.0 開始,shared_ptr 在以下平台上使用了 lock-free 實現:

    GNU GCC on x86 or x86-64;
    GNU GCC on IA64;
    Metrowerks CodeWarrior on PowerPC;
    GNU GCC on PowerPC;
    Windows.

如果你的程序是單線程的,而且在它的缺省配置中沒有連接任何可能使用了 shared_ptr 的庫,你可以在項目基準中 #define 宏 BOOST_SP_DISABLE_THREADS 以轉換到普通的非原子的引用計數更新。

(在部分(而非全部)編譯單元中定義 BOOST_SP_DISABLE_THREADS 在技術上是對單一定義規則和未定義行為的觸犯。然而,實現會盡其所能滿足那些提出使用非原子更新的編譯單元的要求。但是,沒有任何保證。)

你可以定義宏 BOOST_SP_USE_PTHREADS 以避開特定平台的 lock-free 實現,並退回到普通的基於 pthread_mutex_t 的代碼。
Frequently Asked Questions 常見問題

問:有幾種共享指針的變化,反映不同的權衡,為什麼智能指針庫僅提供一種單一的實現?能夠用每一種類型做試驗以發現最適合手邊工作的那一種不是非常有好處的嗎?

答:shared_ptr 的一個重要目標是提供一個標準的共享所有權指針。對於穩定的庫接口來說,單一指針類型是很重要的,因為不同的共享指針一般無法互操作,例如,一個 reference counted pointer(引用計數指針)(用於庫 A)不能和一個 linked pointer(連接指針)(用於庫 B)共享所有權。

問:shared_ptr 為什麼沒有用來提供特性或規則的模板參數以允許廣泛的用戶定制性?

答:參數化會阻礙用戶。shared_ptr 模板小心謹慎地精工細作以滿足通用需求,而沒有大量的參數化。有朝一日,可能會有人發明可配置性很高的智能指針,而且很易於使用並難於犯錯。到那時,shared_ptr 會成為為各種各樣的應用而選擇的智能指針。(那些對基於策略的智能指針感興趣的人可以閱讀 Andrei Alexandrescu 寫的 Modern C++ Design。)

問:我不確定。缺省參數可以用於那些需要隱藏複雜度的地方。再問一次,為什麼不規則化?

答:模板參數影響類型。參見上面第一個問題的回答。

問:shared_ptr 為什麼不用鏈表實現?

答:鏈表實現的好處不足以抵消一個額外的指針所增加的開銷。參見 timings 頁面。另外,讓一個鏈表實現線程安全的代價太大了。

問:shared_ptr(或其它任何一個 Boost 智能指針)不提供一個到 T* 的自動轉換?

答:自動轉換被認為更易於導致錯誤。

問:shared_ptr 為什麼提供 use_count()?

答:為了幫助寫測試用例和調試顯示。一個祖先類有 use_count(),它對於在一個複雜的項目中追蹤 bugs 並切斷循環依賴是非常有用的。

問:為什麼 shared_ptr 不指定複雜度要求?

答:因為複雜度要求限制了實現,並且使規範更複雜,對於 shared_ptr 的用戶卻沒有明顯的好處。例如,如果不得不符合嚴厲的複雜度要求,錯誤檢查的實現可能會變得不一致。

問:為什麼 shared_ptr 不提供一個 release() 函數?

答:shared_ptr 不能放棄所有權除非它是 unique(),因為其它拷貝仍然可以銷毀這個對象。

考慮:

    shared_ptr<int> a(new int);
    shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2

    int * p = a.release();

    // Who owns p now? b will still call delete on it in its destructor.

此外,當源 shared_ptr 可能帶有一個定制化的刪除器時,release() 返回的指針很難可靠地被釋放。

問:為什麼 operator->() 是 const 的,而它的返回值卻是指向元素類型的 non-const 指針?

答:淺拷貝指針,包括裸指針,一般不會傳遞常量性。當你能夠總是從一個 const 指針得到一個 non-const 指針,並繼而通過它改變那個對象的時候,還是有一點兒意義的。shared_ptr 是「盡可能接近而不重合裸指針」。

5
XD ......  一定要這麼難搞...

[root@FIEND wge_server]# gdb sbin/wge core.5472

GNU gdb (GDB) Red Hat Enterprise Linux (7.2-56.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/cpp/wge_server/sbin/wge...done.
[New Thread 5474]
[New Thread 5475]
[New Thread 5472]
[New Thread 5473]
Missing separate debuginfo for /usr/local/wge/server/boost/lib/libboost_system.so.1.50.0
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/c3/337ba893c244011a9007b761af66b82fb5af7a
Missing separate debuginfo for /usr/local/wge/server/wge/lib/libPhpFpm.so
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/7b/cb561cb29f74b1fd8f6121b1ef8b24babe5890
Missing separate debuginfo for /usr/local/wge/server/wge/lib/libWgeBase64.so
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/1b/1cd9c7370849727662953e57da8d4e5c0e7c78
Missing separate debuginfo for /usr/local/wge/server/wge/lib/libWgeJsoncpp.so
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/b8/1f4d99f40ef14d4dbb56900669dad627d4f09d
Missing separate debuginfo for /usr/local/wge/server/wge/lib/libZlib.so
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/6f/50ef6e38d3cb1e25ba8b37d6bce700e6ee6d0f
Missing separate debuginfo for /usr/local/wge/server/wge/lib/libWgeOpenssl.so
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/a1/6668595410ed1f78e46ce2b00168c58107f102
Missing separate debuginfo for /usr/local/wge/server/poco/lib/libPocoFoundation.so.12
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/9b/d1532f5e378a14a2cd3d2ba460fd79ebae579b
Missing separate debuginfo for
Try: yum --disablerepo='*' --enablerepo='*-debug*' install /usr/lib/debug/.build-id/74/22987f6cfa699f465b0327139aac3fdac4a838
Reading symbols from /usr/local/wge/server/boost/lib/libboost_system.so.1.50.0...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/boost/lib/libboost_system.so.1.50.0
Reading symbols from /usr/local/wge/server/wge/lib/libPhpFpm.so...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/wge/lib/libPhpFpm.so
Reading symbols from /usr/local/wge/server/wge/lib/libWgeBase64.so...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/wge/lib/libWgeBase64.so
Reading symbols from /usr/local/wge/server/wge/lib/libWgeJsoncpp.so...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/wge/lib/libWgeJsoncpp.so
Reading symbols from /usr/local/wge/server/wge/lib/libZlib.so...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/wge/lib/libZlib.so
Reading symbols from /usr/local/wge/server/wge/lib/libWgeOpenssl.so...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/wge/lib/libWgeOpenssl.so
Reading symbols from /usr/lib64/libstdc++.so.6...(no debugging symbols found)...done.
Loaded symbols for /usr/lib64/libstdc++.so.6
Reading symbols from /lib64/libm.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libm.so.6
Reading symbols from /lib64/libgcc_s.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libgcc_s.so.1
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
Loaded symbols for /lib64/libpthread.so.0
Reading symbols from /lib64/librt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/librt.so.1
Reading symbols from /usr/local/wge/server/poco/lib/libPocoFoundation.so.12...(no debugging symbols found)...done.
Loaded symbols for /usr/local/wge/server/poco/lib/libPocoFoundation.so.12
Reading symbols from /usr/lib64/libcrypto.so.10...(no debugging symbols found)...done.
Loaded symbols for /usr/lib64/libcrypto.so.10
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Reading symbols from /lib64/libdl.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/libdl.so.2
Reading symbols from /lib64/libz.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libz.so.1
Core was generated by `./sbin/wge'.
Program terminated with signal 11, Segmentation fault.
#0  0x000000000040f3cb in close (this=0x2abe54002e90) at /usr/local/wge/server/boost/include/boost/asio/detail/impl/reactive_socket_service_base.ipp:103
103             (impl.state_ & socket_ops::possible_dup) == 0);
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.80.el6_3.3.x86_64 libgcc-4.4.6-4.el6.x86_64 libstdc++-4.4.6-4.el6.x86_64 openssl-1.0.0-25.el6_3.1.x86_64 zlib-1.2.3-27.el6.x86_64
(gdb) bt
#0  0x000000000040f3cb in close (this=0x2abe54002e90) at /usr/local/wge/server/boost/include/boost/asio/detail/impl/reactive_socket_service_base.ipp:103
#1  close (this=0x2abe54002e90) at /usr/local/wge/server/boost/include/boost/asio/stream_socket_service.hpp:151
#2  boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >::close (this=0x2abe54002e90) at /usr/local/wge/server/boost/include/boost/asio/basic_socket.hpp:309
#3  0x00000000004147d3 in session::loginChk (this=0x2abe54002e10) at ./src/wge.cpp:444
#4  0x0000000000414f00 in session::readClientRequest (this=0x2abe54002e10) at ./src/wge.cpp:606
#5  0x0000000000409545 in call<boost::shared_ptr<session>, boost::system::error_code const, unsigned long> (owner=<value optimized out>, base=<value optimized out>)
    at /usr/local/wge/server/boost/include/boost/bind/mem_fn_template.hpp:271
#6  operator()<boost::shared_ptr<session> > (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/bind/mem_fn_template.hpp:286
#7  operator()<boost::_mfi::mf2<void, session, const boost::system::error_code&, long unsigned int>, boost::_bi::list2<const boost::system::error_code&, const long unsigned int&> > (owner=<value optimized out>,
    base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/bind/bind.hpp:392
#8  operator()<boost::system::error_code, long unsigned int> (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/bind/bind_template.hpp:102
#9  operator() (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/detail/bind_handler.hpp:118
#10 asio_handler_invoke<boost::asio::detail::binder2<boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> >, boost::system::error_code, unsigned long> > (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/handler_invoke_hook.hpp:64
#11 invoke<boost::asio::detail::binder2<boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> >, boost::system::error_code, unsigned long>, boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> > > (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/detail/handler_invoke_helpers.hpp:39
#12 boost::asio::detail::reactive_socket_recv_op<boost::asio::mutable_buffers_1, boost::_bi::bind_t<void, boost::_mfi::mf2<void, session, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<boost::shared_ptr<session> >, boost::arg<1> (*)(), boost::arg<2> (*)()> > >::do_complete (owner=<value optimized out>, base=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/detail/reactive_socket_recv_op.hpp:110
#13 0x000000000040e8f2 in complete (owner=0x2abe54000910, base=<value optimized out>, ec=..., bytes_transferred=<value optimized out>) at /usr/local/wge/server/boost/include/boost/asio/detail/task_io_service_operation.hpp:37
#14 boost::asio::detail::epoll_reactor::descriptor_state::do_complete (owner=0x2abe54000910, base=<value optimized out>, ec=..., bytes_transferred=<value optimized out>)
    at /usr/local/wge/server/boost/include/boost/asio/detail/impl/epoll_reactor.ipp:650
#15 0x0000000000410a15 in complete (this=0x2abe54000910, ec=...) at /usr/local/wge/server/boost/include/boost/asio/detail/task_io_service_operation.hpp:37
#16 do_run_one (this=0x2abe54000910, ec=...) at /usr/local/wge/server/boost/include/boost/asio/detail/impl/task_io_service.ipp:394
#17 boost::asio::detail::task_io_service::run (this=0x2abe54000910, ec=...) at /usr/local/wge/server/boost/include/boost/asio/detail/impl/task_io_service.ipp:146
#18 0x0000000000404c2e in run () at /usr/local/wge/server/boost/include/boost/asio/impl/io_service.ipp:59
#19 startServer () at ./src/wge.cpp:864
#20 0x0000003e978b6470 in ?? () from /usr/lib64/libstdc++.so.6
#21 0x000000342be07851 in start_thread () from /lib64/libpthread.so.0
#22 0x000000342b6e76dd in clone () from /lib64/libc.so.6
(gdb) q



TRACE 到 :

#0  0x000000000040f3cb in close (this=0x2abe54002e90) at /usr/local/wge/server/boost/include/boost/asio/detail/impl/reactive_socket_service_base.ipp:103

跑到 官方看 :

https://svn.boost.org/trac/boost/ticket/7275

@@"

C++11 會造成 103 行的錯誤... 沒錯我也是用 C++11 XD ...

好新的BUG 12天前~


##########

目前正在安裝 1.51 版...

看起來 1.51 修正了很多 c++11  的問題.

http://www.boost.org/users/history/version_1_51_0.html

New Libraries

    Context: Context switching library, from Oliver Kowalke.

Updated Libraries

    Algorithm:
        Fixed is_sorted_until ; now matches the c++11 standard behavior on ranges with duplicate values.
        Added range support for the rest of the search algorithms.
        unhex now uses Boost.Exception to signal bad input.
    Asio:
        Fixed an incompatibility between ip::tcp::iostream and C++11 (#7162).
        Decorated GCC attribute names with underscores to prevent interaction with user-defined macros (#6415).
        Added missing #include <cctype>, needed for some versions of MinGW.
        Changed to use gcc's atomic builtins on ARM CPUs, when available (#7140).
        Changed strand destruction to be a no-op, to allow strand objects to be destroyed after their associated io_service has been destroyed.
        Added support for some newer versions of glibc which provide the epoll_create1() function but always fail with ENOSYS (#7012).
        Changed the SSL implementation to throw an exception if SSL engine initialisation fails (#6303).
        Fixed another regression in buffered_write_stream (#6310).
        Implemented various minor performance improvements, primarily targeted at Linux x86 and x86-64 platforms.
    Config:
        Deprecated a whole bunch of macros that were c++11 specific, but not named to show that they were c++11 specific. Made new macros with better names, and paired the old macros with the new ones. Updated the documentation to list the deprecated macros.
    Chrono:
        #6918 Boost Chrono compilation failure on HP uX due to undefined pthread_getcpuclockid.
        #6241 boost::chrono compilation problems without std::wstring support.
        #6987 Documentation & C++11.
        #7041 time_point.hpp depends on Boost.System.
        #7042 Avoiding time_point and duration dependency on time.h and CLOCK_REALTIME.
        #7058 Make it work when BOOST_NO_EXCEPTIONS is defined.
        #7069 Misspellings in clock_string<thread_clock>.
        #7081 WinError.h capitalization in boost/detail/win/basic_types.hpp.
    Geometry:
        points accessed through a pointer (e.g. in a linestring) should now be specialized without the pointer. In previous versions a type my_point used like linestring<my_point*> had to be specalized like: template<> struct tag<my_point*>. Now the library itself removes the pointer before calling the traits class, so now it should be like: template<> struct tag<my_point>
        intersection was sometimes wrong for integer points, fixed
        documentation, order of parameters in simplify was wrong, fixed
        7030 spherical distance, fixed (by patch of Karsten Ahnert)
    Graph:
        Refactored support for internal and bundled properties in Boost.Graph-provided graph types, and cleaned up named parameter functionality:
            Enabled old-style (non-bundled) internal properties in compressed_sparse_row_graph.
            Bundled properties should work correctly for all graph types and adaptors.
        Bugs fixed:
            #6993: Typo Bundled Properties document
            #7002: Problem with initialization of CSR bidirectional graph
            #7023: Enclose internal type graphml_reader in anonymous namespace
            Other bugs and warnings not in Trac
    Hash:
        Support the standard smart pointers.
        hash_value now implemented using SFINAE to avoid implicit casts to built in types when calling it.
        Updated to use the new config macros.
    Lexical cast:
        Better performance, less memory usage for boost::array<character_type, N> and std::array<character_type, N> conversions.
        Fixed bug with volatile input parameter #7157.
    Math:
        Updated to use the new config macros.
    MSM:
        Support for boost::any http://www.boost.org/doc/libs/1_51_0/libs/msm/doc/HTML/ch03s03.html#any-event or kleene http://www.boost.org/doc/libs/1_51_0/libs/msm/doc/HTML/ch03s04.html#kleene-event as acceptable events
        Bugfix: compiler error with fsm internal table and none (compound) event.
        Bugfix: euml::defer_ leading to stack overflow.
    Proto:
        Proto transforms get pseudo-parameter pack expansion support for unpacking expressions. See the Release Notes for more information.
    Ratio:
        #7075 Workaround for error: the type of partial specialization template parameter constant "n1" depends on another template parameter.
    Regex:
        Updated to use the new config macros.
    Thread:
        #4258 Linking with boost thread does not work on mingw/gcc 4.5.
        #4885 Access violation in set_tss_data at process exit due to invalid assumption about TlsAlloc.
        #6931 mutex waits forwever with Intel Compiler and /debug:parallel
        #7044 boost 1.50.0 header missing.
        #7052 Thread: BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 only masks thread::operator==, thread::operator!= forward declarations, not definitions.
        #7066 An attempt to fix current_thread_tls_key static initialization order.
        #7074 Multiply defined symbol boost::allocator_arg.
        #7078 Trivial 64-bit warning fix on Windows for thread attribute stack size
        #7089 BOOST_THREAD_WAIT_BUG limits functionality without solving anything
    Unordered:
        Fix construction/destruction issue when using a C++11 compiler with a C++03 allocator (#7100).
        Remove a try..catch to support compiling without exceptions.
        Adjust SFINAE use to try to supprt g++ 3.4 (#7175).
        Updated to use the new config macros.
    Wave:
        See the Changelog for details.
    xpressive:
        Work around buggy wide ctype facet on cygwin and mingw.
        Work around absence of __isctype on some glibc implementations.
        op::as shouldn't assume string::iterator != char*.
        Fix assertion in cpp_regex_traits on libc++, thanks to John Fletcher.

Compilers Tested

Boost's primary test compilers are:

    Linux:
        GCC: 4.2.4, 4.3.4, 4.4.3, 4.5.3, 4.6.2, 4.7
        GCC, C++11 mode: 4.3.4, 4.4.3, 4.5.3, 4.6.2
        Intel: 11.1, 12.0, 12.1
        LLVM Clang 2.8
    OS X:
        GCC: 4.4
        GCC, C++11 mode: 4.4
        Intel: 11.1, 12.0
    Windows:
        GCC, mingw: 4.4.0, 4.4.7, 4.5.4, 4.6.3
        Visual C++: 8.0, 9.0, 10.0
    FreeBSD:
        GCC: 4.2.1, 32 and 64 bit

Boost's additional test compilers include:

    Linux:
        Clang: from subversion
        LLVM Clang: 3.0
        GCC: 4.2.4, 4.3.4, 4.4.4, 4.4.7, 4.5.3, 4.6.2, 4.6.3, 4.7.0, 4.7.1
        GCC, C++11 mode: 4.3.4, 4.4.4, 4.5.3, 4.6.3
        pgCC: 11.9
        Intel: 10.1, 11.1, 12.0, 12.1
        Visual Age: 10.1
    OS X:
        Clang: from subversion
        Clang, C++11 mode: from subversion
        Intel: 11.1, 12.0
        GCC: 4.4
        GCC, C++11 mode: 4.4
    Windows:
        Visual C++: 8.0, 9.0, 10.0
        GCC, mingw: 4.4.0, 4.6.3, 4.7.0
    AIX:
        IBM XL C/C++ Enterprise Edition: V12.1.0.0
    FreeBSD:
        GCC: 4.2.1, 32 and 64 bit
    Solaris:
        Sun: 5.10



6
前陣子公司的大陸子公司的一堆工程師都在給我玩 Embedded .

害我差點 發文對子公司 工程部 下 Embedded 禁令.



問他們玩什麼玩那麼兇.

我忍不住去 淘寶看了一下 @@...

啊娘喂~難怪 玩那麼兇 , 真的東西好多.

我看了都手養的要命了!!!!

http://search.taobao.com/search?spm=a230r.1.10.284&q=android+%BF%AA%B7%A2%B0%E5&atype=b&filterFineness=2&newpre=null&s=280#J_FilterTabBar

最哭腰的是...

http://item.taobao.com/item.htm?spm=a230r.1.10.36&id=13860057260   <<< 明目張膽....大補帖...


影音教學.
原始碼
教學文件.
全部都有....

在那裡沒有版權問題 @@.....XD.........



7
#include <iostream>
#include <limits>
#include <map>
using std::cout;
using std::endl;
using std::map;

class Room_Data
{
      public:
             Room_Data() {cout<<"Construct"<<endl;}
             ~Room_Data() {cout<<"Destruct"<<endl;}
             char*        name;
             int          vnum;
};

int main()
{
    Room_Data *pRoom;
    pRoom = new Room_Data;
    pRoom->vnum = 2400;
   
    map<int, Room_Data> rMap;
    map<int, Room_Data>::reverse_iterator iter;
   
    rMap[pRoom->vnum] = *pRoom;
   
    for ( iter = rMap.rbegin() ; iter != rMap.rend(); iter++ )
    {
        cout<<iter->second.vnum<<endl;
        }
    cout<<pRoom->vnum<<endl;
    cout << "Press ENTER to quit." << std::flush;
    std::cin.ignore( std::numeric_limits <std::streamsize> ::max(), '\n' );
    return 0;
}


實驗一下..... 這麼好用 >_<" 不知在異步 IO 下 可不可以拿來做切換器......



8

error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>)’
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/thread:132: note: candidates are: std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (session::*)(), _Args = ]
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/thread:128: note:                 std::thread::thread(_Callable) [with _Callable = void (session::*)()]
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/thread:124: note:                 std::thread::thread(std::thread&&)
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/thread:122: note:                 std::thread::thread(const std::thread&)
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/thread:121: note:                 std::thread::thread()
./src/wge.cpp:484: error: expected ‘;’ before ‘readClientRequest’



有沒有人遇過 一樣的問題 >_<"




9
剛才.... 無聊又~寫了支很簡單的 元件.

手工DIY 只是想看看 這個做法的 效能....

可以掛到 PHP FPM 或 HTTP SERVER 上.

它的功能是取代 PHP 還要去 連線 MEMCACHE 的方式.

讓 SESSION 的處理 大大的降低 MEMECAHE 或 FILE IO 的 使用率.

原本舊的方法是

CLIENT  <---->  NGINX(APACHE) <---> PHP-FPM <---> 你寫的 AP 程式 <---> MEMCACHE

平均每秒一個 CONNECT 只 可以處理 1600 次. ( 原因是 MEMCACHE 跟 PHP 的溝通還是停留在短連結 , 而且溝通太多層 , 併發測試 會高上很多但是 純碎的效能要看單一 CONNECT 的次數喔. )

很浪費效能和頻寬.


新架構的想法 :

CLIENT <----> NGINX ( PLUGING ) <----> PHP-FPM ( PLUGING )  <--- PHP , 直接搖控 PHP-FPM 的存取內容
                                                   |             |
                                                   |             |
                                                   |             |
                                         ( DIY SESSION SERVER )                   


效能預計應該可以 比 傳統做法快.

要從二個地方下手 -

1. PHP-FPM 或 NGINX:

http://php-fpm.org/

2. PHP-EXTTENSION :

http://pecl.php.net/


這支元件我主要是利用 C++ 的 關聯式容器 MAP , 跟 ITERTOR 來實作.


這裡是核心處理的 CODE .

class session{
public:
        //virtual ~user() {}
        bool addSid(int uid, std::string &sid){
                gettimeofday(&time, 0);
                ret = usid.insert(pair<int,std::string>(uid,sid));
                utime.insert(pair<int,long int>(uid,time.tv_sec));
                if(ret.second == false){
                        return false ;
                }
                return true ;
        }
        int getSize(){
                return usid.size() ;
        }
        std::string getSid(int uid){
                if(usid.count(uid) > 0 ){
                        return usid.find(uid)->second;
                }
                return "0" ;
        }
        long int getSidTime(int uid){
                if(utime.count(uid) > 0 ){
                        return utime.find(uid)->second;
                }
                return 0 ;
        }
        void delSid(int uid){
                if(usid.count(uid) > 0 ){
                        usid.erase(uid);
                }
                if(utime.count(uid) > 0){
                        utime.erase(uid);
                }
        }
        void updateUtime(int uid){
                gettimeofday(&time, 0);
                utime[uid] = time.tv_sec ;
        }
        void updateUsid(int uid ,std::string sid){
                usid[uid] = sid ;
        }
        bool checkSid(int uid){
                if(uid != 0 ){
                        gettimeofday(&time, 0);
                        long int sessionTime = SESSION_TIME ;
                        long int thisTime = time.tv_sec ;
                        long int stime = getSidTime(uid);
                        if( (thisTime-sessionTime) > stime){
                                return false ;
                        }
                        return true ;
                }
                return false ;
        }

        std::string sid ;
        std::map<int,std::string> usid;
        std::map<int,long int> utime;
        std::map<int,std::string> ubid;
        std::map<int,std::string>::iterator it;
        std::pair<map<int,std::string>::iterator,bool> ret;
        timeval time;
private :
};


[root@FIEND wge_server]# ./test/session
test session       :
Connection : 10000 , use time : 0.104417
AVG : 95779 (Request/s)  <<< 很嚇人吧~每秒可以跑 九萬五千多次 SESSION 存取
AVG Toime : 1.044066E-05 (s/Request)


裝上這支~PHP 處理 SESSION 的部份 , 肯定飛起來~~~

不過我還要花時間研究怎麼利用 理想的放到 PHP-EXTENSION 或 NGINX  來跟 遠端的這個 容器做 長連結溝通.

這樣才有法子做到分散式架構....

還好新型態的 PHP 有支援 PHP-FPM 長時間運作的 DEAMON .



研究到下一階段再跟大家報告.~~






10
我在 Boost 的官方網站找了很多範例.

有 LIST  , VECTOR  .

但是沒看到 map 如何應用在 share_ptr 的方式....

有沒有大大 做過分享分享~~~

我知道我很懶~~.........



11
代碼: [選擇]
Version 0.9, May 23, 2003

The primary purpose of this benchmark is to show how different standard
containers are in terms of performance. We have observed that programmers
often use sets, multisets, deques in the situations where sorted vectors
are the optimal solutions. Similarly, programmers often choose lists simply
because they do a few insertions and deletions without knowing that vectors
are more efficient at that for small containers.

Frequently, of course, performance does not matter,
but it is important that programmers are aware of the consequences of their
choices. We are not saying that only vectors should be used, there are
cases when one really needs a more complicated data structure, but one needs to
understand the price for additional functionality.

The secondary purpose of the benchmark is to encourage compiler and library vendors to
keep improving performance. For example, it is not acceptable that some compilers give
you a sizable penalty for using vector iterators instead of pointer. It is also quite
clear that  performance of other standard containers could be improved.

The benchmark is doing the same task 7 times using different data structures:
array, vector (using a pointer as iterator), vector (using the defailt cector iterator),
list, deque, set and multiset. The task is to remove duplicates from a sequence of doubles.
This is a simple test, but it illustrates the performance of containers.

It is clear that the benchmark needs to be eventually extended
to slists and even to hash-sets and hash-maps, but we decided that at present it
should work only with the standard containers. As the standard grows, so can
the benchmark. The additional benefit of not including hash based containers is
that now all the test have identical asymptotic complexity and, even more
importantly, do almost the same number of comparisons. The difference is only
in data structure overhead and cache behavior.

The number of times that a given test is run inversly proportional to NlogN where N is the
size of the sequence.  This allows one to see how containers of different size behave.
The instructive values used for the benchmark are: 10, 100, 1000, 10000, 100000, 1000000.

The time taken for a run of the benchmark depends on the machine used, the compiler used,
the compiler and optimizer settings used, as well as the standard library. Please note that
the time taken could be several minutes - and much more if you use a slow debug mode.

The output is a table where columns are separated by tabs and rows by newlines. This is
barely ok for a human reader, but ideal for feeding into a program, such as a spreadsheet
for display or analysis.

If you want to add your own test of a container, add the name of your container to
the "header string, write a test function like the existing ones, e.g. vector_test,
and add a call of "run" for your test in "run_tests".


Alex Stepanov
stepanov@adobe.com

Bjarne Stroustrup
bs@cs.tamu.edu

*/

#include <stddef.h>   // some older implementations lack <cstddef>
#include <time.h>
#include <math.h>
#include <stdlib.h>

#include <vector>
#include <algorithm>
#include <list>
#include <deque>
#include <set>

#include <iostream>
#include <iomanip>

typedef double element_t;

using namespace std;

vector<double> result_times; // results are puched into this vector

const char header[] =
"\tarray"
"\tvector with pointers"
"\tvector with iterators"
"\tdeque"
"\tlist"
"\tset"
"\tmultiset";

void do_head()
{
   cout << "size" << header << '\n';
}

int do_tail()
{
   // in case you want to stop for confirmation in a windows console application
   //char c;
   //cin >> c;
   return 0;
}

void do_row(int size)
{
   cout << size;
   cout << fixed << setprecision(2);
   for (size_t i = 0; i < result_times.size(); ++i)
      cout << '\t' << result_times[i];
   cout << '\n';
}


clock_t start_time;

inline void start_timer() { start_time = clock(); }

inline double timer()
{
   clock_t end_time = clock();
   return (end_time - start_time)/double(CLOCKS_PER_SEC);
}

typedef void(*Test)(element_t*, element_t*, int);
void run(Test f, element_t* first, element_t* last, int number_of_times)
{
   start_timer();
   while (number_of_times-- > 0) f(first,last,number_of_times);
   result_times.push_back(timer());
}

void array_test(element_t* first, element_t* last, int number_of_times)
{
   element_t* array = new element_t[last - first];
   copy(first, last, array);
   sort(array, array + (last - first));
   unique(array, array + (last - first));
   delete [] array;     
}

void vector_pointer_test(element_t* first, element_t* last, int number_of_times)
{
   vector<element_t> container(first, last);
   // &*container.begin() gets us a pointer to the first element
   sort(&*container.begin(), &*container.end());
   unique(&*container.begin(), &*container.end());
}

void vector_iterator_test(element_t* first, element_t* last, int number_of_times)
{
   vector<element_t> container(first, last);
   sort(container.begin(), container.end());
   unique(container.begin(), container.end());
}

void deque_test(element_t* first, element_t* last, int number_of_times)

   //       deque<element_t> container(first, last); CANNOT BE USED BECAUSE OF MVC++ 6
   deque<element_t> container(size_t(last - first), 0.0);
   copy(first, last, container.begin());
   sort(container.begin(), container.end());
   unique(container.begin(), container.end());
}

void list_test(element_t* first, element_t* last, int number_of_times)
{
   list<element_t> container(first, last);
   container.sort();
   container.unique();
}

void set_test(element_t* first, element_t* last, int number_of_times)
{
   set<element_t> container(first, last);
}

void multiset_test(element_t* first, element_t* last, int number_of_times)
{
   multiset<element_t> container(first, last);
   typedef multiset<element_t>::iterator iterator;
   {
      iterator first = container.begin();
      iterator last = container.end();

      while (first != last) {
         iterator next = first;
         if (++next == last) break;
         if (*first == *next)
            container.erase(next);
         else
            ++first;
      }
   }
}

void initialize(element_t* first, element_t* last)
{
   element_t value = 0.0;
   while (first != last) {
      *first++ = value;
      value += 1.;
   }
}

double logtwo(double x)
{
   return log(x)/log((double) 2.0);
}

const int largest_size = 1000000;

int number_of_tests(int size) {
   double n = size;
   double largest_n = largest_size;
   return int(floor((largest_n * logtwo(largest_n)) / (n * logtwo(n))));
}

void run_tests(int size)
{
   const int n = number_of_tests(size);
   const size_t length = 2*size;
   result_times.clear();

   // make a random test set of the chosen size:
   vector<element_t> buf(length);
   element_t* buffer = &buf[0];
   element_t* buffer_end = &buf[length];
   initialize(buffer, buffer + size);      // elements
   initialize(buffer + size, buffer_end);   // duplicate elements
   random_shuffle(buffer, buffer_end);

   // test the containers:
   run(array_test, buffer, buffer_end, n);
   run(vector_pointer_test, buffer, buffer_end, n);
   run(vector_iterator_test, buffer, buffer_end, n);
   run(deque_test, buffer, buffer_end, n);
   run(list_test, buffer, buffer_end, n);
   run(set_test, buffer, buffer_end, n);
   run(multiset_test, buffer, buffer_end, n);
   do_row(size);
}

int main()
{
   do_head();
   const int sizes [] = {10, 100, 1000, 10000, 100000, 1000000};
   const int n = sizeof(sizes)/sizeof(int);
   for (int i = 0; i < n; ++i) run_tests(sizes[i]);
   return do_tail();
}
引用
size    array   vector with pointers    vector with iterators   deque   list    set     multiset
10      0.57    0.56    0.61    1.47    3.80    2.20    4.06
100     0.38    0.39    0.36    0.86    2.32    1.62    2.53
1000    0.62    0.62    0.64    0.88    1.94    1.53    2.12
10000   0.69    0.70    0.71    0.86    2.21    1.98    3.71
100000  0.66    0.66    0.67    0.86    4.17    4.65    7.93
1000000 0.64    0.64    0.66    0.83    9.52    10.31   27.90







執行結果....
代碼: [選擇]
[root@FIEND test]# ./stl_banckmark
size    array   vector with pointers    vector with iterators   deque   list    set     multiset
10      0.19    0.22    0.20    0.38    1.35    0.65    1.22
100     0.09    0.10    0.09    0.17    0.68    0.41    0.70
1000    0.23    0.23    0.24    0.33    0.73    0.65    0.93
10000   0.28    0.29    0.29    0.35    0.90    0.84    1.17
100000  0.28    0.28    0.28    0.33    1.31    1.25    1.63
1000000 0.27    0.28    0.28    0.33    1.52    2.23    2.85
阿娘喂!! 我只能說現在的機器跟五年前的比起來...

簡值是坐穿梭機...................




CPU :
代碼: [選擇]
[root@FIEND test]# cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 0
siblings        : 6
core id         : 0
cpu cores       : 6
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 1
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 0
siblings        : 6
core id         : 1
cpu cores       : 6
apicid          : 1
initial apicid  : 1
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 2
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 0
siblings        : 6
core id         : 2
cpu cores       : 6
apicid          : 2
initial apicid  : 2
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 3
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 0
siblings        : 6
core id         : 3
cpu cores       : 6
apicid          : 3
initial apicid  : 3
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 4
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 0
siblings        : 6
core id         : 4
cpu cores       : 6
apicid          : 4
initial apicid  : 4
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 5
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 0
siblings        : 6
core id         : 5
cpu cores       : 6
apicid          : 5
initial apicid  : 5
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 6
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 1
siblings        : 6
core id         : 0
cpu cores       : 6
apicid          : 8
initial apicid  : 8
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 7
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 1
siblings        : 6
core id         : 1
cpu cores       : 6
apicid          : 9
initial apicid  : 9
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 8
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 1
siblings        : 6
core id         : 2
cpu cores       : 6
apicid          : 10
initial apicid  : 10
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 9
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 1
siblings        : 6
core id         : 3
cpu cores       : 6
apicid          : 11
initial apicid  : 11
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 10
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 1
siblings        : 6
core id         : 4
cpu cores       : 6
apicid          : 12
initial apicid  : 12
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 11
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz
stepping        : 7
cpu MHz         : 1995.192
cache size      : 15360 KB
physical id     : 1
siblings        : 6
core id         : 5
cpu cores       : 6
apicid          : 13
initial apicid  : 13
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 3990.38
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:


哈我忍不住用自己家裡的電腦試.

公司的伺服器雖然是多核...

但是也只是處理線程數高.

(本來超頻到 4.5 GHZ 先降回來....)

試試 Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz 的效能....
代碼: [選擇]
size    |array| |vector with pointers|  |vector with iterators| |deque| |list|  |set|   |multiset|
10      0.10    0.10    0.10    0.18    0.61    0.33    0.58
100     0.05    0.04    0.05    0.08    0.31    0.20    0.34
1000    0.12    0.12    0.13    0.17    0.36    0.32    0.46
10000   0.14    0.15    0.14    0.18    0.42    0.40    0.56
100000  0.14    0.14    0.14    0.17    0.79    0.68    1.15
1000000 0.14    0.14    0.14    0.17    1.08    1.66    2.05
代碼: [選擇]
[root@sgdDEV test]# cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 58
model name      : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
stepping        : 9
cpu MHz         : 3674.729
cache size      : 8192 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 2
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 7349.45
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 1
vendor_id       : GenuineIntel
cpu family      : 6
model           : 58
model name      : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
stepping        : 9
cpu MHz         : 3674.729
cache size      : 8192 KB
physical id     : 0
siblings        : 2
core id         : 1
cpu cores       : 2
apicid          : 1
initial apicid  : 1
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 7349.45
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 2
vendor_id       : GenuineIntel
cpu family      : 6
model           : 58
model name      : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
stepping        : 9
cpu MHz         : 3674.729
cache size      : 8192 KB
physical id     : 1
siblings        : 2
core id         : 0
cpu cores       : 2
apicid          : 2
initial apicid  : 2
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 7349.45
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 3
vendor_id       : GenuineIntel
cpu family      : 6
model           : 58
model name      : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
stepping        : 9
cpu MHz         : 3674.729
cache size      : 8192 KB
physical id     : 1
siblings        : 2
core id         : 1
cpu cores       : 2
apicid          : 3
initial apicid  : 3
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 7349.45
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 4
vendor_id       : GenuineIntel
cpu family      : 6
model           : 58
model name      : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
stepping        : 9
cpu MHz         : 3674.729
cache size      : 8192 KB
physical id     : 2
siblings        : 2
core id         : 0
cpu cores       : 2
apicid          : 4
initial apicid  : 4
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 7349.45
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 5
vendor_id       : GenuineIntel
cpu family      : 6
model           : 58
model name      : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
stepping        : 9
cpu MHz         : 3674.729
cache size      : 8192 KB
physical id     : 2
siblings        : 2
core id         : 1
cpu cores       : 2
apicid          : 5
initial apicid  : 5
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 7349.45
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 6
vendor_id       : GenuineIntel
cpu family      : 6
model           : 58
model name      : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
stepping        : 9
cpu MHz         : 3674.729
cache size      : 8192 KB
physical id     : 3
siblings        : 2
core id         : 0
cpu cores       : 2
apicid          : 6
initial apicid  : 6
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 7349.45
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 7
vendor_id       : GenuineIntel
cpu family      : 6
model           : 58
model name      : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
stepping        : 9
cpu MHz         : 3674.729
cache size      : 8192 KB
physical id     : 3
siblings        : 2
core id         : 1
cpu cores       : 2
apicid          : 7
initial apicid  : 7
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ida arat epb xsaveopt pln pts dts
bogomips        : 7349.45
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

12
前幾天剛好在寫一個 壓縮 TCP 封包內容的功能.

利用 GZIP 和 ZLIB 做 Deflate 和 Inflate 來做 壓縮的 Stream Server

以下是我利用 POCO 來編寫的.

在使用這個元件時 , 我發現它的 GZIP 的 deflate 和 infalte 不能用 .

所以另外寫了一個獨立的 元件 .

在編寫過程中 , 發現這個 FREE 的 元件庫 問題還蠻多的 , 只好 一 一 解決.



以下是我用 POCO 寫的 CODE :
Deflate :
代碼: [選擇]
std::string Zlib::deflate (const std::string &source , int level = (-1))        {

        std::istringstream in(source);
        std::ostringstream out;
        Poco::DeflatingOutputStream deflaterOut(out,DeflatingStreamBuf::STREAM_ZLIB,level);

        // 這裡沒有使用 POCO 的 StreamCopier::copyStream 的原因是因為 , 沒法子 COPY  可能是 BUG.....
        // POCO SUPPORT 是要收費 的 , 如果知道原因的也麻煩賜教 , 謝謝!!!!
        // 寫到這裡時要小心....
        // 在不得已的情況下 ,,,, 直接用這個方式 :
        deflaterOut << in.str() ;

        deflaterOut.close() ; 
        deflateStr = out.str();
        return deflateStr ;
}
Inflate :
代碼: [選擇]
std::string Zlib::inflate (const std::string &source)   {
        std::istringstream in(source);
        std::ostringstream out;
        Poco::InflatingInputStream inflaterIn(in);
        StreamCopier::copyStream(inflaterIn , out);
        inflateStr = out.str();
        return inflateStr ;
}
PHP 就簡單多了 :
代碼: [選擇]
gzDeflate($string,level = (defalut -1));
gzInflate($string);
接下來我分別把 結果 轉成 ASCII 和 HEX 來觀查.


測試結果分析 :
代碼: [選擇]
SOURCE JSON STring :
{"SID":"123456789","BID":"LD0001","DATA":{"args":{"name":"test1","passwd":"test1","item":["itme1","itme2","itme3","itme4"]}}}

POCO Deflate :
x▒▒V
▒#U▒R2426153▒▒T▒Qr▒▒▒.▒!▒JV▒J▒E▒▒ :/17(_▒Z\▒.H,..OA▒,I▒U▒▒ҹ▒~n▒▒6▒▒&J▒▒▒▒

Lengh :
97

Ascii Code :
120 156 171 86 10 246 116 81 178 82 50 52 50 54 49 53 51 183 176 84 210 81 114 2 139 248 184 24 24 24 24 2 185 46 142 33 142 74 86 213 74 137 69 233 197 32 58 47 49 55 21 40 95 146 90 92 2 146 46 72 44 46 46 79 65 18 200 44 73 205 85 178 138 6 210 185 169 16 126 110 170 17 148 54 134 210 38 74 177 181 181 181 0 13 213 35 85

Hex Code :
78 9c ab 56 a f6 74 51 b2 52 32 34 32 36 31 35 33 b7 b0 54 d2 51 72 2 8b f8 b8 18 18 18 18 2 b9 2e 8e 21 8e 4a 56 d5 4a 89 45 e9 c5 20 3a 2f 31 37 15 28 5f 92 5a 5c 2 92 2e 48 2c 2e 2e 4f 41 12 c8 2c 49 cd 55 b2 8a 6 d2 b9 a9 10 7e 6e aa 11 94 36 86 d2 26 4a b1 b5 b5 b5 0 d d5 23 55

PHP Deflate:
▒V
▒tQ▒R2426153▒▒T▒Qr▒▒▒.▒!▒JV▒J▒E▒▒ :/17(_▒Z\▒.H,..OA▒,I▒U▒▒ҹ▒~n▒▒6▒▒&J▒▒▒▒

Lengh :

91
Ascii Code :
171 86 10 246 116 81 178 82 50 52 50 54 49 53 51 183 176 84 210 81 114 2 139 248 184 24 24 24 24 2 185 46 142 33 142 74 86 213 74 137 69 233 197 32 58 47 49 55 21 40 95 146 90 92 2 146 46 72 44 46 46 79 65 18 200 44 73 205 85 178 138 6 210 185 169 16 126 110 170 17 148 54 134 210 38 74 177 181 181 181 0

Hex Code :
ab 56 a f6 74 51 b2 52 32 34 32 36 31 35 33 b7 b0 54 d2 51 72 2 8b f8 b8 18 18 18 18 2 b9 2e 8e 21 8e 4a 56 d5 4a 89 45 e9 c5 20 3a 2f 31 37 15 28 5f 92 5a 5c 2 92 2e 48 2c 2e 2e 4f 41 12 c8 2c 49 cd 55 b2 8a 6 d2 b9 a9 10 7e 6e aa 11 94 36 86 d2 26 4a b1 b5 b5 b5 0
用 HEX 表來分析 :

POCO 在解壓縮和壓縮時 .

必需在

前面 : 多二個字元 ,   78 9c

後面 : 多了四個字元 ,   d d5 23 55


所以造成它跟 PHP 還有 FLASH 無法做 解壓縮和壓縮的動作.

後來我查了一下...

原來 POCO 的 inflate 和 deflate 是使用 ZLIB.

我有試著 從 .h 檔的STRUCT 上分析 , 找到 GZLIP 格式插入 .... 但是不支援.

因為趕著要用 ...... 所以只好先自己硬改一個版本.....



>_<" 免費的就難搞..........


程式也改好了......
代碼: [選擇]
        std::string fixsource;
        std::string str = source ;
        zlibHeader[0] = 0x78  ;
        zlibHeader[1] = 0x9c  ;
        std::string zlibHeaderStr =  zlibHeader;
        std::string fixZlibHeaderStr = zlibHeaderStr.substr(0,2); // 為什麼要再往前抽二個字元 , ( 因為 不知道為什麼我的 編譯器編出來的 CODE 往 fixsource 丟老是會多一個字元 , 為了穩定性加一下....... )

        zlibEnd[0] = 0xd ;
        zlibEnd[1] = 0xd5 ;
        zlibEnd[2] = 0x23 ;
        zlibEnd[3] = 0x55 ;
        std::string zlibEndStr = zlibEnd ;
        std::string fixZlibEndStr = zlibEndStr.substr(0,4); 

        fixsource = fixZlibHeaderStr + source + fixZlibEndStr ; // 將 HEADER 和 END 的 部份修改成 GZIP 看的懂的格式....
       
        std::istringstream in(source);



/*
 * gzip deflate 字串壓縮
*/

std::string Zlib::gzdeflate (const std::string &source , int level = (-1))      {

        std::istringstream in(source);
        std::ostringstream out;
        Poco::DeflatingOutputStream deflaterOut(out,DeflatingStreamBuf::STREAM_ZLIB,level); /// 這裡不用管它 ,我用 DeflatingStreamBuf::STREAM_GZIP 是不 WORK 的 , 它是免費的不是故意的就是還沒寫好.
        deflaterOut << in.str() ;
        deflaterOut.close() ;
        std::string zlibDeflateStr ;
        zlibDeflateStr = out.str();
        zlibDeflateStr = zlibDeflateStr.substr(2,zlibDeflateStr.length()-6); // 將 ZIP 的 HEADER 及 END 拿掉 , 前二個字元 , 後六個字元.
        deflateStr = zlibDeflateStr ;
        return deflateStr ;
}




執行 UNIT TEST .....................
代碼: [選擇]
Convert To HEX   :
ffffffab 56 a fffffff6 74 51 ffffffb2 52 32 34 32 36 31 35 33 ffffffb7 ffffffb0 54 ffffffd2 51 72 2 ffffff8b fffffff8 ffffffb8 18 18 18 18 2 ffffffb9 2e ffffff8e 21 ffffff8e 4a 56 ffffffd5 4a ffffff89 45 ffffffe9 ffffffc5 20 3a 2f 31 37 15 28 5f ffffff92 5a 5c 2 ffffff92 2e 48 2c 2e 2e 4f 41 12 ffffffc8 2c 49 ffffffcd 55 ffffffb2 ffffff8a 6 ffffffd2 ffffffb9 ffffffa9 10 7e 6e ffffffaa 11 ffffff94 36 ffffff86 ffffffd2 26 4a ffffffb1 ffffffb5 ffffffb5 ffffffb5 0 0 0 0 0 Inflate  Success
{"SID":"123456789","BID":"LD0001","DATA":{"args":{"name":"test1","passwd":"test1","item":["itme1","itme2","itme3","itme4"]}}}










XD 寫支 DOS 的攻擊程式狂丟...... 還沒死掉 應該修好了 >_<"

我覺得我下次還是愛用 LINUX 內建的 函式庫比較安全.... 肝都快壞了~~~

13
延續這個主題 :

http://phorum.study-area.org/index.php/topic,67110.0.html

##

當你對 SWITCH 下達 PORT MIRROR 時要小心 SWITCH LOADING 的問題.

NETFLOW 是做SESSION 抽樣分析

SFLOW 是做 SESSION 的抽樣 平均值分析. ( 官方有個公式 可以算回實際的頻寬使用量 , 很久以前我寫過忘了公式在那裡了. )

EX :

你可以使用 NTOP 來分析 NETFLOW 和 SFLOW .

http://www.ntop.org/products/ntop/  << 其實它同時支援了這二種格式.

並且由 NPROBE 來做分析和發出警告.


####################################


如果你真的要用 MIRROR 原始封包時 .

情況會是比較在你要看封包的內容物來檢查是不是有異常的封包流進來.

這時就會使用到 MIRROR 的功能.


我以 坐飛機做比喻~~~


一般的網路流量監控 , 只是去監控 封包的 LAYER 3,4 層的資訊 , 不需要去解開封包的內容去觀查內容有什麼異常..


就好比 過飛機海關 , 只要用X光照一下看看這個人有沒有問題並且做計錄就放行了.




MIRROR 實際封包在檢查封包內容有沒有問題時 就必需打開封包 , 並且 有一份 規則表來檢查封包的內容並發出警報.

就好像海關叫每個客人把行李倒出來 , 每一個客人都要檢查~~~~

所以需要使用比較有計算能力的 伺服器來處理這些封包內容.

而且在 MIRROR 時盡量 MIRROR 你要的指定服務 , 可以善用 SWITCH 的 PORT FORWARD 的功能.

EX :

http://www.snort.org/

它提供了一些 常見的封包內容異常規則表 , 你可以自己客制封包異常的內容.

另外也可以買他的服務 .

他的收費方式是異常規則表維護更新的收費.













14
下午想了又想....想了又想....

先畫了這張圖...

我的需求是建立一個 雙向溝通的 即時知道對方狀態的伺服器

我先把想法畫成一張圖.....





1 會走向 2 也會走向 3 如果往 3 走上去 會走向 4 跟 5 .

如果停在 5 上面 則 5 跟 6 會不停的去讀取 Vector OR MAP 的內容 , 判斷要發送 TCP 給那些人.

如果都處理完了 6 就會走回 4 再走回 1,2,3,4 那二圈.

讓 5,6 會因為 使用者共同組織了一個組織 在裡頭時才會不停的把 TCP 送給 5,6 迴路的人.

讓 5,6 迴路的人可以互相即時知道對方的動態........

提供參考....


有什麼好的建議~~請多多建議~~謝謝~~

PS : 就是不想用 UDP 封包 做才想破頭... >_<" 別建議我用 UDP 做...


15
LINUX 玩久的朋友來篇輕鬆的吧~!!!!



有空多照顧家人 , 替家人搞搞 方便又好用的 家庭專用的影音串流伺服器.

練了那麼多年的功~一技在身 , 家裡只有你有能力架設 , 為了家庭~~看看這篇文章吧~~

另外如果是教育工作者~~也可以考慮用看看...

http://phorum.study-area.org/index.php/topic,67522.0.html   <<< 如果頻寬多可以參考這篇教學 , 開放給親朋好友用.



前幾個月閒來無事 , 發現家裡的 APPLE TV 2 給它有點來的工作不夠忙...

所以試著去 JB 它 , 直接  SSH  進去 APPLE TV 來個 家庭影音 大改造.

自從用了它後 , 我跟我老婆~~使用 IPAD , APPLE TV , PC 躺著也看 , 站著也看 , 用 3G 坐捷運 , 開車時 也在看...


直接把家裡的影片變雲端的應用~~~~


如果你家是使用 50~100MB 以上的光纖網路 , 照過來.......



先認識一下一些 免費的 影音家庭多媒體 軟體 :

http://www.plexapp.com/

http://xbmc.org/


1.
PLEX 是 主從式的架構 , 它勝過 XBMC 的地方是它 直接把 影音串流伺服器與 撥放介面分開 , 讓你在家可以用

IPAD , IPHONE , ANDROID , WINDOWS , APPLE TV 等 安裝 撥放軟體即可撥放.

另外撥放那層還支援 NAS , SMB , LOCAL 端的讀取 ,

最強大的地方是它可以 使用外掛 收看 其它影音串流 雲端系統的視訊回來看.


2. XBMC , 它是一套比較完整的影音撥放軟體.

它支援了 NAS , SMB , LOCAL 端 , 同時 它的功能性來的比 PLEX 強大.

但是很可惜 , 它沒有獨立援影音串流伺服器 , 不像 PLEX 是主從式的架構的楖念.

但是穩定性和操作性上 , 還是 XBMC 來的穩定!!!


XBMC 我想應該太多教學了.


我只介紹 PLEX :

1. 首先我們先從 CLIENT 端來安裝

1. WIN7 的安裝 , 並且解決中文化問題 :  ( 我後來想在家裡的工作室看 , 偷偷裝起來都亂破一氣之下自己中文化....想裝 WIN版的可以參考我的教學. )
http://forums.plexapp.com/index.php/topic/45156-win7-install-plex-fix-chinese-issue/

2. Apple tv :
你要先 JB 你的 APPLE TV 喔.....

http://wiki.plexapp.com/index.php/Apple_TV_Plex_Client_Install
我試過問題不多 .

3.
IPAD , ANDROID .......... 那些都一鍵搞定 , 沒什麼好介紹的.


接下來進入主題了 :

使用 LINUX 來做影音串流伺服器 :

http://www.plexapp.com/linux/linux-pms-download.php   <<< 這裡是教學.
http://wiki.plexapp.com/index.php/Beta_AppCasts#Linux

先將 這串放到 /etc/yum.repos.d/plex.repo

[PlexRepo]
name=PlexRepo
baseurl=http://plexapp.com/rpmrepo/release/$basearch/
enabled=1
gpgcheck=1
      

$ rpm --import http://plexapp.com/plex_pub_key.pub

yum install plexmediaserver


############

接下來你要打開 :

http://{Linux}:32400/manage/index.html   來設定你的影片和分類.



之後的不多說了......沒玩過的人玩下去你一定會迷死它!!!!


為什麼? 因為 PLEX 支援多種 格式的 影音封包 壓縮.

你可以在~CLIENT 端 設定 , 要 影音串流伺服器 給你多少大小的封包 , 解析度 , 還有 每幾秒丟一批影音檔讓你的撥放器撥放.

也就是就算你在 網速不快的地方一樣可以回家看你分類好的影片.

只要買台 NAS , 掛到 LINUX 上

就可以自己管理影音平台喔~~~

玩玩看吧~~~真的很好玩`~~~~~~~~








16
###############################################
# 作       者 : FIEND
# Email       : fiendcly@gmail.com
# Date        : 2012/08/26
# 請盡量保留原文出處以供討論 , 謝謝大家.
###############################################

這幾年我比較少寫 PHP 了.

有陣子很迷它 , 但是因為工作關係 , 把較多的時間花在 網路封包和資料庫行為的分析工作上.

而且 因為年記較大了 所以也很難找到 寫程式的工作 多半都在做 工程師 的 "工頭"


對於這幾年 PHP 的變化 我來不及參與 .

在這裡收集這幾年對 PHP 的變化 , 寫篇 心得 過過小弟自己的乾隱 :

回顧您以往的職業生涯 , 您有好好的管理您寫的 CODE 嗎?

還是每次都寫到專案超級肥大了 , 才延伸出一大堆的 程式碼管理問題.


在這裡 小弟設計一個開發框架的架構 , 讓你的程式更簡潔 而且讓 你的程式 更有條有理的被應用.

當然這些架構教學我己經簡化很多 , 如果放入太多的設計 反而會得到反效果.

如果您是比較重口味的 PHP 設計者 , 先說聲報歉了 .

如果您常為了專案肥大難以管理你的程式 ,

這篇文章對您來說會是個值得參考的文章 , 至少它有著我十幾年的 專案開發經驗.



一. 常見的 PHP 應用的架構 :



在往下教學下去前 , 小弟先定義 一些 名詞 , 以方便大家接下去閱讀教學.


  • DB                :

                                這一塊不用多介紹 , 我相信大家對 DB 的經驗獨道 , 我們直接跳過去.

   
  • Access Layer :

                                這一塊 全部都是放一些 Access Logic 在裡頭 , 主要的工作是負責 跟 DB 還有 MEMCACHE 溝通 , 你可以使用現成的開發框架達成這一層的目地 , 也可以自己開發. 但是這些邏輯建議您都保留在這一層.
   
  • MEMCACHE   :

                                這一塊 主要是做為分散式架構的存取層 , 大家有沒有注意到一件事? 它是走 TCP 11211 PORT .

                                它可以用在什麼地方 ?

                                a.  讓你可以把從 DB 的資料撈到 快取一份到 MEMCACHE , 來減輕資料庫的工作負擔 , 這在大型而且流量很高的系統上 , 它辨演很重要的角色就是可以減輕 DB 的工作量.
                                     * 我們這裡不多介紹 Memcahe 的使用及方式 , 您可以多參考 官方網站或其它網路上的教學.   

                                b.  有一些不用儲存 用完就不要的資料 , 也可以利用 memcache 直接存取不用再交給 DB 去處理.

                                c.  注意一件事 :
                                                        在過去裡我的下屬們在使用它時常會犯一個錯就是爛用 Memcache ,

                                                        memcache 本身是 一個 TCP 的 服務 在單台 linux 伺服器下最多只能 使用 1024 個請求 , 當然你可以用 ulimit 提高它 , 但是請先了解它的本質 用對地方.

                                                        它本身並不能做為程式本身加快程式效能的工具 , 但是它是一個可以做到分散式的存取架構 , 並且可以減輕 DB 負擔的工具 , 的好用工具.

                                                         所以在使用它時要選對時機 , 千萬不要爛用.

   
  • Access Layer                        :  這一層的工作主要是存取 資料層的邏輯 , 我將會 2. 會有更詳細的說明.
  • Content Logic Layer            :  這一層的工作主要是負責處理 存取層 從 資料層要來的資料的邏輯 , 我將會 3. 會有更詳細的說明.
  • Presentation Layer              :  這一層的工作意義重大 , 它主要是標準化 Presentation Logic 與 Content Logic Layer 溝通的標準, 讓你的 畫面邏輯不會愈來愈肥大及復雜 , 我將會 4. 會有更詳細的說明.
  • Presentation Logic Layer     :  這一層的工作 是做為 讓 你的畫面邏輯 可以採用標準化的 介面來 與伺服器溝通 , 如果 Presentation Layer 標準化了 , 你的 畫面邏輯的可重覆利用性就會更高及有彈性 , 我將會 5. 會有更詳細的說明.
  • Client Layer                        :  這一層 就是我們平時便用的 瀏覽器, 雲端服務 等等的應用 , 相信大家非常了解這一層可以做到的事 , 所以我們就不多介紹 Client Layer 了.


二. 功能方塊介紹 :

序 :
 
到這裡我們必需要將圖裡的方塊切的更細讓大家理解 請耐心的看完下一張圖  :






1. Access Logic  Layer :

       Access Logic Layer 主要的工作是做為 與 DB 和 Content Logic 溝通的 區塊 , 在這裡小弟建議大家 在設計物件庫或函式庫前 , 先參考這個架構.

把所有跟 資料庫存取的 邏輯全部包裝在這個區塊下 , 例如大家在設計DB時最愛用 Factory 來做 DB 的 切換 , 同時把 這些邏輯全部整到這一層 讓您的程式更有層次更好管理.

看到這裡大家一定對 一些 使用 Factory 設計的 OOP DB 存取函式庫不漠生.

這時我要介紹大家一個名詞 , Object-relational_mapping :

http://en.wikipedia.org/wiki/Object-relational_mapping

什麼地方有 ORM ? 就是大家常用的 .

CAKE PHP
ZEND FRAMEWORK.
Doctrine
Propel
CoughPHP
Symphony

當然...您也可以自己寫 , 重點是 , 要懂得怎麼有效率的去管理你的存取層的邏輯.


而一但定義了這一層 .

      強烈建議 在接下來的 Content Logic Layer , Presentation Logic Layer 嚴格禁止其它邏輯層的邏輯跳過它來存取資料庫.


           這麼做有什麼好處 ? :
                                           1.    確保其它工作者不會寫出不良的DB存取邏輯造成你的系統不好維護
                                           2.    你可以不用再擔心會有嚴重的存取層 BUG
                                           3.    它在使用上變的更安全 , 不會讓你的資料庫 暴露在 Content & Presentation Logic Layer , 讓你的 DB 有一定程度的保障.
                                           4.    如果你的 ORM TOOL 有提供管理器 , 你還可以把所有的 SQL 語法倒出來檢示有沒有什麼存取過重的語法.
                                           5.    最重要的!! 你可以把 常用的存取層資料 跟 MEMCACHE 做有效的資源管理 , 讓你的 DB 的 資源更有效的被利用!!

補充說明 :
  • Access MYSQL        :   資料庫的新增改查邏輯全部放在這.
  • Access Memcache  :   與 MEMCACHE 存取的新增改查邏輯全部放在這.
  • Access NOSQL       :   現在最流行的 NOSQL , 你可以分別的去包裝你要的邏輯在這裡面.
  • Other                     :  如果你有別的使用資料存取的邏輯 , 可以參造上述的方式 一一的去整理....



3. Content Logic  Layer :

             這一層有什麼東西?

             1. 你們服務用的到的 商業邏輯 , 你可以把每個商業邏輯 用 OOP 設計 , 並且放在這一塊 , 以利日後的管理.

             2. String Parser  :

                                為什麼在這篇教學裡我會建議您設計這塊 ?  因為它必需滿足 Presentation Layer 要求的 幾個素求 :

                                          1.一致性高, 2.可重覆利用性高 , 3.跨平台性高 ,4.雲端應用 , 所以大家不要關掉文章快點看到 3. 怎麼讓你的系統可以符合這四個素求.




3. Presentation  Layer :



                  我為何在這篇教學裡 , 放入了這一層的應用?



                  這要回顧到 10年前 , 我入手了一本 Wrox 的 Professional PHP4 .
                  這本書我印象深刻 , 因為它一共有十一個作者在寫 : 當時看到它有一篇單元 "多層式架構開發" ,  讓我對整個 WEB 架構開發的視野完全打開.
                  不過我得承認我以前很嘴賤 , 常說 SMARTY TEMPLATE 是玩具 .

                  PS : SMARTY TEMPLATE 採用 tpl php var 的方式來做 少了這一層 , 常會極端的用些言語說它不好.

                  你可以參考這二本書 , 會發現 這一層放入這個設計 會讓你未來工作變的輕鬆很多 .
                  http://www.amazon.com/Professional-PHP4-Programming-Deepak-Thomas/dp/1861006918
                  http://www.amazon.com/Professional-PHP4-XML-Luis-Argerich/dp/1861007213/ref=sr_1_1?s=books&ie=UTF8&qid=1345942943&sr=1-1&keywords=PHP4+XML

                   # 回到正題 -
 
                          這一層專門用來處理 Content Logic Layer 處理好的資料 , 利用 XML , JSON 等標準化的 介面語言 , 來規範你的 Content Logic Layer 按照你的 Convention (規範) 來吐出資料給 Presentation Logic Layer
                             
                               a. 這樣做有什麼好處:

                                                     1. 一致性高            :
                                                                                也因為這樣 , 你的 Presentation Layer 有著標準化的 格式 , 所以你在使用 AJAX , AS , PHP SDK 等...做畫面邏輯串接時 ,
                                                                                你的畫面邏輯的程式將會變的一致性很高 , 因為都是參考同樣的格式 , 讓你的畫面邏輯的程式不會亂長.
                                                                                工程師因為熟悉相同的介面格式 , 工作起來將會非常的輕鬆.

                                                     2. 可重覆利用性高 :
                                                                                在你享受 Presentation Layer 有著標準化的格式 的好處時 , 你會發現,  你可以把 畫面邏輯也整理起來重覆利用 ,
                                                                                這時你會發現你少寫好多好多的程式碼.

                                                                                例如 : 換頁邏輯 , 表單的呈現 ...........等等等 , 只要另外塞 CSS 進來就好了 . 根本不用寫什麼程式.
   
                                                      3. 跨平台性高        :
                                                                                啥咪? 還有. 是的!!! 大家記得 RSS 嗎? RSS就是利用了 Presentation Layer  這個特性 讓各種平台都可以串接 BLOG 的文章內容 , 讓你的系統有著強大的誇平台性整合能力.

                                                      4. 雲端應用            :
                                                                                是的 即然跨平台性高了 , 也就是你完成這個專案的同時 , 你所有的系統內容的呈現可以丟給 任何雲端平台的整合!

 
                               b. 使用心得:



                                                  這個設計 , 會讓你的系統架構 非常靈活 , 靈活到什麼程度? 

                                                  以往一組 新增/修改/刪除/換頁/搜尋 , 只要寫完一次 而且完整的從下到上每一層整合上來 .

                                                  我幾乎不用二次開發 , 直接套用 之前寫好的 content Logic , Presentation Logic 就可以完成一個專案 .

                                                  一天可以完工 三十幾組 新增/修改/刪除/換頁/搜尋 的串接 , 所以我當時消耗專案的速度比起一般沒有用這個設計技巧快上非常的多.
                                                 
                                                  而大家心裡會有疑問 , 這不就是 以前 RUBY & CAKE PHP 的特性嗎?   是的!!就這個理念!

                                                  不過有差異 ,  就是 CAKE PHP 在做 畫面邏輯時 , 它並不會真的把 這層切開 , 而是將 MVC 裡的 V 和 C 有效化的重覆利用 , 但是一但 要使用 雲端應用和誇平台時 ,

                                                  之前寫過的程式無法直接透過 Presentation Layer 拉出去給第三方平台做串接.

                                                  雖然省了 ORM 那一層的重覆開發 , 但是 Content Layer 和 Presentation Layer 還是要在手工調整的.

                                                  而一但一調整 , 就會產生 , DEBUG  , 開發 , 穩定性 , 和你又多了一堆CODE 要維護的工作....




4. Presentation Logic  Layer :

                 這一層講起來輕鬆多了 , 因為大家己經有了非常多的 AJAX , XSL , FACEBOOK SDK ,  IOS  , ANDROID , FLASH AS 的串接經驗.

       沒錯 , 這裡就是把之前辛苦定義並且做好的 Presentation Layer 吐出來的格式做應用 .

                你可以透過~HTTP , SOCKET SERVER 等等.. 將你的 Presentation Layer 的 JSON , XML 吐出來 , 並且交給你的畫面邏輯程式去串接.

       這麼一來你也輕鬆完成了一個 雲端的整合介面 , 讓你寫的 PHP 可以廣泛的使用在任何不同的平台上.


           
5. Unit Test & Stress Test & Integration Test  :

               在我開發每一層的 元件時 , 我都會要求工程師 , 做 單元測試(UNIT TEST) , 壓力測試 ( Stress Test ) , 整合測試 ( Integration Test )
             

                a. 單元測試(UNIT TEST)          : 你可以使用 PHPUNIT 或是自己寫 , 針對你的一個 函數的 進和出的測試 , 並且預先寫好 TEST CASE , 確保每一層的 函式庫都是非常穩定而且沒有問題的 , 來讓你管理程式的品質.

                b. 壓力測試(Stess TEST)         : 針對每一個函式庫的邏輯 , 在做 UNIT TEST 的同時 , 將 STRESS TEST 的 TEST CASE 餵進去 , 並且記錄每一個函式處理 TEST 所消耗的時間.

                c. 整合測試(Integration Test)  : 你可以寫一支程式 , 做 DAILY BUILD 每天去檢查 所有 程式設計師 COMMIT 到 SVN 的 程式碼是否有問題 , 確保每個函式之間整合 是正常的 , 降低 DEBUG 的工作量.



















17
Linux 討論版 / Linux Kernel 記憶體 資訊
« 於: 2012-08-25 08:15 »
用 c++ 取得 Kernel 的記憶體資訊.


################################################################

首先找到 :

vim /usr/include/linux/kernel.h

struct sysinfo {
        long uptime;                    /* Seconds since boot */
        unsigned long loads[3];         /* 1, 5, and 15 minute load averages */
        unsigned long totalram;         /* Total usable main memory size */
        unsigned long freeram;          /* Available memory size */
        unsigned long sharedram;        /* Amount of shared memory */
        unsigned long bufferram;        /* Memory used by buffers */
        unsigned long totalswap;        /* Total swap space size */
        unsigned long freeswap;         /* swap space still available */
        unsigned short procs;           /* Number of current processes */
        unsigned short pad;             /* explicit padding for m68k */
        unsigned long totalhigh;        /* Total high memory size */
        unsigned long freehigh;         /* Available high memory size */
        unsigned int mem_unit;          /* Memory unit size in bytes */
        char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */
};


測試 Kernel 內的資訊 :

#include "sys/types.h"
#include "sys/sysinfo.h"
#include <cstdlib>
#include <iostream>
#include <string>
#include <stdio.h>


struct sysinfo memInfo;

using namespace std; // For atoi.


int main(){

        //long uptime;                    /* Seconds since boot */
        //unsigned long loads[3];         /* 1, 5, and 15 minute load averages */
        //unsigned long totalram;         /* Total usable main memory size */
        //unsigned long freeram;          /* Available memory size */
        //unsigned long sharedram;        /* Amount of shared memory */
        //unsigned long bufferram;        /* Memory used by buffers */
        //unsigned long totalswap;        /* Total swap space size */
        //unsigned long  freeswap;         /* swap space still available */
        //unsigned short procs;           /* Number of current processes */
        //unsigned short pad;             /* explicit padding for m68k */
        //unsigned long  totalhigh;        /* Total high memory size */
        //unsigned long  freehigh;         /* Available high memory size */
        //unsigned int   mem_unit;          /* Memory unit size in bytes */
        //char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */




        //while(true){
                sysinfo (&memInfo);
                std::cout << " Kernel meminfo                                   : " << "List - " << std::endl ;
                std::cout << " Seconds since boot                               : " << memInfo.uptime << std::endl ;
                std::cout << " 1, 5, and 15 minute load averages                : " << memInfo.loads[0] << " , " << memInfo.loads[1]  << " , " << memInfo.loads[2]  << " , " << memInfo.loads[3] << std::endl ;
                std::cout << " Total usable main memory size                    : " << memInfo.totalram << std::endl ;
                std::cout << " Available memory size                            : " << memInfo.freeram << std::endl ;
                std::cout << " Amount of shared memory                          : " << memInfo.sharedram << std::endl ;
                std::cout << " Memory used by buffers                           : " << memInfo.bufferram << std::endl ;
                std::cout << " Total swap space size                            : " << memInfo.totalswap << std::endl ;
                std::cout << " swap space still available                       : " << memInfo.freeswap << std::endl ;
                std::cout << " Number of current processes                      : " << memInfo.procs    << std::endl ;
                std::cout << " explicit padding for m68k                        : " << memInfo.pad      << std::endl ;
                std::cout << " Total high memory size                           : " << memInfo.totalhigh << std::endl ;
                std::cout << " Available high memory size                       : " << memInfo.freehigh << std::endl ;
                std::cout << " Memory unit size in bytes                        : " << memInfo.mem_unit << std::endl ;
                std::cout << std::endl ;
                sleep(1);
        //}
}



結果 :

[root@FIEND memory]# vim mc.cpp
[root@FIEND memory]# g++ mc.cpp -o mc
[root@FIEND memory]# ./mc
 Kernel meminfo                                   : List -
 Seconds since boot                               : 53296
 1, 5, and 15 minute load averages                : 0 , 0 , 0 , 33669029888
 Total usable main memory size                    : 33669029888
 Available memory size                            : 29155844096
 Amount of shared memory                          : 0
 Memory used by buffers                           : 24367104
 Total swap space size                            : 0
 swap space still available                       : 0
 Number of current processes                      : 2365
 explicit padding for m68k                        : 0
 Total high memory size                           : 0
 Available high memory size                       : 0
 Memory unit size in bytes                        : 1

18
昨天寫了支 SOCKET SERVER.

使用 C++ BOOST ASIO 異步 IO .


經過 (PHP-FPM)FAST-CGI 跟 PHP 溝通


我一口氣拉了 2400 個 PHP-FPM  PROCES 來接受 SOCKET SERVER 的請求.

我的測試架構如下 :

PHP<--->PHP-FPM<--->(boost asio 異步IO)SOCKET SERVER <--> (五台) CLIENT STRESS TEST ( 連續開 一千個線程 每個線程 無限制(SLEEP)開 1億個 SOCKET 請求 跑迴圈送資料(DOS 攻擊)  )

SOCKET SERVER 回應字串長度 : 64個字元
CLIENT 端 發送請求 : 64個字元.

SOCKET SERVER 用 CHAR[1024] 限制在 1024.

以下是我的 Ulimit 表..
ulimit -c 102400
ulimit -u 102400
ulimit -n 102400
ulimit -d unlimited
ulimit -m unlimited
ulimit -s unlimited
ulimit -t unlimited
ulimit -v unlimited

使用 CENTOS6.2
HP-DL380Gen8 XEON E52620 , 32G ECC RAM , RAID 10 4個 SAS 一萬轉硬碟做 磁碟陣列

做測試.....

結果 :

SERVER 在六小時又43分:24秒 PROCESS 直接把 SOCKET SERVER 給 KILL 掉

CLIENT 端的( 幾千個 DOS PROCESS )連線全部中斷.

五台 CLIENT 全部 用 SNIFFER 監控封包... KILLED 後 , SOEKCT 的封包全部沒有了 , 因為 SERVER 連線斷了...

到 SERVER 端 發現 . SERVER 端出現 KILLED .


想請教...


KILLED 會發生的原因? 有那些?

什麼方式可以不要讓 KILLED 去關掉 SOCKET SERVER .

如果它會大量使用記憶體 ( 只要不超過 16 G 都是正常的 ) , 因為我有使用 MAP 跟 VECTOR 將 PHP 回應的資料選擇性的 CACHE 在 SOCKET SERVER

以降低 PHP-FPM 的工作...

所以如果是記憶體使用量大而關掉它 ? 有沒有什麼方法可以讓作業系統不要去 KILL 我的 PROCESS.


請有經驗的大大解答...

19
############################################
# 文章來源 : bbs.ecstart.com
# 程式作者 : FIEND (fiend@ecstart.com.tw)
# 轉貼文章請註明 文章出處
############################################


晚上睡不著 , 整理了一下 最近 玩 cakephp 的 code .

雖然不把它做為專案用 , 不過當玩具拿來玩了一下 練練功也好.

分享給大家玩看看好了 .

主要功能 :

1. 自動換頁

2. 自動排序

3. 搜尋

4. 群組 db 組成 下拉選單


一般您 開發一個 新增 , 修改 , 刪除 , 搜尋 , 換頁 ,排序 , 下拉 RELATION TABLE 選單 需要多久?

以往不是模組化開發 , 這樣從頭寫到尾可能要一二個星期.

小弟以此為例.

教大家在 利用 cakephp + 小弟 自製的 components+helper 五分鐘以內 快速 create 一個 完整的功能.

因為 是利用 components+helper 來製作 , 所以 不會有版本問題 .

讓大家體驗一下 CAKEPHP 可以加速開發專案到什麼程度.

演示 : http://fiend.no-ip.biz/test2   << 我用我家 vmware 寫的... ^^!! 有時連不上 請多包含.


#######

1. db schema :
代碼: [選擇]
-- 資料表格式: `ecstart_groups`
--

CREATE TABLE IF NOT EXISTS `ecstart_groups` (
  `prefixid` varchar(20) NOT NULL default '',
  `id` varchar(32) NOT NULL default 'user',
  `name` varchar(32) NOT NULL default '',
  `seq` int(3) NOT NULL default '60',
  `created` datetime NOT NULL default '0000-00-00 00:00:00',
  `updated` datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY  (`prefixid`,`id`)
) ENGINE=MyISAM ;

-- --------------------------------------------------------

--
-- 資料表格式: `ecstart_test2s`
--

CREATE TABLE IF NOT EXISTS `ecstart_test2s` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `title` varchar(50) default NULL,
  `groupid` varchar(32) NOT NULL,
  `body` text,
  `created` datetime default NULL,
  `modified` datetime default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  ;
2. app/controllers/components/ecstart_model.php

這裡我改寫了 一些 model 拉資料的方法 , 讓 controler 可以更便利的拉資料 .
代碼: [選擇]
<?php
class EcstartModelComponent extends Object {



        function 
ecstart_show_me_the_var($ecstart){
                echo 
"<pre>";
                
print_r($ecstart);
                exit ;
        }

        function 
ecstart_show_me_the_obj($this){
                echo 
"<pre>";
                
print_r($this);
                exit ;
        }




        function 
ecstart_record_page($p $max_page ,$max_range $rows){

                if(!isset(
$p)){$p "" ;}
                if(
trim($p)=="" or $p 1){$p 1  ; }
                
$lastpage ceil($rows/$max_page);
                if(
$p $lastpage){ $p=;}
                
$rec_start= ($p-1)*$max_page +1;
                
$rec_end  $rec_start $max_page -1;
                
$ploops   floor(($p-1)/$max_range)*$max_range ;
                
$ploope   $ploops $max_range -1;
                if(
$ploope >= $lastpage){ $ploope=$lastpage;}
                
$ppg      $p ;
                
$npg      $p ;
                if(
$ppg<= 0$ppg=$lastpage;
                if(
$npg $lastpage$npg=1;
                if(
$rec_end $rows$rec_end=$rows;

                
$ecstart_page["rec_start"]       = $rec_start ;
                
$ecstart_page["rec_end"]         = $rec_end ;
                
$ecstart_page["firstpage"]       = ;
                
$ecstart_page["lastpage"]        = $lastpage ;
                
$ecstart_page["previousrange"]   = $ploops $max_range ;
                
$ecstart_page["nextrange"]       = $ploops $max_range ;
                
$ecstart_page["previouspage"]    = $ppg ;
                
$ecstart_page["nextpage"]        = $npg ;
                
$ecstart_page["thispage"]        = $p ;
                
$ecstart_page["total"]           = $rows ;
                
$ecstart_page["loop"]            = $lastpage+;
                for(
$i=$ploops;$i <= $ploope;$i++){
                        
$ecstart_page["item"][]["p"] = $i ;
                }
                return 
$ecstart_page;
        }


        function 
ecstart_record_sort($field_arr,$params){
                
//echo "<pre>"; echo $field_list; print_r($field_arr); exit;
                
foreach($field_arr as $fv){

                        
$fvs explode(&#39;.&#39;,$fv);
                        
if(isset($params["url"]["sort_".str_replace(&#39;`&#39;,&#39;&#39;,$fvs[1])])){
                                //print_r($this->params["url"]["sort_id"]);
                                
$sort["subquery"]  = $fv." ".$params["url"]["sort_".str_replace(&#39;`&#39;,&#39;&#39;,$fvs[1])];
                                
$sort["status"]["path"]["sort"] = &#39;&sort_&#39;.str_replace(&#39;`&#39;,&#39;&#39;,$fvs[1]).&#39;=&#39;.$params["url"]["sort_".str_replace(&#39;`&#39;,&#39;&#39;,$fvs[1])]  ;
                                
$sort["status"]["sort"][str_replace(&#39;`&#39;,&#39;&#39;,$fvs[1])] = $params["url"]["sort_".str_replace(&#39;`&#39;,&#39;&#39;,$fvs[1])];
                        
}

                }
                if(isset(
$sort)){
                        return  
$sort ;
                }
        }


        function 
ecstart_get_field($CALL,$funname){

                
$fields_arr $CALL->getColumnTypes() ;
                if(
is_array($fields_arr)){
                        foreach(
$fields_arr as $fk => $fv){
                                
$fields[$fk] = "`".$funname."`.`".$fk."`" ;
                        }
                }

                return 
$fields ;
        }


        function 
ecstart_get_one_record($CALL,$field_str){
                
$field_arr explode(",",str_replace("\t","",str_replace("\n","",str_replace(" ","",$field_str))));
                
$subquery = array();
                foreach(
$field_arr as $fv){
                        
$fd explode(":",$fv);
                        if(@
$this->params["url"][$fd[2]] != ""){
                                        
$fd[1] = ucfirst($fd[1]);
                                        
$subquery[$fd[0]]["`".$fd[1]."`.`".$fd[2]."`"] = $fd[3] ." ".@$fd[4].$this->params["url"][$fd[2]].@$fd[5] ;
                                        
//@$search["status"]["search"][$fd[2]] = $this->params["url"][$fd[2]] ;
                                        //@$search["status"]["path"]["search"] .= $fd[2].&#39;=&#39;.$this->params["url"][$fd[2]] ;
                        
}
                        else{
                                
$this->ecstart_alert_msg(MSG_SEARCH_ID);
                        }

                }

                if(
is_array($subquery)){

                        
//print_r($subquery); exit ;

                        
$record =
                                   
$CALL->find(
                                                        
$conditions $subquery,
                                                        
$fields null,
                                                        
$order null,
                                                        
$page 1,
                                                        
$recursive null
                                   
);

                        return  
$record ;
                }
                else{
                        return 
false ;
                }


        }



        function 
ecstart_record_search($field_str,$params){
                
$field_arr explode(",",str_replace("\t","",str_replace("\n","",str_replace(" ","",$field_str))));
                
$search = array();
                foreach(
$field_arr as $fv){
                        
$fd explode(":",$fv);
                        if(isset(
$params["url"]["search_".$fd[2]])){
                                if(
$params["url"]["search_".$fd[2]] != ""){
                                        
$fd[1] = ucfirst($fd[1]);
                                        @
$search["subquery"][$fd[0]]["`".$fd[1]."`.`".$fd[2]."`"] = $fd[3] ." ".@$fd[4].$params["url"]["search_".$fd[2]].@$fd[5] ;
                                        @
$search["status"]["search"]["search_".$fd[2]] = $params["url"]["search_".$fd[2]] ;
                                        @
$search["status"]["path"]["search"] .= &#39;&search_&#39;.$fd[2].&#39;=&#39;.$params["url"]["search_".$fd[2]] ;
                                
}
                        }
                }
                return  
$search ;
        }


        function 
ecstart_get_page_record($CALL,$funname,$search_str,$default_sort=&#39;&#39;,$params,$relation_str){


                
$search_arr $this->ecstart_record_search($search_str,$params);


                if(!isset(
$params["url"]["p"])){
                        
$params["url"]["p"] = "1";
                }
                
$ecstart["params"] = $params ;


                
$fields $this->ecstart_get_field($CALL,$funname);

                
$sort_arr $this->ecstart_record_sort($fields,$params);


                if(@
$sort_arr["subquery"] == ""){ // default sort
                        
$sort_arr["subquery"] = $default_sort ;
                }



                
$ecstart["record"] =
                                   
$CALL->findAll(
                                                        
$conditions = @$search_arr["subquery"] ,
                                                        
$fields null,
                                                        
$order = @$sort_arr["subquery"],
                                                        
$limit MAX_RECORD,
                                                        
$page $params["url"]["p"],
                                                        
$recursive null
                                   
);
                
$num $CALL->findCount(@$search_arr["subquery"]) ;

                
//$num = $CALL->getNumRows() ;
                
$ecstart["rt"] =  $this->ecstart_get_relation($CALL,$relation_str);

                
$ecstart["page"] = $this->ecstart_record_page($params["url"]["p"],MAX_RECORD,MAX_RANGE,$num) ;

                
$ecstart["status"]["funname"] = $funname ;
                
$ecstart["status"]["search"] = @$search_arr["status"]["search"];
                
$ecstart["status"]["search_path"] = @$search_arr["status"]["path"]["search"];
                
$ecstart["status"]["sort"] = @$sort_arr["status"]["sort"];
                
$ecstart["status"]["sort_path"] = @$sort_arr["status"]["path"]["sort"];

                
//$this->set(&#39;ecstart&#39;, $ecstart);
                
return $ecstart ;
        }

        function 
ecstart_get_relation($CALL,$relation_str){


                
$relation_arr = array();
                
$relation = array();
                
$where "";
                
$order_by "";

                
//$relation_arr = explode(",",str_replace("\t","",str_replace("\n","",str_replace(" ","",$relation_str))));
                
$relation_arr explode(",",$relation_str);

                foreach(
$relation_arr as $rk => $rv){
                        
$q_arr explode(":",$rv);

                        foreach(
$q_arr as $qk => $qv){
                                if(
$qk == 3){
                                        
$q_arr[$qk] = trim(str_replace("\t","",str_replace("\n","",$qv))) ;
                                }
                                elseif(
$qk == 4){
                                        
$q_arr[$qk] = str_replace("\t","",str_replace("\n","",$qv)) ;
                                }
                                else{
                                        
$q_arr[$qk] = str_replace("\t","",str_replace("\n","",str_replace(" ","",$qv))) ;

                                }
                        }

                        if(
$CALL->tablePrefix != ""){
                                
$prefix_table "`".$CALL->tablePrefix;
                                
$table_name $CALL->tablePrefix.$q_arr[0] ;

                        }
                        else{
                                
$prefix_table "`";
                                
$table_name $q_arr[0] ;
                        }

                        if(
$q_arr[1] != ""){
                                
$field_id "`".$q_arr[1]."` as id ,";
                        }
                        else{
                                echo 
"ID ERROR!!"; exit ;
                        }


                        if(
$q_arr[2] != ""){
                                
$field_name "`".$q_arr[2]."` as name ";
                        }
                        else{
                                echo 
"NAME ERROR!!"; exit ;
                        }

                        if(
$q_arr[3] != ""){
                                
$where " where ".$q_arr[3];

                        }
                        
$query "SELECT ".$field_id.$field_name." FROM ".$prefix_table.$q_arr[0]."`".$where." ".$q_arr[4] ;
                        
//print_r($q_arr) ;
                        //echo $query . "
" ;
                        
$relation_arr = $CALL->findBySql($query);

                        foreach(
$relation_arr as $rk => $rv){
                                //print_r(
$rv[$table_name]);
                                
$relation[$q_arr[0]][$rk] = $rv[$table_name] ;
                        }
                        unset(
$relation_arr);


                }



                //print_r(
$relation);




                return 
$relation ;
        }














}
?>

20
最近 K 了一陣子 CAKEPHP 對它的 primary key composed 問題真的蠻頭大的.

https://trac.cakephp.org/ticket/2811   <<<< 唉唉唉~~老實說 我說 CAKEPHP 是玩具實在太客氣了

盡然處理順序還排在中間 ....

我可以體量它的 三層架構都要因為這個問題而大改.

同時也可以發現寫 CAKEPHP 的人對 WEB 原件的 功力真的有待加強..這種東西一開始設計時就要考慮到了.

^^!! 雖然它的架構OK 但是 這是最基本的說...

一句話送給大家 ... 在它還沒有成熟前千萬不要用來寫專案.

當玩具玩 很OK .


代碼: [選擇]
00707 /**
00708  * Returns a list of fields from the database
00709  *
00710  * @param mixed $id The ID of the record to read
00711  * @param mixed $fields String of single fieldname, or an array of fieldnames.
00712  * @return array Array of database fields
00713  * @access public
00714  */
00715     function read($fields = null, $id = null) {
00716         $this->validationErrors = array();
00717
00718         if ($id != null) {
00719             $this->id = $id;
00720         }
00721
00722         $id = $this->id;
00723
00724         if (is_array($this->id)) {
00725             $id = $this->id[0];
00726         }
00727
00728         if ($this->id !== null && $this->id !== false) {
00729             $db =& ConnectionManager::getDataSource($this->useDbConfig);
00730             $field = $db->name($this->alias) . '.' . $db->name($this->primaryKey);
00731             return $this->find($field . ' = ' . $db->value($id, $this->getColumnType($this->primaryKey)), $fields);
00732         } else {
00733             return false;
00734         }
00735     }
看起來有支援 復合 KEY 不過我看它的程式應該邏輯上是不可能支援復合KEY的

當我做實驗 :
代碼: [選擇]
   function edit($id = null)
   {
       if (empty($this->data))
       {
           //$this->Fun->id = $id;
           //$this->data = $this->Fun->read();
           $this->set('fun', $this->Fun->read(array('id','pjid'),array('userms','0')));
       }
       else
       {
           //print_r($this->data);        exit ;
           if ($this->Fun->save($this->data['Fun']))
           {
               //$this->flash('Your post has been updated.','/fun');
                $this->redirect('/fun');
           }
       }
   }
結果 DB 組合結果 :

SELECT `Fun`.`id`, `Fun`.`pjid` FROM `ecstart_funs` AS `Fun` WHERE `Fun`.`id` = 'userms' LIMIT 1

果然真的很去它的難用....

用的超級 美爽爽的情況之下...

發現 它最後是吐 return $this->find($field . ' = ' . $db->value($id, $this->getColumnType($this->primaryKey)), $fields);

回來的格式.

看來 READ 的部份只好 另外 再新增一個 METHOD 來寫了...

鳴鳴~~ 如果一開始有支援就不用搞這麼多飛機了.

CAKEPHP 的成熟度還有待加強 ...



^^!! 好辛苦 CAKEPHP 真難用 鳴鳴~~~

雖然它不夠成熟 但是還好它的 架構夠強 ^^ 可以自定新的 METHOD ....

寫了一支新 METHOD 來解決它.
代碼: [選擇]
   function edit($id = null)
   {
       if (empty($this->data))
       {
           //$this->Fun->id = $id;
           //$this->data = $this->Fun->read();
                $search_str = "
                                AND:    Fun:    id:             =:                      ,
                                AND:    Fun:    pjid:           =:
                ";
                //echo "<pre>";
                //print_r($this->ecstart_get_one_record($this->Fun,$search_str));
                //exit ;
                $this->data =  $this->ecstart_get_one_record($this->Fun,$search_str);
       }
       else
       {
           //print_r($this->data);        exit ;
           if ($this->Fun->save($this->data['Fun']))
           {
               //$this->flash('Your post has been updated.','/fun');
                $this->redirect('/fun');
           }
       }
   }
這裡我解釋一下 :

                $search_str = "
                                AND:    Fun:    id:             =:                      ,
                                AND:    Fun:    pjid:           =:
                ";
這個字串是要告訴 我的 $this->ecstart_get_one_record($this->Fun,$search_str);

我有二個 ID 分別是 ID 和 PJID 這二個 ID 要用 AND 的方式.

然後丟給 ecstart_get_one_record() METHOD

它會自動演算將 RECORD 丟回來給我.

然後我再把它丟給

$this->data 則版型就會取用 解決 READ 不能做覆合 KEY 的問題 .
代碼: [選擇]
        ####################################################################################################
        function ecstart_get_one_record($CALL,$field_str){
                $field_arr = explode(",",str_replace("\t","",str_replace("\n","",str_replace(" ","",$field_str))));
                $subquery = array();
                foreach($field_arr as $fv){
                        $fd = explode(":",$fv);
                        if(isset($this->params["url"][$fd[2]])){
                                if($this->params["url"][$fd[2]] != ""){
                                        $fd[1] = ucfirst($fd[1]);
                                        $subquery[$fd[0]]["`".$fd[1]."`.`".$fd[2]."`"] = $fd[3] ." ".@$fd[4].$this->params["url"][$fd[2]].@$fd[5] ;
                                        //@$search["status"]["search"][$fd[2]] = $this->params["url"][$fd[2]] ;
                                        //@$search["status"]["path"]["search"] .= $fd[2].'='.$this->params["url"][$fd[2]] ;
                                }
                        }
                }

                if(is_array($subquery)){

                        //print_r($subquery); exit ;

                        $record =
                                   $CALL->find(
                                                        $conditions = $subquery,
                                                        $fields = null,
                                                        $order = null,
                                                        $page = 1,
                                                        $recursive = null
                                   );

                        return  $record ;
                }
                else{
                        return false ;
                }


        }

結果.... SAVE METHOD 好像也要改一下版...

哇哈哈哈~~ 看起來

展示邏輯層 , 程式邏輯層 , 內容邏輯層 都要做出對應的元件才能解決這個問題

看來又要花我一些時間 CAKEPHP 才能使用 鳴鳴~~老闆可以不要用它來寫小專案嗎~~ << 心聲 .



21
###############################################
# 資料來源 : http://bbs.ecstart.com/viewthread.php?tid=30325
# 作者 : FIEND
# 轉貼請註明出處
###############################################

最近太無聊了 花了一星期玩了一下 cakephp ^^bb

果然是一套有趣的大玩具 .

雖然功能很弱看起來還沒有很成熟 .

不過蠻適合做小專案的 , create 程式的速度超快  ^^

官方並沒有出 cake php 的換頁和排序 method .

而 1.2 版有出 但好像也不怎麼好用.

放棄~~~

所以後來想想還是自己寫 比較好用..

1.2 以下的使用者 苦腦怎麼實現 換頁 排序 功能的 或是覺得官方預設的不夠強 .

可以抄小弟寫好的 回家用 下星期有空我再加上 搜尋功能

^^

cakephp 換頁 排序 (第一版) :

1. create tests table :
代碼: [選擇]
CREATE TABLE IF NOT EXISTS `ecstart_tests` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `title` varchar(50) default NULL,
  `body` text,
  `created` datetime default NULL,
  `modified` datetime default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=35 ;
2. vim cake/app_controller.php << 你也可以將其放在 app/controllers/components :

首先將 這些寫好的 method 放進 app_controler class 內 .
代碼: [選擇]
       
        function ecstart_record_page($p , $max_page ,$max_range , $rows){

                if(!isset($p)){$p = "" ;}
                if(trim($p)=="" or $p < 1){$p = 1  ; }
                $lastpage = ceil($rows/$max_page);
                if($p > $lastpage){ $p=1 ;}
                $rec_start= ($p-1)*$max_page +1;
                $rec_end  = $rec_start + $max_page -1;
                $ploops   = floor(($p-1)/$max_range)*$max_range + 1 ;
                $ploope   = $ploops + $max_range -1;
                if($ploope >= $lastpage){ $ploope=$lastpage;}
                $ppg      = $p - 1 ;
                $npg      = $p + 1 ;
                if($ppg<= 0) $ppg=$lastpage;
                if($npg > $lastpage) $npg=1;
                if($rec_end > $rows) $rec_end=$rows;

                $ecstart_page["rec_start"]       = $rec_start ;
                $ecstart_page["rec_end"]         = $rec_end ;
                $ecstart_page["firstpage"]       = 1 ;
                $ecstart_page["lastpage"]        = $lastpage ;
                $ecstart_page["previousrange"]   = $ploops - $max_range ;
                $ecstart_page["nextrange"]       = $ploops + $max_range ;
                $ecstart_page["previouspage"]    = $ppg ;
                $ecstart_page["nextpage"]        = $npg ;
                $ecstart_page["thispage"]        = $p ;
                $ecstart_page["total"]           = $rows ;
                $ecstart_page["loop"]            = $lastpage+1 ;
                for($i=$ploops;$i <= $ploope;$i++){
                        $ecstart_page["item"][]["p"] = $i ;
                }
                return $ecstart_page;
        }


        function ecstart_show_me_the_var($ecstart){
                echo "<pre>";
                print_r($ecstart);
                exit ;
        }




        function ecstart_show_me_the_obj(){
                echo "<pre>";
                print_r($this);
                exit ;
        }



        function ecstart_record_sort($field_arr){
                //echo "<pre>"; echo $field_list; print_r($field_arr); exit;
                foreach($field_arr as $fv){

                        $fvs = explode('.',$fv);
                        if(isset($this->params["url"]["sort_".str_replace('`','',$fvs[1])])){
                                //print_r($this->params["url"]["sort_id"]);
                                $sort["subquery"]  = $fv." ".$this->params["url"]["sort_".str_replace('`','',$fvs[1])];
                                $sort["status"]["path"]["sort"] = '&sort_'.str_replace('`','',$fvs[1]).'='.$this->params["url"]["sort_".str_replace('`','',$fvs[1])]  ;
                                $sort["status"]["sort"][str_replace('`','',$fvs[1])] = $this->params["url"]["sort_".str_replace('`','',$fvs[1])];
                        }

                }
                if(isset($sort)){
                        return  $sort ;
                }
        }


        function ecstart_get_page_record($CALL,$funname){



                if(!isset($this->params["url"]["p"])){
                        $this->params["url"]["p"] = "1";
                }
                $ecstart["params"] = $this->params ;

                $fields_arr = $CALL->getColumnTypes() ;

                if(is_array($fields_arr)){
                        foreach($fields_arr as $fk => $fv){
                                $fields[$fk] = "`".$funname."`.`".$fk."`" ;
                        }
                }



                $ecstart["sort"] = $this->ecstart_record_sort($fields);
                $ecstart["record"] =
                                   $CALL->findAll(
                                                        $conditions = null,
                                                        $fields = null,
                                                        $order = $ecstart["sort"]["subquery"],
                                                        $limit = MAX_RECORD,
                                                        $page = $this->params["url"]["p"],
                                                        $recursive = null
                                   );
                $num = $CALL->findCount() ;

                $ecstart["page"] = $this->ecstart_record_page($this->params["url"]["p"],MAX_RECORD,MAX_RANGE,$num) ;

                $ecstart["status"]["funname"] = $funname ;

                if(isset($this->params["url"]["show_me_the_var"])){
                        $this->ecstart_show_me_the_var($ecstart) ;
                }

                if(isset($this->params["url"]["show_me_the_obj"])){
                        $this->ecstart_show_me_the_obj() ;
                }


                $this->set('ecstart', $ecstart);
        }
3. 呼叫 ecstart_get_page_record method :

app/controllers/test_controller.php
代碼: [選擇]
class TestController extends AppController {

   var $name = 'Test';

   var $helpers = array('Html','Ecstartsort');  // << 這是 排序的 helper 版型邏輯 未來要給 標題使用的 稍後再跟大家介紹 helper 相信己玩過 cakephp的人不漠生 .

   function index() {
                $this->ecstart_get_page_record($this->Test,$this->name);  // << 呼叫先前寫好的 換頁和 排序 邏輯 .
   }

   function add()
   {

        if (!empty($this->data))
        {
            if ($this->Test->save($this->data))
            {
                $this->flash('Your post has been saved.','/test');
                //$this->redirect('/test');
            }
        }

   }

   function edit($id = null)
   {
       if (empty($this->data))
       {
           $this->Test->id = $id;
           $this->data = $this->Test->read();
       }
       else
       {
           //print_r($this->data);        exit ;
           if ($this->Test->save($this->data['Test']))
           {
               $this->flash('Your post has been updated.','/test');
           }
       }
   }


   function delete($id)
   {
        $this->Test->del($id);
        $this->flash('The post with id: '.$id.' has been deleted.', '/test');
   }



}
4. SORTHELPER :
   
 這是 要給所有版型 可以呼叫用的 helper method , 您可以參考 3. 小弟 的註解

主要的功能是使標題的排序 .

vim app/views/helpers/ecstartsort.php
代碼: [選擇]
<?php
class EcstartsortHelper extends Helper {

    var 
$helpers = array(&#39;Html&#39;);

    
function fieldsort($name,$field,$url,$ecstart)
    {
        
// Use the HTML helper to output
        // formatted data:
        
if(@$ecstart["sort"]["status"]["sort"][$field] == "desc"){
                
$url .= "&sort_".$field."=asc" ;
        }
        else{
                
$url .= "&sort_".$field."=desc" ;
        }


        if(@
$ecstart["sort"]["status"]["sort"][$field] == "desc"){
                
$image_path "<img src=&#39;/images/s_desc.png&#39;>" ;
        }
        elseif(@
$ecstart["sort"]["status"]["sort"][$field] == "asc"){
                
$image_path "<img src=&#39;/images/s_asc.png&#39;>" ;

        }
        else{
                
$image_path "" ;
        }
        
$url .= "&p=".$ecstart["page"]["thispage"] ;
        
//echo "<pre>";         print_r($ecstart["page"]["thispage"]);  exit ;
        
unset($ecstart);


        return 
$this->output("<a href=".$url." class=\"editOuter\">".$name."</a> ".$image_path);
    }
}
?>
5. 換頁區塊 :

   因為換頁的區塊一般都長一樣 , 所以小弟將換頁 做成 區塊讓所有的版型可以去呼叫它

vim app/views/elements/ecstart_record_page.thtml
代碼: [選擇]
<table>
<tr>
 <td>

<?php
echo $html->link(&#39;最前頁&#39;, &#39;/test&p=&#39;.$ecstart["page"]["firstpage"].$ecstart["sort"]["status"]["path"]["sort"]);echo " | ";
echo $html->link(&#39;上一頁&#39;, &#39;/test&p=&#39;.$ecstart["page"]["previouspage"].$ecstart["sort"]["status"]["path"]["sort"]);echo " | ";
if(is_array($ecstart["page"]["item"])){
        foreach(
$ecstart["page"]["item"] as $pv){
                if(
$ecstart["params"]["url"]["p"] == $pv[&#39;p&#39;]){
                        
echo "<b>[ ".$pv[&#39;p&#39;]." ]</b>";
                        
echo " " ;
                        echo 
" " ;
                }
                else{
                        echo 
"".$html->link($pv[&#39;p&#39;], &#39;/test&p=&#39;.$pv[&#39;p&#39;].$ecstart["sort"]["status"]["path"]["sort"])."";
                        
echo " " ;
                        echo 
" " ;
                }
        }
}
echo 
" | ";
echo 
$html->link(&#39;下一頁&#39;, &#39;/test&p=&#39;.$ecstart["page"]["nextpage"].$ecstart["sort"]["status"]["path"]["sort"]);echo " | ";
echo $html->link(&#39;最終頁&#39;, &#39;/test&p=&#39;.$ecstart["page"]["lastpage"].$ecstart["sort"]["status"]["path"]["sort"]);
?>


 </td>
</tr>
</table>
6. record 頁的 換頁 排序 版型 :
代碼: [選擇]
<table>
    <tr>
        <th>No</th>
        <th>
        <?= $ecstartsort->fieldsort("ID","id","/test",$ecstart);?>  <!-- 利用 helper 寫好的 展示層排序邏輯 直接呼叫 method 即可組合 連結 -->
        </th>
        <th>
        <?= $ecstartsort->fieldsort("標題","title","/test",$ecstart);?>
        </th>
        <th>
        <?= $ecstartsort->fieldsort("新增時間","created","/test",$ecstart);?>
        </th>
        <th>Update</th>
        <th>Delete</th>
    </tr>

   <!-- Here's where we loop through our $posts array, printing out post info -->

    <?PHP //echo "<pre>";       print_r($test);         exit ; ?>
    <?php foreach ($ecstart["record"] as $rid => $record): ?> <!-- // 由 test_controler 去呼叫 ecstart_get_page_record 的 record 陣列再由這裡去 做 foreach -->
    <tr>
        <td><?php echo $rid+1?></td>
        <td><?php echo $record[$ecstart["status"][&#39;funname&#39;]]["id"]; ?></td>
        <td>
            <?php echo $html->link($record[$ecstart["status"][&#39;funname&#39;]][&#39;title&#39;], &#39;/test/view/&#39;.$record[$ecstart["status"][&#39;funname&#39;]][&#39;id&#39;]);?>
        </td>
        <td><?php echo $record[$ecstart["status"][&#39;funname&#39;]][&#39;created&#39;]; ?></td>
        <td>
                <?php echo $html->link(&#39;Edit&#39;, &#39;/test/edit/&#39;.$record[$ecstart["status"][&#39;funname&#39;]][&#39;id&#39;]);?>
        </td>
        <td>
            <?php echo $html->link(
                &
#39;Delete&#39;,
                
"/test/delete/{$record[$ecstart["status"][&#39;funname&#39;]][&#39;id&#39;]}",
                
null,
                &
#39;Are you sure?&#39;
            
)?>

        </td>

    </tr>
    <?php endforeach; ?>

</table>
<?php echo $this->renderElement(&#39;ecstart_record_page&#39;); ?>   <!-- // 這裡就是將 5. 做好的 區塊版型抓進來用   -->

<p><?php echo $html->link(&#39;Add Post&#39;, &#39;/test/add&#39;); ?></p>
對了這裡是完成的 程式 範例 用我家的 vmware 架的 linux 有時會連不上請多包含:

http://fiend.no-ip.biz/test/


^^ po 完了 大家慢慢消化吧 .

fiend 上

22
想組個敗金團 去 幾家 開放源碼組織 相關產品的公司走走 哇哈哈哈!!!!

這個想法如何 ^^!!!

23
玩了二天 .... ^^!!

一直 build 不過去 ...

LDFLAGS=-L/usr/lib64 ./configure --prefix=/usr/local/ecstart

然後 打開  Makefile

找到 AC_CFLAGS = -g -O2 改成 ...    AC_CFLAGS = -g -O2 -fPIC
make
make install

.................. ^^!! 終於 build 過了  鳴鳴~~


之後 :

到  php-4.4.4/ext/ldap
/usr/local/ecstart/bin/phpize
./configure --with-php-config=/usr/local/ecstart/bin/php-config
make
make install

^^ YAYA~~ ...

24
這個問題存在很久了 .

官方一直沒有解決 .

當你在 compiler gd 時 jpeg 老是 compiler 不過..

原因是 lib 底下 跟 include 底下 jpeg 沒有把 binary 和 .h 檔  在 make install 時帶過去 ..

解決方法  :

    jpeg :
    cd ../jpeg-XX
    ./configure --prefix=/usr/local/ecstart
    make
    make install
    cp libjpeg.a /usr/local/ecstart/lib/
    cp *.h /usr/local/ecstart/include/

     
    cd php-XXX/ext/gd
    phpize
    ./configure  --with-png-dir=/usr/local/ecstart --with-zlib-dir=/usr/local/ecstart --with-ttf=/usr --with-freetype-dir=/usr/local/ecstart --with-jpeg-dir=/usr/local/ecstart
    make
    make install

25
官方  在包裝時 常常 都有 bug 唉唉~~


今天 compiler php4.4.4 的 imap 時 發現一個 bug ... 機車!! 害我查半天 .

如果 你的 imap 指定路徑不是 /usr/local 或是 usr 時 .

因為 ext 底下 configure 指定 --with-imap 的變數 根本就不會被帶進去 .

所以你要在 confirure 底下 找到 :

for i in $PHP_IMAP /usr/local /usr; do

然後 將 你要的路徑填進去 :

改成


    for i in $PHP_IMAP /usr/local/ecstart/imap-2004e.DEV.SNAP-0505252319; do


就可以了  ^^!! 搞了我一下午 血特...


有碰到相同狀況的 用這招解看看吧 ...

26
最近做專案 碰到一個問題 .....

提出來給大家 一起討論


我有一個需求 :

假設我有 十萬個 ip 要堅控 在這種情況之下 ,  我每隔 五分鐘 會將這十萬個 ip 的 流量計錄起來 .

再來我有個規則 就是 24 小時之內 , 我可以定義多個時段  最多 使用者可以使用 幾 g 的流量  .

假設 我定義 :

早上六點 ~ 下午六點  只能使用 10 gb
下午六點 ~ 晚上十二點點  只能使用 5 gb
晚上十二點~ 早上六點  只能使用 25 gb


問題來了 !

每隔 五分鐘 我要去判斷這十萬的 ip 是不是 超過流量的限制 .

不管如何 只要累積滿 我限制的 流量數在這個時段下 .

我就會 將這個 ip 的任何封包連線阻擋下來 .


在不考慮 其它因素 .

只要探討 這十萬個 ip 如何在我規定的時段下 可以正常判斷 又可以讓 cpu 的效能不會 因為執行這個 process 超過 10 % .

^^!! 大家一起動動腦 ...

這個問題絕對不能用 db 解 .


我的想法是 用 hash table 的方式 每五分鐘去 自動更新用量 .

然後去 sort 超過 n gb 的量 .

再把有問題的 ip 抽出來 放入準被 阻擋的 process .

有沒有人有更好的解法 ...

28
好久沒來酷學園了...

嘿嘿灌水完畢 再分享一下 小script ..

無聊時寫的..還有改良空間 無需嫌棄 有需要的用看看 ..


#############################################################################
# 作者 : fiend
#  轉貼請註明出處
#############################################################################

義務替 黑秀網將 big5 轉成 utf-8 環境 :

所以寫了這支程式 ,

這支程式 會 dump 出 db 下的所有 insert 的 query ,

使用方法

1.

將 big5 環境的 create dump 出來 ,

然後 再將 CHARSET=latin1 或 CHARSET=big5

改成 CHARSET=utf8

然後 create 一個空的 databases + table .

2.  
下載 metabase :  請參考附件

3.
convert.php
代碼: [選擇]

#!/usr/bin/php -q
<?php
set_time_limit
&#40;0&#41; ;
############################################################################
# sql link start
############################################################################
$db_type                "mysql";
$host_name              "localhost" ;
$database_name          "heyforum_dz5" ;
$user_id                "root" ;
$user_password          "xxxxxxxxxxxx" ;
include_once&
#40;"metabase/metabase_interface.php"&#41;;
include_once&#40;"metabase/metabase_database.php"&#41;;
$db_params=array&#40;
                     
"Host"             =>$host_name
                     
,"Type"            =>$db_type
                     
,"User"            =>$user_id
                     
,"Password"        =>$user_password
                     
,"IncludePath"     =>"metabase/"
                     
,"Persistent"      =>0
                     
&#41;;
############################################################################
# sql link end
############################################################################

$error=MetabaseSetupDatabase&#40;$db_params,$db&#41;;
MetabaseSetDatabase&#40;$db,$database_name&#41;;

$query ="show tables";
$db_res=MetabaseQuery&#40;$db,$query&#41;;
if&#40;!$db_res&#41; &#123;
        
ecstart_alert_err&#40;$msg["system_err"&#93;&#41;;
&#125;
$rows=MetabaseNumberOfRows&#40;$db,$db_res&#41;;
MetabaseGetColumnNames&#40;$db,$db_res,$db_field_name&#41;;
if&#40;$rows&#41;
&#123;
        
for&#40;$row=1;$row<=$rows;$row++&#41;
        
&#123;
                
if&#40;is_array&#40;$db_field_name&#41;&#41;&#123;
                        
foreach&#40;$db_field_name as $key => $value&#41;&#123;
                                
$table[$row-1&#93;=MetabaseFetchResult&#40;$db,$db_res,$row-1,$key&#41; ;
                        
&#125;
                
&#125;
        
&#125;
&#125;
if&#40;is_array&#40;$table&#41;&#41;&#123;
        
foreach&#40;$table as $k => $v&#41;&#123;
                
$query ="describe ".$v;
                
$db_res=MetabaseQuery&#40;$db,$query&#41;;
                
if&#40;!$db_res&#41; &#123;
                        
ecstart_alert_err&#40;$msg["system_err"&#93;&#41;;
                
&#125;
                
$rows=MetabaseNumberOfRows&#40;$db,$db_res&#41;;
                
MetabaseGetColumnNames&#40;$db,$db_res,$db_field_name&#41;;
                
if&#40;$rows&#41;
                
&#123;
                        
for&#40;$row=1;$row<=$rows;$row++&#41;
                        
&#123;
                                
if&#40;is_array&#40;$db_field_name&#41;&#41;&#123;
                                        
foreach&#40;$db_field_name as $key => $value&#41;&#123;
                                                
$field[$v&#93;[$row-1&#93;=MetabaseFetchResult&#40;$db,$db_res,$row-1,"field"&#41; ;
                                        
&#125;
                                
&#125;
                        
&#125;
                
&#125;
                //print_r&#40;$field&#41;;



        
&#125;
&#125;




if&#40;is_array&#40;$field&#41;&#41;&#123;
        
foreach&#40;$field as $k => $v&#41;&#123;
                // get field value
                
$query ="select * from ".$k;
                
$db_res=MetabaseQuery&#40;$db,$query&#41;;
                
if&#40;!$db_res&#41; &#123;
                        
ecstart_alert_err&#40;$msg["system_err"&#93;&#41;;
                
&#125;
                
$rows=MetabaseNumberOfRows&#40;$db,$db_res&#41;;
                
MetabaseGetColumnNames&#40;$db,$db_res,$db_field_name&#41;;
                
if&#40;$rows&#41;
                
&#123;
                        
for&#40;$row=1;$row<=$rows;$row++&#41;
                        
&#123;
                                
if&#40;is_array&#40;$db_field_name&#41;&#41;&#123;
                                        
foreach&#40;$db_field_name as $key => $value&#41;&#123;
                                                
$field_value[$row-1&#93;[$key&#93;=MetabaseFetchResult&#40;$db,$db_res,$row-1,$key&#41; ;

                                        
&#125;
                                
&#125;
                                
$no ;
                                
$field_str "";
                                foreach&
#40;$v as $fv&#41;&#123;
                                        
if&#40;$no == 0&#41;&#123;
                                                
$field_str .= "`".$fv."`";
                                        &
#125;
                                        
else&#123;
                                                
$field_str .= ",`".$fv."`";
                                        &
#125;
                                        
$no $no+;
                                &
#125;

                                
$sno ;
                               
$field_value_str "";
                                foreach&
#40;$field_value[$row-1&#93; as $fvk =>  $fvv&#41;&#123;
                                        
if&#40;$sno == 0&#41;&#123;
                                                
$field_value_str .= "'".mysql_escape_string&#40;iconv&#40;'BIG5','UTF-8',$fvv&#41;&#41;."'";
                                        
&#125;
                                        
else&#123;
                                                
$field_value_str .= ",'".mysql_escape_string&#40;iconv&#40;'BIG5','UTF-8',$fvv&#41;&#41;."'";
                                        
&#125;
                                        
$sno $sno+;
                                &
#125;


                                
$query "insert into ".$k."&#40;".$field_str."&#41; values&#40;".$field_value_str."&#41;;";
                                unset&
#40;$field_value[$row-1&#93;&#41;;
                                
unset&#40;$field_str&#41;;
                                
unset&#40;$field_value_str&#41;;
                                
echo $query "\n";
                                
//print_r&#40;$field_value&#41;;
                        
&#125;
                
&#125;

                
unset&#40;$field_value&#41;;
        
&#125;
&#125;





MetabaseCloseSetup&#40;$db&#41;

?>





4.  
將 convert.php 存檔後

執行 ./convert.php > convert.sql

5. mysql database_name -uroot -p < convert.sql

好了 ccc|



酷不能上傳附加檔案 ...

請至這裡下載 metabase 套件 ..

http://bbs.ecstart.com/viewthread.php?tid=16851&extra=page%3D1

29
這個方法 適用 cisco 跟 3com ,  Foundry 的

而 其它不行的廠牌 如 :

etxxxx , ibxxx 啦 好像都不行 , 實際自己測過才知道 必要時可能要查一下 該牌的官方網站 :

如果 有其它廠牌有機會借測 或是大家公司有幫幫忙測測 回報在這謝謝 ^^

資料來源 cisco 官方網站 :

Using SNMP to Find a Port Number from a MAC Address on a Catalyst Switch

Introduction

This document describes how to use Simple Network Management Protocol (SNMP) to obtain the port number on a Cisco Catalyst switch from which you know the MAC address.
Prerequisites
Requirements

Readers of this document should have knowledge of these topics:

    *

      How to get VLANs from a Catalyst switch with use of SNMP
    *

      How to use community string indexing with SNMP
    *

      General use of the SNMP get command and walk command

Components Used

This document applies to Catalyst switches that run regular Catalyst OS (CatOS) or Cisco IOS® Software. The software supports the BRIDGE-MIB and the IF-MIB.

The information in this document is based on these software and hardware versions:

    *

      Catalyst 3524XL that runs Cisco IOS Software Release 12.0(5)WC5a
    *

      Net-SNMP version 5.0.6

      Note: To obtain this software, refer to Net-SNMP leavingcisco.com.

The information in this document was created from the devices in a specific lab environment. All of the devices used in this document started with a cleared (default) configuration. If your network is live, make sure that you understand the potential impact of any command.
Conventions

For more information on document conventions, refer to the Cisco Technical Tips Conventions.
Background

For more information on how to query the content-addressable memory (CAM) table, VLANs, and all related MIBs, such as the CISCO-VTP-MIB and the BRIDGE-MIB, refer to the Background section of the document How To Get Dynamic CAM Entries (CAM Table) for Catalyst Switches Using SNMP.
Details of the MIB Variables, Which Includes Object Identifiers (OIDs)

.1.3.6.1.2.1.17.4.3.1.1
dot1dTpFdbAddress OBJECT-TYPE
         -- FROM BRIDGE-MIB
         -- TEXTUAL CONVENTION MacAddress
         SYNTAX          OCTET STRING (6)
         MAX-ACCESS      read-only
         STATUS          Mandatory
         DESCRIPTION    "A unicast MAC address for which the bridge has forwarding
                 and/or filtering information."
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) dot1dBridge(17) dot1dTp(4)
dot1dTpFdbTable(3) dot1dTpFdbEntry(1) 1 }

.1.3.6.1.2.1.17.4.3.1.2
dot1dTpFdbPort OBJECT-TYPE
         -- FROM BRIDGE-MIB
         SYNTAX          Integer
         MAX-ACCESS      read-only
         STATUS          Mandatory
         DESCRIPTION    "Either the value "0", or the port number of the port on which
                 a frame having a source
                 address equal to the value of the corresponding instance of
                 dot1dTpFdbAddress has been seen.  
                 A value of "0" indicates that the port number has not been learned,
                 but that the bridge does
                 have some forwarding/filtering information about this address (that is,
                 in the StaticTable).
                       Implementors are encouraged to assign the port value to this
                 object whenever it is
                 learned, even for addresses for which the corresponding value of
                 dot1dTpFdbStatus is not learned(3)."
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) dot1dBridge(17) dot1dTp(4)
dot1dTpFdbTable(3) dot1dTpFdbEntry(1) 2 }

.1.3.6.1.2.1.2.2.1.1
ifIndex OBJECT-TYPE
    SYNTAX      InterfaceIndex
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION      "A unique value, greater than zero, for each interface.  It
            is recommended that values are assigned contiguously
            starting from 1.  The value for each interface sub-layer
            must remain constant at least from one re-initialization of
            the entity's network management system to the next re-
            initialization."
    ::= { ifEntry 1 }

.1.3.6.1.2.1.17.1.4.1.2   
dot1dBasePortIfIndex OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The value of the instance of the ifIndex object,
                      defined in MIB-II, for the interface corresponding
                      to this port."
              ::= { dot1dBasePortEntry 2 }

.1.3.6.1.2.1.31.1.1.1.1
ifName OBJECT-TYPE
    SYNTAX      DisplayString
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION    "The textual name of the interface.  The value of this
            object should be the name of the interface as assigned by
            the local device and should be suitable for use in commands
            entered at the device's `console'.  This might be a text
            name, such as `le0' or a simple port number, such as `1',
            depending on the interface naming syntax of the device.  If
            several entries in the ifTable together represent a single
            interface as named by the device, then each will have the
            same value of ifName.  Note that for an agent which responds
            to SNMP queries concerning an interface on some other
            (proxied) device, then the value of ifName for such an
            interface is the proxied device's local name for it.
            If there is no local name, or this object is otherwise not
            applicable, then this object contains a zero-length string."
    ::= { ifXEntry 1 }

Get the Port Number on Which a MAC Address Has Been Learned
Step-by-Step Instructions

Complete the steps in this section in order to use SNMP to get the port number on which a MAC address has been learned.

Note: In the commands in this section:

    *

      public is the read community string.
    *

      @1 is the VLAN 1 part of the read community string.
    *

      crumpy is the device host name.

      Note: You can also use the IP address for this host name.

Note: The Conclusion section uses the values that appear in italics in the command output.

   1.

      Issue this command in order to use VLAN 1 to obtain the MAC address table:

snmpwalk -c public@1 crumpy .1.3.6.1.2.1.17.4.3.1.1

17.4.3.1.1.0.0.12.7.172.8 =  Hex:
00 00 0C 07 AC 08

17.4.3.1.1.0.1.2.27.80.145 =  Hex: 00 01 02 1B 50 91
17.4.3.1.1.0.1.3.72.77.90 =  Hex: 00 01 03 48 4D 5A
17.4.3.1.1.0.1.3.72.221.191 =  Hex: 00 01 03 48 DD BF


      The command lists all MAC addresses that have been learned on all ports that belong to VLAN 1.

      This command uses community string indexing. The command also uses dot1dTpFdbAddress, which has OID .1.3.6.1.2.1.17.4.3.1.1. If you have loaded the MIBs onto your network management system (NMS), you can use the object name instead of the OID. Issue this command instead:

snmpwalk -c public@1 crumpy dot1dTpFdbAddress

      Note: You can also use the object names in Steps 2–5.
   2.

      Issue this command to determine the bridge port number for VLAN 1:

snmpwalk -c public@1 crumpy .1.3.6.1.2.1.17.4.3.1.2

17.4.3.1.2.0.0.12.7.172.8 =
13

17.4.3.1.2.0.1.2.27.80.128 = 13
17.4.3.1.2.0.1.2.27.80.145 = 13
17.4.3.1.2.0.1.2.163.145.225 = 13


      Note: VLAN 1 is dot1dTpFdbPort , or .1.3.6.1.2.1.17.4.3.1.2.
   3.

      Issue this command to map the bridge port to the ifIndex, OID .1.3.6.1.2.1.2.2.1.1:

snmpwalk -c public@1 crumpy .1.3.6.1.2.1.17.1.4.1.2

17.1.4.1.2.13 =
2

17.1.4.1.2.14 = 3
17.1.4.1.2.15 = 4
17.1.4.1.2.16 = 5

      This command queries the dot1dBasePortIfIndex, which has OID .1.3.6.1.2.1.17.1.4.1.2.
   4.

      Use the walk command with ifName in order to correlate the ifIndex value with a correct port name.

      Issue this command:

      Note: The ifName has OID .1.3.6.1.2.1.31.1.1.1.1.

snmpwalk -c public@1 crumpy .1.3.6.1.2.1.31.1.1.1.1

ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.1 = VL1
ifMIB.ifMIBObjects.ifXTable.ifXEntry.
ifName.2
 = Fa0/1
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.3 = Fa0/2
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.4 = Fa0/3
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.5 = Fa0/4
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.6 = Fa0/5
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.7 = Fa0/6
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.8 = Fa0/7
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.9 = Fa0/8
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.10 = Fa0/9
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.11 = Fa0/10
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.12 = Fa0/11
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.13 = Fa0/12
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.14 = Fa0/13
ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.15 = Fa0/14


   5.

      Link a MAC address to the port on which the address was learned.
          *

            From Step 1, the MAC address is:

17.4.3.1.1.0.0.12.7.172.8 = Hex:
00 00 0C 07 AC 08

          *

            From Step 2, the bridge port tells that the MAC address belongs to bridge port number 13:

13 17.4.3.1.2.0.0.12.7.172.8 =
13
 

          *

            From Step 3, the bridge port number 13 has ifIndex number 2:

17.1.4.1.2.13 =
2

          *

            From Step 4, the ifIndex 2 corresponds to port Fast Ethernet 0/1:

ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.2 =
Fa0/1
 


Conclusion

The MAC address 00 00 0C 07 AC 08 is learned on port Fa0/1.

Compare this conclusion with output from:

    *

      The show cam dynamic command for CatOS switches
    *

      The show mac command for Cisco IOS Software switches

Here is sample output:

crumpy# show mac
Dynamic Address Count:                 58
Secure Address Count:                  2
Static Address (User-defined) Count:   0
System Self Address Count:             51
Total MAC addresses:                   111
Maximum MAC addresses:                 8192
Non-static Address Table:
Destination Address  Address Type  VLAN  Destination Port
-------------------  ------------  ----  -------------------

0000.0c07.ac08       Dynamic          1  FastEthernet0/1

0001.021b.5091       Dynamic          1  FastEthernet0/1
0001.0348.4d5a       Dynamic          1  FastEthernet0/1
0001.0348.ddbf       Dynamic          1  FastEthernet0/1
0001.972d.dfae       Dynamic          1  FastEthernet0/1
0002.55c6.cfe7       Dynamic          1  FastEthernet0/1
0002.7d61.d400       Dynamic          1  FastEthernet0/1

30
############################################################
# 作者 : FIEND
############################################################

最近在做 一個 802.1x 架構下的專案 , 剛好 碰到無線的問題 ldap 是 先要解決的條件


所以 寫了以下這個 function :

以下是 ldap 的認證 寫法 :

解說一下 如何做到的 不然看的人可能會看不懂 :


原理很簡單 :

首先 你要用 admin 的 dn 跟 password 去做一次  binding 然後才可以 ldap_search

然後 $uid_field 則是讓你查找 userid 的 這是 search query 的用法 .

search 出來 最後你在陣列內會看到  

一串 這個user 專門的 dn , 此時不用管它 再把它 拿出來 做一次  binding

用它取出來的 dn 跟 user 輸入的 password 再做一次  binding  確 認這個 user 是否正確 .

代碼: [選擇]

function ldap_auth($adhost, $port, $uid_field, $basedn, $binddn, $passwd, $userid, $userpasswd) {
        global $msg, $db, $default_prefix, $default_prefix_id ;
        $ds = @ldap_connect($adhost, $port) ;           // must be a valid LDAP server!
        if ($ds) {
                $r = @ldap_bind($ds, $binddn, $passwd);
                //$r = @ldap_bind($ds, "netsecure", "net!QAZxsw2");
                if(!$r){                         ecstart_alert_err("binding failed !!") ;
                }
                // Search surname entry
                $sr = @ldap_search($ds, $basedn, "(".$uid_field."=".$userid.")") ;
                $user_arr = @ldap_get_entries($ds, $sr) ;
                //echo print_r($user_arr) ; exit ;

                if ($user_arr["count"] == "1") {
                        $user_binddn = $user_arr[0]["dn"] ;
                        $ub = @ldap_bind($ds, $user_binddn, $userpasswd) ;
                        if(!$ub) {      ecstart_alert_err($msg["ad_passwd_err"]);       }
                }
                else {
                        ecstart_alert_err($msg["ad_search_err"]) ;
                }


                ldap_close($ds);
                return true ;
        } else {
                ecstart_alert_err("Unable to connect to LDAP server") ;
        }
}

頁: [1] 2