Lucene(2.4.1)技術研究(5)--IndexWrite類源代碼解析(四)RAMDirectory介紹
Posted on 2009-05-08 13:56 天空蒼茫 閱讀(1605) 評論(0) 編輯 收藏 所屬分類: java知識 RAMDirectory是Directory抽象類在使用內存最為文件存儲的實現類,其主要是將所有的索引文件保存到內存中。這樣可以提高效率。但是如果索引文件過大的話,則會導致內存不足,因此,小型的系統推薦使用,如果大型的,索引文件達到G級別上,推薦使用FSDirectory
首先我們看看該類的源代碼:
首先該類繼承與抽象類Directory,并且實現了序列話接口
1
/**一個對于Directory的內存實現的類,鎖工廠是有SingleInstanceLockFactory來實現,但是鎖工廠可以更改 */
2
public class RAMDirectory extends Directory implements Serializable {
3
private static final long serialVersionUID = 1l;
4
HashMap fileMap = new HashMap(); //首先定了保存文件名以及的Map
5
long sizeInBytes = 0; //文件占用的字節數
6
/** 構造函數。指定LockFactory為該類的一個實例SingleInstanceLockFactory,SingleInstanceLockFactory類的特點是,所有的加鎖操作必須通過該SingleInstanceLockFactory的一個實例而發生,也就是說,在進行加鎖操作的時候,必須獲取到這個SingleInstanceLockFactory的實例*/
7
public RAMDirectory() {
8
setLockFactory(new SingleInstanceLockFactory());
9
}
10
/** 定義一個新的RAMDirectory,并且指定其目錄,這個做的目的可以將一個文件系統的索引加載到內存中,這個只能使用在該索引能夠被全部加在到內存中。這次只是將系統文件的索引拷貝一份到內存中,加載后,系統文件索引發生變化,將不會在該實例中體現。 */
11
public RAMDirectory(Directory dir) throws IOException {
12
this(dir, false);
13
}
14
/** 根據目錄,以及參數將該目錄中的所有文件復制到內存中,需要復制的文件已經存在,則直接覆蓋。closeDir表示是否關閉源目錄*/
15
private RAMDirectory(Directory dir, boolean closeDir) throws IOException {
16
this();
17
Directory.copy(dir, this, closeDir);
18
}
19
/**根據提供的文件路徑,將該文件路徑下的所有的文件復制到內存中,并且創建一個RAMDirectory對象。如果需要復制的對象已經存在,則覆蓋原來的文件*/
20
public RAMDirectory(File dir) throws IOException {
21
this(FSDirectory.getDirectory(dir), true);
22
}
23
/**根據提供的String路徑,將該文件路徑下的所有的文件復制到內存中,并且創建一個RAMDirectory對象。如果需要復制的對象已經存在,則覆蓋原來的文件*/
24
public RAMDirectory(String dir) throws IOException {
25
this(FSDirectory.getDirectory(dir), true);
26
}
27
/**返回所有該文件該內存索引中的所有文件 */
28
public synchronized final String[] list() {
29
ensureOpen();
30
Set fileNames = fileMap.keySet(); //該文件的所有key
31
String[] result = new String[fileNames.size()];
32
int i = 0;
33
Iterator it = fileNames.iterator();
34
while (it.hasNext())
35
result[i++] = (String)it.next();
36
return result;
37
}
38
/**如果指定文件名的文件在索引中存在,則返回true,否則返回false*/
39
public final boolean fileExists(String name) {
40
ensureOpen();
41
RAMFile file;
42
synchronized (this) {
43
file = (RAMFile)fileMap.get(name);
44
}
45
return file != null;
46
}
47
/**返回指定文件最后的修改時間 */
48
public final long fileModified(String name) throws IOException {
49
ensureOpen();
50
RAMFile file;
51
synchronized (this) {
52
file = (RAMFile)fileMap.get(name);
53
}
54
if (file==null)
55
throw new FileNotFoundException(name);
56
return file.getLastModified();
57
}
58
/**將指定文件的最后修改時間設置為現在 */
59
public void touchFile(String name) throws IOException {
60
ensureOpen();
61
RAMFile file;
62
synchronized (this) {
63
file = (RAMFile)fileMap.get(name);
64
}
65
if (file==null)
66
throw new FileNotFoundException(name);
67
68
long ts2, ts1 = System.currentTimeMillis();
69
do {
70
try {
71
Thread.sleep(0, 1);
72
} catch (InterruptedException e) {}
73
ts2 = System.currentTimeMillis();
74
} while(ts1 == ts2);
75
76
file.setLastModified(ts2);
77
}
78
/** 返回指定文件的大小*/
79
public final long fileLength(String name) throws IOException {
80
ensureOpen();
81
RAMFile file;
82
synchronized (this) {
83
file = (RAMFile)fileMap.get(name);
84
}
85
if (file==null)
86
throw new FileNotFoundException(name);
87
return file.getLength();
88
}
89
90
/** 返回當前目錄中所有的文件大小*/
91
public synchronized final long sizeInBytes() {
92
ensureOpen();
93
return sizeInBytes;
94
}
95
/** 刪除指定文件名的文件*/
96
public synchronized void deleteFile(String name) throws IOException {
97
ensureOpen();
98
RAMFile file = (RAMFile)fileMap.get(name);
99
if (file!=null) {
100
fileMap.remove(name);
101
file.directory = null;
102
sizeInBytes -= file.sizeInBytes; // updates to RAMFile.sizeInBytes synchronized on directory
103
} else
104
throw new FileNotFoundException(name);
105
}
106
/**根據制定的名稱,創建一個空文件,并且返回操作該文件的輸出流。 */
107
public IndexOutput createOutput(String name) throws IOException {
108
ensureOpen();
109
RAMFile file = new RAMFile(this);
110
synchronized (this) {
111
RAMFile existing = (RAMFile)fileMap.get(name);
112
if (existing!=null) {
113
sizeInBytes -= existing.sizeInBytes;
114
existing.directory = null;
115
}
116
fileMap.put(name, file);
117
}
118
return new RAMOutputStream(file);
119
}
120
/** 根據指定的文件名返回一個操作該文件的輸入流 */
121
public IndexInput openInput(String name) throws IOException {
122
ensureOpen();
123
RAMFile file;
124
synchronized (this) {
125
file = (RAMFile)fileMap.get(name);
126
}
127
if (file == null)
128
throw new FileNotFoundException(name);
129
return new RAMInputStream(file);
130
}
131
132
/** 關閉并且釋放索引占用的內存 */
133
public void close() {
134
isOpen = false;
135
fileMap = null;
136
}
137
}

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

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

由于RAMDirectory是抽象類Directory根據內存來實現的,所以他不是永久性存在,一旦內存釋放,索引就會消失。不像FSDirectory有一個本地的文件來存儲索引。
我們看看RAMDirectory的構造函數,特別是根據本地的目錄來創建。將永久保存的文件初始化到內存中。因為內存的操作速度肯定比操作文件要快很倍。這樣索引的速度就大大的提供了。
將指定的dir目錄拷貝到當前的內存中,即實例化一個RAMDirectory。這里,closeDir是一個很重要的狀態變量,指定了拷貝完成后,源目錄dir是否關閉。如果實例化一個RAMDirectory完成后就關閉源目錄dir,可能會因為處理的時間非常短,而需要再次打開源目錄dir,持久化到文件系統目錄,開銷可能會比直接操作源目錄dir要大,這點要權衡。