hashmapにslotを追加する
dwb_slots_hash_insert ()
dwb slotをhashmapに追加
https://github.com/innovationacademy-kr/dbstudy
dwb slotをhashmapに追加
/*
* dwb_slots_hash_insert () - Insert entry in slots hash.
*
* return : Error code.
* thread_p (in): The thread entry.
* vpid(in): The page identifier.
* slot(in): The DWB slot.
* inserted (out): 1, if slot inserted in hash.
*/
STATIC_INLINE int
dwb_slots_hash_insert (THREAD_ENTRY * thread_p, VPID * vpid, DWB_SLOT * slot, bool * inserted)
{
int error_code = NO_ERROR;
// NO_ERROR : 0
DWB_SLOTS_HASH_ENTRY *slots_hash_entry = NULL;
assert (vpid != NULL && slot != NULL && inserted != NULL);
// vpid, slot, inserted == NULL -> crash
*inserted = dwb_Global.slots_hashmap.find_or_insert (thread_p, *vpid, slots_hash_entry);
/*
* lf_hash_find_or_insert () - find or insert an entry in the hash table
vpid 를 key 값으로 dwb_global 변수의 slots_hashmap 변수에서 해쉬 함수를 사용해 value 를 가져오고 해쉬맵을 탐색한다.
해쉬맵에서 slots_hash_entry 가 있으면 가져오고 inserted 0,
없으면 thread_p의 freelist에서 받아와 해쉬맵에 추가하고 inserted 1로 설정한다.
*/
assert (VPID_EQ (&slots_hash_entry->vpid, &slot->vpid));
/*
* #define VPID_EQ(vpid_ptr1,vpid_ptr2)
* ((vpid_ptr1) == (vpid_ptr2) || ((vpid_ptr1)->pageid == (vpid_ptr2)->pageid && (vpid_ptr1)->volid == (vpid_ptr2)->volid))
* 같은 주소를 가르키거나, 페이지 아이디가 같거나, volid가 같아야 한다.
*/
assert (slots_hash_entry->vpid.pageid == slot->io_page->prv.pageid
&& slots_hash_entry->vpid.volid == slot->io_page->prv.volid);
/*
* prv.page id, prv.volid ? ?
*/
if (!(*inserted)) // *inserted == 0 인경우, find 한 경우
{
assert (slots_hash_entry->slot != NULL);
// slot == NULL -> crash
if (LSA_LT (&slot->lsa, &slots_hash_entry->slot->lsa))
// log 는 순서대로 쌓인다.
// slot의 lsa보다, slots_hash_entry의 lsa가 최신인 경우
// 같은 정보가 중복으로 들어온 경우?
{
dwb_log ("DWB hash find key (%d, %d), the LSA=(%lld,%d), better than (%lld,%d): \n",
vpid->volid, vpid->pageid, slots_hash_entry->slot->lsa.pageid,
slots_hash_entry->slot->lsa.offset, slot->lsa.pageid, slot->lsa.offset);
// The older slot is better than mine - leave it in hash.
pthread_mutex_unlock (&slots_hash_entry->mutex); // unlock
return NO_ERROR; // NO_ERROR 리턴
}
else if (LSA_EQ (&slot->lsa, &slots_hash_entry->slot->lsa))
{
/*
* If LSA's are equals, still replace slot in hash. We are in "flushing to disk without logging" case.
* The page was modified but not logged. We have to flush this version since is the latest one.
*/
// LSA 가 동일하더라도 해쉬의 슬롯을 바꾼다.
// Page는 변경되었지만, 로그가 남지는 않았다. flush해야함.
if (slots_hash_entry->slot->block_no == slot->block_no)
{
/* Invalidate the old slot, if is in the same block. We want to avoid duplicates in block at flush. */
assert (slots_hash_entry->slot->position_in_block < slot->position_in_block);
// slot->position_in_block이 더 최신임을 assert
VPID_SET_NULL (&slots_hash_entry->slot->vpid);
// hash 테이블에 있는 page id 를 null 로 바꿔줌
fileio_initialize_res (thread_p, slots_hash_entry->slot->io_page, IO_PAGESIZE);
// 초기화
dwb_log ("Found same page with same LSA in same block - %d - at positions (%d, %d) \n",
slots_hash_entry->slot->position_in_block, slot->position_in_block);
// 로그 남겨줌
}
else // LSA 가 동일한데, block_no가 다를 때
{
#if !defined (NDEBUG) // No Debug?
int old_block_no = ATOMIC_INC_32 (&slots_hash_entry->slot->block_no, 0);
// slot_hash_enty의 block_no 반환
if (old_block_no > 0)
{
/* Be sure that the block containing old page version is flushed first. */
DWB_BLOCK *old_block = &dwb_Global.blocks[old_block_no];
DWB_BLOCK *new_block = &dwb_Global.blocks[slot->block_no];
/* Maybe we will check that the slot is still in old block. */
assert ((old_block->version < new_block->version)
|| (old_block->version == new_block->version && old_block->block_no < new_block->block_no));
// new_block 이 더 최신임을 assert한다.
dwb_log ("Found same page with same LSA in 2 different blocks old = (%d, %d), new = (%d,%d) \n",
old_block_no, slots_hash_entry->slot->position_in_block, new_block->block_no,
slot->position_in_block);
}
#endif
}
}
dwb_log ("Replace hash key (%d, %d), the new LSA=(%lld,%d), the old LSA = (%lld,%d)",
vpid->volid, vpid->pageid, slot->lsa.pageid, slot->lsa.offset,
slots_hash_entry->slot->lsa.pageid, slots_hash_entry->slot->lsa.offset);
// 바꿀게라고 로그 표시
}
else // inserted가 됐을때
{
dwb_log ("Inserted hash key (%d, %d), LSA=(%lld,%d)", vpid->volid, vpid->pageid, slot->lsa.pageid,
slot->lsa.offset);
}
slots_hash_entry->slot = slot; // 바꿔줌
pthread_mutex_unlock (&slots_hash_entry->mutex); // unlock
*inserted = true;
return NO_ERROR;
}
DWB_SLOTS_HASH_ENTRY/* Slots hash entry. */
typedef struct dwb_slots_hash_entry DWB_SLOTS_HASH_ENTRY;
struct dwb_slots_hash_entry
{
VPID vpid; /* Page VPID. */
DWB_SLOTS_HASH_ENTRY *stack; /* Used in freelist. */
DWB_SLOTS_HASH_ENTRY *next; /* Used in hash table. */
pthread_mutex_t mutex; /* The mutex. */
UINT64 del_id; /* Delete transaction ID (for lock free). */
DWB_SLOT *slot; /* DWB slot containing a page. */
// *INDENT-OFF*
dwb_slots_hash_entry ()
{
pthread_mutex_init (&mutex, NULL);
}
~dwb_slots_hash_entry ()
{
pthread_mutex_destroy (&mutex);
}
// *INDENT-ON*
};
LSA_LTbool
LSA_LT (const log_lsa *plsa1, const log_lsa *plsa2)
{
assert (plsa1 != NULL && plsa2 != NULL);
return *plsa1 < *plsa2;
}
LSA_EQbool
LSA_EQ (const log_lsa *plsa1, const log_lsa *plsa2)
{
assert (plsa1 != NULL && plsa2 != NULL);
return *plsa1 == *plsa2;
}
この記事では、42ソウルで行われたCUBRID DB Engine学習を背景に、チームメンバーと一緒に学ぶ内容を紹介しています.https://github.com/innovationacademy-kr/dbstudy
Reference
この問題について(hashmapにslotを追加する), 我々は、より多くの情報をここで見つけました https://velog.io/@minjune8506/Slotshashinsertテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol