DWB에 page 저장 (코드분석 03)

개발새발·2021년 12월 29일
0
post-thumbnail
post-custom-banner

DWB에 page 저장 (코드분석 03)

코드 위치 : https://github.com/CUBRID/cubrid

dwb_add_page()

storage/double_write_buffer.c: 2694

/*
 * dwb_add_page () - Add page content to DWB.
 *
 * return   : Error code.
 * thread_p (in): The thread entry.
 * io_page_p(in): In-memory address where the current content of page resides.
 * vpid(in): Page identifier.
 * p_dwb_slot(in/out): DWB slot where the page content must be added.
 *
 *  Note: thread may flush the block, if flush thread is not available or we are in stand alone.
 */
int dwb_add_page(THREAD_ENTRY *thread_p, FILEIO_PAGE *io_page_p, VPID *vpid, DWB_SLOT **p_dwb_slot)
{
	unsigned int count_wb_pages;		// write buffer에 추가된 페이지 수
	int error_code = NO_ERROR;		// #define NO_ERROR 0
	bool inserted = false;		// DWB에 slot이 잘 추가되었는지 확인하는 bool 타입 변수
	DWB_BLOCK *block = NULL;		// block 포인터
	DWB_SLOT *dwb_slot = NULL;		// slot 포인터
	bool needs_flush;		// flush가 필요한지 확인하는 bool 타입 변수 (count_wb_pages >= DWB 각 block의 page 수 → flush)

	assert(p_dwb_slot != NULL && (io_page_p != NULL || (*p_dwb_slot)->io_page != NULL) && vpid != NULL);
	// 위 조건에 만족하지 않으면 crash

	if (thread_p == NULL)
	{
		thread_p = thread_get_thread_entry_info();
		// 인자로 thread_p가 제대로 들어오지 않았다면 위 함수를 통해 자체적으로 thread entry 구함
	}

	if (*p_dwb_slot == NULL)
	// *p_dwb_slot이 NULL이라면
	{
		error_code = dwb_set_data_on_next_slot(thread_p, io_page_p, true, p_dwb_slot);
		// 가능한 경우, next DWB slot에 데이터 set / error code 설정
		// dwb_acquire_next_slot()에서 position_with_flags에서 현재 block num, 다음 slot의 위치를 구함
		// 현재 block의 slot pointer + 구한 slot의 index로 slot의 pointer를 구하고 p_dwb_slot에 대입
		// dwb_set_slot_data()에서 p_dwb_slot에 io_page_p를 입력
		if (error_code != NO_ERROR)
		{
			return error_code;
			// 위 함수 안에서 에러 발생 시 add_page 중단 / error_code 반환
		}

		if (*p_dwb_slot == NULL)
		{
			return NO_ERROR;
			// 위 함수를 거치고도 아직 *p_dwb_slot이 NULL이라면 add_page 중단 / NO_ERROR 반환
		}
	}

	dwb_slot = *p_dwb_slot;
	// 함수 내에서 선언한 dwb_slot 포인터 변수에 *p_dwb_slot 대입

	assert(VPID_EQ(vpid, &dwb_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))
	// vipd와 slot->vpid를 비교하는 이유는 dwb_set_slot_data() 함수에서 입력 과정에서 error가 발생됐는지 check하기 위함으로 추측됨
	// vpid와 &dwb_slot->vpid가 일치하지 않으면 crash

	if (!VPID_ISNULL(vpid))
	// vpid가 NULL이 아니면
	{
		error_code = dwb_slots_hash_insert(thread_p, vpid, dwb_slot, &inserted);
		// slots hash에 삽입 진행 / error code 설정
		if (error_code != NO_ERROR)
		{
			return error_code;
			// 위 함수 안에서 에러 발생 시 add_page 중단 / error_code 반환
		}

		if (!inserted)
		// 삽입 진행 후에도 inserted 변수가 아직 false라면
		{
			/* Invalidate the slot to avoid flushing the same data twice. */
			VPID_SET_NULL(&dwb_slot->vpid);
			// 동일한 데이터를 두 번 flush하지 않도록 slot을 NULL로 세팅해 무효화 시킴
			fileio_initialize_res(thread_p, dwb_slot->io_page, IO_PAGESIZE);
			// LSA를 NULL로 세팅 / io_page 구조체 내의 변수들 default값으로 초기화
		}
	}

	dwb_log("dwb_add_page: added page = (%d,%d) on block (%d) position (%d)\n", vpid->volid, vpid->pageid,
			dwb_slot->block_no, dwb_slot->position_in_block);
	// 추가된 page 정보를 log에 남김

	block = &dwb_Global.blocks[dwb_slot->block_no];
	// 함수 내에서 선언한 block 포인터 변수에 DWB 전역 구조체 내의 블록 배열의 slot의 block 번호 주소 대입
	count_wb_pages = ATOMIC_INC_32(&block->count_wb_pages, 1);
	// 함수 내에서 선언한 count_wb_pages에 ATOMIC_INC_32로 &block->count_wb_pages 대입
	// write_buffer의 page가 1개 추가되었으므로 +1 해서 대입
	assert_release(count_wb_pages <= DWB_BLOCK_NUM_PAGES);
	// count_wb_pages가 DWB 각 block의 page 수보다 크면 crash

	if (count_wb_pages < DWB_BLOCK_NUM_PAGES)
	// count_wb_pages가 DWB 각 block의 page 수보다 작으면
	{
		needs_flush = false;
		// flush 불필요
	}
	else
	{
		needs_flush = true;
		// flush 필요
	}

	if (needs_flush == false)
	{
		return NO_ERROR;
		// flush 할 필요 없으면 add_page 중단 / NO_ERROR 반환
	}

	/*
	 * The blocks must be flushed in the order they are filled to have consistent data.
	 * The flush block thread knows how to flush the blocks in the order they are filled.
	 * So, we don't care anymore about the flushing order here.
	 * Initially, we waited here if the previous block was not flushed.
	 * That approach created delays.
	 * Block은 일관된 데이터를 갖기 위해 채워진 순서대로 flush 되어야 한다.
	 * Flush block thread는 채워진 순서대로 block을 flush하는 방법을 알고 있다.
	 * 따라서 여기에선 flushing 순서에 대해 더 이상 신경 쓰지 않는다.
	 * 최초에는 이전 block이 flush되지 않은 경우 여기에서 기다렸었다.
	 * 이러한 접근 방식으로 인해 지연이 발생됐었다.
	 */

// SEVER_MODE로 실행됐을 경우에만 진행
#if defined(SERVER_MODE)
	/*
	 * Wake ups flush block thread to flush the current block.
	 * The current block will be flushed after flushing the previous block.
	 * 현재 block을 flush하기 위해 flush block thread를 깨운다.
	 * 현재 block은 이전 block을 flush한 후 flush된다.
	 */
	if (dwb_is_flush_block_daemon_available())
	// flush block daemon이 가능한 상태이면
	{
		/* Wakeup the thread that will flush the block. */
		dwb_flush_block_daemon->wakeup();
		// block을 flush할 thread를 깨움

		return NO_ERROR;
	}
#endif /* SERVER_MODE */

	/* Flush all pages from current block */
	error_code = dwb_flush_block(thread_p, block, false, NULL);
	// 현재 block에서 모든 pages flush / error code 설정
	if (error_code != NO_ERROR)
	{
		dwb_log_error("Can't flush block = %d having version %lld\n", block->block_no, block->version);

		return error_code;
		// flush 실패 시 log에 에러 메세지 남기고 error code 반환
	}

	dwb_log("Successfully flushed DWB block = %d having version %lld\n", block->block_no, block->version);

	return NO_ERROR;
	// flush 성공 시 해당 메세지를 log에 성공 메세지 남기고 함수 종료
}

 

