《Lucene天書》 Lucene的檔案系統

來源:互聯網
上載者:User

Lucene的檔案系統分為記憶體和硬碟兩個部分,檔案邏輯組織方式暫且不提,本文將關注其物理結構,包括它在記憶體中如何存放,以及如何寫入硬碟。

目錄
一、相關類
   1.1 Directory
   1.2 IndexInput和IndexOutput
   1.3 RAMFile
二、索引概述
   2.1 IndexOutput
 2.2 RAMOutputStream和RAMFile
   2.3 記憶體檔案是如何寫入硬碟的

一、相關類

1.1 Directory
一個Directory在Lucene系統中可以被稱為“一份索引”,可以有許多份索引共同提供搜尋資料來源,而一個Directory就是對其每份索引的描述。它可以存放在記憶體中,也可以存放於硬碟上。存放在記憶體中的時候,是使用它子類RAMDirectory的執行個體,存放在硬碟上的時候是使用FSDirectory的執行個體。

圖 1.1.1 Directory類圖

1.2 IndexInput和IndexOutput
IndexInput負責讀取,IndexOutput負責寫入。其子類負責具體的工作。這裡暫且不多講。


圖1.2.1 IndexOutput和IndexInput

1.3 RAMFile
RAMFile是Lucene檔案系統記憶體檔案的基本單位。一個Directory可以包含N個RAMFile(N >= 2)。

二、索引概述
這裡不討論索引的邏輯結構,而只單純地看索引是如何在記憶體中儲存,如何持久化到硬碟。


圖 2.1 索引過程

圖2.1體現整個過程。首先調用IndexWriter類的AddDocument方法,這個是外部調用,走入內部,是由IndexWriter調用了DocumentWriter的AddDocument方法。然後DocumentWriter完成調用自身的UpdateDocument,ProcessDocument,ProcessField方法,再轉入FieldWriter的WriteField方法,這個方法又調用了IndexOutput裡WriteInt或者其它一些按類型寫入的方法,最終由RAMOutputStream調用自身的WriteByte寫入記憶體。(IndexOutput裡的方法實際存在於RAMOutputStream的執行個體。)

2.1 IndexOutput
IndexOutput主要定義了一些按類型寫入的方法,最終都會走向虛方法WriteByte。這些方法在我寫的解讀Lucene中都有講到。值得一提的是WriteChars方法,這個方法看似很複雜,但是其完成的功能卻很簡單,其實是做了.Net Framework中的Encoding.UTF8.GetBytes方法的工作。看下代碼2.1.1和2.1.2的相似之處就可以明白。(代碼2.1.1摘自Lucene IndexOutput源碼,2.1.2摘自.Net Framework UTF8Encoding類源碼。其自己實現是因為翻譯自Java版本。)

代碼 2.1.1
public virtual void  WriteChars(char[] s, int start, int length)
{
    int end = start + length;
    for (int i = start; i < end; i++)
    {
        int code = (int) s[i];
        if (code >= 0x01 && code <= 0x7F)
            WriteByte((byte) code);
        else if (((code >= 0x80) && (code <= 0x7FF)) || code == 0)
        {
            WriteByte((byte) (0xC0 | (code >> 6)));
            WriteByte((byte) (0x80 | (code & 0x3F)));
        }
        else
        {
            WriteByte((byte) (0xE0 | (SupportClass.Number.URShift(code, 12))));
            WriteByte((byte) (0x80 | ((code >> 6) & 0x3F)));
            WriteByte((byte) (0x80 | (code & 0x3F)));
        }
    }
}

 

代碼 2.1.2
// Count bytes needed 
int bytesNeeded = 1;
if (ch > 0x7F) {
    if (ch > 0x7FF) {
        if (ch > 0xFFFF) { 
            bytesNeeded++;  // 4 bytes (surrogate pair)
        } 
        bytesNeeded++;      // 3 bytes (800-FFFF) 
    }
    bytesNeeded++;          // 2 bytes (80-7FF) 
}

if (ch <= 0x7F) { 
    *pTarget = (byte)ch; 
}
else { 
    // use separate helper variables for local contexts so that the jit optimizations
    // won't get confused about the variable lifetimes
    int chb;
    if (ch <= 0x7FF) { 
        // 2 byte encoding
        chb = (byte)(unchecked((sbyte)0xC0) | (ch >> 6)); 
    } 
    else
    { 
        if (ch <= 0xFFFF) {
            chb = (byte)(unchecked((sbyte)0xE0) | (ch >> 12));
        }
        else 
        {
            *pTarget = (byte)(unchecked((sbyte)0xF0) | (ch >> 18)); 
            pTarget++; 

            chb = unchecked((sbyte)0x80) | (ch >> 12) & 0x3F; 
        }
        *pTarget = (byte)chb;
        pTarget++;

        chb = unchecked((sbyte)0x80) | (ch >> 6) & 0x3F;
    } 
    *pTarget = (byte)chb; 
    pTarget++;

    *pTarget = (byte)(unchecked((sbyte)0x80) | ch & 0x3F);
}

2.2 RAMOutputStream和RAMFile
RAMOutputStream是IndexOutput的一個子類,其主要點在於三個元素。
1、BUFFER_SIZE 是其緩衝片段的長度;
2、RAMFile 記憶體檔案執行個體;
3、它的一些方法。
它的方法最終都是完成把資料寫入緩衝片段,再把緩衝片段存入RAMFile的執行個體。它們之間就是這個關係。
RAMOutputStream需要寫入資料,最終會寫入一個byte數組,這個數組的長度就是BUFFER_SIZE,由RAMOutputStream調用RAMFile的AddBuffer方法負責建立這個數組,同時把這個數組作為一個節點存入RAMFile的ArrayList。也就是說RAMFile代表的一個記憶體檔案,實際上是一個ArrayList數組。而ArrayList數組的每個索引又都由一個byte數組組成,這個byte數組的長度是BUFFER_SIZE。RAMOutputStream的WriteByte方法負責把資料寫入byte數組。(看到這個是不是覺得Lucene的檔案系統根本就不是什麼天書嘛,也是很好理解的嘛,呵呵。)

2.3 記憶體檔案如何寫入硬碟的
Lucene檔案系統在硬碟的表現執行個體就是FSDirectory。這個類會負責建立其檔案系統所需的描述性檔案和資料檔案。而具體寫入硬碟的工作是由它的內嵌類FSIndexOutput來完成的。這也就是我們的圖1.2.1沒有描繪到這個類的原因,這個類繼承自BufferedIndexOutput。BufferedIndexOutput大體上與RAMOutputStream差不多,區別在於其Flush方法與會調用到FSIndexOutput的FlushBuffer方法,最終把RAMFile的資料寫入硬碟檔案。

時間原因,這裡就不詳細介紹了,感興趣的朋友可以自己去實驗一下。

______________________________________________________________________________________________
2009-2-18 by yurow
@ http://birdshover.cnblogs.com

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.