feat: add TransactionStatus column family and test (#6958)

This commit is contained in:
Sunny Gleason 2019-11-17 11:26:01 -05:00 committed by GitHub
parent c1b06817a2
commit 086e5da8d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 106 additions and 1 deletions

View File

@ -68,6 +68,7 @@ pub struct Blocktree {
index_cf: LedgerColumn<cf::Index>,
data_shred_cf: LedgerColumn<cf::ShredData>,
code_shred_cf: LedgerColumn<cf::ShredCode>,
transaction_status_cf: LedgerColumn<cf::TransactionStatus>,
last_root: Arc<RwLock<u64>>,
insert_shreds_lock: Arc<Mutex<()>>,
pub new_shreds_signals: Vec<SyncSender<bool>>,
@ -171,6 +172,7 @@ impl Blocktree {
let data_shred_cf = db.column();
let code_shred_cf = db.column();
let transaction_status_cf = db.column();
let db = Arc::new(db);
@ -192,6 +194,7 @@ impl Blocktree {
index_cf,
data_shred_cf,
code_shred_cf,
transaction_status_cf,
new_shreds_signals: vec![],
completed_slots_senders: vec![],
insert_shreds_lock: Arc::new(Mutex::new(())),
@ -283,6 +286,10 @@ impl Blocktree {
.code_shred_cf
.delete_slot(&mut write_batch, from_slot, batch_end)
.unwrap_or(false)
&& self
.transaction_status_cf
.delete_slot(&mut write_batch, from_slot, batch_end)
.unwrap_or(false)
&& self
.orphans_cf
.delete_slot(&mut write_batch, from_slot, batch_end)
@ -1985,6 +1992,7 @@ pub mod tests {
use rand::{seq::SliceRandom, thread_rng};
use solana_sdk::{
hash::Hash, instruction::CompiledInstruction, packet::PACKET_DATA_SIZE, pubkey::Pubkey,
signature::Signature, transaction::TransactionError,
};
use std::{iter::FromIterator, time::Duration};
@ -4071,4 +4079,59 @@ pub mod tests {
drop(ledger);
Blocktree::destroy(&ledger_path).expect("Expected successful database destruction");
}
#[test]
pub fn test_persist_transaction_status() {
let blocktree_path = get_tmp_ledger_path!();
{
let blocktree = Blocktree::open(&blocktree_path).unwrap();
let transaction_status_cf = blocktree.db.column::<cf::TransactionStatus>();
// result not found
assert!(transaction_status_cf
.get((0, Signature::default()))
.unwrap()
.is_none());
// insert value
assert!(transaction_status_cf
.put(
(0, Signature::default()),
&(
solana_sdk::transaction::Result::<()>::Err(
TransactionError::AccountNotFound
),
5u64
)
)
.is_ok());
// result found
let (status, fee) = transaction_status_cf
.get((0, Signature::default()))
.unwrap()
.unwrap();
assert_eq!(status, Err(TransactionError::AccountNotFound));
assert_eq!(fee, 5u64);
// insert value
assert!(transaction_status_cf
.put(
(9, Signature::default()),
&(solana_sdk::transaction::Result::<()>::Ok(()), 9u64)
)
.is_ok());
// result found
let (status, fee) = transaction_status_cf
.get((9, Signature::default()))
.unwrap()
.unwrap();
// deserialize
assert_eq!(status, Ok(()));
assert_eq!(fee, 9u64);
}
Blocktree::destroy(&blocktree_path).expect("Expected successful database destruction");
}
}

View File

@ -9,7 +9,7 @@ use rocksdb::{
};
use serde::de::DeserializeOwned;
use serde::Serialize;
use solana_sdk::clock::Slot;
use solana_sdk::{clock::Slot, signature::Signature};
use std::collections::HashMap;
use std::fs;
use std::marker::PhantomData;
@ -35,6 +35,8 @@ const INDEX_CF: &str = "index";
const DATA_SHRED_CF: &str = "data_shred";
/// Column family for Code Shreds
const CODE_SHRED_CF: &str = "code_shred";
/// Column family for Transaction Status
const TRANSACTION_STATUS_CF: &str = "transaction_status";
#[derive(Debug)]
pub enum BlocktreeError {
@ -111,6 +113,10 @@ pub mod columns {
#[derive(Debug)]
/// The shred erasure code column
pub struct ShredCode;
#[derive(Debug)]
/// The transaction status column
pub struct TransactionStatus;
}
#[derive(Debug)]
@ -120,6 +126,7 @@ impl Rocks {
fn open(path: &Path) -> Result<Rocks> {
use columns::{
DeadSlots, ErasureMeta, Index, Orphans, Root, ShredCode, ShredData, SlotMeta,
TransactionStatus,
};
fs::create_dir_all(&path)?;
@ -140,6 +147,8 @@ impl Rocks {
ColumnFamilyDescriptor::new(ShredData::NAME, get_cf_options());
let shred_code_cf_descriptor =
ColumnFamilyDescriptor::new(ShredCode::NAME, get_cf_options());
let transaction_status_cf_descriptor =
ColumnFamilyDescriptor::new(TransactionStatus::NAME, get_cf_options());
let cfs = vec![
meta_cf_descriptor,
@ -150,6 +159,7 @@ impl Rocks {
index_cf_descriptor,
shred_data_cf_descriptor,
shred_code_cf_descriptor,
transaction_status_cf_descriptor,
];
// Open the database
@ -161,6 +171,7 @@ impl Rocks {
fn columns(&self) -> Vec<&'static str> {
use columns::{
DeadSlots, ErasureMeta, Index, Orphans, Root, ShredCode, ShredData, SlotMeta,
TransactionStatus,
};
vec![
@ -172,6 +183,7 @@ impl Rocks {
SlotMeta::NAME,
ShredData::NAME,
ShredCode::NAME,
TransactionStatus::NAME,
]
}
@ -248,6 +260,36 @@ pub trait TypedColumn: Column {
type Type: Serialize + DeserializeOwned;
}
impl TypedColumn for columns::TransactionStatus {
type Type = (solana_sdk::transaction::Result<()>, u64);
}
impl Column for columns::TransactionStatus {
const NAME: &'static str = TRANSACTION_STATUS_CF;
type Index = (Slot, Signature);
fn key((slot, index): (Slot, Signature)) -> Vec<u8> {
let mut key = vec![0; 8 + 64];
BigEndian::write_u64(&mut key[..8], slot);
key[8..72].clone_from_slice(&index.as_ref()[0..64]);
key
}
fn index<'a>(key: &[u8]) -> (Slot, Signature) {
let slot = BigEndian::read_u64(&key[..8]);
let index = Signature::new(&key[8..72]);
(slot, index)
}
fn slot(index: Self::Index) -> Slot {
index.0
}
fn as_index(slot: Slot) -> Self::Index {
(slot, Signature::default())
}
}
impl Column for columns::ShredCode {
const NAME: &'static str = CODE_SHRED_CF;
type Index = (u64, u64);