dwb_set_data_on_next_slot()

storage/double_write_buffer.c: 2656

/*
 * dwb_set_data_on_next_slot () - Sets data at the next DWB slot, if possible.
 *
 * return   : Error code.
 * thread_p(in): The thread entry.
 * io_page_p(in): The data that will be set on next slot.
 * can_wait(in): True, if waiting is allowed.
 * p_dwb_slot(out): Pointer to the next free DWB slot.
 */
int dwb_set_data_on_next_slot(THREAD_ENTRY *thread_p, FILEIO_PAGE *io_page_p, bool can_wait, DWB_SLOT **p_dwb_slot)
{
	int error_code;

	assert(p_dwb_slot != NULL && io_page_p != NULL);

	/* Acquire the slot before setting the data. */
	error_code = dwb_acquire_next_slot(thread_p, can_wait, p_dwb_slot);
	// 페이지를 놓을 슬롯을 찾아 *p_dwb_slot 에 넣어줌
	if (error_code != NO_ERROR)
	{
		return error_code;
	}

	assert(can_wait == false || *p_dwb_slot != NULL);
	// can_wait가 false 이거나, can_wait가 true이면서 *p_dwb_slot이 NULL은 아니어야 함
	if (*p_dwb_slot == NULL)
	{
		/* Can't acquire next slot. */
		return NO_ERROR;
	}
	// can_wait가 false이고, *p_dwb_slot이 NULL인 경우 처리에 사용할 슬롯을 찾을 수 없었던 것이므로 종료

	/* Set data on slot. */
	dwb_set_slot_data(thread_p, *p_dwb_slot, io_page_p);
	// 찾은 슬롯에 페이지 놓기

	return NO_ERROR;
}

 

