rux 0.1.0

Experimental Linux I/O library
Documentation
use pad::{PadStr, Alignment};
use log::{LogLevel, LogMetadata, LogRecord, Log};

use error::Result;
use handler::Handler;
use poll::*;

/// TODO: provide debug/warn/info/... macro implementations with thread_local!
/// Logging Handler
pub trait LoggingBackend
    where Self: Handler<EpollEvent> + 'static
{
    fn level(&self) -> LogLevel;

    fn setup(&self, epfd: &EpollFd) -> Result<Box<Log>>;
}

pub struct SimpleLogging {
    level: LogLevel, /* TODO with proper buffering bufcap: usize,
                      * buf: Vec<u8>,
                      * pos: usize,
                      * limit: usize,
                      * fd: RawFd, */
}

impl SimpleLogging {
    pub fn new(level: LogLevel) -> SimpleLogging {
        SimpleLogging { level: level }
    }
    // pub fn stdout(level: LogLevel) -> SimpleLogging {
    //    let cap = 8 * MEGABYTE;
    //    Self::new(level, cap, 1)
    // }

    // pub fn stderr(level: LogLevel) -> SimpleLogging {
    //    let cap = 8 * MEGABYTE;
    //    Self::new(level, cap, 2)
    // }

    // pub fn new(level: LogLevel, bufcap: usize, fd: RawFd) -> SimpleLogging {
    //    // let logger = SimpleLogging {
    //    //    level: level,
    //    //    // bufcap: bufcap,
    //    //    fd: fd,
    //    //    pos: 0,
    //    //    limit: 0,
    //    //    buf: Vec::with_capacity(bufcap),
    //    // };
    //    // let _ = ::log::set_logger(|max_log_level| {
    //    //    // FIXME
    //    //    //max_log_level.set(LogLevelFilter::Trace);
    //    //    Box::new(logger)
    //    // });
    //    unimplemented!()
    // }
}

// struct SimpleLoggingSender<'a> {
//    //TODO Arc + Sender ?
//    tx: Arc<Sender<&'a LogRecord<'a>>>,
//    level: LogLevel,
// }
//
// unsafe impl <'a> Sync for SimpleLoggingSender<'a> {}
// unsafe impl <'a> Send for SimpleLoggingSender<'a> {}

// impl <'a> Log for SimpleLoggingSender<'a> {
//    fn enabled(&self, metadata: &LogMetadata) -> bool {
//        metadata.level() <= self.level
//    }
//
//    fn log(&self, record: &LogRecord) {
//        self.tx.deref()
//        if self.enabled(record.metadata()) {
//            let ms = format!("{:.*}",
//                             3,
//                             ((::time::precise_time_ns() % 1_000_000_000) / 1_000_000));
//            println!("{}.{} {:<5} [{}] {}",
//                     ::time::strftime("%Y-%m-%d %H:%M:%S", &::time::now()).unwrap(),
//                     ms.pad(3, '0', Alignment::Right, true),
//                     record.level().to_string(),
//                     "rpc-perf",
//                     record.args());
//        }
//    }
// }
struct TracingLogger {
    level: LogLevel,
}

impl Log for TracingLogger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            let location = record.location();
            let ms = format!("{:.*}",
                             3,
                             ((::time::precise_time_ns() % 1_000_000_000) / 1_000_000));
            println!("{}.{} {:<5} {:<20}:{} - {}",
                     ::time::strftime("%Y-%m-%d %H:%M:%S", &::time::now()).unwrap(),
                     ms.pad(3, '0', Alignment::Right, true),
                     record.level().to_string(),
                     location.file(),
                     location.line(),
                     record.args());
        }
    }
}


impl LoggingBackend for SimpleLogging {
    fn level(&self) -> LogLevel {
        self.level
    }
    fn setup(&self, _: &EpollFd) -> Result<Box<Log>> {
        // let interest = EpollEvent {
        //    events: EPOLLOUT | EPOLLET,
        //    data: self.fd as u64,
        // };
        // try!(epfd.register(self.fd, &interest));
        // let (tx, rx) = channel();
        Ok(Box::new(TracingLogger { level: self.level }))
    }
}

impl Handler<EpollEvent> for SimpleLogging {
    fn is_terminated(&self) -> bool {
        false
    }
    fn ready(&mut self, _: &EpollEvent) {
        // let dst = &mut self.buf[self.pos..self.limit];

        // if !dst.is_empty() {
        //    if let Some(cnt) = try!(io::write(self.fd, &dst)) {
        //        self.pos += cnt;
        //        // naive buffering
        //        if self.pos == self.limit {
        //            self.pos = 0;
        //            self.limit = 0;
        //        }
        //    }
        // }
    }
}