E81086713E446D36F62B2AA2A3502B5EB155

          Java雜家

          雜七雜八。。。一家之言

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            40 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks

          #

          一直以來,整合Apache HTTP Server和其他Java容器時,可能你最好的選擇就是mod_jk,但是mod_jk在Apache和外部Java服務(wù)器之間使用socket來進(jìn)行協(xié)議轉(zhuǎn)換,性能不能盡如人意。
          正如我上一篇博客里說的,mod_java通過在apache嵌入的JVM中直接執(zhí)行Java來響應(yīng)HTTP請求,當(dāng)然是要快于mod_jk的。

          但是缺點是,不是Servlet API(雖然實現(xiàn)Servlet API不是很難,但是工作量肯定很大的),優(yōu)點是,接口很清晰,很靈活,可以做到的事情也就很多。


          那么如何開發(fā)一個基于mod_java的java handler呢?OK,假設(shè)你要在Apache里響應(yīng)所有/test/*上的請求.
          你要做的是:
          1)配置Apache啟用mod_java
          LoadModule java_module modules/mod_java.so

          <mod_java your_main_class>
          JVMLibrary D:\jdk6\jre\bin\server\jvm.dll
          CurDir D:\apache-tomcat-6.0.14
          ADDJVMOpt -Djava.class.path=D:\apache-tomcat-6.0.14\bin\bootstrap.jar;D:\dev\vccode\mod_java\mod_java.jar
          ADDJVMOpt -Djava.library.path=D:\apache-tomcat-6.0.14\bin
          ADDJVMOpt -Dcatalina.home=D:\apache-tomcat-6.0.14
          ADDJVMOpt -Duser.dir=D:\apache-tomcat-6.0.14
          ADDJVMParam start
          ADDJVMStopParam stop
          ADDJavaHandler javatest com.yovn.apache.modj.HelloWorld
          </mod_java>
          這里main_class是可選的,如果有,那么JVM啟動時自動調(diào)用main方法。

          2)在配置文件里加入你將要開發(fā)的Java Handler
          想上面文件中的
          ADDJavaHandler javatest com.yovn.apache.modj.HelloWorld
          這里 javatest是handler名字,后面是你的實現(xiàn)的class
          3)在配置文件里告訴Apache 你的handler名字對應(yīng)的路徑
          <Location /test>
              SetHandler javatest
          </Location>

          完成這些配置動作后,apache在收到到/test/*的請求后mod_java會call你的handler class的processRequest方法了。

          RequestHandler接口如下定義,你的Handler都需要實現(xiàn)該接口:
          package com.yovn.apache.modj;

          import java.io.IOException;

          /**
           * 
          @author yovn
           * 
           
          */
          public  interface RequestHandler {

              
          public abstract void processRequest(ModJRequest request) throws IOException,
                      ModJavaException;

          }

          正如你看到的很簡單的接口,但是ModJRequest就不簡單了,該接口代表你跟Apache通行的直接的接口,目前定義如下:

          package com.yovn.apache.modj;

          import java.io.IOException;
          import java.io.InputStream;
          import java.io.OutputStream;
          import java.nio.ByteBuffer;

          /**
           * 
          @author yovn
           *
           
          */
          public interface ModJRequest {
              
              
          /**
               * 
               * 
          @param name
               * 
          @return the request header value of that name
               
          */
              String getRequestHeader(String name);
              
              
          /**
               * 
               * 
          @return similar as HttpServletRequest.getRequestURI()
               
          */
              String getRequestURI();
              
          /**
               * 
               * 
          @param name header name
               * 
          @param value header value
               
          */
              
          void setResponseHeader(String name,String value);
              
              
          /**
               * 
               * 
          @param type 'text/html' etc.. 
               
          */
              
          void setContentType(String type);
              
              
          /**
               * 
               * 
          @param code response code
               
          */
              
          void setResponseCode(int code);
              
              
          /**
               * 
               * 
          @return HTTP method
               
          */
              String getMethod();
              
              
              
          /**
               * Give you the  chance when you need push datas to client
               * Also,you can use it to close a connection 
               * Note:
               * HTTP Server may close the connection when it timeout automatically.
               * When you pass use an invalid connection id to call some function , it will failed.
               * 
          @see com.yovn.apache.modj.ApacheModule#flushConnection(long, byte[], int, int)
               * 
          @see com.yovn.apache.modj.ApacheModule#closeConnection(long)
               * 
          @return the connection id for this request.
               
          */
              
          long getConnectionId();
              
              
          /**
               * same as HttpServletRequest.getServletInputStream
               * 
          @return 
               
          */
              InputStream getRequestInputStream();
              
              
          /**
               * same as HttpServletResponse.getServletOutputStream
               * 
          @return
               
          */
              OutputStream getResponseOutputStream();
              
              
              
          /**
               * You should not call the {
          @link #getRequestInputStream()} before you call this method this method.
               * In other words, You should either use this method or {
          @link #getRequestInputStream()}  to do read data from clients
               * 
          @return the direct byte buffer from native side
               * 
          @throws IOException
               
          */
              ByteBuffer readTotalRequestBody()
          throws IOException;
              
              
              
          /**
               * Use apache's apr_send_fd to send a file.
               * Before send file, you may need setup proper HTTP headers, such as 'Content-Disposition' 
               * 
          @param fileName
               * 
          @return 
               * 
          @throws IOException
               
          */
              
          boolean sendFile(String fileName)throws IOException;

          }
          如你所看,基本可以做任何事情(如果還有你想要而沒有請一定要告訴我哦)!

          下面給個發(fā)送文件的例子:

          /**
           * 
           
          */
          package com.yovn.apache.modj;

          import java.io.File;
          import java.io.IOException;

          /**
           * 
          @author yovn
           *
           
          */
          public class HelloWorld implements RequestHandler {

              
          /**
               * 
               
          */
              
          public HelloWorld() {
                  
          // TODO Auto-generated constructor stub
              }

              
          /*
               * (non-Javadoc)
               * 
               * @see com.yovn.apache.modj.RequestHandler#processRequest(ModJRequest request)
               
          */

              
          public void processRequest(ModJRequest request) throws IOException,
                      ModJavaException {

                  request.setContentType(
          "APPLICATION/OCTET-STREAM");
              

                  File f
          =new File("D:\\cspace\\mod_java\\release\\ddd.bin");
                  request.setResponseHeader(
          "Content-Disposition""attachment;filename=\"ddd.bin\"");
                  request.setResponseHeader(
          "Content-Length",f.length()+"");
                  
                  request.sendFile(f.getCanonicalPath());
                  

              }

          }

          下載:
          mod_java_0.1

          posted @ 2008-06-19 15:38 DoubleH 閱讀(4709) | 評論 (5)編輯 收藏

          一 。Apache Java Module是什么?

          Apache Java Module是一個Apache2.2 Server下的一個模塊,這個模塊可以嵌入一個JVM,可以無縫地跟Apache整合在一塊,從而便于發(fā)布高性能的基于Java的HTTP解決方案。

          二。為什么要這么做
          1)首先,Apache是HTTP服務(wù)器市場的領(lǐng)頭羊
          2)處于性能的考量。
          3)Servlet API有它本身的局限性,例如連接相關(guān)的信息基本是被隱藏起來了,這樣當(dāng)你想要異步推數(shù)據(jù)給客戶端時,只能去求助Comet了。
          4)只要愿意,我可以同時跑Apache和Tomcat,并在一個進(jìn)程內(nèi)同時為兩個端口服務(wù)。
          三。示例

          目前初步實現(xiàn)了基本框架,一個Hellow,world的例子見下:
          首先配置Apache,在conf文件里加上:
          LoadModule java_module modules/mod_java.so

          <mod_java org.apache.catalina.startup.Bootstrap>
          JVMLibrary D:\jdk1
          .6\jre\bin\server\jvm.dll
          CurDir D:\apache-tomcat-
          6.0.10
          ADDJVMOpt -Djava.class.path
          =D:\apache-tomcat-6.0.10\bin\bootstrap.jar;D:\cspace\mod_java\mod_java.jar
          ADDJVMOpt -Djava.library.path=D:\apache-tomcat-6.0.10\bin
          ADDJVMOpt -Dcatalina.home
          =D:\apache-tomcat-6.0.10
          ADDJVMOpt -Duser.dir
          =D:\apache-tomcat-6.0.10
          ADDJVMParam start
          ADDJVMStopParam stop
          ADDJavaHandler javatest com.yovn.apache.modj.HelloWorld
          </mod_java>
          <Location /javatest>
              SetHandler javatest
          </Location>

          這段配置腳本,同時會啟動一個Tomcat在一個新的線程。
          并且,當(dāng)你請求/javatest/*時,自動會執(zhí)行com.yovn.apache.modj.HelloWorld來滿足這個請求,下面看
          這個示例程序:

          /**
           * 
           
          */
          package com.yovn.apache.modj;

          import java.io.IOException;
          import java.io.InputStream;
          import java.io.OutputStream;
          import java.io.PrintStream;

          /**
           * 
          @author yovn
           *
           
          */
          public class HelloWorld implements RequestHandler {

              
          /**
               * 
               
          */
              
          public HelloWorld() {
                  
          // TODO Auto-generated constructor stub
              }

              
          /* (non-Javadoc)
               * @see com.yovn.apache.modj.RequestHandler#processRequest(java.lang.String, int, long, long, java.io.InputStream, java.io.OutputStream)
               
          */
              @Override
              
          public void processRequest(String url, int method, long req, long conn,
                      InputStream in, OutputStream out) 
          throws IOException,
                      ModJavaException {
              

                  //ApacheModule.setHeader(req, "X-Server", "mod_java");
                  out.write("<html><head><title>Hello,World</title></head><body><h1>Hello,World</h1></body></html>".getBytes());
                  out.close();

                  

              }

          }
          這是個很簡單的程序,當(dāng)你在瀏覽器輸入http://host:apache_port/javatest/時,顯示Hello,World.

          目前讀取輸入數(shù)據(jù)尚未實現(xiàn),等完善了我再提供下載文件。


          posted @ 2008-06-18 00:05 DoubleH 閱讀(2075) | 評論 (1)編輯 收藏

          問題背景
          面對艱巨復(fù)雜的技術(shù)挑戰(zhàn),百度所崇尚的系統(tǒng)設(shè)計哲學(xué)是“簡單可依賴”,而百度的工程師們正在互聯(lián)網(wǎng)世界中實踐著這種理念。這里正好有一個挑戰(zhàn),讓作為百度之星的你小試牛刀:

          在處理數(shù)以百億計的網(wǎng)絡(luò)信息的過程中,有一個很常見的問題: 
          怎么樣將一個集群上的信息以最低的成本傳輸?shù)搅硗庖粋€集群上?


          數(shù)據(jù)源集群A有n臺服務(wù)器,編號為 1, 2, ..., n,i號服務(wù)器上待傳輸?shù)臄?shù)據(jù)量為Ai ,單位是GB。 
          目的地集群B有m臺服務(wù)器,編號為 1, 2, ..., m,j號服務(wù)器上的空閑容量為 Bj,單位為 GB。 
          A集群的i號服務(wù)器上的每GB數(shù)據(jù)對于B的集群的j號服務(wù)器收益為Vi,j,從 A 集群的 i 號服務(wù)器向 B 集群的 j 號服務(wù)器傳輸 1GB數(shù)據(jù)的開銷為Ci,j。 
          你的任務(wù)是在保證A中的所有數(shù)據(jù)傳輸完畢的前提下,性價比V/C盡量高。其中V為所有數(shù)據(jù)在B集群上的價值之和,C為總開銷。換句話說,若A集群的i號服務(wù)器向B集群的j號服務(wù)器發(fā)送了Ti,j個GB的數(shù)據(jù)(Ti,j不一定是整數(shù)),則性價比定義為:





          輸入格式
          第1行兩個整數(shù)n, m(1<=n,m<=50),即集群A和B各自的服務(wù)器臺數(shù)。
          第2行包含n個不超過100的正整數(shù)A1,A2,…,An,即集群A中每臺服務(wù)器的待傳輸數(shù)據(jù)量(單位:GB)。
          第3行包含m個不超過100的正整數(shù)B1,B2,…,Bm,即集群B中每臺服務(wù)器所能接受的最大數(shù)據(jù)量(單位:GB)。
          第 4 ~ n+3 行每行包含m個不超過100的非負(fù)整數(shù)Vi,j,表示集群A的i號服務(wù)器中每GB數(shù)據(jù)對于集群B中的j號服務(wù)器的價值。
          第 n+4 ~ 2n+3 行每行包含m個不超過100的正整數(shù)Ci,j,表示集群A的i號服務(wù)器中每GB數(shù)據(jù)傳輸?shù)郊築中的j號服務(wù)器所需要的開銷。 

          輸出格式
          僅一行,為最大性價比。輸出保留三位小數(shù)(四舍五入)。如果A的數(shù)據(jù)無法傳輸完畢,輸出字符串 “-1”(無引號)。 

          樣例輸入
          2 2
          1 2
          2 1
          11 0
          7 5
          6 1
          3 2 

          樣例輸出
          2.091 

          樣例解釋
          一個方案是:
          集群A的1號服務(wù)器把所有數(shù)據(jù)傳輸?shù)郊築的1號服務(wù)器,價值11,開銷6。
          集群A的2號服務(wù)器把1GB數(shù)據(jù)傳輸?shù)郊築的1號服務(wù)器,價值7,開銷3,然后把剩下的1GB數(shù)據(jù)傳輸?shù)郊築的2號服務(wù)器,價值5,開銷2。
          性價比:(11+7+5)/(6+3+2)=2.091

          另一個方案是:
          集群A的1號服務(wù)器把所有數(shù)據(jù)傳輸?shù)郊築的2號服務(wù)器,價值0,開銷1。
          集群A的2號服務(wù)器把所有數(shù)據(jù)傳輸?shù)郊築的1號服務(wù)器,價值14,開銷6。
          性價比:(0+14)/(1+6)=2。

          第一種方案更優(yōu)

          我的解答:
          該題應(yīng)該是貪心法可解,每次求性價比最高的,跟部分背包問題很像。
          可惜不是,子問題不是獨立的,我的解法肯定不是最優(yōu)解。sign~~~,據(jù)說是最大流的問題,改天研究研究。
          我的解法用了N+1個最大值堆,一個是全局所有為傳輸完的源站點的最高性價比方案,
          其余每個源站點一個最大值堆含該站點所有傳輸方案。

          //============================================================================
          // Name        : TransportOpt.cpp
          // Author      : Yovn
          // Version     :
          // Copyright   : yovnchine@gmail.com
          //============================================================================

          #include <iostream>
          #include <string>
          #include <cstring>
          #include <cstdio>

          using namespace std;



          int numA;
          int numB;
          int* valuesA;
          int* valuesB;
          int** values=NULL;
          int** costs=NULL;


          typedef struct _HeapNode
          {
              int a;
              int b;
              float vPerC;
             
          }HeapNode;
          class MaxHeap
          {
          public:
              MaxHeap(int n):nodes(new HeapNode[n]),total(n),len(0){
                 
              }
              MaxHeap():nodes(NULL),total(0),len(0){
                     
              }
              ~MaxHeap()
              {
                  delete[] nodes;
              }
              bool isEmpty()
              {
                  return len<=0;
              }
              void setSize(int n)
              {
                  nodes=new HeapNode[n];
                  total=n;
                  len=0;
              }
              HeapNode removeMax()
              {
                 
                  HeapNode ret=nodes[0];
                  nodes[0]=nodes[--len];
                  shift_down(0);
                  return ret;
              }
              void insert(HeapNode val)
              {
                 
                  nodes[len++]=val;
                  shift_up(len-1);
              }
             
          private :
             
             
              void shift_up(int pos) {

                  HeapNode tmp=nodes[pos];
                  int index=(pos-1)/2;
             
                  while (index>=0) {
                      if (tmp.vPerC>nodes[index].vPerC) {
                          nodes[pos]=nodes[index];
                          pos=index;
                          if (pos==0)
                              break;
                          index=(pos-1)/2;
                      } else
                          break;
                  }
                  nodes[pos]=tmp;
              }
              void shift_down(int pos) {

                  HeapNode tmp=nodes[pos];
                  int index=pos*2+1;//use left child
                  while (index<len)//until no child
                  {
                      if (index+1<len&&nodes[index+1].vPerC>nodes[index].vPerC)//right child is smaller
                      {
                          index+=1;//switch to right child
                      }
                      if (tmp.vPerC<nodes[index].vPerC) {
                          nodes[pos]=nodes[index];
                          pos=index;
                          index=pos*2+1;

                      } else {
                          break;
                      }

                  }
                  nodes[pos]=tmp;
                 
              }
              HeapNode* nodes;
              int total;
              int len;


             
          };

          void parseToInts(string& line, int* arr, int num) {
              int pos=0;
              for (int i=0; i<line.length(); i++) {
                  if (line[i]>='0'&&line[i]<='9') {
                      if (line[i+1]>='0'&&line[i+1]<='9') {
                          int a=(line[i]-'0')*10+(line[i+1]-'0');
                          arr[pos++]=a;
                          i++;
                      } else {
                          int a=(line[i]-'0');
                          arr[pos++]=a;
                         
                      }
                     
                  }
              }
          }
          void input()
          {
              string line;
              getline(cin,line);
             
              sscanf(line.c_str(),"%d %d",&numA,&numB);
              valuesA=new int[numA];
              valuesB=new int[numB];
              line.clear();
              getline(cin,line);
              parseToInts(line,valuesA,numA);
             
              line.clear();
              getline(cin,line);
              parseToInts(line,valuesB,numB);
             
            
              values=new int*[numA];
              costs=new int*[numA];
              for (int i=0; i<numA; i++) {
                  values[i]=new int[numB];
                  line.clear();
                  getline(cin, line);
                  parseToInts(line, values[i], numB);
              }
             
              for (int i=0; i<numA; i++) {
                  costs[i]=new int[numB];
                  line.clear();
                  getline(cin, line);
                  parseToInts(line, costs[i], numB);
              }
             
             
             
          }
          bool validate() {
              int sumA=0, sumB=0;
              for (int i=0; i<numA; i++) {
                  sumA+=valuesA[i];
              }
              for (int i=0; i<numB; i++) {
                  sumB+=valuesB[i];
              }
              return sumA<=sumB;
          }
          void calc() {
              MaxHeap totalHeap(numA);
              MaxHeap* aHeaps=new MaxHeap[numA];
              int totalC=0;
              int totalV=0;

              if(!validate())
              {
                  printf("-1\n");
                  return;
              }
              for (int i=0; i<numA; i++) {

                  aHeaps[i].setSize(numB);
                  for(int j=0;j<numB;j++)
                  {
                      HeapNode node;
                      node.a=i;
                      node.b=j;
                      node.vPerC=(float)values[i][j]/(float)costs[i][j];
                      aHeaps[i].insert(node);
                  }
                  totalHeap.insert(aHeaps[i].removeMax());
              }
              while(!totalHeap.isEmpty())
              {
                  HeapNode node=totalHeap.removeMax();
             
                  if(valuesA[node.a]==valuesB[node.b])
                  {
                      totalV+=values[node.a][node.b]*valuesA[node.a];
                      totalC+=costs[node.a][node.b]*valuesA[node.a];
                      valuesB[node.b]=0;
                      valuesA[node.a]=0;
                     
                  }
                  else if(valuesA[node.a]>valuesB[node.b])
                  {
                      totalV+=values[node.a][node.b]*valuesB[node.b];
                      totalC+=costs[node.a][node.b]*valuesB[node.b];
                      valuesA[node.a]-=valuesB[node.b];
                      valuesB[node.b]=0;
                     
                  }
                  else
                  {
                      totalV+=values[node.a][node.b]*valuesA[node.a];
                      totalC+=costs[node.a][node.b]*valuesA[node.a];
                      valuesB[node.b]-=valuesA[node.a];
                     
                      valuesA[node.a]=0;
                 
                  }
                  while(!aHeaps[node.a].isEmpty())
                  {
                      HeapNode todo=aHeaps[node.a].removeMax();
                      if(valuesA[todo.a]>0&&valuesB[todo.b]>0)
                      {
                          totalHeap.insert(todo);
                          break;
                      }
                  }
              }
              printf("%lf\n",(float)totalV/totalC);
          }
          int main() {
             
              input();
              calc();
             
              return 0;
          }




          posted @ 2008-06-01 18:53 DoubleH 閱讀(2443) | 評論 (0)編輯 收藏

          問題背景

          有一種簡單的網(wǎng)頁判重的方法,通過求兩個網(wǎng)頁內(nèi)容的最長公共子序列(LCS)長度來判定兩個網(wǎng)頁的相似程度。如:
          (網(wǎng)頁A)老師:請用“果然”造句。
          (網(wǎng)頁B)學(xué)生:先吃水果,然后喝汽水……
          它們的最長公共子序列為“果然”,長度為2。注意這里的“子序列”并不要求連續(xù)。

          類似的,下面兩個網(wǎng)頁:
          (網(wǎng)頁A)老師:請用“果然”造句。
          (網(wǎng)頁B)學(xué)生:先吃水果,然后喝汽水,果然拉肚子……

          最長公共子序列還是“果然”,長度為2。但不難看出,由于“果然”兩個字在網(wǎng)頁B中也曾連續(xù)出現(xiàn),第二組網(wǎng)頁比第一組更加“相似”。為了區(qū)分開這兩種情況的區(qū)分度,我們改用一種稱為LZW的理論。為了嚴(yán)格的敘述相似度的計算方法,我們首先定義“文本單元”。

          假定網(wǎng)頁用一個不包含空白字符(空格、回車換行、水平制表符)的字符串來表示。它只包含純文本,沒有標(biāo)簽。在計算相似度之前,你應(yīng)該首先對該字符串進(jìn)行處理,劃分成一個個“文本單元”。每個文本單位可以是一個中文字、英文單詞(由一個或多個連續(xù)的半角英文字母和數(shù)字組成,正規(guī)表達(dá)式為[a-zA-Z0- 9]+)、或者一個標(biāo)點符號。

          根據(jù)上述定義,同一個標(biāo)點符號的全角和半角應(yīng)該被作為不同的文本單元,盡管他們看起來可能很相近;每個單獨全角英文和全角數(shù)字都應(yīng)該被看成一個單獨的文本單元,而連續(xù)的半角英文字母和數(shù)字應(yīng)被看成一個整體。總之,全角的字符可以與中文字同等對待。

          這樣,網(wǎng)頁被看成文本單元序列。例如,網(wǎng)頁“內(nèi)容?123456??web2.00#”切分出的文本單元序列為(為了顯示方便,用下劃線分隔各文本單元):
          內(nèi)_容_?_1_2_345_6_?_?_web2_._00_#

          而網(wǎng)頁“why內(nèi)容相似??1234567890,web#00”的切分結(jié)果為:
          why_內(nèi)_容_相_似_?_?_1234567890_,_web_#_00

          黑體部分給出了兩個網(wǎng)頁的一個公共子序列。注意“內(nèi)容”、“??”分別在兩個網(wǎng)頁中都是連續(xù)出現(xiàn)的文本單元。為了獎勵這種情況,LZW規(guī)定一段由連續(xù)k個文本單元組成的字符串權(quán)值為k^2。在剛才的例子中,“內(nèi)容”、“??”的權(quán)值均為4。但“00”是一個數(shù)字串,應(yīng)當(dāng)被看成一個單獨的文本單元。所以權(quán)值僅為1。

          根據(jù)上述規(guī)則,公共子序列“內(nèi)容 ?? 00”的權(quán)值為2^2+2^2+1=9。在所有可能的子序列中,這個權(quán)值是最大的。

          給定兩個網(wǎng)頁,求他們的LZW相似度,即所有可能的公共子序列中的最大權(quán)值。

          注意

          1) 輸入的網(wǎng)頁內(nèi)容以GBK編碼(參見FAQ)
          2) 除了大小寫英文字母和數(shù)字之外的其他半角字符均視為標(biāo)點符號。
          輸入格式

          包含兩行,分別是網(wǎng)頁A和B對應(yīng)的字符串(不包含空白字符)。每行至少包含5個字節(jié),最多包含200個字節(jié)。
          輸出格式

          輸出僅一行,包含一個整數(shù),為兩個網(wǎng)頁的LZW相似度。
          樣例輸入

          內(nèi)容?123456??web2.00#
          why內(nèi)容相似??1234567890,web#00
          樣例輸出
          9


          解答:
          該題主要分兩部分,一部分就是解析成文本單元,另一部分就是LZW的實現(xiàn),LZW其實是最長公共子序列算法的一個變形。

          //============================================================================
          // Name        : LZW.cpp
          // Author      : Yovn
          // Version     :
          // Copyright   : yovnchine@gmail.com
          //============================================================================

          #include 
          <iostream>
          #include 
          <string>
          #include 
          <cstring>
          using namespace std;

          void parseToLZWLine(const char* in, int inLen, char**& out, int& actualLen) {
              
          int mark=0;
              actualLen
          =0;
              out
          =new char*[inLen];

              
          for (int i=0; i<inLen; i++) {
                  
          char ch=in[i];
                  
          if (ch<0) {
                      
          if (mark<i) {
                          out[actualLen]
          =new char[i-mark+1];
                          strncpy(out[actualLen], in
          +mark, i-mark);
                          out[actualLen][i
          -mark]='\0';
                          actualLen
          ++;
                      }
                      out[actualLen]
          =new char[3];
                      out[actualLen][
          0]=ch;
                      out[actualLen][
          1]=in[++i];
                      out[actualLen][
          2]='\0';
                      actualLen
          ++;

                      mark
          =i+1;
                  } 
          else if ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')) {
                      
          continue;
                  } 
          else//only one case left
                  {
                      
          if (mark<i) {
                          out[actualLen]
          =new char[i-mark+1];
                          strncpy(out[actualLen], in
          +mark, i-mark);
                          out[actualLen][i
          -mark]='\0';
                          actualLen
          ++;

                      }
                      out[actualLen]
          =new char[2];
                      out[actualLen][
          0]=ch;
                      out[actualLen][
          1]='\0';
                      actualLen
          ++;
                      mark
          =i+1;
                  }
              }
              
          if (mark<inLen) {
                  out[actualLen]
          =new char[inLen-mark+1];
                  strncpy(out[actualLen], in
          +mark, inLen-mark);
                  out[actualLen][inLen
          -mark]='\0';
                  actualLen
          ++;

              }
          }
          void printLZWStr(char** lzwStr, int lzwLen) {
              
          for (int i=0; i<lzwLen; i++) {
                  printf(
          "%s", lzwStr[i]);
                  
          if (i<lzwLen-1) {
                      printf(
          "_");
                  }
              }
              printf(
          "\n");
          }
          void freeLZWStr(char** lzwStr, int lzwLen) {
              
          for (int i=0; i<lzwLen; i++) {
                  delete[] lzwStr[i];
              }
              delete[] lzwStr;
          }

          int calcLZW(char** left, int leftLen, char** right, int rightLen) {
              
          //printLZWStr(left, leftLen);
              
          //printLZWStr(right, rightLen);
              int** result=new int*[leftLen+1];
              
          int** len=new int*[leftLen+1];
              
          for (int i=0; i<=leftLen; i++) {
                  result[i]
          =new int[rightLen+1];
                  len[i]
          =new int[rightLen+1];
                  result[i][
          0]=0;
                  len[i][
          0]=0;
              }
              memset(result[
          0], 0, sizeof(int)*(rightLen+1));
              memset(len[
          0], 0, sizeof(int)*(rightLen+1));
              
          for (int i=1; i<=leftLen; i++) {
                  
          for (int j=1; j<=rightLen; j++) {
                      
          if (strcmp(left[i-1], right[j-1])==0) {
                          
          //back trace one

                          len[i][j]
          =len[i-1][j-1]+1;
                          result[i][j]
          =result[i-1][j-1]-(len[i-1][j-1]*len[i-1][j-1])
                                  
          +(len[i][j]*len[i][j]);

                      } 
          else if (result[i-1][j]>=result[i][j-1]) {
                          result[i][j]
          =result[i-1][j];
                      } 
          else {
                          result[i][j]
          =result[i][j-1];
                      }

                  }
              }

              
          int ret= result[leftLen][rightLen];
              
          for (int i=0; i<=leftLen; i++) {
                  delete[] result[i];
                  delete[] len[i];

              }
              delete[] result;
              delete[] len;
              
          return ret;

          }

          int main() {
              
          char** lzwStr1=NULL;
              
          char** lzwStr2=NULL;
              string str1;
              string str2;
              
          int lzwLen1=0;
              
          int lzwLen2=0;
              getline(cin,str1);
              getline(cin,str2);
              
              parseToLZWLine(str1.c_str(), strlen(str1.c_str()), lzwStr1, lzwLen1);
              parseToLZWLine(str2.c_str(), strlen(str2.c_str()), lzwStr2, lzwLen2);

              cout
          <<calcLZW(lzwStr1, lzwLen1, lzwStr2, lzwLen2)<<endl;

              freeLZWStr(lzwStr1, lzwLen1);
              freeLZWStr(lzwStr2, lzwLen2);

              
          return 0;
          }



          posted @ 2008-05-31 23:20 DoubleH 閱讀(2427) | 評論 (3)編輯 收藏

          如果Web服務(wù)器需要頻繁傳送文件給客戶端時,大多數(shù)web容器會提供異步發(fā)送的支持,像IIS中的通過ServerSupportFunction(),Apache里面apr_sendfile(),Tomcat6.X通過設(shè)置Servlet Request的請求屬性等等。。。都可以做到異步發(fā)送文件,從而提高服務(wù)器性能。

          Jetty6.X默認(rèn)也不提供相關(guān)支持,本文提供一種hack方法,僅供參考:

          先看測試Servlet:
          package com.yovn.labs.testweb;

          import java.io.File;
          import java.io.IOException;

          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServlet;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;

          import com.yovn.labs.sendfile.JettySendFile;
          import com.yovn.labs.sendfile.NormalSendFile;
          import com.yovn.labs.sendfile.SendFile;

          /**
           * 
          @author yovn
           *
           
          */
          public class SendFileServlet extends HttpServlet {

              
          protected void doGet(HttpServletRequest req, HttpServletResponse res)
                      
          throws ServletException, IOException {
              
                  
                  
          try {
                      
                      File f
          =new File("D:\\workspace\\TEST.rar");//about 45M
                      String action
          =req.getParameter("action");
                      SendFile sf
          =null;
                      
          if("1".equals(action))
                      {
                          sf
          =new JettySendFile();
                      }
                      
          else
                      {
                          sf
          =new NormalSendFile();
                      }
                      
          long start=System.currentTimeMillis();
                      sf.doSend(req, res, f, 
          null);
                      System.out.println(
          " service ok, action="+action+",use:"+(System.currentTimeMillis()-start)+"!!!");
                  } 
          catch (Exception e) {
                      
          throw new ServletException(e);
                  }
                
              }
              
              

          }
          代碼很簡單明了,action=1時使用Jetty的異步發(fā)送,action=2時使用正常方式。

          下面是通過firefox直輸入地址回車后,下載文件,后臺的程序運行結(jié)果:
           service ok, action=1,use:62!!!
           service ok, action
          =2,use:10688!!!
           service ok, action
          =2,use:9063!!!
           service ok, action
          =1,use:47!!!
          當(dāng)運行1時,實際上客戶端還沒有下完文件,但是該段代碼已經(jīng)執(zhí)行完了,IO的操作是異步的。
          當(dāng)運行2時,客戶端下完代碼才執(zhí)行完。

          以下是Jetty異步發(fā)送的代碼:
          package com.yovn.labs.sendfile;

          import java.io.File;
          import java.io.IOException;
          import java.lang.reflect.Field;

          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;

          import org.mortbay.io.EndPoint;
          import org.mortbay.io.nio.NIOBuffer;

          /**
           * 
          @author yovn
           *
           
          */
          public class JettySendFile implements SendFile {

              
          static Field endpointField=null;
              
          static Class reqCls=null;
              
          static 
              {
                  
          try {
                      reqCls
          =Class.forName("org.mortbay.jetty.Request");
                      endpointField
          =reqCls.getDeclaredField("_endp");
                      endpointField.setAccessible(
          true);
                  } 
          catch (Exception e) {
                      
          // TODO Auto-generated catch block
                      e.printStackTrace();
                  } 
              }
                  
              
              


              
          public void doSend(HttpServletRequest req, HttpServletResponse res,File todo,String headerOpt)
                      
          throws IOException {
                  
                  
          if(endpointField==null)throw new IOException("Jetty Not Available!!");
                  
          if(!req.getClass().equals(reqCls))
                  {
                      
          throw new IOException("Not in Jetty Context!!");
                  }
                  EndPoint ep;
                  
          try {
                      ep 
          = (EndPoint)endpointField.get(req);
                  
                      
          if(headerOpt==null)
                      {
                          headerOpt
          ="HTTP/1.1 200 OK \r\nContent-Type: APPLICATION/OCTET-STREAM\r\n"+
                                
          "Content-Disposition: attachment;filename=\""+todo.getName()+"\"\r\n"+
                                
          "Content-Length: "+todo.length()+"\r\n\r\n";
                      }
                      
          byte[] headerBytes=headerOpt.getBytes("UTF-8");
                      NIOBuffer header
          =new NIOBuffer(headerBytes.length,false);
                      header.put(headerBytes);
                      
                      NIOBuffer buffer
          =new NIOBuffer(todo);
                      
                      ep.flush(header, buffer, 
          null);
                  } 
          catch (IllegalArgumentException e) {
                      
          throw new IOException(e);
                  } 
          catch (IllegalAccessException e) {
                      
          throw new IOException(e);
                  }
                  
                  
                  
              }

          }

          正常發(fā)送文件的代碼:
          package com.yovn.labs.sendfile;

          import java.io.File;
          import java.io.FileInputStream;
          import java.io.IOException;
          import java.io.InputStream;
          import java.io.OutputStream;

          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;

          /**
           * 
          @author yovn
           *
           
          */
          public class NormalSendFile implements SendFile {

              
          /* (non-Javadoc)
               * We simply ignore the 'headerOpt'
               * @see com.yovn.labs.sendfile.SendFile#doSend(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.io.File, java.lang.String)
               
          */
              
          public void doSend(HttpServletRequest req, HttpServletResponse res,
                      File todo, String headerOpt) 
          throws IOException {
                  res.setHeader(
          "Content-Type""APPLICATION/OCTET-STREAM");
                  res.setHeader(
          "Content-Disposition""attachment;filename=\""+todo.getName()+"\"");
                  res.setHeader(
          "Content-Length", todo.length()+"");
                  res.setStatus(HttpServletResponse.SC_OK);
                  OutputStream out
          =res.getOutputStream();
                  InputStream in
          =new FileInputStream(todo);
                  
                  
          byte[] buffer=new byte[8192];
                  
                  
          int read=0;
                  
          while((read=in.read(buffer))>0)
                  {
                      out.write(buffer, 
          0, read);
                  }
                  out.flush();
                  in.close();
                  
                  

              }

          }


          posted @ 2008-03-29 01:54 DoubleH 閱讀(1769) | 評論 (0)編輯 收藏

          過道里依次掛著標(biāo)號是1,2,3, ......,100的電燈泡,開始它們
          都是滅著的。當(dāng)?shù)谝粋€人走過時,他將標(biāo)號為 1 的倍數(shù)的電燈泡的開關(guān)
          線拉了一下;當(dāng)?shù)诙€人走過時,他將標(biāo)號為 2 的倍數(shù)的電燈泡的開關(guān)
          線拉了一下;當(dāng)?shù)谌齻€人走過時,他將標(biāo)號為 3 的倍數(shù)的電燈泡的開關(guān)
          線拉了一下;......  如此進(jìn)行下去,當(dāng)?shù)谝话賯€人走過時,他將標(biāo)號為
          100 的倍數(shù)的電燈泡的開關(guān)線拉了一下。
          問:當(dāng)?shù)谝话賯€人走過后,過道里亮著的電燈泡標(biāo)號是多少?


          我的思路:
          設(shè)標(biāo)號為K的燈泡被拉了L(K)次,那么當(dāng)L(K)為奇數(shù)的時候,燈泡是亮的。
          那么那些標(biāo)號被拉了奇數(shù)次呢?
          K=1時,很顯然是只拉了1次,最后是亮的。
          其次K>=2時,據(jù)題意,K號燈第1次,和第K次肯定是拉下了,其余的只會被第K的因子次拉,
          據(jù)因式分解定理,數(shù)K分解為
          K=p1^(n1)*p2^(n2)*.....pi^(ni)
          其中p1,p2,...pi為素數(shù)。
          那么,K有那些因子呢?
          其實可以考慮任一個因子,他可能是從n1個p1中選若干個(0個到n1個),從n2個p2中選若干個。。。。。(當(dāng)全是0個的時候,這個特殊的因子是1)
          這樣,根據(jù)乘法原理,總共有L(K)=(n1+1)*(n2+1)*(n3+1).....
          比如,12=2^2*3
          一種有3*2=6個因子,他們是1,2,3,4,6,12.

          現(xiàn)在考慮要使L(K)為奇數(shù),那么n1,n2,n3不能有一個是奇數(shù),或則,有一個ni+1為偶數(shù),而偶數(shù)與任何數(shù)相乘仍為偶數(shù)。
          從而,n1,n2,n3都為偶數(shù),都能被2除。
          因為n1,n2,n3都為偶數(shù),顯然該數(shù)必須是個平方數(shù),可寫成K=(X)^2.
          從而,1,4,9,16,25,36,49,64,81,100最后是亮的。

          posted @ 2008-03-05 15:00 DoubleH 閱讀(2133) | 評論 (7)編輯 收藏

          去年也大概是這個時候?qū)懥说谝粋€Java2EXE,之后又加了寫特性,但是每次我看代碼都感覺慘不忍睹,很混亂,而且編譯,鏈接的過程也有點繞。
          現(xiàn)在又過了一年了,如果說上次版本的Load過程主要是靠Java(Java加密,解壓),那么這次基本把這些費時的操作全交給CPP了。
          好了,總結(jié)一下這次的改動
          1)Loader以及Starter完全是CPP代碼,結(jié)構(gòu)很清晰了。
          2)加密以及解壓交給CPP,速度比以前快了。
          3)整合了JNative,這個是重點,下文詳述。
          4)生成工具用MFC寫,一個簡單的向?qū)А?br />
          OK,那么JNative是干什么的呢?
          官方的描述是 “JNative, Java framework for DLL access for Windows and Linux”
          就是說,有了這個框架,你訪問DLL里的方法就不再需要寫DLL了,只需要寫Java Code了,可能有人問它是怎么做到的呢?
          假如說你要訪問Kernel32.dll里的某個方法A,你首先需要這個方法的句柄,這個句柄就是通過new一個org.xvolks.jnative.JNative實例來保持的,
          類似如:
          org.xvolks.jnative.Native methodA=new org.xvolks.jnative.JNative("Kernel32.dll","A");
          有了這個句柄,你只要在上面設(shè)置參數(shù),返回值,以及類型就可以調(diào)用它了。每個調(diào)用它上面的JNI里的本地方法就會自動來進(jìn)行參數(shù)解析,解碼,調(diào)用到目標(biāo)DLL方法,這個過程基本不可避免需要少量的匯編代碼。
          JNative為了可移植性,代碼是在Cygwin下可編譯的,沒有MSVC可編譯的版本。

          對此,本人改了部分代碼用于直接一起鏈接(主要是把GCC嵌入?yún)R編改為對應(yīng)的MSVC的嵌入?yún)R編代碼),而不是讓JNative生成一個動態(tài)鏈接庫。

          如上,由于JNative改成了靜態(tài)庫,程序發(fā)布的時候,只要是通過Java2EXE Builder來創(chuàng)建成EXE的話,你就不需要那個JNativeCpp.dll文件了,只有一個EXE.

          你調(diào)試的時候可以用官方的版本,發(fā)布就只要你的代碼(JNative的class也都在集成在生成工具里,不需要你自己添加進(jìn)來)。

          來看個簡單的例子,我們從Java代碼里取得當(dāng)前進(jìn)程的全路徑名:
          import org.xvolks.jnative.JNative;
          import org.xvolks.jnative.Type;
          import org.xvolks.jnative.exceptions.NativeException;
          import org.xvolks.jnative.pointers.Pointer;
          import org.xvolks.jnative.pointers.memory.HeapMemoryBlock;

          /**
           * DWORD GetModuleFileName(
           * HMODULE hModule,
           * LPTSTR lpFilename,
           * DWORD nSize
           *);

           * 
          @author yovn
           *
           
          */
          public class TestReadProcessPath {

              
          /**
               * 
               * 
          @param args
               * 
          @throws NativeException 
               * 
          @throws IllegalAccessException 
               
          */
              
          public static void main(String[] args) throws NativeException, IllegalAccessException {
                  JNative v
          =new JNative("Kernel32.dll","GetModuleFileNameA");
                  
          int i = 0;
                  v.setRetVal(Type.INT);
                  Pointer pName 
          = new Pointer(new HeapMemoryBlock(1024));
                  
                  v.setParameter(i
          ++0);//module handle
                  v.setParameter(i++, pName);//pFileName
                  v.setParameter(i++1024);//nSize
                  v.setRetVal(Type.INT);
                  v.invoke();
                  
          int ret = Integer.parseInt(v.getRetVal());
                  
          if (ret == 0) {
                      
          // return "null";
                      System.err.println(
                              
          "GetModuleFileName failed!");
                  } 
          else {
                      
                      String path 
          = pName.getAsString().substring(0,
                              ret);
                      pName.dispose();
                      v.dispose();
                      System.out.println(
          "current process's path is:"+path);
                  }
              }

          }

          編譯,把這個文件單獨打包成一個jar文件,下面是個用這個工具生成EXE的截圖:
          生成EXE向?qū)У谝徊?/a>
          生成 EXE向?qū)У诙?/a>



          請從這里下載
          Java2EXE Builder Platform











          posted @ 2008-02-26 00:31 DoubleH 閱讀(1817) | 評論 (7)編輯 收藏

               摘要: 紅黑樹可能是要考慮情況最多的BST樹了,它有自己的規(guī)則(見代碼的注釋),通過這些規(guī)則可以保證花費較小的代價來達(dá)到相對平衡。 注意,紅黑樹仍然不是平衡樹,但是統(tǒng)計性能要好于AVL樹。 要保持紅黑樹的規(guī)則,主要通過兩類操作,一類是換色,一類還是旋轉(zhuǎn)。 紅黑樹插入主要要解決紅-紅沖突,而刪除主要則解決“雙黑” 同樣,紅黑樹的刪除節(jié)點實現(xiàn)是最復(fù)雜的,不過,復(fù)雜也就在于考...  閱讀全文
          posted @ 2007-12-20 18:25 DoubleH 閱讀(8496) | 評論 (20)編輯 收藏

               摘要: 伸展樹與半伸展樹屬于自組織的數(shù)據(jù)結(jié)構(gòu),能按訪問頻率調(diào)整節(jié)點的位置 調(diào)整一般通過如下方式: 1)繞根的單旋轉(zhuǎn),跟AVL的單旋轉(zhuǎn)類似 2)一字型旋轉(zhuǎn)(ZigZig Rotation) 3)之字形旋轉(zhuǎn)(ZigZag Rotation) 旋轉(zhuǎn)操作較簡單,有點點繁瑣。 半伸展樹不做完全的一字型旋轉(zhuǎn),它只讓父節(jié)點繞祖父節(jié)點做單旋轉(zhuǎn)。 不管怎樣,每次訪問(插入/查找 ,刪除時展開被刪除父節(jié)...  閱讀全文
          posted @ 2007-12-19 00:39 DoubleH 閱讀(2418) | 評論 (0)編輯 收藏

               摘要: AVL樹的是一種平衡的二叉搜索樹。每次插入,刪除的時候需要一個局部的平衡化操作。 實現(xiàn)AVL樹的插入操作一般不是很難,清楚的理解了平衡因子以及旋轉(zhuǎn)操作實現(xiàn)起來就沒多大問題了。 難點一般在于刪除操作的實現(xiàn),教科書上一般用很大的篇幅來詳細(xì)說明各種情況,看起來很凌亂,理解起來很是費勁。考慮到可以把刪除操作看成插入操作的逆操作,這里我給出另一種較為清晰的實現(xiàn)方式: 1)刪除的時候做一個標(biāo)記的過程 ...  閱讀全文
          posted @ 2007-12-18 18:30 DoubleH 閱讀(3625) | 評論 (0)編輯 收藏

          僅列出標(biāo)題
          共5頁: 上一頁 1 2 3 4 5 下一頁 
          主站蜘蛛池模板: 台东县| 舟山市| 台中市| 长宁县| 亳州市| 尉氏县| 赤峰市| 瓦房店市| 宁强县| 公安县| 宝坻区| 阳西县| 庄浪县| 仁寿县| 潼关县| 揭东县| 沧源| 东宁县| 洪雅县| 自贡市| 门源| 西贡区| 宣威市| 德令哈市| 西青区| 玛沁县| 宜昌市| 鲁山县| 集贤县| 胶南市| 承德市| 海晏县| 眉山市| 商都县| 陆河县| 丰镇市| 奉新县| 叶城县| 雷州市| 财经| 德安县|