dwb_acquire_next_slot()

storage/double_write_buffer.c: 2442

/*
 * dwb_acquire_next_slot () - Acquire the next slot in DWB.
 *
 * return   : Error code.
 * thread_p(in): The thread entry.
 * can_wait(in): True, if can wait to get the next slot.
 * p_dwb_slot(out): The pointer to the next slot in DWB.
 */
STATIC_INLINE int
dwb_acquire_next_slot(THREAD_ENTRY *thread_p, bool can_wait, DWB_SLOT **p_dwb_slot)
{
	UINT64 current_position_with_flags, current_position_with_block_write_started, new_position_with_flags;
	unsigned int current_block_no, position_in_current_block;
	int error_code = NO_ERROR;
	DWB_BLOCK *block;

	assert(p_dwb_slot != NULL);
	*p_dwb_slot = NULL;

start:
	/* Get the current position in double write buffer. */
	current_position_with_flags = ATOMIC_INC_64(&dwb_Global.position_with_flags, 0ULL);
	// current_position_with_flags = dwb_Global.position_with_flags

	if (DWB_NOT_CREATED_OR_MODIFYING(current_position_with_flags))
	// dwb가 만들어지지 않았고, 만들어지는 중이라면
	{
		/* Rarely happens. */
		if (DWB_IS_MODIFYING_STRUCTURE(current_position_with_flags))
		// 만들어지는 중이라면
		{
			if (can_wait == false)
			// (dwb가 만들어질 때까지) 대기가 불가능하다면
			{
				return NO_ERROR;
			}

			/* DWB structure change started, needs to wait. */
			error_code = dwb_wait_for_strucure_modification(thread_p);
			// dwb 가 만들어질 때까지 대기
			if (error_code != NO_ERROR)
			// 에러 발생
			{
				if (error_code == ER_CSS_PTHREAD_COND_TIMEDOUT)
				{
					/* timeout, try again */
					goto start;
					// 타임아웃일 경우 위에서부터 재시도
				}
				return error_code;
				// 다른 에러일 경우 에러 반환
			}

			/* Probably someone else advanced the position, try again. */
			goto start;
			// 다시 제일 위 조건부터 플래그 검증
		}
		else if (!DWB_IS_CREATED(current_position_with_flags))
		// 만들어지지 않았으면
		{
			if (DWB_IS_ANY_BLOCK_WRITE_STARTED(current_position_with_flags))
			// 블록이 하나라도 WRITE_STARTED 상태라면 (0~31 번째 비트 중 하나라도 SET 이라면)
			{
				/* Someone deleted the DWB, before flushing the data. */
				er_set(ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_DWB_DISABLED, 0);
				return ER_DWB_DISABLED;
				// 에러처리
			}

			/* Someone deleted the DWB */
			return NO_ERROR;
			// DWB 가 사용불가하므로 종료
		}
		else
		{
			assert(false);
		}
	}

	current_block_no = DWB_GET_BLOCK_NO_FROM_POSITION(current_position_with_flags);
	// current_block_no = (current_position_with_flags & DWB_POSITION_MASK) >> dwb_Global.log2_num_block_pages
	position_in_current_block = DWB_GET_POSITION_IN_BLOCK(current_position_with_flags);
	// position_in_current_block = current_position_with_flags & DWB_POSITION_MASK & (dwb_Global.num_block_pages - 1)

/*
 * ex)
 * num_block_pages: 64
 * log2_num_block_pages: 6

 * current_position_with_flags & DWB_POSITION_MASK 을 통해 block 번호와 slot index를 알아낼 수 있음
 * 해당 값이 0 이면 블록 번호 0 // 64 = 0, 슬롯 인덱스 0 % 64 = 0
 * 해당 값이 65 이면 블록 번호 65 // 64 = 1, 슬롯 인덱스 65 % 64 = 1

 * 이 과정을 비트로 나타내면 아래와 같습니다

 * current_position_with_flags & DWB_POSITION_MASK => 1이라고 가정 => 00 0000 0000 0000 0000 0000 0000 0001
 * 블록 번호: 0000 0001 >> 6 = 0
 * 슬롯 인덱스: 0000 0001 & 63 = 0000 0001 & 0011 1111 = 1

 * current_position_with_flags & DWB_POSITION_MASK => 65라고 가정 => 00 0000 0000 0000 0000 0000 0100 0001
 * 블록 번호: 0100 0001 >> 6 = 1
 * 슬롯 인덱스: 0100 0001 & 0011 1111 = 1
 */

	assert(current_block_no < DWB_NUM_TOTAL_BLOCKS && position_in_current_block < DWB_BLOCK_NUM_PAGES);

	if (position_in_current_block == 0)
	// 처리하게 될 슬롯이 0번째 슬롯일 때
	{
		/* This is the first write on current block. Before writing, check whether the previous iteration finished. */
		if (DWB_IS_BLOCK_WRITE_STARTED(current_position_with_flags, current_block_no))
		// current_position_with_flags의 MSB에서 current_block_no 번째 비트가 SET 되어 있으면 = current_block_no 블록이 쓰기 작업 중이면
		{
			if (can_wait == false)
			{
				return NO_ERROR;
				// 대기가 불가능하면 종료
			}

			dwb_log("Waits for flushing block=%d having version=%lld) \n",
					current_block_no, dwb_Global.blocks[current_block_no].version);

			/*
	   		 * The previous iteration didn't finished, needs to wait, in order to avoid buffer overwriting.
	   		 * Should happens relative rarely, except the case when the buffer consist in only one block.
	   		 */
			error_code = dwb_wait_for_block_completion(thread_p, current_block_no);
			// 버퍼가 덮어씌워지는 것을 피하기 위해서 이전 쓰기 작업이 끝날 때까지 대기
			// dwb_wait_for_strucure_modification 와 체크 플래그만 다르고 나머진 동일
			if (error_code != NO_ERROR)
			{
				if (error_code == ER_CSS_PTHREAD_COND_TIMEDOUT)
				{
					/* timeout, try again */
					goto start;
					// timeout의 경우 처음부터 재시도
				}

				dwb_log_error("Error %d while waiting for flushing block=%d having version %lld \n",
							  error_code, current_block_no, dwb_Global.blocks[current_block_no].version);
				return error_code;
				// 다른 에러의 경우 에러처리
			}

			/* Probably someone else advanced the position, try again. */
			goto start;
			// 대기가 끝난 이후 플래그 검토를 위해 처음부터 시작
		}

		/* First write in the current block. */
		assert(!DWB_IS_BLOCK_WRITE_STARTED(current_position_with_flags, current_block_no));

		current_position_with_block_write_started =
			DWB_STARTS_BLOCK_WRITING(current_position_with_flags, current_block_no);
		// current_position_with_block_write_started =
		// current_position_with_flags의 MSB에서 current_block_no 번째 비트를 SET

		new_position_with_flags = DWB_GET_NEXT_POSITION_WITH_FLAGS(current_position_with_block_write_started);
		// new_position_with_flags = slot의 index가 (num_pages - 1) 과 같다면 0, 아니라면 slot을 1 증가하고 플래그를 반환
		// 위 방식으로 슬롯을 순회
	}
	else
	{
		/* I'm sure that nobody else can delete the buffer */
		assert(DWB_IS_CREATED(dwb_Global.position_with_flags));
		assert(!DWB_IS_MODIFYING_STRUCTURE(dwb_Global.position_with_flags));

		/* Compute the next position with flags */
		new_position_with_flags = DWB_GET_NEXT_POSITION_WITH_FLAGS(current_position_with_flags);
		// new_position_with_flags = slot의 index가 (num_pages - 1) 과 같다면 0, 아니라면 slot을 1 증가하고 플래그를 반환
		// 위 방식으로 슬롯을 순회
	}

	/* Compute and advance the global position in double write buffer. */
	if (!ATOMIC_CAS_64(&dwb_Global.position_with_flags, current_position_with_flags, new_position_with_flags))
	// 만약 다른 스레드에서 처리가 이뤄져 플래그가 바뀌었다면, 다시 처음부터 시작
	// 그게 아니라면 dwb_Global.position_with_flags에 새 플래그를 대입
	{
		/* Someone else advanced the global position in double write buffer, try again. */
		goto start;
	}

	block = dwb_Global.blocks + current_block_no;
	// block = 포인터 dwb_Global.blocks에 현재 블록 번호를 더한 포인터

	*p_dwb_slot = block->slots + position_in_current_block;
	// *p_dwb_slot = 해당 블록의 슬롯 포인터에 슬롯 위치를 더한 포인터

	/* Invalidate slot content. */
	VPID_SET_NULL(&(*p_dwb_slot)->vpid);

	assert((*p_dwb_slot)->position_in_block == position_in_current_block);

	return NO_ERROR;
}

 

