Lucene(2.4.1)技術(shù)研究(5)--IndexWrite類源代碼解析(四)RAMDirectory介紹
Posted on 2009-05-08 13:56 天空蒼茫 閱讀(1605) 評論(0) 編輯 收藏 所屬分類: java知識 RAMDirectory是Directory抽象類在使用內(nèi)存最為文件存儲的實現(xiàn)類,其主要是將所有的索引文件保存到內(nèi)存中。這樣可以提高效率。但是如果索引文件過大的話,則會導(dǎo)致內(nèi)存不足,因此,小型的系統(tǒng)推薦使用,如果大型的,索引文件達到G級別上,推薦使用FSDirectory
首先我們看看該類的源代碼:
首先該類繼承與抽象類Directory,并且實現(xiàn)了序列話接口
1
/**一個對于Directory的內(nèi)存實現(xiàn)的類,鎖工廠是有SingleInstanceLockFactory來實現(xiàn),但是鎖工廠可以更改 */
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; //文件占用的字節(jié)數(shù)
6
/** 構(gòu)造函數(shù)。指定LockFactory為該類的一個實例SingleInstanceLockFactory,SingleInstanceLockFactory類的特點是,所有的加鎖操作必須通過該SingleInstanceLockFactory的一個實例而發(fā)生,也就是說,在進行加鎖操作的時候,必須獲取到這個SingleInstanceLockFactory的實例*/
7
public RAMDirectory() {
8
setLockFactory(new SingleInstanceLockFactory());
9
}
10
/** 定義一個新的RAMDirectory,并且指定其目錄,這個做的目的可以將一個文件系統(tǒng)的索引加載到內(nèi)存中,這個只能使用在該索引能夠被全部加在到內(nèi)存中。這次只是將系統(tǒng)文件的索引拷貝一份到內(nèi)存中,加載后,系統(tǒng)文件索引發(fā)生變化,將不會在該實例中體現(xiàn)。 */
11
public RAMDirectory(Directory dir) throws IOException {
12
this(dir, false);
13
}
14
/** 根據(jù)目錄,以及參數(shù)將該目錄中的所有文件復(fù)制到內(nèi)存中,需要復(fù)制的文件已經(jīng)存在,則直接覆蓋。closeDir表示是否關(guān)閉源目錄*/
15
private RAMDirectory(Directory dir, boolean closeDir) throws IOException {
16
this();
17
Directory.copy(dir, this, closeDir);
18
}
19
/**根據(jù)提供的文件路徑,將該文件路徑下的所有的文件復(fù)制到內(nèi)存中,并且創(chuàng)建一個RAMDirectory對象。如果需要復(fù)制的對象已經(jīng)存在,則覆蓋原來的文件*/
20
public RAMDirectory(File dir) throws IOException {
21
this(FSDirectory.getDirectory(dir), true);
22
}
23
/**根據(jù)提供的String路徑,將該文件路徑下的所有的文件復(fù)制到內(nèi)存中,并且創(chuàng)建一個RAMDirectory對象。如果需要復(fù)制的對象已經(jīng)存在,則覆蓋原來的文件*/
24
public RAMDirectory(String dir) throws IOException {
25
this(FSDirectory.getDirectory(dir), true);
26
}
27
/**返回所有該文件該內(nèi)存索引中的所有文件 */
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
/**將指定文件的最后修改時間設(shè)置為現(xiàn)在 */
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
/**根據(jù)制定的名稱,創(chuàng)建一個空文件,并且返回操作該文件的輸出流。 */
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
/** 根據(jù)指定的文件名返回一個操作該文件的輸入流 */
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
/** 關(guān)閉并且釋放索引占用的內(nèi)存 */
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根據(jù)內(nèi)存來實現(xiàn)的,所以他不是永久性存在,一旦內(nèi)存釋放,索引就會消失。不像FSDirectory有一個本地的文件來存儲索引。
我們看看RAMDirectory的構(gòu)造函數(shù),特別是根據(jù)本地的目錄來創(chuàng)建。將永久保存的文件初始化到內(nèi)存中。因為內(nèi)存的操作速度肯定比操作文件要快很倍。這樣索引的速度就大大的提供了。
將指定的dir目錄拷貝到當前的內(nèi)存中,即實例化一個RAMDirectory。這里,closeDir是一個很重要的狀態(tài)變量,指定了拷貝完成后,源目錄dir是否關(guān)閉。如果實例化一個RAMDirectory完成后就關(guān)閉源目錄dir,可能會因為處理的時間非常短,而需要再次打開源目錄dir,持久化到文件系統(tǒng)目錄,開銷可能會比直接操作源目錄dir要大,這點要權(quán)衡。