Skip to content
GitLab
Explore
Projects
Groups
Topics
Snippets
Projects
Groups
Topics
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
educg-net-24542-2332654
DB2024-OSCore-3402
Commits
439de35b
Commit
439de35b
authored
1 year ago
by
z2z63
Browse files
Options
Download
Patches
Plain Diff
fix(BufferPoolManager): complete concurrency control, rewrite `flush_all_pages`
parent
47ee40ec
main
format
p1-storage-management
p2-query-execute
p3-unique-index
p4-aggregation-and-group
p5-unrelated-subquery
p6-merge-join
p7-transaction
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/storage/buffer_pool_manager.cpp
+37
-29
src/storage/buffer_pool_manager.cpp
with
37 additions
and
29 deletions
+37
-29
src/storage/buffer_pool_manager.cpp
+
37
−
29
View file @
439de35b
...
...
@@ -16,15 +16,15 @@ See the Mulan PSL v2 for more details. */
* @return {bool} true: 可替换帧查找成功 , false: 可替换帧查找失败
* @param {frame_id_t*} frame_id 帧页id指针,返回成功找到的可替换帧id
*/
bool
BufferPoolManager
::
find_victim_page
(
frame_id_t
*
frame_id
)
{
bool
BufferPoolManager
::
find_victim_page
(
frame_id_t
*
frame_id
)
{
// Todo:
// 1 使用BufferPoolManager::free_list_判断缓冲池是否已满需要淘汰页面
// 1.1 未满获得frame
// 1.2 已满使用lru_replacer中的方法选择淘汰页面
if
(
free_list_
.
empty
()){
if
(
free_list_
.
empty
())
{
return
replacer_
->
victim
(
frame_id
);
}
else
{
}
else
{
*
frame_id
=
free_list_
.
front
();
free_list_
.
pop_front
();
return
true
;
...
...
@@ -43,7 +43,7 @@ void BufferPoolManager::update_page(Page *page, PageId new_page_id, frame_id_t n
// 2 更新page table
// 3 重置page的data,更新page id
auto
page_id
=
page
->
get_page_id
();
if
(
page
->
is_dirty
()){
if
(
page
->
is_dirty
())
{
disk_manager_
->
write_page
(
page_id
.
fd
,
page_id
.
page_no
,
page
->
get_data
(),
PAGE_SIZE
);
page
->
is_dirty_
=
false
;
}
...
...
@@ -51,7 +51,7 @@ void BufferPoolManager::update_page(Page *page, PageId new_page_id, frame_id_t n
page_table_
[
new_page_id
]
=
new_frame_id
;
Page
*
ptr
=
&
pages_
[
new_frame_id
];
Page
*
ptr
=
&
pages_
[
new_frame_id
];
ptr
->
is_dirty_
=
false
;
// disk_manager_->read_page(new_page_id.fd, new_page_id.page_no, ptr->data_, PAGE_SIZE);
ptr
->
id_
=
new_page_id
;
...
...
@@ -64,7 +64,7 @@ void BufferPoolManager::update_page(Page *page, PageId new_page_id, frame_id_t n
* @return {Page*} 若获得了需要的页则将其返回,否则返回nullptr
* @param {PageId} page_id 需要获取的页的PageId
*/
Page
*
BufferPoolManager
::
fetch_page
(
PageId
page_id
)
{
Page
*
BufferPoolManager
::
fetch_page
(
PageId
page_id
)
{
//Todo:
// 1. 从page_table_中搜寻目标页
// 1.1 若目标页有被page_table_记录,则将其所在frame固定(pin),并返回目标页。
...
...
@@ -73,16 +73,16 @@ Page* BufferPoolManager::fetch_page(PageId page_id) {
// 3. 调用disk_manager_的read_page读取目标页到frame
// 4. 固定目标页,更新pin_count_
// 5. 返回目标页
if
(
page_table_
.
find
(
page_id
)
!=
page_table_
.
end
()){
// 在buffer pool中
Page
*
p
=
&
pages_
[
page_table_
[
page_id
]];
std
::
scoped_lock
lock
{
latch_
};
if
(
page_table_
.
find
(
page_id
)
!=
page_table_
.
end
())
{
// 在buffer pool中
Page
*
p
=
&
pages_
[
page_table_
[
page_id
]];
// pin_cout_ == 0时此页还能留在buffer_pool中,可能已经unpinned,确保已经pin
replacer_
->
pin
(
page_table_
[
page_id
]);
p
->
pin_count_
++
;
return
p
;
}
frame_id_t
victim
;
if
(
!
find_victim_page
(
&
victim
)){
if
(
!
find_victim_page
(
&
victim
))
{
return
nullptr
;
// 没有可淘汰页或空闲页,无法加载到buffer pool中
}
update_page
(
&
pages_
[
victim
],
page_id
,
victim
);
...
...
@@ -109,20 +109,20 @@ bool BufferPoolManager::unpin_page(PageId page_id, bool is_dirty) {
// 2.2.1 若自减后等于0,则调用replacer_的Unpin
// 3 根据参数is_dirty,更改P的is_dirty_
std
::
scoped_lock
lock
{
latch_
};
if
(
page_table_
.
find
(
page_id
)
==
page_table_
.
end
()){
if
(
page_table_
.
find
(
page_id
)
==
page_table_
.
end
())
{
return
false
;
}
Page
*
p
=
&
pages_
[
page_table_
[
page_id
]];
Page
*
p
=
&
pages_
[
page_table_
[
page_id
]];
bool
retval
=
p
->
pin_count_
>
0
;
if
(
p
->
pin_count_
==
0
){
if
(
p
->
pin_count_
==
0
)
{
return
false
;
}
else
if
(
p
->
pin_count_
>
0
){
p
->
pin_count_
--
;
}
else
if
(
p
->
pin_count_
>
0
)
{
p
->
pin_count_
--
;
}
if
(
p
->
pin_count_
==
0
){
if
(
p
->
pin_count_
==
0
)
{
replacer_
->
unpin
(
page_table_
[
page_id
]);
}
if
(
is_dirty
){
if
(
is_dirty
)
{
p
->
is_dirty_
=
true
;
// 避免`p->is_dirty_`被`false`覆盖
}
return
retval
;
...
...
@@ -142,10 +142,10 @@ bool BufferPoolManager::flush_page(PageId page_id) {
// 3. 更新P的is_dirty_
std
::
scoped_lock
lock
{
latch_
};
auto
it
=
page_table_
.
find
(
page_id
);
if
(
it
==
page_table_
.
end
()){
if
(
it
==
page_table_
.
end
())
{
return
false
;
}
Page
*
p
=
&
pages_
[
it
->
second
];
Page
*
p
=
&
pages_
[
it
->
second
];
disk_manager_
->
write_page
(
page_id
.
fd
,
page_id
.
page_no
,
p
->
data_
,
PAGE_SIZE
);
p
->
is_dirty_
=
false
;
return
true
;
...
...
@@ -156,15 +156,15 @@ bool BufferPoolManager::flush_page(PageId page_id) {
* @return {Page*} 返回新创建的page,若创建失败则返回nullptr
* @param {PageId*} page_id 当成功创建一个新的page时存储其page_id
*/
Page
*
BufferPoolManager
::
new_page
(
PageId
*
page_id
)
{
Page
*
BufferPoolManager
::
new_page
(
PageId
*
page_id
)
{
// 1. 获得一个可用的frame,若无法获得则返回nullptr
// 2. 在fd对应的文件分配一个新的page_id
// 3. 将frame的数据写回磁盘
// 4. 固定frame,更新pin_count_
// 5. 返回获得的page
std
::
scoped_lock
lock
{
latch_
};
frame_id_t
victim
;
if
(
!
find_victim_page
(
&
victim
)){
if
(
!
find_victim_page
(
&
victim
))
{
return
nullptr
;
}
page_id
->
page_no
=
disk_manager_
->
allocate_page
(
page_id
->
fd
);
...
...
@@ -184,15 +184,20 @@ bool BufferPoolManager::delete_page(PageId page_id) {
// 2. 若目标页的pin_count不为0,则返回false
// 3. 将目标页数据写回磁盘,从页表中删除目标页,重置其元数据,将其加入free_list_,返回true
std
::
scoped_lock
lock
{
latch_
};
auto
it
=
page_table_
.
find
(
page_id
);
if
(
it
==
page_table_
.
end
()){
if
(
it
==
page_table_
.
end
())
{
return
true
;
}
if
(
pages_
[
it
->
second
].
pin_count_
!=
0
){
if
(
pages_
[
it
->
second
].
pin_count_
!=
0
)
{
return
false
;
}
flush_page
(
page_id
);
memset
(
&
pages_
[
it
->
second
],
0
,
sizeof
(
Page
));
// 填充零
Page
*
page
=
&
pages_
[
it
->
second
];
if
(
page
->
is_dirty_
)
{
disk_manager_
->
write_page
(
page_id
.
fd
,
page_id
.
page_no
,
page
->
data_
,
PAGE_SIZE
);
// page->is_dirty_ = false; // no need
}
memset
(
page
,
0
,
sizeof
(
Page
));
// 填充零
free_list_
.
push_back
(
it
->
second
);
page_table_
.
erase
(
it
);
return
true
;
...
...
@@ -203,9 +208,12 @@ bool BufferPoolManager::delete_page(PageId page_id) {
* @param {int} fd 文件句柄
*/
void
BufferPoolManager
::
flush_all_pages
(
int
fd
)
{
for
(
auto
pair
:
page_table_
)
{
if
(
pair
.
first
.
fd
==
fd
){
flush_page
(
pair
.
first
);
std
::
scoped_lock
lock
{
latch_
};
for
(
frame_id_t
i
=
0
;
i
<
pool_size_
;
i
++
)
{
auto
page_id
=
pages_
[
i
].
get_page_id
();
if
(
page_id
.
fd
==
fd
)
{
disk_manager_
->
write_page
(
fd
,
page_id
.
page_no
,
pages_
[
i
].
data_
,
PAGE_SIZE
);
}
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment
Menu
Explore
Projects
Groups
Topics
Snippets