Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ serde = "1.0"
serde_json = { version = "1.0", features = ["preserve_order"] }
time = "0.1"
linked-hash-map = "0.5"
hostname = "0.1"
hex = "0.3"
md5 = "0.3"
try_from = "0.2"
Expand Down
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@
extern crate byteorder;
extern crate chrono;
extern crate hex;
extern crate hostname;
extern crate libc;
extern crate linked_hash_map;
extern crate rand;
extern crate serde;
Expand Down
84 changes: 8 additions & 76 deletions src/oid.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,27 @@
//! ObjectId

use libc;

use std::sync::atomic::{AtomicUsize, Ordering};
use std::{error, fmt, io, result};

use byteorder::{BigEndian, ByteOrder, LittleEndian};
use md5;
use byteorder::{BigEndian, ByteOrder};

use hex::{self, FromHexError};

use rand::{thread_rng, Rng};

use hostname::get_hostname;
use time;

const TIMESTAMP_SIZE: usize = 4;
const MACHINE_ID_SIZE: usize = 3;
const PROCESS_ID_SIZE: usize = 2;
const PROCESS_ID_SIZE: usize = 5;
const COUNTER_SIZE: usize = 3;

const TIMESTAMP_OFFSET: usize = 0;
const MACHINE_ID_OFFSET: usize = TIMESTAMP_OFFSET + TIMESTAMP_SIZE;
const PROCESS_ID_OFFSET: usize = MACHINE_ID_OFFSET + MACHINE_ID_SIZE;
const PROCESS_ID_OFFSET: usize = TIMESTAMP_OFFSET + TIMESTAMP_SIZE;
const COUNTER_OFFSET: usize = PROCESS_ID_OFFSET + PROCESS_ID_SIZE;

const MAX_U24: usize = 0xFF_FFFF;

static OID_COUNTER: AtomicUsize = AtomicUsize::new(0);
static mut MACHINE_BYTES: Option<[u8; 3]> = None;

/// Errors that can occur during OID construction and generation.
#[derive(Debug)]
Expand Down Expand Up @@ -97,17 +90,13 @@ impl ObjectId {
/// for more information.
pub fn new() -> Result<ObjectId> {
let timestamp = ObjectId::gen_timestamp();
let machine_id = ObjectId::gen_machine_id()?;
let process_id = ObjectId::gen_process_id();
let counter = ObjectId::gen_count()?;

let mut buf: [u8; 12] = [0; 12];
for i in 0..TIMESTAMP_SIZE {
buf[TIMESTAMP_OFFSET + i] = timestamp[i];
}
for i in 0..MACHINE_ID_SIZE {
buf[MACHINE_ID_OFFSET + i] = machine_id[i];
}
for i in 0..PROCESS_ID_SIZE {
buf[PROCESS_ID_OFFSET + i] = process_id[i];
}
Expand Down Expand Up @@ -154,20 +143,6 @@ impl ObjectId {
BigEndian::read_u32(&self.id)
}

/// Retrieves the machine id associated with an ObjectId.
pub fn machine_id(&self) -> u32 {
let mut buf: [u8; 4] = [0; 4];
for i in 0..MACHINE_ID_SIZE {
buf[i] = self.id[MACHINE_ID_OFFSET + i];
}
LittleEndian::read_u32(&buf)
}

/// Retrieves the process id associated with an ObjectId.
pub fn process_id(&self) -> u16 {
LittleEndian::read_u16(&self.id[PROCESS_ID_OFFSET..])
}

/// Retrieves the increment counter from an ObjectId.
pub fn counter(&self) -> u32 {
let mut buf: [u8; 4] = [0; 4];
Expand All @@ -193,47 +168,11 @@ impl ObjectId {
buf
}

// Generates a new machine id represented as an MD5-hashed 3-byte-encoded hostname string.
// Represented in Little Endian.
fn gen_machine_id() -> Result<[u8; 3]> {
// Short-circuit if machine id has already been calculated.
// Since the generated machine id is not variable, arising race conditions
// will have the same MACHINE_BYTES result.
unsafe {
if let Some(bytes) = MACHINE_BYTES.as_ref() {
return Ok(*bytes);
}
}

let hostname = get_hostname();
if hostname.is_none() {
return Err(Error::HostnameError);
}

// Hash hostname string
let digest = md5::compute(hostname.unwrap().as_str());
let hash = format!("{:x}", digest);

// Re-convert string to bytes and grab first three
let mut bytes = hash.bytes();
let mut vec: [u8; 3] = [0; 3];
for v in &mut vec {
match bytes.next() {
Some(b) => *v = b,
None => break,
}
}

unsafe { MACHINE_BYTES = Some(vec) };
Ok(vec)
}

// Gets the process ID and returns it as a 2-byte array.
// Represented in Little Endian.
fn gen_process_id() -> [u8; 2] {
let pid = unsafe { libc::getpid() as u16 };
let mut buf: [u8; 2] = [0; 2];
LittleEndian::write_u16(&mut buf, pid);
// Generate a random 5-byte array.
fn gen_process_id() -> [u8; 5] {
let rng = thread_rng().gen_range(0, MAX_U24) as u32;
let mut buf: [u8; 5] = [0; 5];
BigEndian::write_u32(&mut buf, rng);
buf
}

Expand Down Expand Up @@ -276,13 +215,6 @@ impl fmt::Debug for ObjectId {
}
}

#[test]
fn pid_generation() {
let pid = unsafe { libc::getpid() as u16 };
let generated = ObjectId::gen_process_id();
assert_eq!(pid, LittleEndian::read_u16(&generated));
}

#[test]
fn count_generated_is_big_endian() {
let start = 1_122_866;
Expand Down
24 changes: 7 additions & 17 deletions tests/modules/oid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,12 @@ use hex;

#[test]
fn deserialize() {
let bytes: [u8; 12] = [0xDEu8,
0xADu8,
0xBEu8,
0xEFu8, // timestamp is 3735928559
0xEFu8,
0xCDu8,
0xABu8, // machine_id is 11259375
0xFAu8,
0x29u8, // process_id is 10746
0x11u8,
0x22u8,
let bytes: [u8; 12] = [0xDEu8, 0xADu8, 0xBEu8, 0xEFu8, // timestamp is 3735928559
0xEFu8, 0xCDu8, 0xABu8, 0xFAu8, 0x29u8, 0x11u8, 0x22u8,
0x33u8 /* increment is 1122867 */];

let oid = ObjectId::with_bytes(bytes);
assert_eq!(3735928559 as u32, oid.timestamp());
assert_eq!(11259375 as u32, oid.machine_id());
assert_eq!(10746 as u16, oid.process_id());
assert_eq!(1122867 as u32, oid.counter());
}

Expand Down Expand Up @@ -83,14 +72,15 @@ fn oid_not_equals() {
assert!(oid1 != oid2);
}

// check that the last byte in objectIDs is increasing
#[test]
fn increasing() {
fn counter_increasing() {
let oid1_res = ObjectId::new();
let oid2_res = ObjectId::new();
assert!(oid1_res.is_ok());
assert!(oid2_res.is_ok());

let oid1 = oid1_res.unwrap();
let oid2 = oid2_res.unwrap();
assert!(oid1 < oid2);
let oid1_bytes = oid1_res.unwrap().bytes();
let oid2_bytes = oid2_res.unwrap().bytes();
assert!(oid1_bytes[11] < oid2_bytes[11]);
}