-
Notifications
You must be signed in to change notification settings - Fork 279
Expand file tree
/
Copy pathPageCacheImpl.java
More file actions
163 lines (140 loc) · 4.12 KB
/
PageCacheImpl.java
File metadata and controls
163 lines (140 loc) · 4.12 KB
1
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package top.guoziyang.mydb.backend.dm.pageCache;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import top.guoziyang.mydb.backend.common.AbstractCache;
import top.guoziyang.mydb.backend.dm.page.Page;
import top.guoziyang.mydb.backend.dm.page.PageImpl;
import top.guoziyang.mydb.backend.utils.Panic;
import top.guoziyang.mydb.common.Error;
public class PageCacheImpl extends AbstractCache<Page> implements PageCache {
private static final int MEM_MIN_LIM = 10;
public static final String DB_SUFFIX = ".db";
private RandomAccessFile file;
private FileChannel fc;
private Lock fileLock;
private AtomicInteger pageNumbers;
PageCacheImpl(RandomAccessFile file, FileChannel fileChannel, int maxResource) {
super(maxResource);
if(maxResource < MEM_MIN_LIM) {
Panic.panic(Error.MemTooSmallException);
}
long length = 0;
try {
length = file.length();
} catch (IOException e) {
Panic.panic(e);
}
this.file = file;
this.fc = fileChannel;
this.fileLock = new ReentrantLock();
this.pageNumbers = new AtomicInteger((int)length / PAGE_SIZE);
}
/*
* 改用重载方法flush()
*/
public int newPage(byte[] initData) {
int pgno = pageNumbers.incrementAndGet();
// Page pg = new PageImpl(pgno, initData, null);
// flush(pg);
flush(pgno, initData);
return pgno;
}
public Page getPage(int pgno) throws Exception {
return get((long)pgno);
}
/**
* 根据pageNumber从数据库文件中读取页数据,并包裹成Page
*/
@Override
protected Page getForCache(long key) throws Exception {
int pgno = (int)key;
long offset = PageCacheImpl.pageOffset(pgno);
ByteBuffer buf = ByteBuffer.allocate(PAGE_SIZE);
fileLock.lock();
try {
fc.position(offset);
fc.read(buf);
} catch(IOException e) {
Panic.panic(e);
}
fileLock.unlock();
return new PageImpl(pgno, buf.array(), this);
}
@Override
protected void releaseForCache(Page pg) {
if(pg.isDirty()) {
flush(pg);
pg.setDirty(false);
}
}
public void release(Page page) {
release((long)page.getPageNumber());
}
public void flushPage(Page pg) {
flush(pg);
}
private void flush(Page pg) {
int pgno = pg.getPageNumber();
long offset = pageOffset(pgno);
fileLock.lock();
try {
ByteBuffer buf = ByteBuffer.wrap(pg.getData());
fc.position(offset);
fc.write(buf);
fc.force(false);
} catch(IOException e) {
Panic.panic(e);
} finally {
fileLock.unlock();
}
}
/*
* 重载 flush()方法
* 作者:RioAngle
* 时间:2023.5.23
*/
private void flush(int pgno,byte[] data) {
long offset = pageOffset(pgno);
fileLock.lock();
try {
ByteBuffer buf = ByteBuffer.wrap(data);
fc.position(offset);
fc.write(buf);
fc.force(false);
} catch(IOException e) {
Panic.panic(e);
} finally {
fileLock.unlock();
}
}
public void truncateByBgno(int maxPgno) {
long size = pageOffset(maxPgno + 1);
try {
file.setLength(size);
} catch (IOException e) {
Panic.panic(e);
}
pageNumbers.set(maxPgno);
}
@Override
public void close() {
super.close();
try {
fc.close();
file.close();
} catch (IOException e) {
Panic.panic(e);
}
}
public int getPageNumber() {
return pageNumbers.intValue();
}
private static long pageOffset(int pgno) {
return (pgno-1) * PAGE_SIZE;
}
}