Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ env:
sudo: false

script:
- rustup target add wasm32-unknown-unknown
- cargo build -v
- cargo check --target wasm32-unknown-unknown
- cargo test -v --no-fail-fast
- cargo test -v --no-fail-fast --features u2i
- cd serde-tests && cargo test -v --no-fail-fast
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, ATOMIC_USIZE_INIT};
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 = 0xFFFFFF;

static OID_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
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 @@ -156,20 +145,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 @@ -195,47 +170,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.clone());
}
}

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 i in 0..MACHINE_ID_SIZE {
match bytes.next() {
Some(b) => vec[i] = 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 @@ -278,13 +217,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 = 1122866;
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]);
}