ryochack
9/16/2018 - 12:47 PM

linux.rs

use std::fs::File;
use std::io::{self, Seek, SeekFrom};
use std::time::Duration;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use mio;
use mio::unix::{EventedFd, UnixReady};
use nix::poll::{self, PollFd, EventFlags};
use libc::c_int;
use super::*;
use inotify;

use logger;

pub struct FileWatcher {
    inotify: inotify::Inotify,
    poll: mio::Poll,
    events: mio::Events,
}

impl FileWatcher {
    pub fn new(file_path: &str) -> io::Result<Self> {
        let mut inotify = inotify::Inotify::init()?;
        inotify.add_watch(file_path, inotify::WatchMask::MODIFY)?;
        let poll = mio::Poll::new()?;
        let events = mio::Events::with_capacity(1024);

        logger::log(&format!("ino:fd={}", inotify.as_raw_fd()));

        poll.register(
            &EventedFd(&inotify.as_raw_fd()),
            mio::Token(0),
            mio::Ready::readable(),
            mio::PollOpt::edge(),
        ).unwrap();

        Ok( Self { inotify, poll, events } )
    }
}

impl FileWatch for FileWatcher {
    fn block(&mut self, timeout: Option<Duration>) -> io::Result<Option<bool>> {
        self.poll.poll(&mut self.events, timeout)?;
        Ok(
            if self.events.is_empty() {
                logger::log("inotify:timeout");
                None
            } else {
                static token_id: usize = 0;
                let evt = &self.events.iter().next();
                let mut buf = [0u8; 1024];
                self.inotify.read_events(&mut buf)?;
                // self.poll.register(
                //     &EventedFd(&self.inotify.as_raw_fd()),
                //     mio::Token(if token_id == 0 { 1 } else { 0 }),
                //     mio::Ready::readable(),
                //     mio::PollOpt::edge(),
                //     ).unwrap();
                if let Some(e) = evt {
                    logger::log("inotify:some");
                    Some(UnixReady::from(e.readiness()).is_hup())
                } else {
                    logger::log("inotify:none");
                    None
                }
            }
        )
    }
}

pub struct StdinWatcher {
    poll: mio::Poll,
    events: mio::Events,
}

impl StdinWatcher {
    pub fn new(fd: RawFd) -> io::Result<Self> {
        let poll = mio::Poll::new()?;
        let events = mio::Events::with_capacity(1024);
        poll.register(
            &EventedFd(&fd),
            mio::Token(0),
            mio::Ready::readable(),
            mio::PollOpt::edge(),
        )?;

        Ok( Self{ poll, events } )
    }
}

impl FileWatch for StdinWatcher {
    fn block(&mut self, timeout: Option<Duration>) -> io::Result<Option<bool>> {
        self.poll.poll(&mut self.events, timeout)?;
        Ok(
            if self.events.is_empty() {
                None
            } else {
                let evt = &self.events.iter().next();
                if let Some(e) = evt {
                    Some(UnixReady::from(e.readiness()).is_hup())
                } else {
                    None
                }
            }
        )
    }
}