1. 程式人生 > >lighttpd1.4.18中的stat_cache

lighttpd1.4.18中的stat_cache

這個cache主要是針對stat()函式呼叫結果的一個cache,這麼做有兩個考慮,一個當然是快取stat()函式呼叫的結果,比如需要向客戶端傳送一個檔案的內容時,需要知道這個檔案的尺寸,一般都是通過stat()呼叫得來;如果僅僅是這樣,那似乎這個cache是沒有太大必要的,所以還有第二層的考量,http協議中有一個所謂的etag的概念,比如你接收了一個檔案,http協議中帶了一個欄位last-modified存放這個檔案請求的時間,同時有針對這個檔案的etag值,下一次再次請求時,如果該檔案沒有更新過,那麼直接使用客戶端瀏覽器中快取的結果即可.有關這部分的內容可以參考這裡. 這裡,關於"檔案是否被更改過",在lighttpd中,有三種判斷的標準,分別是typedef enum { ETAG_USE_INODE = 1, ETAG_USE_MTIME = 2, ETAG_USE_SIZE = 4 } etag_flags_t; 簡單的理解,就是從inode number值,mtime(修改時間),檔案尺寸三種標準來判斷,而這些,都是可以從stat函式的返回值也就是stat 結構體中獲得的.

下面來具體看這個cache的實現,我也不貼程式碼了,還是看虛擬碼好了,關於這部分實現,可以看lighttpd中的stat_cache.c檔案:
根據查詢的檔名算出一個hash值,
根據這個hash值去sptree中搜索,這個結構體中cache住之前查詢的結果
假如可以在cache中找到記錄,還要將記錄的時間與伺服器當前的時間做比較,如果一致才認為是找到了cache,返回結果.

程式繼續往下走,這個時候只有兩種可能,一種是沒有找到,另一種找到了但是時間不對應,因此很可能cache中的資訊已經過期了.
此時,需要到檔案所在的目錄去查詢,對於快取目錄結果的cache而言,如果找到了需要檢視快取資料的版本號,以這個來定義是否一致
假如找到了目錄資訊,版本號也一致,並且之前也找到了檔案的cache,那麼認為cache中快取的檔案資訊沒有過時,返回結果.

程式繼續往下走,此時可以確定cache中要麼是沒有要找的資訊,要麼是資訊過期.
這時需要真正呼叫stat()函式獲取檔案相關的資訊,並且插入到cache中,
同時,如果檔案的目錄資訊之前是沒有的,也需要將檔案所在目錄的資訊插入到cache中,同時儲存cache資料的當前時間點.

最後,還需要針對etag做一些處理,根據之前說的etag型別將相關資訊存放到cache中,這裡只需要etag值不會重複就可以.


提到cache目錄資訊這一點,lighttpd採用了FAM的API,使用這個API,可以把需要監控是否發生變化的目錄加入到一個集合中,這個集合可以對應一個fd,這樣,就可以select/epoll等多路複用I/O處理器在檔案目錄情況發生變化的時候去非同步通知伺服器更新cache中關於該目錄的情況了.

關於FAM API,可以參考這裡:
http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650&db=bks&fname=/SGI_Developer/books/IIDsktp_IG/sgi_html/ch08.html