<commit_before>//! Wrappers around `rados_completion_t`, providing a safe, futures-based API
//! for asynchronous RADOS operations.

use std::ffi::CString;
use std::mem;
use std::ptr;
use std::sync::Arc;

use ceph_rust::rados::{self, rados_completion_t};
use chrono::{Local, TimeZone};
use futures::{Async, Future, Poll};
use futures::task::AtomicTask;
use libc;

use errors::{self, Error, ErrorKind, Result, get_error_string};
use rados::RadosStat;


/// An abstraction over the handling of RADOS completions which have finished execution.
pub trait Finalize {
    type Output;

    /// On success, we produce output from the state stored in the `Self` type.
    fn on_success(self) -> Self::Output;

    /// On failure, we may either recover from the raw error code or convert the raw error code
    /// into a nicely readable error.
    fn on_failure(self, u32) -> Result<Self::Output>;
}


struct CompletionInfo {
    task: AtomicTask,
}


extern "C" fn callback(_handle: rados_completion_t, info_ptr: *mut libc::c_void) {
    println!("RADOS callback, future ready: {:p}", _handle);

    let info = unsafe { Arc::from_raw(info_ptr as *const CompletionInfo) };

    info.task.notify();
    mem::drop(info);
}


/// Asynchronous I/O through RADOS is abstracted behind the `RadosFuture` type.  Different
/// behaviors corresponding to different AIO operations are implemented as differing type
/// parameters implementing `Finalize`. Use of the `Finalize` trait instead of directly
/// implementing `Future` for every unique AIO operation reduces the risk of incorrectly
/// implementing the different completion modes (called `RadosCaution` here, we allow AIO
/// operations to wait for either acknowledgement from the cluster or for the assurance that the
/// operation has been committed to stable memory.)
pub struct RadosFuture<F: Finalize> {
    info: Arc<CompletionInfo>,
    caution: RadosCaution,
    finalize: Option<F>,
    handle: rados_completion_t,
}


// `RadosFuture` is send as long as the finalizer is. It does not implement `Clone` nor `Sync`,
// however, so all accesses to the `rados_completion_t` - the sole dangerous component - are forced
// to be single-threaded.
unsafe impl<F: Finalize + Send> Send for RadosFuture<F> {}


/// The `RadosCaution` enum is used to denote the level of safety the caller desires from an
/// asynchronous operation.
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum RadosCaution {
    /// Wait for the operation to be acknowledged by the cluster. This indicates
    /// the operation is in-memory in the cluster, but has not yet necessarily
    /// been written to disk.
    Complete,

    /// Wait for the operation to be guaranteed to be successfully written to
    /// disk.
    Safe,
}


impl<F: Finalize> Drop for RadosFuture<F> {
    fn drop(&mut self) {
        println!("RADOS future dropping: {:p}", self.handle);

        unsafe {
            rados::rados_aio_release(self.handle);
        }

        println!("RADOS future dropped: {:p}", self.handle);
    }<commit_msg>Remove debug print statement again<commit_after>//! Wrappers around `rados_completion_t`, providing a safe, futures-based API
//! for asynchronous RADOS operations.

use std::ffi::CString;
use std::mem;
use std::ptr;
use std::sync::Arc;

use ceph_rust::rados::{self, rados_completion_t};
use chrono::{Local, TimeZone};
use futures::{Async, Future, Poll};
use futures::task::AtomicTask;
use libc;

use errors::{self, Error, ErrorKind, Result, get_error_string};
use rados::RadosStat;


/// An abstraction over the handling of RADOS completions which have finished execution.
pub trait Finalize {
    type Output;

    /// On success, we produce output from the state stored in the `Self` type.
    fn on_success(self) -> Self::Output;

    /// On failure, we may either recover from the raw error code or convert the raw error code
    /// into a nicely readable error.
    fn on_failure(self, u32) -> Result<Self::Output>;
}


struct CompletionInfo {
    task: AtomicTask,
}


extern "C" fn callback(_handle: rados_completion_t, info_ptr: *mut libc::c_void) {
    let info = unsafe { Arc::from_raw(info_ptr as *const CompletionInfo) };

    info.task.notify();
    mem::drop(info);
}


/// Asynchronous I/O through RADOS is abstracted behind the `RadosFuture` type.  Different
/// behaviors corresponding to different AIO operations are implemented as differing type
/// parameters implementing `Finalize`. Use of the `Finalize` trait instead of directly
/// implementing `Future` for every unique AIO operation reduces the risk of incorrectly
/// implementing the different completion modes (called `RadosCaution` here, we allow AIO
/// operations to wait for either acknowledgement from the cluster or for the assurance that the
/// operation has been committed to stable memory.)
pub struct RadosFuture<F: Finalize> {
    info: Arc<CompletionInfo>,
    caution: RadosCaution,
    finalize: Option<F>,
    handle: rados_completion_t,
}


// `RadosFuture` is send as long as the finalizer is. It does not implement `Clone` nor `Sync`,
// however, so all accesses to the `rados_completion_t` - the sole dangerous component - are forced
// to be single-threaded.
unsafe impl<F: Finalize + Send> Send for RadosFuture<F> {}


/// The `RadosCaution` enum is used to denote the level of safety the caller desires from an
/// asynchronous operation.
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum RadosCaution {
    /// Wait for the operation to be acknowledged by the cluster. This indicates
    /// the operation is in-memory in the cluster, but has not yet necessarily
    /// been written to disk.
    Complete,

    /// Wait for the operation to be guaranteed to be successfully written to
    /// disk.
    Safe,
}


impl<F: Finalize> Drop for RadosFuture<F> {
    fn drop(&mut self) {
        unsafe {
            rados::rados_aio_release(self.handle);
        }
    }
{'fraction_non_alphanumeric': 0.10355329949238579, 'fraction_numerical': 0.0006768189509306261, 'mean_word_length': 3.7062101910828025, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4349312', 'n_tokens_mistral': 1738, 'n_tokens_neox': 1657, 'n_words': 680}