use std::sync::atomic::AtomicI32;
use std::sync::atomic::Ordering;
const NOT_READABLE_BIT: i32 = 1;
const NOT_WRITEABLE_BIT: i32 = 1 << 1;
const WRITE_LOGICS_QUEUE_ERROR_BIT: i32 = 1 << 2;
const WRITE_INDEX_FILE_ERROR_BIT: i32 = 1 << 3;
const DISK_FULL_BIT: i32 = 1 << 4;
const FENCED_BIT: i32 = 1 << 5;
const LOGIC_DISK_FULL_BIT: i32 = 1 << 6;
pub struct RunningFlags {
flag_bits: AtomicI32,
}
impl Default for RunningFlags {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl RunningFlags {
#[inline]
pub fn new() -> Self {
RunningFlags {
flag_bits: AtomicI32::new(0),
}
}
#[inline]
pub fn get_flag_bits(&self) -> i32 {
self.flag_bits.load(Ordering::SeqCst)
}
#[inline]
pub fn get_and_make_readable(&self) -> bool {
let result = self.is_readable();
if !result {
self.flag_bits
.fetch_and(!NOT_READABLE_BIT, Ordering::SeqCst);
}
result
}
#[inline]
pub fn is_readable(&self) -> bool {
(self.flag_bits.load(Ordering::SeqCst) & NOT_READABLE_BIT) == 0
}
#[inline]
pub fn is_fenced(&self) -> bool {
(self.flag_bits.load(Ordering::SeqCst) & FENCED_BIT) != 0
}
#[inline]
pub fn get_and_make_not_readable(&self) -> bool {
let result = self.is_readable();
if result {
self.flag_bits.fetch_or(NOT_READABLE_BIT, Ordering::SeqCst);
}
result
}
#[inline]
pub fn clear_logics_queue_error(&self) {
self.flag_bits
.fetch_and(!WRITE_LOGICS_QUEUE_ERROR_BIT, Ordering::SeqCst);
}
#[inline]
pub fn get_and_make_writeable(&self) -> bool {
let result = self.is_writeable();
if !result {
self.flag_bits
.fetch_and(!NOT_WRITEABLE_BIT, Ordering::SeqCst);
}
result
}
#[inline]
pub fn is_writeable(&self) -> bool {
(self.flag_bits.load(Ordering::SeqCst)
& (NOT_WRITEABLE_BIT
| WRITE_LOGICS_QUEUE_ERROR_BIT
| DISK_FULL_BIT
| WRITE_INDEX_FILE_ERROR_BIT
| FENCED_BIT
| LOGIC_DISK_FULL_BIT))
== 0
}
#[inline]
pub fn is_cq_writeable(&self) -> bool {
(self.flag_bits.load(Ordering::SeqCst)
& (NOT_WRITEABLE_BIT
| WRITE_LOGICS_QUEUE_ERROR_BIT
| WRITE_INDEX_FILE_ERROR_BIT
| LOGIC_DISK_FULL_BIT))
== 0
}
#[inline]
pub fn get_and_make_not_writeable(&self) -> bool {
let result = self.is_writeable();
if result {
self.flag_bits.fetch_or(NOT_WRITEABLE_BIT, Ordering::SeqCst);
}
result
}
#[inline]
pub fn make_logics_queue_error(&self) {
self.flag_bits
.fetch_or(WRITE_LOGICS_QUEUE_ERROR_BIT, Ordering::SeqCst);
}
#[inline]
pub fn make_fenced(&self, fenced: bool) {
if fenced {
self.flag_bits.fetch_or(FENCED_BIT, Ordering::SeqCst);
} else {
self.flag_bits.fetch_and(!FENCED_BIT, Ordering::SeqCst);
}
}
#[inline]
pub fn is_logics_queue_error(&self) -> bool {
(self.flag_bits.load(Ordering::SeqCst) & WRITE_LOGICS_QUEUE_ERROR_BIT)
== WRITE_LOGICS_QUEUE_ERROR_BIT
}
#[inline]
pub fn make_index_file_error(&self) {
self.flag_bits
.fetch_or(WRITE_INDEX_FILE_ERROR_BIT, Ordering::SeqCst);
}
#[inline]
pub fn is_index_file_error(&self) -> bool {
(self.flag_bits.load(Ordering::SeqCst) & WRITE_INDEX_FILE_ERROR_BIT)
== WRITE_INDEX_FILE_ERROR_BIT
}
#[inline]
pub fn get_and_make_disk_full(&self) -> bool {
let result = (self.flag_bits.load(Ordering::SeqCst) & DISK_FULL_BIT) != DISK_FULL_BIT;
self.flag_bits.fetch_or(DISK_FULL_BIT, Ordering::SeqCst);
result
}
#[inline]
pub fn get_and_make_disk_ok(&self) -> bool {
let result = (self.flag_bits.load(Ordering::SeqCst) & DISK_FULL_BIT) != DISK_FULL_BIT;
self.flag_bits.fetch_and(!DISK_FULL_BIT, Ordering::SeqCst);
result
}
#[inline]
pub fn get_and_make_logic_disk_full(&self) -> bool {
let result =
(self.flag_bits.load(Ordering::SeqCst) & LOGIC_DISK_FULL_BIT) != LOGIC_DISK_FULL_BIT;
self.flag_bits
.fetch_or(LOGIC_DISK_FULL_BIT, Ordering::SeqCst);
result
}
#[inline]
pub fn get_and_make_logic_disk_ok(&self) -> bool {
let result =
(self.flag_bits.load(Ordering::SeqCst) & LOGIC_DISK_FULL_BIT) != LOGIC_DISK_FULL_BIT;
self.flag_bits
.fetch_and(!LOGIC_DISK_FULL_BIT, Ordering::SeqCst);
result
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_flag_bits() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.get_flag_bits(), 0);
}
#[test]
fn test_get_and_make_readable() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.get_and_make_readable(), true);
assert_eq!(running_flags.is_readable(), true);
assert_eq!(running_flags.get_and_make_readable(), true);
assert_eq!(running_flags.is_readable(), true);
}
#[test]
fn test_is_readable() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.is_readable(), true);
running_flags
.flag_bits
.store(NOT_READABLE_BIT, Ordering::Relaxed);
assert_eq!(running_flags.is_readable(), false);
}
#[test]
fn test_is_fenced() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.is_fenced(), false);
running_flags.flag_bits.store(FENCED_BIT, Ordering::Relaxed);
assert_eq!(running_flags.is_fenced(), true);
}
#[test]
fn test_get_and_make_not_readable() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.get_and_make_not_readable(), true);
assert_eq!(running_flags.is_readable(), false);
assert_eq!(running_flags.get_and_make_not_readable(), false);
assert_eq!(running_flags.is_readable(), false);
}
#[test]
fn test_clear_logics_queue_error() {
let running_flags = RunningFlags::new();
running_flags
.flag_bits
.store(WRITE_LOGICS_QUEUE_ERROR_BIT, Ordering::Relaxed);
running_flags.clear_logics_queue_error();
assert_eq!(running_flags.is_logics_queue_error(), false);
}
#[test]
fn test_get_and_make_writeable() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.get_and_make_writeable(), true);
assert_eq!(running_flags.is_writeable(), true);
assert_eq!(running_flags.is_cq_writeable(), true);
}
#[test]
fn test_is_writeable() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.is_writeable(), true);
running_flags
.flag_bits
.store(NOT_WRITEABLE_BIT, Ordering::Relaxed);
assert_eq!(running_flags.is_writeable(), false);
}
#[test]
fn test_is_cq_writeable() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.is_cq_writeable(), true);
running_flags.flag_bits.store(
NOT_WRITEABLE_BIT | WRITE_LOGICS_QUEUE_ERROR_BIT,
Ordering::Relaxed,
);
assert_eq!(running_flags.is_cq_writeable(), false);
}
#[test]
fn test_get_and_make_not_writeable() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.get_and_make_not_writeable(), true);
assert_eq!(running_flags.is_writeable(), false);
assert_eq!(running_flags.get_and_make_not_writeable(), false);
assert_eq!(running_flags.is_writeable(), false);
}
#[test]
fn test_make_logics_queue_error() {
let running_flags = RunningFlags::new();
running_flags.make_logics_queue_error();
assert_eq!(running_flags.is_logics_queue_error(), true);
}
#[test]
fn test_make_fenced() {
let running_flags = RunningFlags::new();
running_flags.make_fenced(true);
assert_eq!(running_flags.is_fenced(), true);
running_flags.make_fenced(false);
assert_eq!(running_flags.is_fenced(), false);
}
#[test]
fn test_is_logics_queue_error() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.is_logics_queue_error(), false);
running_flags
.flag_bits
.store(WRITE_LOGICS_QUEUE_ERROR_BIT, Ordering::Relaxed);
assert_eq!(running_flags.is_logics_queue_error(), true);
}
#[test]
fn test_make_index_file_error() {
let running_flags = RunningFlags::new();
running_flags.make_index_file_error();
assert_eq!(running_flags.is_index_file_error(), true);
}
#[test]
fn test_is_index_file_error() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.is_index_file_error(), false);
running_flags
.flag_bits
.store(WRITE_INDEX_FILE_ERROR_BIT, Ordering::Relaxed);
assert_eq!(running_flags.is_index_file_error(), true);
}
#[test]
fn test_get_and_make_disk_full() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.get_and_make_disk_full(), true);
}
#[test]
fn test_get_and_make_disk_ok() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.get_and_make_disk_ok(), true);
}
#[test]
fn test_get_and_make_logic_disk_full() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.get_and_make_logic_disk_full(), true);
}
#[test]
fn test_get_and_make_logic_disk_ok() {
let running_flags = RunningFlags::new();
assert_eq!(running_flags.get_and_make_logic_disk_ok(), true);
}
}