dwb_set_slot_data()

storage/double_write_buffer.c: 2585

/*
 * dwb_set_slot_data () - Set DWB data at the location indicated by the slot.
 *
 * return   : Error code.
 * thread_p(in): Thread entry
 * dwb_slot(in/out): DWB slot that contains the location where the data must be set.
 * io_page_p(in): The data.
 */
STATIC_INLINE void
dwb_set_slot_data(THREAD_ENTRY *thread_p, DWB_SLOT *dwb_slot, FILEIO_PAGE *io_page_p)
{
	assert(dwb_slot != NULL && io_page_p != NULL);

	assert(io_page_p->prv.p_reserve_2 == 0);

	if (io_page_p->prv.pageid != NULL_PAGEID)
	// 데이터 페이지의 페이지가 유효하다면
	{
		memcpy(dwb_slot->io_page, (char *)io_page_p, IO_PAGESIZE);
		// 슬롯의 페이지 위치에 해당 페이지 복사
	}
	else
	{
		/* Initialize page for consistency. */
		fileio_initialize_res(thread_p, dwb_slot->io_page, IO_PAGESIZE);
		// 슬롯의 페이지 자체를 초기화
	}

	assert(fileio_is_page_sane(io_page_p, IO_PAGESIZE));
	LSA_COPY(&dwb_slot->lsa, &io_page_p->prv.lsa);
	VPID_SET(&dwb_slot->vpid, io_page_p->prv.volid, io_page_p->prv.pageid);
	// dwb_slot->vpid.volid = io_page_p->prv.volid
	// dwb_slot->vpid.pageid = io_page_p->prv.pageid
}

 

dwb_slots_hash_insert()

storage/double_write_buffer.c: 1368

/*
 * 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;
	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));
	// 같은 주소를 가르키거나, 페이지 아이디가 같거나, volid가 같아야 한다.
	assert(slots_hash_entry->vpid.pageid == slot->io_page->prv.pageid && slots_hash_entry->vpid.volid == slot->io_page->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);
			return 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)
				int old_block_no = ATOMIC_INC_32(&slots_hash_entry->slot->block_no, 0);
				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);
	*inserted = true;

	return NO_ERROR;
}

 

본 시리즈의 글들은 CUBRID DB엔진 오픈 스터디를 진행하며 팀원들과 함께 공부한 내용을 정리한 것입니다.
Github 링크

profile
블록체인 개발 어때요
post-custom-banner

0개의 댓글