codec.rs
이 코드는 Heed
라이브러리와 관련된 데이터 인코딩 및 디코딩 기능을 구현하고 있습니다. Heed
는 Rust에서 사용되는 고성능의 키-값 저장소 라이브러리로, 이 코드는 로그 엔트리(Entry
)와 로그 엔트리 키(String
)를 Heed
에 저장하거나 불러올 때 사용할 수 있도록 바이트 배열로 변환하는 기능을 제공합니다.
format_entry_key_string
함수pub fn format_entry_key_string(entry_key: &str) -> String {
let entry_key: u64 = entry_key.parse().unwrap();
let mut result = String::new();
write!(result, "{:0width$}", entry_key, width = ENTRY_KEY_LENGTH).unwrap();
result
}
ENTRY_KEY_LENGTH
)의 문자열로 포맷팅합니다. 키 값을 u64
로 파싱한 후, 지정된 너비만큼 0으로 채워진 문자열로 변환합니다.Heed
에 저장할 때 일정한 길이를 유지하기 위해 사용됩니다. 일정한 길이의 키는 데이터 정렬 및 검색 성능을 높이는 데 유용합니다.HeedEntryKeyString
구조체#[derive(Eq, PartialEq)]
pub struct HeedEntryKeyString(String);
역할: HeedEntryKeyString
구조체는 String
타입을 감싸며, Heed
데이터베이스에서 키로 사용될 문자열을 표현합니다.
BytesEncode
구현:
impl<'a> BytesEncode<'a> for HeedEntryKeyString {
type EItem = String;
fn bytes_encode(item: &'a Self::EItem) -> std::result::Result<Cow<'a, [u8]>, BoxedError> {
Ok(Cow::Owned(
format_entry_key_string(item).as_bytes().to_vec(),
))
}
}
HeedEntryKeyString
을 바이트 배열로 인코딩합니다. format_entry_key_string
함수를 사용하여 문자열을 고정된 길이의 문자열로 변환한 후, 바이트 배열로 변환하여 반환합니다.BytesDecode
구현:
impl<'a> BytesDecode<'a> for HeedEntryKeyString {
type DItem = String;
fn bytes_decode(bytes: &'a [u8]) -> std::result::Result<Self::DItem, BoxedError> {
Ok(String::from_utf8_lossy(bytes).into_owned())
}
}
String
으로 디코딩합니다. 바이트 배열을 UTF-8 문자열로 변환하고 이를 반환합니다.HeedEntry
열거형pub enum HeedEntry {}
역할: HeedEntry
는 로그 엔트리(Entry
)를 인코딩 및 디코딩하기 위한 열거형입니다. 실제 데이터는 없고, 주로 타입 시스템에서 사용하기 위한 목적으로 존재합니다.
BytesEncode
구현:
impl BytesEncode<'_> for HeedEntry {
type EItem = Entry;
fn bytes_encode(item: &Self::EItem) -> std::result::Result<Cow<'_, [u8]>, BoxedError> {
let mut bytes = vec![];
item.encode(&mut bytes)?;
Ok(Cow::Owned(bytes))
}
}
Entry
를 바이트 배열로 인코딩합니다. prost::Message
트레이트의 encode
메서드를 사용하여 Entry
를 바이트 벡터로 변환하고 반환합니다.BytesDecode
구현:
impl BytesDecode<'_> for HeedEntry {
type DItem = Entry;
fn bytes_decode(bytes: &[u8]) -> std::result::Result<Self::DItem, BoxedError> {
Ok(Entry::decode(bytes)?)
}
}
Entry
로 디코딩합니다. prost::Message
트레이트의 decode
메서드를 사용하여 바이트 배열을 Entry
구조체로 복원합니다.constant.rs
이 코드는 Raft 저장소에서 사용될 중요한 키와 상수들을 정의하고 있습니다. 이러한 상수들은 Raft 알고리즘에서 데이터를 저장하고 조회할 때 사용되며, 일관된 키를 사용함으로써 코드의 가독성을 높이고 실수를 방지하는 데 도움을 줍니다.
SNAPSHOT_KEY
:
pub const SNAPSHOT_KEY: &str = "snapshot";
SNAPSHOT_KEY
는 이 스냅샷 데이터를 저장할 때 사용되는 키입니다.LAST_INDEX_KEY
:
pub const LAST_INDEX_KEY: &str = "last_index";
LAST_INDEX_KEY
는 이 인덱스를 저장하는 데 사용됩니다.HARD_STATE_KEY
:
pub const HARD_STATE_KEY: &str = "hard_state";
HARD_STATE_KEY
는 이 데이터를 저장하는 데 사용됩니다.CONF_STATE_KEY
:
pub const CONF_STATE_KEY: &str = "conf_state";
CONF_STATE_KEY
는 이 데이터를 저장하는 데 사용됩니다.ENTRY_KEY_LENGTH
:
pub const ENTRY_KEY_LENGTH: usize = 10;
이 코드에서 정의된 상수들은 Raft 알고리즘의 중요한 부분을 구성합니다. 이러한 상수들은 데이터 저장소에서 일관된 키와 길이를 사용함으로써 코드의 가독성, 유지보수성, 그리고 오류 방지에 기여합니다. SNAPSHOT_KEY
, LAST_INDEX_KEY
, HARD_STATE_KEY
, CONF_STATE_KEY
와 같은 키는 각각의 데이터를 명확하게 식별하는 데 사용되며, ENTRY_KEY_LENGTH
는 로그 엔트리 키의 일관된 길이를 보장합니다.
heed_storage 폴더의 mod.rs
이 코드는 Heed
라는 데이터베이스 라이브러리를 사용하여 Raft 알고리즘의 상태 및 로그 엔트리를 저장하고 관리하는 기능을 구현하고 있습니다. HeedStorage
구조체는 StableStorage
트레이트를 구현하여 Raft 알고리즘에서 사용하는 스토리지로 활용되며, 로그 엔트리의 추가, 삭제, 조회 및 스냅샷 관리 등의 작업을 처리합니다.
HeedStorage
구조체HeedStorage
는 HeedStorageCore
라는 내부 구조체를 감싼 Arc<RwLock<HeedStorageCore>>
타입의 구조체입니다. 이 구조체는 Raft 알고리즘의 상태와 로그를 안전하게 관리할 수 있도록 동시성을 제어합니다.
주요 메서드:
create
: 새로운 HeedStorage
인스턴스를 생성합니다. log_dir_path
, config
, 그리고 logger
를 인자로 받아 스토리지를 초기화합니다.wl
, rl
: 내부 RwLock
을 사용하여 HeedStorageCore
에 대한 쓰기 및 읽기 접근을 제공합니다.StableStorage
트레이트 구현이 트레이트는 Raft 알고리즘에서 스토리지를 사용하기 위해 필요한 다양한 메서드를 정의합니다. HeedStorage
는 이 트레이트를 구현하여 로그 엔트리의 추가, 압축, 하드 스테이트 및 구성 상태 관리, 스냅샷 생성 및 복구 기능을 제공합니다.
주요 메서드:
compact
: 주어진 인덱스 이전의 로그 엔트리를 삭제하여 공간을 절약합니다.append
: 새로운 로그 엔트리를 추가합니다.hard_state
, set_hard_state
: Raft의 하드 스테이트를 가져오거나 설정합니다.conf_state
, set_conf_state
: Raft의 구성 상태를 가져오거나 설정합니다.create_snapshot
, apply_snapshot
: 스냅샷을 생성하거나 스냅샷을 적용합니다.all_entries
: 저장된 모든 로그 엔트리를 반환합니다.Storage
트레이트 구현HeedStorage
는 raft::Storage
트레이트도 구현하여 Raft 알고리즘의 상태 관리와 로그 접근을 위한 다양한 기능을 제공합니다.
주요 메서드:
initial_state
: 초기 Raft 상태를 반환합니다.entries
: 주어진 범위 내에서 로그 엔트리를 가져옵니다.term
: 주어진 인덱스의 로그 엔트리의 term 값을 반환합니다.first_index
, last_index
: 첫 번째 및 마지막 로그 엔트리의 인덱스를 반환합니다.snapshot
: 요청된 인덱스의 스냅샷을 반환합니다.HeedStorageCore
구조체HeedStorageCore
는 실제 데이터베이스(Env
, Database
) 인스턴스를 관리하며, HeedStorage
의 대부분의 기능을 내부적으로 처리합니다.
주요 메서드:
create
: Heed
데이터베이스 환경 및 관련 데이터베이스를 초기화합니다.compact
: 로그 엔트리 압축을 수행합니다.set_hard_state
, hard_state
: 하드 스테이트를 설정하거나 가져옵니다.set_conf_state
, conf_state
: 구성 상태를 설정하거나 가져옵니다.set_snapshot
, snapshot
: 스냅샷을 설정하거나 가져옵니다.last_index
, first_index
: 마지막 및 첫 번째 로그 인덱스를 반환합니다.entry
, entries
: 특정 인덱스의 로그 엔트리 또는 주어진 범위의 로그 엔트리를 반환합니다.append
: 로그 엔트리를 데이터베이스에 추가합니다.HeedStorage
의 기능을 테스트합니다.test_storage_term
: 특정 인덱스의 로그 엔트리의 term 값을 정확히 반환하는지 테스트합니다.test_storage_entries
: 주어진 범위의 로그 엔트리를 올바르게 가져오는지 테스트합니다.test_storage_last_index
: 마지막 로그 인덱스를 정확히 반환하는지 테스트합니다.test_storage_first_index
: 첫 번째 로그 인덱스를 정확히 반환하는지 테스트합니다.test_storage_compact
: 로그 엔트리의 압축 기능을 테스트합니다.test_storage_append
: 로그 엔트리 추가 기능을 테스트합니다.test_storage_apply_snapshot
: 스냅샷 적용 기능을 테스트합니다.HeedStorage
는 Raft 알고리즘에서 로그와 상태를 효율적으로 관리하기 위해 설계된 스토리지 구현체로, 로그 엔트리와 스냅샷의 저장, 조회, 압축, 복구 등의 기능을 제공합니다. Heed
데이터베이스를 사용하여 높은 성능과 신뢰성을 보장하며, StableStorage
및 Storage
트레이트를 구현하여 Raft의 핵심 기능을 지원합니다. 이 구현은 특히 로그 복제와 일관성 유지가 중요한 분산 시스템에서 유용하게 사용될 수 있습니다.
storage 폴더의 mod.rs
이 코드는 StableStorage
라는 트레이트를 정의하고 있으며, 이는 Raft 알고리즘에서 사용되는 안정적인 스토리지 인터페이스를 제공하기 위한 것입니다. StableStorage
트레이트는 Storage
트레이트를 상속하며, 로그 엔트리와 상태(State)를 저장하고 관리하는 다양한 기능을 제공합니다.
StableStorage
트레이트이 트레이트는 Storage
트레이트를 상속하며, Raft 알고리즘에서 로그와 상태를 안정적으로 저장하고 관리하기 위해 필요한 다양한 메서드를 정의합니다.
주요 메서드:
append
:
entries
: 저장할 Entry
객체들의 슬라이스.Result<()>
- 성공 또는 실패 여부를 나타냅니다.hard_state
:
Result<HardState>
- 현재 저장된 하드 스테이트.set_hard_state
:
hard_state
: 저장할 HardState
객체.Result<()>
- 성공 또는 실패 여부를 나타냅니다.set_hard_state_commit
:
commit
: 새로운 커밋 인덱스.Result<()>
- 성공 또는 실패 여부를 나타냅니다.conf_state
:
Result<ConfState>
- 현재 저장된 구성 상태.set_conf_state
:
conf_state
: 저장할 ConfState
객체.Result<()>
- 성공 또는 실패 여부를 나타냅니다.create_snapshot
:
data
: 스냅샷 데이터.index
: 스냅샷의 로그 인덱스.term
: 스냅샷의 로그 용어(term).Result<()>
- 성공 또는 실패 여부를 나타냅니다.apply_snapshot
:
snapshot
: 적용할 Snapshot
객체.Result<()>
- 성공 또는 실패 여부를 나타냅니다.compact
:
index
: 압축을 수행할 인덱스.Result<()>
- 성공 또는 실패 여부를 나타냅니다.all_entries
:
raft::Result<Vec<Entry>>
- 모든 로그 엔트리의 벡터.utils.rs
이 코드는 Raft 시스템에서 로그 데이터와 스토리지 관련 유틸리티 기능을 제공하는 모듈입니다. 주로 파일 시스템과 관련된 작업을 수행하며, 로그 데이터를 관리하는 데 필요한 다양한 함수를 포함하고 있습니다.
get_storage_path(log_dir: &str, node_id: u64) -> String
:
get_storage_path("/var/logs", 1)
은 "/var/logs/node-1"
을 반환합니다.get_data_mdb_path(log_dir: &str, node_id: u64) -> String
:
data.mdb
) 경로를 생성합니다.data.mdb
파일의 경로를 문자열로 반환합니다.clear_storage_path(log_dir_path: &str) -> Result<()>
:
Ok(())
를 반환하며, 오류 발생 시 오류 정보를 반환합니다.ensure_directory_exist(dir_pth: &str) -> Result<()>
:
Ok(())
를 반환하며, 오류 발생 시 오류 정보를 반환합니다.entry_type_to_str(entry_type: i32) -> &'static str
:
entry_type_to_str(0)
은 "EntryNormal"
을 반환합니다.append_compacted_logs(dest_path: &Path, new_data: &[Entry]) -> io::Result<()>
:
설명: 압축된 로그 데이터를 JSON 파일에 추가합니다. 만약 파일이 없으면 새로 생성하고, 기존 데이터가 있으면 이를 읽어와 새 데이터를 추가한 후 다시 저장합니다.
매개변수:
dest_path
: 로그 데이터를 저장할 경로.new_data
: 추가할 새로운 로그 엔트리 데이터.반환값: 성공 시 Ok(())
를 반환하며, 오류 발생 시 io::Result
타입의 오류 정보를 반환합니다.
구현 과정: