• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            戰魂小筑

            討論群:309800774 知乎關注:http://zhihu.com/people/sunicdavy 開源項目:https://github.com/davyxu

               :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
              257 隨筆 :: 0 文章 :: 506 評論 :: 0 Trackbacks

            #

            最近從Qt4.7.0 升級到 Qt4.8.2, 裝好了新的open sdk, 但是觀察工程中的引用依舊是4.7.0

            在Windows環境變量中沒有找到$(QTDIR)

            隨即在Qt的Visual Studio 插件菜單中, Qt->Qt Options-> Qt Versions

            設置Default Qt/Win version為新版本

            選中原有的Qt工程, 在插件菜單中找到Qt Project Settings->Properties->Version中,將版本設置為最新版本

            如果裝有Visual AssitX, 此時這東西應該開始Parse新的Qt庫了

            have fun 微笑!

            posted @ 2012-07-14 15:35 戰魂小筑 閱讀(13412) | 評論 (0)編輯 收藏

            MySQL++在MySQL原始C接口上做了一些封裝, 給操作帶來很大便利.

            最近遇到DB服務器中報出一個MySQL的錯誤:Commands out of sync; you can't run this command now,2014

            查閱很多代碼, 解決方法都是使用C接口的方式, 模仿其解決方法,在MySQL++中找到了比較好的解決方案:

            方案A: 清空每次未使用的記錄

            for (int i = 1; DataQuery.more_results(); ++i)
            {
               DataQuery.store_next();                
            }

            其中 DataQuery類型為mysqlpp::Query

             

            方案B: 對于存儲過程中,使用了多個select語句返回同樣的列結果, 就需要使用以下語句

            static void print_multiple_results(Query& query)
            {
                // 執行查詢并輸出結果表
             StoreQueryResult res = query.store();
             print_result(res, 0);
             for (int i = 1; query.more_results(); ++i) {
              res = query.store_next();
              print_result(res, i);
             }
            }
             
            參考文章:http://hi.baidu.com/freeknight/item/ea9fd88e7d291f854514cf43
            posted @ 2012-06-13 17:57 戰魂小筑 閱讀(6787) | 評論 (0)編輯 收藏

            本文轉自: http://coolshell.cn/articles/7526.html

             

            Lisp之魅

            長久以來,Lisp一直被許多人視為史上最非凡的編程語言。它不僅在50多年前誕生的時候帶來了諸多革命性的創新并極大地影響了后來編程語言的發展,即使在一大批現代語言不斷涌現的今天,Lisp的諸多特性仍然未被超越。當各式各樣的編程語言擺在面前,我們可以從運行效率、學習曲線、社區活躍度、廠商支持等多種不同的角度進行評判和選擇,但我特別看中的一點在于語言能否有效地表達編程者的設計思想。學習C意味著學習如何用過程來表達設計思想,學習Java意味著學習如何用對象來表達設計思想,而雖然Lisp與函數式編程有很大的關系,但學習Lisp絕不僅僅是學習如何用函數表達設計思想。實際上,函數式編程并非Lisp的本質,在已經掌握了lambda、高階函數、閉包、惰性求值等函數式編程概念之后,學習Lisp仍然大大加深了我對編程的理解。學習Lisp所收獲的是如何“自由地”表達你的思想,這正是Lisp最大的魅力所在,也是這門古老的語言仍然具有很強的生命力的根本原因。

            Lisp之源

            Lisp意為表處理(List Processing),源自設計者John McCarthy于1960年發表的一篇論文《符號表達式的遞歸函數及其機器計算》。McCarthy在這篇論文中向我們展示了用一種簡單的數據結構S表達式(S-expression)來表示代碼和數據,并在此基礎上構建一種完整的語言。Lisp語言形式簡單、內涵深刻,Paul Graham在《Lisp之根源》中將其對編程的貢獻與歐幾里德對幾何的貢獻相提并論。

            Lisp之形

            然而,與數學世界中簡單易懂的歐氏幾何形成鮮明對比,程序世界中的Lisp卻一直是一種古老而又神秘的存在,真正理解其精妙的人還是少數。從表面上看,Lisp最明顯的特征是它“古怪”的S表達式語法。S表達式是一個原子(atom),或者若干S表達式組成的列表(list),表達式之間用空格分開,放入一對括號中。“列表“這個術語可能會容易讓人聯想到數據結構中的鏈表之類的線形結構,實際上,Lisp的列表是一種可嵌套的樹形結構。下面是一些S表達式的例子:

            foo
            
            ()
            
            (a b (c d) e)
            
            (+ (* 2 3) 5)
            
            (defun factorial (N)
                (if (= N 1)
                    1
                    (* N (factorial (- N 1)))
                )
            )
            

            據說,這個古怪的S表達式是McCarthy在發明Lisp時候所采用的一種臨時語法,他實際上是準備為Lisp加上一種被稱為M表達式(M-expression)的語法,然后再把M表達式編譯為S表達式。用一個通俗的類比,S表達式相當于是JVM的字節碼,而M表達式相當于Java語言,但是后來Lisp的使用者都熟悉并喜歡上了直接用S表達式編寫程序,并且他們發現S表達式有許多獨特的優點,所以M表達式的引入也就被無限期延遲了。

            許多Lisp的入門文章都比較強調Lisp的函數式特性,而我認為這是一種誤導。真正的Lisp之門不在函數式編程,而在S表達式本身,Lisp最大的奧秘就藏在S表達式后面。S表達式是Lisp的語法基礎,語法是語義的載體,形式是實質的寄托。“S表達式”是程序的一種形,正如“七言”是詩的一種形,“微博”是信息的一種形。正是形的不同,讓微博與博客有了質的差異,同樣的道理,正是S表達式讓Lisp與C、Java、SQL等語言有了天壤之別。

            Lisp之道

            一門語言能否有效地表達編程者的設計思想取決于其抽象機制的語義表達能力。根據抽象機制的不同,語言的抽象機制形成了面向過程、面向對象、函數式、并發式等不同的范式。當你采用某一種語言,基本上就表示你已經“面向XXX“了,你的思維方式和解決問題的手段就會依賴于語言所提供的抽象方式。比如,采用Java語言通常意味著采用面向對象分析設計;采用Erlang通常意味著按Actor模型對并發任務進行建模。

            有經驗的程序員都知道,無論是面向XXX編程,程序設計都有一條“抽象原則“:What與How解耦。但是,普通語言的問題就在于表達What的手段非常有限,無非是過程、類、接口、函數等幾種方式,而諸多領域問題是無法直接抽象為函數或接口的。比如,你完全可以在C語言中定義若干函數來做到make file所做的事情,但C代碼很難像make file那樣聲明式地體現出target、depends等語義,它們只會作為實現細節被淹沒在一個個的C函數之中。采用OOP或是FP等其它范式也會遇到同樣的困難,也就是說make file語言所代表的抽象維度與面向過程、OOP以及FP的抽象維度是正交的,使得各種范式無法直接表達出make file的語義。這就是普通語言的“剛性”特征,它要求我們必須以語言的抽象維度去分析和解決問題,把問題映射到語言的基本語法和語義。

            更進一步,如果仔細探究這種剛性的根源,我們會發現正是由于普通語言語法和語義的緊耦合造成了這種剛性。比如,C語言中printf(“hello %s”, name)符合函數調用語法,它表達了函數調用語義,除此之外別無他義;Java中interface IRunnable { … }符合接口定義語法,它表達了接口定義語義,除此之外別無他義。如果你認為“語法和語義緊耦合“是理所當然的,看不出這有什么問題,那么理解Lisp就會讓你對此產生更深的認識。

            當你看到Lisp的(f a (b c))的時候,你會想到什么?會不會馬上聯想到函數求值或是宏擴展?就像在C語言里看到gcd(10, 15)馬上想到函數調用,或者在Java里看到class A馬上想到類定義一樣。如果真是這樣,那它就是你理解Lisp的一道障礙,因為你已經習慣了順著語言去思考,總是在想這一句話機器怎么解釋執行?那一句話又對應語言的哪個特性?理解Lisp要反過來,讓語言順著你,Lisp的(f a (b c))可以是任何語義,完全由你來定,它可以是函數定義、類定義、數據庫查詢、文件依賴關系,異步任務的執行關系,業務規則 …

            下面我準備先通過幾個具體的例子逐步展示Lisp的本質。需要說明的是,由于Lisp的S表達式和XML的語法形式都是一種樹形結構,在語義表達方面二者并無本質的差別。所以,為了理解方便,下面我暫且用多數人更為熟悉的XML來寫代碼,請記住我們可以很輕易地把XML代碼和Lisp代碼相互轉換。

            首先,我們可以輕易地用XML來定義一個求兩個數最大公約數的函數:

                <func name='gcd' return_type='int'>
                    <params>
                        <a type='int'/>
                        <b type='int'/>
                    </params>
                    <body>
                        <if>
                           <equals>
                               <a/>
                               <int>0</int>
                           </equals>
                        </if>
                        <then>
                            <return><b/></return>
                        </then>
                        <else>
                            <return>
                                <gcd>
                                    <modulo><b/><a/></modulo>
                                    <a/>
                                </gcd>
                            </return>
                        </else>
                    </body>
                </func>
            

            其次,我們可以用它來定義類:

                <class name="Computer">
                    <field access="private" type="MainBoard" name="main-board" />
                    <field access="private" type="CPU" name="cpu" />
                    <field access="private" type="Memory" name="memory" />
            
                    <method access="public" return_type="boolean" name="powerOn" />
                        <params>...</params>
                        <body>...</body>
                    </method>
            
                    <method access="public" return_type="boolean" name="powerOff" />
                        <params>...</params>
                        <body>...</body>
                    </method>
                </class>
            

            還可以輕易地用它來編寫關系查詢:

            <sql>
                <select>
                    <column name="employees.id" />
                    <column name="bonus.amount" />
                </select>
                <from>
                    <table name="employees" />
                    <table name="bonus" />
                </from>
                <where>
                    <equals>
                        <column name="employees.id" />
                        <column name="bonus.employee_id" />
                    </equals>
                </where>
            </sql>
            

            還可以用它來實現類似make file的自動化構建(語法取自ant):

                <project name="MyProject" default="dist" basedir=".">
                    <property name="src" location="src"/>
                    <property name="build" location="build"/>
                    <property name="dist"  location="dist"/>
            
                    <target name="init">
                        <mkdir dir="${build}"/>
                    </target>
            
                    <target name="compile" depends="init" description="compile the source " >
                        <javac srcdir="${src}" destdir="${build}"/>
                    </target>
            
                    <target name="dist" depends="compile" description="generate the distribution" >
                        <mkdir dir="${dist}/lib"/>
                        <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
                    </target>
            
                    <target name="clean" description="clean up" >
                        <delete dir="${build}"/>
                        <delete dir="${dist}"/>
                    </target>
                </project>
            

            一口氣舉了這么多個例子,目的在于用XML這種樹形結構來說明Lisp的S表達式所能夠描述的語義。不知道你是否發現了S表達式和XML這種樹形語法在語義構造方面有著特別的“柔性”?我們可以輕易地用它構造出函數、變量、條件判斷語義;類、屬性、方法語義;可以輕易地構造出關系模型的select、where語義;可以輕易地構造出make的target、depends語義,等等數不清的語義。在普通語言里,你可以定義一個函數、一個類,但你無法為C語言增加匿名函數特性,也沒法給Java語言加上RAII語義,甚至連自己創造一個foreach循環都不行,而自定義語義意味著在Lisp之上你創造了一門語言!不管是面向過程,面向對象,函數式,還是關系模型,在Lisp里統統都變成了一種DSL,而Lisp本身也就成了一種定義語言的語言,即元語言(Meta Language)。

            Lisp的柔性與S表達式有著密切的關系。Lisp并不限制你用S表達式來表達什么語義,同樣的S表達式語法可以表達各種不同領域的語義,這就是語法和語義解耦。如果說普通語言的剛性源于“語法和語義緊耦合”,那么Lisp的柔性正是源于“語法和語義解耦”!“語法和語義解耦”使得Lisp可以隨意地構造各種領域的DSL,而不強制用某一種范式或是領域視角去分析和解決問題。本質上,Lisp編程是一種超越了普通編程范式的范式,這就是Lisp之道:面向語言編程(LOP, Language Oriented Programming)。Wikipedia上是這樣描述LOP的:

            Language oriented programming (LOP) is a style of computer programming in which, rather than solving problems in general-purpose programming languages, the programmer creates one or more domain-specific languages for the problem first, and solves the problem in those languages … The concept of Language Oriented Programming takes the approach to capture requirements in the user’s terms, and then to try to create an implementation language as isomorphic as possible to the user’s descriptions, so that the mapping between requirements and implementation is as direct as possible.

            LOP范式的基本思想是從問題出發,先創建一門描述領域模型的DSL,再用DSL去解決問題,它具有高度的聲明性和抽象性。SQL、make file、CSS等DSL都可以被認為是LOP的具體實例,下面我們再通過兩個常見的例子來理解LOP的優勢。

            例1:在股票交易系統中,交易協議定義若干二進制的消息格式,交易所和客戶端需要對消息進行編碼和解碼。

            消息格式是一種抽象的規范,本身不對語言做任何的限制,你可以用C,C++,Java,或者Python。普通的實現方式是按照消息格式規范,在相應的語言中定義消息結構,并編寫相應的編解碼函數。假設為一個消息定義結構和實現編解碼函數的工作量為M,不同消息類型的數量為N,這種方式的工作量大致為M*N。也就是說每增加一種消息類型,就需要為該消息定義結構,實現編解碼函數,引入bug的可能性當然也和M*N成正比。如果仔細觀察不難發現,各個消息結構其實是高度類似的,編解碼函數也大同小異,但是普通語言卻找不到一種抽象機制能表達這種共性,比如,我們無法通過面向對象的方法定義一個基類把消息結構的共性抽象出來,然后讓具體的消息去繼承它,達到復用的目的。這正是由于普通語言的抽象維度限制所致,在普通語言中,你只能從函數、接口等維度對事物進行抽象,而恰好消息格式共性所在的維度與這些抽象維度并不匹配。

            其實,不同消息類型的共性在于它們都具有相同的領域語義,比如:“某字段內容是另一個字段內容的md5碼”就是一種消息格式的領域語義,這種領域語義是OOP的抽象機制無法描述的。LOP的思路是先創建一門消息定義DSL,比如,類似Google的Protocol Buffer,Android的AIDL。然后,通過DSL編寫消息定義文件,直接聲明式地描述消息的結構特征,比如,我們可以聲明式地描述“某字段內容是另一個字段內容的md5碼”。我們還需要為DSL開發編譯器用于生成C、Java等通用語言的消息定義和編解碼函數。

            有了消息定義DSL和編譯器之后,由于DSL編寫消息定義是一種高度聲明式的編程方法,每增加一種消息的只需要多編寫一個消息定義文件而已,工作量幾乎可以忽略不計。所有的工作量都集中在編譯器的開發上,工作量是一個常數C,與消息的數量沒有關系;質量保證方面也只需要關注編譯器這一點,不會因為增加新的消息類型而引入bug。

            例2:在圖書管理系統中,需要支持在管理界面上對書籍、學生、班級等各種實體進行管理操作。

            如果按傳統的三層架構,一般需要在后端程序中為每一種實體定義一個類,并定義相應的方法實現CRUD操作,與之相應的,還需要在前端頁面中為每一個實體編寫相應的管理頁面。這些實體類的CRUD操作都是大同小異的,但細節又各不相同,雖然我們很想復用某些共同的設計實現,但OOP所提供的封裝、繼承、多態等抽象機制不足以有效捕獲實體之間的共性,大量的代碼還是必須放在子類中來完成。比如,Student和Book實體類的實現非常相似,但是如果要通過OOP的方式去抽象它們的共性,得出的結果多半是Entity這樣的大而空的基類,很難起到復用的效果。

            其實,不同實體之間的共性還是在于它們具有相同的領域語義,比如:實體具有屬性,屬性具有類型,屬性具有取值范圍,屬性具有可讀取、可編輯等訪問屬性,實體之間有關聯關系等。LOP方法正是直接面向這種領域語義的。采用LOP方法,我們并不需要為每一個實體類單獨編寫CRUD方法,也不需要單獨編寫管理頁面,只需要定義一種DSL并實現其編譯器;然后,用DSL聲明式地編寫實體描述文件,去描述實體的屬性列表,屬性的類型、取值范圍,屬性所支持的操作,屬性之間的關系和約束條件等;最后,通過這個實體描述文件自動生成后端的實體類和前端管理頁面。采用LOP,不論前后端采用何種技術,Java也好,C#也好,JSP也好,ASP.NET也好,都可以自動生成它們的代碼。采用LOP的工作量和質量都集中在DSL的設計和編譯器的開發,與實體的數量無關,也就是說,越是龐大的系統,實體類越多越是能體現LOP的優勢。

            通過上面兩個小例子我們可以感受到,LOP是一種面向領域的,高度聲明式的編程方式,它的抽象維度與領域模型的維度完全一致。LOP能讓程序員從復雜的實現細節中解脫出來,把關注點集中在問題的本質上,從而提高編程的效率和質量。

            接下來的問題是如果需要為某領域設計DSL,我們是應該發明一門類似SQL這樣的專用DSL呢,還是用XML或S表達式去定義DSL呢?它們各有何優缺點呢?

            我認為采用XML或S表達式定義DSL的優點主要有:1) SQL、make file、CSS等專用DSL都只能面向各自的領域,而一個實際的領域問題通常是跨越多個領域的,有時我們需要將不同領域融合在一起,但是由于普通語言的剛性,多語言融合通常會是一件非常困難的事情,而XML和S表達式語法結構的單一性和“代碼及數據”的特點使得跨領域融合毫無障礙。2) 在為DSL開發編譯器或解釋器的方面,二者難度不同。對XML和S表達式定義的DSL進行語法分析非常簡單,相比之下,對SQL這樣的專用DSL進行語法分析,雖然可以借助Lex、Yacc、ANTLR等代碼生成工具,但總的來講復雜度還是要明顯高一些。

            當然,XML和S表達式的優點也正好是其缺點,由于XML和S表達式的語法形式是固定的,不能像專用DSL那樣自由地設計語法。所以,一般來講專用DSL的語法顯得更加簡潔。換句話說,XML和Lisp其實是在語法和語義間做了一個交換,用語法的限制換來了語義的靈活。

            Lisp之器

            接下來我們繼續探討DSL的解釋執行問題。DSL代碼的解釋執行一般分為3種典型的方式:1) 通過專門的解釋器解釋執行;2) 編譯生成其他語言的代碼,再通過其他語言的解釋器解釋執行(或編譯運行);3) 自解釋。比如,第1類的代表是SQL,上一節舉的兩個例子都屬于第2類,而第3類自解釋正是Lisp的特色。

            為了理解自解釋,我們可以先從內部DSL的解釋執行說起。內部DSL是指嵌入在宿主語言中的DSL,比如,Google Test單元測試框架定義了一套基于流暢接口(Fluent Interface)的C++單元測試DSL。從語義構造的角度看,內部DSL直接借用宿主語言的語法定義了自己的領域語義,是一種語法和語義解耦;從解釋執行的角度看,內部DSL是隨宿主語言的解釋器而自動解釋的,不需要像外部DSL一樣開發專門的解釋器,因而實現的代價很低。當然,并不是說設計內部DSL不用關心任何的解釋實現,實際上,還是需要熟悉宿主語言的特性,并利用該特性使得DSL能隨著宿主語言的解釋器得到解釋執行。

            Lisp擁有強大的自解釋特性,這得益于獨一無二的Lisp之器:宏 (macro)。宏使得Lisp編寫的DSL可以被Lisp解釋器直接解釋執行,這在原理上與內部DSL是相通的,只是內部DSL一般是利用宿主語言的鏈式調用等特性,通常形式簡陋,功能有限,而Lisp的宏則要強大和靈活得多。

            C語言中也有宏的概念,不過Lisp的宏與C語言的宏完全不同,C語言的宏是簡單的字符串替換。比如,下面的宏定義:

            #define square(x) (x*x)
            

            square(1+1)的期望結果是4,而實際上它會被替換成(1+1*1+1),結果是3。這個例子說明,C語言的宏只在預編譯階段進行簡單的字符串替換,對程序語法結構缺乏理解,非常脆弱。Lisp的宏不是簡單的字符串替換,而是一套完整的代碼生成系統,它是在語法解析的基礎上把Lisp代碼從一種形式轉換為另一種形式,本質上起到了普通語言編譯器的作用。不同的是,普通編譯器是把一種語言的代碼轉換為另一種語言的代碼,比如,Java編譯器把Java代碼轉換成Java字節碼;而Lisp宏的輸入和輸出都是S表達式,它本質上是把一種DSL轉換為另一種DSL。下面的例子是宏的一個典型用法。

            例3:假設Lisp解釋器已經具備解釋執行面向過程DSL的能力,需要實現類似ant的自動化構建工具。

            我們可以基于宏構建一門類ant的DSL,宏的作用是把類ant DSL通過宏展開變成面向過程的DSL,最后被Lisp解釋器所解釋執行。這樣用Lisp編寫的ant DSL就不需要被編譯為其他語言,也不需要像XML的ant一樣依賴于專門的解釋器了。

            當然,和開發專門的解釋器/編譯器相比,Lisp的宏也并非沒有缺點,宏難以理解,開發和調試更加困難。到底是開發專門的解釋器/編譯器還是直接采用宏應該視具體情況而定。

            總結

            Lisp采用單一的S表達式語法表達不同的語義,實現了語法和語義解耦。這使得Lisp具有強大的語義構造能力,擅長于構造DSL實現面向語言編程,而宏使得Lisp具有自解釋能力,讓不同DSL之間的轉換游刃有余。進入Lisp的世界應當從理解面向語言編程入門,這是Lisp之道,而函數式編程和宏皆為Lisp之器,以道馭器方為正途。

            后記

            本文是我學習Lisp的一個總結,也是寫給有興趣學習Lisp的程序員的入門資料。必須說明,我還是一個標準的Lisp初學者,幾乎沒有寫過像樣的Lisp程序,文中的錯誤和不足在所難免,希望讀者批評指正,感謝!

            參考

            The Roots of Lisp

            The Nature of Lisp

            Why Lisp macros are cool, a Perl perspective

            Wikipedia: Language-oriented programming

            《實用Common Lisp編程》

            《冒號課堂 – 編程范式與OOP思想》

            posted @ 2012-06-12 12:38 戰魂小筑 閱讀(1063) | 評論 (0)編輯 收藏

            最近團隊已經全面棄用SVN全面轉移到HG(Mercurial)分布式代碼管理

            Visual Studio系編輯工具由于質量過硬, 兼容性超強,因此使用HG一直沒有出現過問題

            但是第三方開發的FlashDevelop對UNICODE兼容性不好, 出現了很多亂碼問題, 特別是在HG合并代碼后, 代碼中的中文在FlashDevelop中的亂碼現象更是嚴重. 經過驗證, 同樣代碼在FlashBuilder中沒有問題. 因此可以推斷是FlashDevelop兼容性問題

            為解決此問題, 需要調整HG的配置, 這里以Windows環境下的TortoiseHg為例

            解決方案如下:

            kdiff3是TortoiseHg的默認合并工具, 默認安裝路徑在c:\Program Files\TortoiseHg\kdiff3.exe, 找到并運行

            在菜單中找到Settings->Configure KDiff3...

            在Regional Settings選項卡中選擇Unicode, 8 bit(UTF-8) 然后取消勾選右邊的Auto Detect Unicode

            image

            注意, 如果需要混合開發UTF8保存的源碼和UNICODE保存的源碼, 需要準備兩套合并方案, 可以選擇兼容性比較好的BeyondCompare

            posted @ 2012-05-12 10:17 戰魂小筑 閱讀(2358) | 評論 (0)編輯 收藏

            傳統發布現狀

            傳統的服務器/客戶端版本發布流程都需要經歷以下流程:

            1. 獲取代碼

            2. 編譯代碼

            3. 將配置,二進制文件, 資源打包

            4. 掛接遠程服務器磁盤拷貝打包文件

            5. 遠程操作解壓打包文件

            6. 修改設置,指向最新版本

            7. 重啟服務器

            此流程繁瑣,重復且無聊, 同時, 由于網絡帶寬,網速等約束, 每次若使用完整包發布,傳輸起來非常吃力

            本文討論的外網服務器由于安全性要求,禁止root登錄,只能用普通帳號登錄或傳輸后, 提權為root繼續進行以上操作, 因此rsync的使用受到嚴重限制

            即便使用Windows下的同步軟件, 也幾乎不可能.

            HG特性及優勢

            HG作為一個優秀,小巧的跨平臺代碼管理軟件的特性,正好能解決以上問題, 主要特性:

            1. 安裝簡便, 可以使用代碼直接安裝

            2. 利用本地映射版本可以對新版本做差異比較

            3. 增量包傳輸, 100%同步, 本地文件刪除后, 遠程文件也會同步刪除

            4. 傳輸壓縮

            5. 增量包可以打包為patch進行離線更新

            6. 可以恢復到任意版本, 提交版本有據可查

             

            以下部署系統以CentOS為基礎, 其他系統類似

            本文來自戰魂小筑的博客http://www.shnenglu.com/sunicdavy 轉載請注明來源

            為遠程服務器安裝HG

            安裝依賴庫

            yum install python-devel

            獲取HG源碼

            wget http://mercurial.selenic.com/release/mercurial-2.1.tar.gz

            tar zxvf ./mercurial-2.1.tar.gz

            編譯安裝

            make all

            make install

            hg debuginstall

             

            使用HG同步數據

            創建倉庫

            找到你需要同步的目錄,進入目錄

            執行

            hg init

            vi .hg/hgrc

            添加以下內容,讓這個倉庫支持外部push

            [ui]

            username=服務器提交后看到的用戶名

            [web]

            push_ssl = false
            allow_push=*

            同步

            vi /etc/sysconfig/iptables

            添加HG服務的8000端口

            -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8000 -j ACCEPT

            開啟倉庫同步服務

            hg serve

            本地機器同樣找到文件夾,創建倉庫

            hg init

            以后每次需要同步時,使用命令,或者烏龜HG的界面工具拉取服務器數據即可

            hg pull http://服務器地址:8000

             

            版本提交方法與HG日常使用類似, 這里不再闡述

            離線更新

            對于某些服務器深處防火墻或者安全登錄后方,不能直接開啟8000端口的情況

            可以使用hg導出一個patch, 傳輸到遠程服務器, 使用hg import PATCH 即可

            posted @ 2012-04-26 11:11 戰魂小筑 閱讀(3066) | 評論 (0)編輯 收藏

            BasicLayout.cpp:37:5: error: 'auto_ptr' in namespace 'std' does not name a type

            在包含中添加#include <memory>即可

            posted @ 2012-04-21 16:43 戰魂小筑 閱讀(2951) | 評論 (2)編輯 收藏

            由于服務器需要靜態鏈接所有庫,但mysql++默認編譯使用的是共享庫, 因此使用ar手動生成一個

            mysql++版本3.1.0

            進入mysql++目錄,執行以下指令生成libmysqlpp.a

            ar rcu libmysqlpp.a mysqlpp_beemutex.o mysqlpp_cmdline.o mysqlpp_connection.o mysqlpp_cpool.o mysqlpp_datetime.o mysqlpp_dbdriver.o mysqlpp_field_names.o mysqlpp_field_types.o mysqlpp_manip.o mysqlpp_myset.o mysqlpp_mysql++.o mysqlpp_mystring.o mysqlpp_null.o mysqlpp_options.o mysqlpp_qparms.o mysqlpp_query.o mysqlpp_result.o mysqlpp_row.o mysqlpp_scopedconnection.o mysqlpp_sql_buffer.o mysqlpp_sqlstream.o mysqlpp_ssqls2.o mysqlpp_stadapter.o mysqlpp_tcp_connection.o mysqlpp_transaction.o mysqlpp_type_info.o mysqlpp_uds_connection.o mysqlpp_utility.o mysqlpp_vallist.o mysqlpp_wnp_connection.o ssqls2parse_parsev2.o

            然后mv到usr/local/lib,重新鏈接服務器即可

            posted @ 2012-04-20 14:48 戰魂小筑 閱讀(3462) | 評論 (1)編輯 收藏

            最近頁游開放平臺比較多, 每個平臺要求的Linux版本各不相同, 這給開發人員部署服務器帶來了很大的困難. 在本機Linux編譯的程序,發布時即便將依賴的so附帶到目標Linux環境,仍然會碰到依賴及版本問題,例如:

            [root@localhost bin]# ldd wkcenter
            ./wkcenter: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.11' not found (required by ./wkcenter)
            ./wkcenter: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by ./wkcenter)
            ./wkcenter: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by ./wkcenter)
            ./wkcenter: /lib/libc.so.6: version `GLIBC_2.9' not found (required by ./wkcenter)
            ./wkcenter: /lib/libc.so.6: version `GLIBC_2.7' not found (required by ./wkcenter)
            ./wkcenter: /lib/libc.so.6: version `GLIBC_2.8' not found (required by ./wkcenter)
            ./wkcenter: /lib/libc.so.6: version `GLIBC_2.11' not found (required by ./wkcenter)

                    linux-gate.so.1 =>  (0xffffe000)
                    liblog4cpp.so.4 => not found
                    libprotobuf.so.7 => not found
                    libboost_filesystem.so.1.48.0 => not found
                    libboost_system.so.1.48.0 => not found
                    libboost_thread.so.1.48.0 => not found
                    libboost_program_options.so.1.48.0 => not found
                    libunwind-x86.so.7 => not found
                    libluabind.so.0.9.0 => not found
                    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x008ae000)
                    libm.so.6 => /lib/libm.so.6 (0x0044b000)
                    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00476000)
                    libc.so.6 => /lib/libc.so.6 (0x002c1000)
                    libpthread.so.0 => /lib/libpthread.so.0 (0x0041d000)
                    librt.so.1 => /lib/librt.so.1 (0x00440000)
                    /lib/ld-linux.so.2 (0x002a2000)

            上面紅字部分表示glibc及glibcxx庫依賴不正確. 本人使用的Linux編譯版本為Mint 11(基于Ubuntu), 一般Ubuntu發行版的glibc配備非常高. 但是上文中的發布的Linux版本為CentOS 5.8

            使用/lib/libc.so.6 查看libc版本為2.5, 遠遠低于開發環境的2.11

            GNU C Library stable release version 2.5, by Roland McGrath et al.
            Copyright (C) 2006 Free Software Foundation, Inc.
            This is free software; see the source for copying conditions.
            There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
            PARTICULAR PURPOSE.
            Compiled by GNU CC version 4.1.2 20080704 (Red Hat 4.1.2-51).
            Compiled on a Linux 2.6.9 system on 2012-02-21.
            Available extensions:
                    The C stubs add-on version 2.1.2.
                    crypt add-on version 2.1 by Michael Glad and others
                    GNU Libidn by Simon Josefsson
                    GNU libio by Per Bothner
                    NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk
                    Native POSIX Threads Library by Ulrich Drepper et al
                    BIND-8.2.3-T5B
                    RT using linux kernel aio
            Thread-local storage support included.
            For bug reporting instructions, please see:
            <
            http://www.gnu.org/software/libc/bugs.html>.

            由于Linux操作系統的特有elf加載順序. (可以參考此文). 雖然可以很大程度上解決Windows早期版本的dll hell問題, 但是給部署帶來了很大難度

            一般常見的解決方法是, 找到一個與目標Linux版本及glibc版本一致的Linux, 將代碼及依賴包放在之上編譯, 完成后再發布.這種方法與Linux下常見軟件安裝方法類似. 但是對于商用服務器部署步驟來說未免繁瑣, 安全性低.

            還有一種方法,使用靜態鏈接. 將所有可執行文件文件依賴的靜態庫, 系統庫,全部靜態鏈接到可執行文件中,可以一次性解決這個問題

            步驟:

                1. 在gcc鏈接命令行中添加-static -static-libgcc -static-libstdc++

                2. 將第三方依賴庫打開靜態鏈接開關, 將原來鏈接.so的庫,全改為鏈接.a

                3. gcc對鏈接庫順序很敏感, 鏈接庫順序需要按照從前至后為:  項目產生的靜態庫 > 第三方庫靜態庫 > 系統靜態庫

                4. 鏈接時, 若有未解決的symbol, 可以嘗試在最后添加-lpthread及-lrt解決

               

            在發布版本Linux上運行可能遇到的問題:

            terminate called after throwing an instance of 'std::runtime_error'

            what(): locale::facet::_S_create_c_locale name not valid

            解決方法: 執行之前運行export LC_ALL="C"

            posted @ 2012-04-20 11:35 戰魂小筑 閱讀(7196) | 評論 (4)編輯 收藏

            #!/bin/bash
            # chkconfig: 3 3 1
            # description: svclauncher
            ServicePath=/usr/local/bin
            
            ServiceList=(
            "wkcenterd --toc /home/davy/dev/kaze/Config/CenterService.toc --logfile /tmp/centerd.log"
            "wkagentd --toc /home/davy/dev/kaze/Config/AgentService.toc --logfile /tmp/agentd.log"
            )
            
            StartAll()
            {
                for((i = 0;i<${#ServiceList[*]};i=i+1))
                do
            
                 echo "start:" $ServicePath/${ServiceList[i]}
                 $ServicePath/${ServiceList[i]} > /dev/null &
            
                done
            }
            
            StopAll()
            {
                for((i = 0;i<${#ServiceList[*]};i=i+1))
                do
            
                 echo "stop:" $ServicePath/${ServiceList[i]}
                 svcname=`echo ${ServiceList[i]} | awk '{print $1}'`
                 killall $svcname > /dev/null
            
                done
            }
            
            RestartAll()
            {
                StopAll
                StartAll
            }
            
            
            InstallService()
            {
                svcname=`basename $0`
                chmod +x $svcname
                cp $svcname /etc/init.d
                ln /etc/init.d/$svcname /etc/rc3.d/S03$svcname
                ln /etc/init.d/$svcname /etc/rc0.d/K03$svcname
                chkconfig --add $svcname
                chkconfig $svcname on
                chkconfig --list | grep $svcname
            }
            
            UninstallService()
            {
                svcname=`basename $0`
                chkconfig --del $svcname
                rm -f /etc/init.d/$svcname
                rm -f /etc/rc3.d/S03$svcname
                rm -f /etc/rc3.d/K03$svcname
            }
            
            
            
            case "$1" in
                start)
                StartAll
                ;;
                stop)
                StopAll
                ;;
                restart)
                RestartAll
                ;;
                install)
                InstallService
                ;;
                uninstall)
                UninstallService
                ;;
                *)
                       echo "Usage: service $EXEC {install|start|stop|restart|uninst}"
                   exit 1
            esac
             
            exit $? 

            posted @ 2012-04-12 09:33 戰魂小筑 閱讀(2080) | 評論 (0)編輯 收藏

            用作團隊編碼標準很不錯

             

            態度篇
            1. 做實事
            不要抱怨,發牢騷,指責他人,找出問題所在,想辦法解決。對問題和錯誤,要勇于承擔。
            2. 欲速則不達
            用小聰明、權宜之計解決問題,求快而不顧代碼質量,會給項目留下要命的死角。
            3. 對事不對人
            就事論事,明智、真誠、虛心地討論問題,提出創新方案。
            4. 排除萬難,奮勇前進
            勇氣往往是克服困難的唯一方法。
            學習篇
            5. 跟蹤變化
            新技術層出不窮并不可怕。堅持學習新技術,讀書,讀技術雜志,參加技術活動,與人交流。要多理解新詞背后的所以然,把握技術大趨勢,將新技術用于產品開發要謹慎。
            6. 對團隊投資
            打造學習型團隊,不斷提高兄弟們的平均水平。
            7. 懂得丟棄
            老的套路和技術,該丟,就得丟。不要固步自封。
            8. 打破砂鍋問到底
            不斷追問,真正搞懂問題的本質。為什么?應該成為你的口頭禪。
            9. 把握開發節奏
            控制好時間,養成好習慣,不要加班。

            開發流程篇
            10. 讓客戶做決定
            讓用戶在現場,傾聽他們的聲音,對業務最重要的決策應該讓他們說了算。
            11. 讓設計指導而不是操縱開發
            設計是前進的地圖,它指引的是方向,而不是目的本身。設計的詳略程度應該適當。
            12. 合理地使用技術
            根據需要而不是其他因素選擇技術。對各種技術方案進行嚴格地追問,真誠面對各種問題。
            13. 讓應用隨時都可以發布
            通過善用持續集成和版本管理,你應該隨時都能夠編譯、運行甚至部署應用。
            14. 提早集成,頻繁集成
            集成有風險,要盡早盡量多地集成。
            15. 提早實現自動化部署
            16. 使用演示獲得頻繁反饋
            17. 使用短迭代,增量發布
            18. 固定價格就意味著背叛承諾
            估算應該基于實際的工作不斷變化。
            用戶篇
            19. 守護天使
            自動化單元測試是你的守護天使。
            20. 先用它再實現它
            測試驅動開發其實是一種設計工具。
            21. 不同環境,就有不同問題
            要重視多平臺問題。
            22. 自動驗收測試
            23. 度量真實的進度
            在工作量估算上,不要自欺欺人。
            24. 傾聽用戶的聲音
            每一聲抱怨都隱藏著寶貴的真理。

            編程篇
            25. 代碼要清晰地表達意圖

            代碼是給人讀的,不要耍小聰明。
            26. 用代碼溝通
            注釋的藝術。
            27. 動態地進行取舍

            記住,沒有最佳解決方案。各種目標不可能面面俱到,關注對用戶重要的需求。
            28. 增量式編程
            寫一點代碼就構建、測試、重構、休息。讓代碼干凈利落。
            29. 盡量簡單
            寧簡勿繁。如果沒有充足的理由,就不要使用什么模式、原則和特別的技術。
            30. 編寫內聚的代碼
            類和組件應該足夠小,任務單一。
            31. 告知,不要詢問
            多用消息傳遞,少用函數調用。
            32. 根據契約進行替換
            委托往往優于繼承。

            調試篇
            33. 記錄問題解決日志
            不要在同一地方摔倒兩次。錯誤是最寶貴的財富。
            34. 警告就是錯誤
            忽視編譯器的警告可能鑄成大錯。
            35. 對問題各個擊破
            分而治之是計算機科學中最重要的思想之一。但是,要從設計和原型階段就考慮各部分應該能夠很好地分離。
            36. 報告所有的異常
            37. 提供有用的錯誤信息
            稍微多花一點心思,出錯的時候,將給你帶來極大便利。

            團隊協作篇
            38. 定期安排會面時間
            常開會,開短會。
            39. 架構師必須寫代碼

            不寫代碼的架構師不是好架構師。好的設計都來自實際編程。編程可以帶來深入的理解。
            40. 實行代碼集體所有制
            讓開發人員在系統不同區域中不同的模塊和任務之間輪崗。
            41. 成為指導者
            教學相長。分享能提高團隊的總體能力。
            42. 讓大家自己想辦法

            指引方向,而不是直接提供解決方案。讓每個人都有機會在干中學習。
            43. 準備好后再共享代碼
            不要提交無法編譯或者沒有通過單元測試的代碼!
            44. 做代碼復查
            復查對提高代碼質量、減少錯誤極為重要。
            45. 及時通報進展與問題

            主動通報,不要讓別人來問你。

            posted @ 2012-04-03 21:40 戰魂小筑 閱讀(1270) | 評論 (1)編輯 收藏

            僅列出標題
            共26頁: First 5 6 7 8 9 10 11 12 13 Last 
            国内精品久久久久影院一蜜桃| 久久中文精品无码中文字幕| 精品乱码久久久久久久| 国产产无码乱码精品久久鸭| 久久香蕉国产线看观看99| 久久久久亚洲av毛片大| 久久久久久人妻无码| 99久久国产综合精品网成人影院| 综合久久给合久久狠狠狠97色| 久久久av波多野一区二区| 精品久久久久久无码国产| 亚洲AV日韩精品久久久久| 国产午夜电影久久| 久久精品亚洲精品国产色婷| 人妻中文久久久久| 97久久精品人人做人人爽| 东方aⅴ免费观看久久av| 久久精品国产亚洲5555| 久久Av无码精品人妻系列| 亚洲精品99久久久久中文字幕| 国产精品久久久久无码av| 精品国产乱码久久久久软件| 日本久久久久久中文字幕| 国产偷久久久精品专区| 久久久久无码专区亚洲av| 国产精品久久影院| 国产人久久人人人人爽| 亚洲中文字幕久久精品无码喷水| 久久亚洲视频| 怡红院日本一道日本久久 | 久久人人超碰精品CAOPOREN| 久久精品www人人爽人人| 无遮挡粉嫩小泬久久久久久久| 伊人色综合九久久天天蜜桃 | 狠狠综合久久综合88亚洲| 久久精品国产清自在天天线| 久久久精品久久久久久| 久久天天躁狠狠躁夜夜2020| 伊人 久久 精品| 99久久国产精品免费一区二区 | 久久成人小视频|