use std::{cmp, ops::Deref, sync::Arc};
use bytes::Bytes;
use crate::data::ObjectStatus;
use crate::watch::State;
use super::{ServeError, Track};
pub struct Subgroups {
pub track: Arc<Track>,
}
impl Subgroups {
pub fn produce(self) -> (SubgroupsWriter, SubgroupsReader) {
let (writer, reader) = State::default().split();
let writer = SubgroupsWriter::new(writer, self.track.clone());
let reader = SubgroupsReader::new(reader, self.track);
(writer, reader)
}
}
impl Deref for Subgroups {
type Target = Track;
fn deref(&self) -> &Self::Target {
&self.track
}
}
struct SubgroupsState {
latest_subgroup_reader: Option<SubgroupReader>,
epoch: u64, closed: Result<(), ServeError>,
}
impl Default for SubgroupsState {
fn default() -> Self {
Self {
latest_subgroup_reader: None,
epoch: 0,
closed: Ok(()),
}
}
}
pub struct SubgroupsWriter {
pub info: Arc<Track>,
state: State<SubgroupsState>,
next_subgroup_id: u64, next_group_id: u64, last_group_id: u64, }
impl SubgroupsWriter {
fn new(state: State<SubgroupsState>, track: Arc<Track>) -> Self {
Self {
info: track,
state,
next_subgroup_id: 0,
next_group_id: 0,
last_group_id: 0,
}
}
pub fn append(&mut self, priority: u8) -> Result<SubgroupWriter, ServeError> {
let group_id;
let subgroup_id;
let start_new_group = true;
if start_new_group {
group_id = self.next_group_id;
subgroup_id = 0;
} else {
group_id = self.last_group_id;
subgroup_id = self.next_subgroup_id;
}
self.create(Subgroup {
group_id,
subgroup_id,
priority,
})
}
pub fn create(&mut self, subgroup: Subgroup) -> Result<SubgroupWriter, ServeError> {
let subgroup = SubgroupInfo {
track: self.info.clone(),
group_id: subgroup.group_id,
subgroup_id: subgroup.subgroup_id,
priority: subgroup.priority,
};
let (writer, reader) = subgroup.produce();
let mut state = self.state.lock_mut().ok_or(ServeError::Cancel)?;
if let Some(latest) = &state.latest_subgroup_reader {
if writer.group_id.cmp(&latest.group_id) == cmp::Ordering::Equal {
match writer.subgroup_id.cmp(&latest.subgroup_id) {
cmp::Ordering::Less => return Ok(writer), cmp::Ordering::Equal => return Err(ServeError::Duplicate),
cmp::Ordering::Greater => state.latest_subgroup_reader = Some(reader),
}
} else if writer.group_id.cmp(&latest.group_id) == cmp::Ordering::Greater {
state.latest_subgroup_reader = Some(reader);
} else {
return Ok(writer); }
} else {
state.latest_subgroup_reader = Some(reader);
}
self.next_subgroup_id = state.latest_subgroup_reader.as_ref().unwrap().subgroup_id + 1;
self.next_group_id = state.latest_subgroup_reader.as_ref().unwrap().group_id + 1;
self.last_group_id = state.latest_subgroup_reader.as_ref().unwrap().group_id;
state.epoch += 1;
Ok(writer)
}
pub fn close(self, err: ServeError) -> Result<(), ServeError> {
let state = self.state.lock();
state.closed.clone()?;
let mut state = state.into_mut().ok_or(ServeError::Cancel)?;
state.closed = Err(err);
Ok(())
}
}
impl Deref for SubgroupsWriter {
type Target = Track;
fn deref(&self) -> &Self::Target {
&self.info
}
}
#[derive(Clone)]
pub struct SubgroupsReader {
pub info: Arc<Track>,
state: State<SubgroupsState>,
epoch: u64,
}
impl SubgroupsReader {
fn new(state: State<SubgroupsState>, track_info: Arc<Track>) -> Self {
Self {
info: track_info,
state,
epoch: 0,
}
}
pub async fn next(&mut self) -> Result<Option<SubgroupReader>, ServeError> {
loop {
{
let state = self.state.lock();
if self.epoch != state.epoch {
self.epoch = state.epoch;
return Ok(state.latest_subgroup_reader.clone());
}
state.closed.clone()?;
match state.modified() {
Some(notify) => notify,
None => return Ok(None),
}
}
.await; }
}
pub fn latest(&self) -> Option<(u64, u64)> {
let state = self.state.lock();
state
.latest_subgroup_reader
.as_ref()
.map(|group| (group.group_id, group.latest()))
}
}
impl Deref for SubgroupsReader {
type Target = Track;
fn deref(&self) -> &Self::Target {
&self.info
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Subgroup {
pub group_id: u64,
pub subgroup_id: u64,
pub priority: u8,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SubgroupInfo {
pub track: Arc<Track>,
pub group_id: u64,
pub subgroup_id: u64,
pub priority: u8,
}
impl SubgroupInfo {
pub fn produce(self) -> (SubgroupWriter, SubgroupReader) {
let (writer, reader) = State::default().split();
let info = Arc::new(self);
let writer = SubgroupWriter::new(writer, info.clone());
let reader = SubgroupReader::new(reader, info);
(writer, reader)
}
}
impl Deref for SubgroupInfo {
type Target = Track;
fn deref(&self) -> &Self::Target {
&self.track
}
}
struct SubgroupState {
objects: Vec<SubgroupObjectReader>,
closed: Result<(), ServeError>,
}
impl Default for SubgroupState {
fn default() -> Self {
Self {
objects: Vec::new(),
closed: Ok(()),
}
}
}
pub struct SubgroupWriter {
state: State<SubgroupState>,
pub info: Arc<SubgroupInfo>,
next_object_id: u64,
}
impl SubgroupWriter {
fn new(state: State<SubgroupState>, group: Arc<SubgroupInfo>) -> Self {
Self {
state,
info: group,
next_object_id: 0,
}
}
pub fn write(&mut self, payload: bytes::Bytes) -> Result<(), ServeError> {
let mut object = self.create(payload.len(), None)?;
object.write(payload)?;
Ok(())
}
pub fn create(
&mut self,
size: usize,
extension_headers: Option<crate::data::ExtensionHeaders>,
) -> Result<SubgroupObjectWriter, ServeError> {
let (writer, reader) = SubgroupObject {
group: self.info.clone(),
object_id: self.next_object_id,
status: ObjectStatus::NormalObject,
size,
extension_headers: extension_headers.unwrap_or_default(),
}
.produce();
self.next_object_id += 1;
let mut state = self.state.lock_mut().ok_or(ServeError::Cancel)?;
state.objects.push(reader);
Ok(writer)
}
pub fn close(self, err: ServeError) -> Result<(), ServeError> {
let state = self.state.lock();
state.closed.clone()?;
let mut state = state.into_mut().ok_or(ServeError::Cancel)?;
state.closed = Err(err);
Ok(())
}
pub fn len(&self) -> usize {
self.state.lock().objects.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl Deref for SubgroupWriter {
type Target = SubgroupInfo;
fn deref(&self) -> &Self::Target {
&self.info
}
}
#[derive(Clone)]
pub struct SubgroupReader {
state: State<SubgroupState>,
pub info: Arc<SubgroupInfo>,
read_index: usize,
}
impl SubgroupReader {
fn new(state: State<SubgroupState>, subgroup: Arc<SubgroupInfo>) -> Self {
Self {
state,
info: subgroup,
read_index: 0,
}
}
pub fn latest(&self) -> u64 {
let state = self.state.lock();
state
.objects
.last()
.map(|o| o.object_id)
.unwrap_or_default()
}
pub async fn read_next(&mut self) -> Result<Option<Bytes>, ServeError> {
let object = self.next().await?;
match object {
Some(mut object) => Ok(Some(object.read_all().await?)),
None => Ok(None),
}
}
pub async fn next(&mut self) -> Result<Option<SubgroupObjectReader>, ServeError> {
loop {
{
let state = self.state.lock();
if self.read_index < state.objects.len() {
let object = state.objects[self.read_index].clone();
self.read_index += 1;
return Ok(Some(object));
}
state.closed.clone()?;
match state.modified() {
Some(notify) => notify,
None => return Ok(None),
}
}
.await; }
}
pub fn pos(&self) -> usize {
self.read_index
}
pub fn len(&self) -> usize {
self.state.lock().objects.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl Deref for SubgroupReader {
type Target = SubgroupInfo;
fn deref(&self) -> &Self::Target {
&self.info
}
}
#[derive(Clone, PartialEq, Debug)]
pub struct SubgroupObject {
pub group: Arc<SubgroupInfo>,
pub object_id: u64,
pub size: usize,
pub status: ObjectStatus,
pub extension_headers: crate::data::ExtensionHeaders,
}
impl SubgroupObject {
pub fn produce(self) -> (SubgroupObjectWriter, SubgroupObjectReader) {
let (writer, reader) = State::default().split();
let info = Arc::new(self);
let writer = SubgroupObjectWriter::new(writer, info.clone());
let reader = SubgroupObjectReader::new(reader, info);
(writer, reader)
}
}
impl Deref for SubgroupObject {
type Target = SubgroupInfo;
fn deref(&self) -> &Self::Target {
&self.group
}
}
struct SubgroupObjectState {
chunks: Vec<Bytes>,
closed: Result<(), ServeError>,
}
impl Default for SubgroupObjectState {
fn default() -> Self {
Self {
chunks: Vec::new(),
closed: Ok(()),
}
}
}
pub struct SubgroupObjectWriter {
state: State<SubgroupObjectState>,
pub info: Arc<SubgroupObject>,
remain: usize,
}
impl SubgroupObjectWriter {
fn new(state: State<SubgroupObjectState>, object: Arc<SubgroupObject>) -> Self {
Self {
state,
remain: object.size,
info: object,
}
}
pub fn write(&mut self, chunk: Bytes) -> Result<(), ServeError> {
if chunk.len() > self.remain {
return Err(ServeError::Size);
}
self.remain -= chunk.len();
let mut state = self.state.lock_mut().ok_or(ServeError::Cancel)?;
state.chunks.push(chunk);
Ok(())
}
pub fn close(self, err: ServeError) -> Result<(), ServeError> {
if self.remain != 0 {
return Err(ServeError::Size);
}
let state = self.state.lock();
state.closed.clone()?;
let mut state = state.into_mut().ok_or(ServeError::Cancel)?;
state.closed = Err(err);
Ok(())
}
}
impl Drop for SubgroupObjectWriter {
fn drop(&mut self) {
if self.remain == 0 {
return;
}
if let Some(mut state) = self.state.lock_mut() {
state.closed = Err(ServeError::Size);
}
}
}
impl Deref for SubgroupObjectWriter {
type Target = SubgroupObject;
fn deref(&self) -> &Self::Target {
&self.info
}
}
#[derive(Clone)]
pub struct SubgroupObjectReader {
state: State<SubgroupObjectState>,
pub info: Arc<SubgroupObject>,
index: usize,
}
impl SubgroupObjectReader {
fn new(state: State<SubgroupObjectState>, object: Arc<SubgroupObject>) -> Self {
Self {
state,
info: object,
index: 0,
}
}
pub async fn read(&mut self) -> Result<Option<Bytes>, ServeError> {
loop {
{
let state = self.state.lock();
if self.index < state.chunks.len() {
let chunk = state.chunks[self.index].clone();
self.index += 1;
return Ok(Some(chunk));
}
state.closed.clone()?;
match state.modified() {
Some(notify) => notify,
None => return Ok(None), }
}
.await; }
}
pub async fn read_all(&mut self) -> Result<Bytes, ServeError> {
let mut chunks = Vec::new();
while let Some(chunk) = self.read().await? {
chunks.push(chunk);
}
Ok(Bytes::from(chunks.concat()))
}
}
impl Deref for SubgroupObjectReader {
type Target = SubgroupObject;
fn deref(&self) -> &Self::Target {
&self.info
}
}