其中有一些連結提到 JDBM 這個函式庫,因此就來嘗試看看了。
JDBM 本質上其實並不是實作資料結構的函式庫,而是要做一個 Java 版的資料庫系統
具有 B+-tree 只不過是因為他的資料庫系統會用到的關係。
JDBM 目前看起來有分 JDBM 到 JDBM4 總共四個版本,從原始碼的註記來看,JDBM2、JDBM3 似乎換作者了。
而 JDBM [1]、JDBM2 [2] 和 JDBM3 [3] 的差異在哪裡我也不是很確定~
光看專案的描述來說,JDBM2 有做一些效能調校,但調校的部份不知道在哪~
而 JDBM3 看起來好像多了不少 feature,像是它有特別提出它的 serialization 有客製化,可以提昇讀寫的效率
不過從 JDBM 到 JDBM3,整個函式庫的用法都不太一樣就是了。
舉例來說,JDBM 初始化時是用 RecordManager,可以單獨初始化 B+-tree
但到了 JDBM3 好像一定要用 DBMaker 去創建資料庫,而且看來沒辦法單獨抽 B+-tree 出來
因為 JDBM3 的 B+-tree 的 class 並沒有宣告 public...。
另外,JDBM 的 License 是 BSD Licence(參照 JDBM 的 SourceForge 頁面標示)
而 JDBM2 和 JDBM3 則是 Apache 2.0 Licence。
這裡先用 JDBM 來嘗試使用它的 B+-tree。
以下的範例程式碼是參考 JDBM 官方的 B+-tree 範例 FamousPeople
import java.io.IOException;
import jdbm.RecordManager;
import jdbm.RecordManagerFactory;
import jdbm.btree.BTree;
import jdbm.helper.StringComparator;
import jdbm.helper.Tuple;
import jdbm.helper.TupleBrowser;
public class FamousPeople {
static String[] people =
{ "Greenspan, Alan",
"Williams-Byrd, Julie",
"Picasso, Pablo",
"Stallman, Richard",
"Fort, Paul",
"Søndergaard, Ole",
"Schwarzenegger, Arnold",
"Dulkinys, Susanna" };
static String[] occupations =
{ "Federal Reserve Board Chairman",
"Engineer",
"Painter",
"Programmer",
"Poet",
"Typographer",
"Actor",
"Designer" };
static String DATABASE = "people";
static String BTREE_NAME = "FamousPeople";
public static void main(String[] args) {
RecordManager rm = null;
BTree tree = null;
try {
rm = RecordManagerFactory.createRecordManager(DATABASE);
long recordId = rm.getNamedObject(BTREE_NAME);
if(recordId == 0) {
tree = BTree.createInstance( rm, new StringComparator() );
rm.setNamedObject( BTREE_NAME, tree.getRecid() );
// insert people with their respective occupation
System.out.println();
for ( int i=0; i<people.length; i++ ) {
System.out.println( "Insert: " + people[i] );
tree.insert( people[ i ], occupations[ i ], false );
}
// make the data persistent in the database
rm.commit();
}
else {
tree = BTree.load(rm, recordId);
}
System.out.println("getNamedObject: " + recordId);
// Find a record.
tree = BTree.load(rm, recordId);
Object result = tree.find("Greenspan, Alan");
if(result == null)
System.out.println("Not found.");
else {
System.out.println(result.toString());
}
// Traverse all the records.
tree = BTree.load(rm, recordId);
TupleBrowser browser = tree.browse();
Tuple tuple = new Tuple();
System.out.println("Traverse:");
while(browser.getNext(tuple)) {
System.out.println(tuple.getKey().toString());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}簡要來說,在 38~39 行呼叫 RecordManager.getNamedObject() 函式,會嘗試去尋找指定名稱的 BTree 檔案
(實際上是資料庫檔案,不過因為我只在裡面存 B+-tree,所以就直接稱為 BTree 檔案吧)
如果檔案不存在會回傳 0,這時就要重新建立 Btree 檔案(42~43 行)。
而要讀取已經存在的 BTree 檔案時,就呼叫 BTree.load() 函式(55 行)。
取得 BTree 之後,自然就可以用 find()或 browse() 函式去搜尋 B+-tree 裡的資料
要插入資料到 B+-tree 裡面則是用 insert() 函式。
PS. find() 可參考 60~67 行、browse() 可參考 69~76 行、insert() 可參考 47~52 行
關於檔案儲存的問題,JDBM 函式庫預設是直接將檔案儲存在跟 Java 執行路徑相同的目錄下
如果要改變的話,可以直接在指定檔案名稱時給完整的路徑,或者去修改儲存檔案的原始碼~
修改的位置在 RecordFile.java 檔案中的 98 行:
file = new RandomAccessFile(fileName + extension, "rw");
有關 JDBM 的效率討論,可以看一下 SourceForge 上的討論
例如 [4] 是一個討論有關 JDBM 的 H+-tree 有沒有 memory leak 問題的討論。
PS. 使用 JDBM3 取出 B+-tree 的方法請參閱下一篇文章「B+-tree implementation:JDBM3」
參考資料:
1、JDBM
2、JDBM2
3、JDBM3
4、JDBM discussion:HTree memory not released
沒有留言:
張貼留言