1use super::cache::*;
2use super::diff::*;
3use super::iterator::*;
4use super::visitor::*;
5use crate::codec as cyfs_base;
6use crate::*;
7use crate::{RawDecode, RawEncode, RawEncodePurpose};
8
9use async_std::sync::Mutex as AsyncMutex;
10use sha2::Digest;
11use std::collections::{btree_map::Entry, BTreeMap, BTreeSet};
12use std::sync::{Arc, Mutex};
13use serde::Serialize;
14
15
16pub const OBJECT_MAP_KEY_MAX_LEN: usize = 256;
18
19pub const OBJECT_MAP_DESC_FIELDS_RESERVED_SIZE: u8 = 64;
27
28pub const OBJECT_MAP_CONTENT_MAX_ENCODE_SIZE: u64 =
30 (u16::MAX - OBJECT_MAP_DESC_FIELDS_RESERVED_SIZE as u16) as u64;
31
32const SUB_LIST_CONST_LENGTH: u64 = 1900;
34
35#[derive(Debug, Clone, Copy, Eq, PartialEq)]
52pub enum ObjectMapCreateStrategy {
53 NotCreate = 0,
54 CreateNew = 1,
55 CreateIfNotExists = 2,
56}
57
58pub type ObjectMapRef = Arc<AsyncMutex<ObjectMap>>;
59
60#[derive(Clone, Debug, RawEncode, RawDecode)]
61pub struct MapContentT<T>
62where
63 T: Send
64 + Sync
65 + Clone
66 + Eq
67 + PartialEq
68 + std::fmt::Display
69 + RawEncode
70 + IntoObjectMapContentItem,
71{
72 values: BTreeMap<String, T>,
73
74 #[cyfs(skip)]
75 dirty: bool,
76}
77
78impl<T> MapContentT<T>
79where
80 T: Send
81 + Sync
82 + Clone
83 + Eq
84 + PartialEq
85 + std::fmt::Display
86 + RawEncode
87 + IntoObjectMapContentItem,
88{
89 pub fn new() -> Self {
90 Self {
91 values: BTreeMap::new(),
92 dirty: false,
93 }
94 }
95
96 pub fn values(&self) -> &BTreeMap<String, T> {
97 &self.values
98 }
99
100 pub fn into_values(self) -> BTreeMap<String, T> {
101 self.values
102 }
103
104 pub fn merge(&mut self, other: Self) -> BuckyResult<()> {
105 for (key, value) in other.into_values() {
106 match self.values.entry(key.clone()) {
107 Entry::Vacant(v) => {
108 v.insert(value);
109 self.dirty = true;
110 }
111 Entry::Occupied(_o) => {
112 let msg = format!("merge ObjectMap with map content error! object with key already exists! key={}", key);
113 warn!("{}", msg);
114 return Err(BuckyError::new(BuckyErrorCode::AlreadyExists, msg));
115 }
116 }
117 }
118
119 Ok(())
120 }
121
122 pub fn list(&self, list: &mut ObjectMapContentList) -> BuckyResult<usize> {
123 let mut len = 0;
124 for (key, value) in &self.values {
125 list.push_key_value(key, value.to_owned());
126 len += 1;
127 }
128
129 Ok(len)
130 }
131
132 pub fn next(&self, it: &mut ObjectMapIterator) -> BuckyResult<()> {
133 let pos = it.current_pos().into_simple_map();
135 let begin = match pos {
138 Some(key) => std::ops::Bound::Excluded(key),
139 None => std::ops::Bound::Unbounded,
140 };
141
142 let end = std::ops::Bound::Unbounded;
143
144 let range = self.values.range((begin, end));
145 for (key, value) in range {
146 it.push_key_value(key, value.to_owned());
147 if it.is_enough() {
148 it.update_pos(
150 it.depth(),
151 IteratorPosition::SimpleMap(Some(key.to_owned())),
152 );
153 break;
154 }
155 }
156
157 Ok(())
158 }
159
160 pub(crate) fn diff(&self, other: &MapContentT<T>, diff: &mut ObjectMapDiff) {
161 for (key, value) in &self.values {
162 if let Some(other_value) = other.values.get(key) {
163 if value != other_value {
164 diff.map_alter_item(&key, value.to_owned(), other_value.to_owned());
165 }
166 } else {
167 diff.map_item(ObjectMapDiffAction::Remove, &key, value.to_owned());
168 }
169 }
170
171 for (key, value) in &other.values {
172 if let None = self.values.get(key) {
173 diff.map_item(ObjectMapDiffAction::Add, &key, value.to_owned());
174 }
175 }
176 }
177
178 pub fn get_by_key(&self, key: &str) -> BuckyResult<Option<T>> {
180 match self.values.get(key) {
181 Some(v) => Ok(Some(v.to_owned())),
182 None => Ok(None),
183 }
184 }
185
186 pub fn insert_with_key(&mut self, key: &str, value: &T) -> BuckyResult<()> {
187 match self.values.entry(key.to_owned()) {
188 Entry::Vacant(v) => {
189 v.insert(value.to_owned());
190 self.dirty = true;
191 Ok(())
192 }
193 Entry::Occupied(_o) => {
194 let msg = format!("object with key already exists! key={}", key);
195 warn!("{}", msg);
196 Err(BuckyError::new(BuckyErrorCode::AlreadyExists, msg))
197 }
198 }
199 }
200
201 pub fn set_with_key(
202 &mut self,
203 key: &str,
204 value: &T,
205 prev_value: &Option<T>,
206 auto_insert: bool,
207 ) -> BuckyResult<Option<T>> {
208 match self.values.entry(key.to_owned()) {
209 Entry::Vacant(v) => {
210 if auto_insert {
211 debug!(
212 "set_with_key auto insert new value: key={}, value={}",
213 key, value
214 );
215
216 v.insert(value.to_owned());
217 self.dirty = true;
218 Ok(None)
219 } else {
220 let msg = format!("set_with_key but not found! key={}", key);
221 warn!("{}", msg);
222 Err(BuckyError::new(BuckyErrorCode::NotFound, msg))
223 }
224 }
225 Entry::Occupied(o) => {
226 let o = o.into_mut();
227 let old = o.clone();
228
229 if let Some(prev_value) = prev_value {
231 if *prev_value != old {
232 let msg = format!(
233 "set_with_key but not match! key={}, now={}, prev={}",
234 key, old, prev_value
235 );
236 warn!("{}", msg);
237 return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg));
238 }
239 }
240
241 if *value != old {
242 debug!("set_with_key: key={}, {} -> {}", key, old, value);
243 *o = value.to_owned();
244 self.dirty = true;
245 }
246
247 Ok(Some(old))
248 }
249 }
250 }
251
252 pub fn remove_with_key(&mut self, key: &str, prev_value: &Option<T>) -> BuckyResult<Option<T>> {
253 match prev_value {
254 Some(prev_value) => {
255 match self.values.get(key) {
257 Some(current) => {
258 if *current != *prev_value {
259 let msg = format!(
260 "remove_with_key but not match! key={}, now={}, prev={}",
261 key, current, prev_value
262 );
263 warn!("{}", msg);
264 return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg));
265 }
266
267 let ret = self.values.remove(key).unwrap();
268 self.dirty = true;
269 Ok(Some(ret))
270 }
271 None => {
272 Ok(None)
274 }
275 }
276 }
277 None => {
278 let ret = self.values.remove(key);
279 if ret.is_some() {
280 self.dirty = true;
281 }
282 Ok(ret)
283 }
284 }
285 }
286}
287
288#[derive(Clone, Debug, RawEncode, RawDecode)]
289pub struct SetContentT<T>
290where
291 T: Send
292 + Sync
293 + Clone
294 + Ord
295 + std::fmt::Display
296 + RawEncode
297 + IntoObjectMapContentItem
298 + From<SetIteratorPostion>,
299{
300 values: BTreeSet<T>,
301
302 #[cyfs(skip)]
303 dirty: bool,
304}
305
306impl<T> SetContentT<T>
307where
308 T: Send
309 + Sync
310 + Clone
311 + Ord
312 + std::fmt::Display
313 + RawEncode
314 + IntoObjectMapContentItem
315 + From<SetIteratorPostion>,
316 SetIteratorPostion: From<T>,
317{
318 pub fn new() -> Self {
319 Self {
320 values: BTreeSet::new(),
321 dirty: false,
322 }
323 }
324
325 pub fn values(&self) -> &BTreeSet<T> {
326 &self.values
327 }
328
329 pub fn into_values(self) -> BTreeSet<T> {
330 self.values
331 }
332
333 pub fn merge(&mut self, other: Self) -> BuckyResult<()> {
334 for value in other.into_values() {
335 match self.values.insert(value.clone()) {
336 true => {
337 self.dirty = true;
338 continue;
339 }
340 false => {
341 let msg = format!(
342 "merge ObjectMap with set content error! object already exists! value={}",
343 value
344 );
345 warn!("{}", msg);
346 }
347 }
348 }
349
350 Ok(())
351 }
352
353 pub fn list(&self, list: &mut ObjectMapContentList) -> BuckyResult<usize> {
354 let mut len = 0;
355 for value in &self.values {
356 list.push_value(value.to_owned());
357 len += 1;
358 }
359
360 Ok(len)
361 }
362
363 pub fn next(&self, it: &mut ObjectMapIterator) -> BuckyResult<()> {
364 let pos = it.current_pos().into_simple_set();
366
367 let begin: std::ops::Bound<T> = match pos {
368 Some(key) => std::ops::Bound::Excluded(key.into()),
369 None => std::ops::Bound::Unbounded,
370 };
371
372 let end = std::ops::Bound::Unbounded;
373
374 let range = self.values.range((begin, end));
375 for value in range {
376 it.push_value(value.to_owned());
377 if it.is_enough() {
378 let pos = SetIteratorPostion::from(value.to_owned());
380 it.update_pos(it.depth(), IteratorPosition::SimpleSet(Some(pos)));
381 break;
382 }
383 }
384
385 Ok(())
386 }
387
388 pub(crate) fn diff(&self, other: &SetContentT<T>, diff: &mut ObjectMapDiff) {
389 for value in &self.values {
390 if let None = other.values.get(value) {
391 diff.set_item(ObjectMapDiffAction::Remove, value.to_owned());
392 }
393 }
394
395 for value in &other.values {
396 if let None = self.values.get(value) {
397 diff.set_item(ObjectMapDiffAction::Add, value.to_owned());
398 }
399 }
400 }
401
402 pub fn contains(&self, value: &T) -> BuckyResult<bool> {
404 Ok(self.values.contains(value))
405 }
406
407 pub fn insert(&mut self, value: &T) -> BuckyResult<bool> {
408 let ret = self.values.insert(value.to_owned());
409 if ret {
410 self.dirty = true;
411 }
412
413 Ok(ret)
414 }
415
416 pub fn remove(&mut self, value: &T) -> BuckyResult<bool> {
417 let ret = self.values.remove(value);
418 if ret {
419 self.dirty = true;
420 }
421
422 Ok(ret)
423 }
424}
425
426type MapContent = MapContentT<ObjectId>;
427type DiffMapContent = MapContentT<ObjectMapDiffMapItem>;
428
429type SetContent = SetContentT<ObjectId>;
430type DiffSetContent = SetContentT<ObjectMapDiffSetItem>;
431
432#[derive(Clone, Debug, RawEncode, RawDecode)]
433pub enum SimpleContent {
434 Map(MapContent),
435 DiffMap(DiffMapContent),
436 Set(SetContent),
437 DiffSet(DiffSetContent),
438}
439
440impl SimpleContent {
441 pub fn content_type(&self) -> ObjectMapSimpleContentType {
442 match &self {
443 Self::Map(_) => ObjectMapSimpleContentType::Map,
444 Self::DiffMap(_) => ObjectMapSimpleContentType::DiffMap,
445 Self::Set(_) => ObjectMapSimpleContentType::Set,
446 Self::DiffSet(_) => ObjectMapSimpleContentType::DiffSet,
447 }
448 }
449
450 pub fn as_map(&self) -> &MapContent {
451 match &self {
452 Self::Map(value) => value,
453 _ => unreachable!(),
454 }
455 }
456
457 pub fn as_diff_map(&self) -> &DiffMapContent {
458 match &self {
459 Self::DiffMap(value) => value,
460 _ => unreachable!(),
461 }
462 }
463
464 pub fn as_set(&self) -> &SetContent {
465 match &self {
466 Self::Set(value) => value,
467 _ => unreachable!(),
468 }
469 }
470
471 pub fn as_diff_set(&self) -> &DiffSetContent {
472 match &self {
473 Self::DiffSet(value) => value,
474 _ => unreachable!(),
475 }
476 }
477}
478
479#[derive(Clone, Debug, RawEncode, RawDecode)]
480pub struct ObjectMapSimpleContent {
481 depth: u8,
482 content: SimpleContent,
483}
484
485impl ObjectMapSimpleContent {
486 pub fn new(content_type: ObjectMapSimpleContentType, depth: u8) -> Self {
487 let content = match content_type {
488 ObjectMapSimpleContentType::Map => SimpleContent::Map(MapContent::new()),
489 ObjectMapSimpleContentType::DiffMap => SimpleContent::DiffMap(DiffMapContent::new()),
490 ObjectMapSimpleContentType::Set => SimpleContent::Set(SetContent::new()),
491 ObjectMapSimpleContentType::DiffSet => SimpleContent::DiffSet(DiffSetContent::new()),
492 };
493
494 Self { depth, content }
495 }
496
497 pub fn content(&self) -> &SimpleContent {
498 &self.content
499 }
500
501 pub fn len(&self) -> usize {
502 match &self.content {
503 SimpleContent::Map(content) => content.values.len(),
504 SimpleContent::DiffMap(content) => content.values.len(),
505 SimpleContent::Set(content) => content.values.len(),
506 SimpleContent::DiffSet(content) => content.values.len(),
507 }
508 }
509
510 pub fn is_dirty(&self) -> bool {
511 match &self.content {
512 SimpleContent::Map(content) => content.dirty,
513 SimpleContent::DiffMap(content) => content.dirty,
514 SimpleContent::Set(content) => content.dirty,
515 SimpleContent::DiffSet(content) => content.dirty,
516 }
517 }
518
519 pub fn clear_dirty(&mut self) {
520 match &mut self.content {
521 SimpleContent::Map(content) => content.dirty = false,
522 SimpleContent::DiffMap(content) => content.dirty = false,
523 SimpleContent::Set(content) => content.dirty = false,
524 SimpleContent::DiffSet(content) => content.dirty = false,
525 }
526 }
527
528 pub fn merge(&mut self, other: Self) -> BuckyResult<()> {
529 match &mut self.content {
530 SimpleContent::Map(content) => match other.content {
531 SimpleContent::Map(other) => {
532 content.merge(other)?;
533 }
534 _ => {
535 let msg =
536 format!("merge ObjectMap with map content error! unmatch content type");
537 error!("{}", msg);
538 return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg));
539 }
540 },
541 SimpleContent::DiffMap(content) => match other.content {
542 SimpleContent::DiffMap(other) => {
543 content.merge(other)?;
544 }
545 _ => {
546 let msg =
547 format!("merge ObjectMap with diffmap content error! unmatch content type");
548 error!("{}", msg);
549 return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg));
550 }
551 },
552
553 SimpleContent::Set(content) => match other.content {
554 SimpleContent::Set(other) => {
555 content.merge(other)?;
556 }
557 _ => {
558 let msg =
559 format!("merge ObjectMap with set content error! unmatch content type");
560 error!("{}", msg);
561 return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg));
562 }
563 },
564 SimpleContent::DiffSet(content) => match other.content {
565 SimpleContent::DiffSet(other) => {
566 content.merge(other)?;
567 }
568 _ => {
569 let msg =
570 format!("merge ObjectMap with diffet content error! unmatch content type");
571 error!("{}", msg);
572 return Err(BuckyError::new(BuckyErrorCode::Unmatch, msg));
573 }
574 },
575 }
576
577 Ok(())
578 }
579
580 pub async fn get_or_create_child_object_map(
582 &mut self,
583 builder: &ObjectMapBuilder,
584 cache: &ObjectMapOpEnvCacheRef,
585 key: &str,
586 auto_create: ObjectMapCreateStrategy,
587 access: Option<AccessString>,
588 ) -> BuckyResult<Option<ObjectMapRef>> {
589 let ret = self.get_by_key(key)?;
590 match ret {
591 Some(sub_id) => {
592 if auto_create == ObjectMapCreateStrategy::CreateNew {
593 let msg = format!(
594 "objectmap solt already been taken! key={}, current={}, type={:?}",
595 key, sub_id, sub_id.obj_type_code(),
596 );
597 warn!("{}", msg);
598 return Err(BuckyError::new(BuckyErrorCode::AlreadyExists, msg));
599 }
600
601 if sub_id.obj_type_code() != ObjectTypeCode::ObjectMap {
603 let msg = format!(
604 "objectmap solt already been taken by other object! key={}, current={}, type={:?}",
605 key, sub_id, sub_id.obj_type_code(),
606 );
607 warn!("{}", msg);
608 return Err(BuckyError::new(BuckyErrorCode::AlreadyExists, msg));
609 }
610
611 let sub_map = cache.get_object_map(&sub_id).await?;
613 if sub_map.is_none() {
614 let msg = format!(
615 "get sub objectmap from cache but not found! key={}, id={}",
616 key, sub_id
617 );
618 error!("{}", msg);
619 return Err(BuckyError::new(BuckyErrorCode::NotFound, msg));
620 }
621
622 Ok(Some(sub_map.unwrap()))
623 }
624 None => {
625 if auto_create == ObjectMapCreateStrategy::NotCreate {
626 return Ok(None);
627 }
628
629 let sub = builder.clone().class(ObjectMapClass::Root).build();
631 let sub_id = sub.flush_id();
632 if let Err(e) = self.insert_with_key(key, &sub_id) {
633 let msg = format!("insert object map with key={} error! {}", key, e);
634 error!("{}", msg);
635 return Err(BuckyError::new(e.code(), msg));
636 }
637
638 debug!("object map new sub: key={}, sub={}", key, sub_id);
639 let sub_map = cache.put_object_map(&sub_id, sub, access)?;
640 Ok(Some(sub_map))
641 }
642 }
643 }
644
645 pub fn list(&self, list: &mut ObjectMapContentList) -> BuckyResult<usize> {
646 match &self.content {
647 SimpleContent::Map(content) => content.list(list),
648 SimpleContent::DiffMap(content) => content.list(list),
649 SimpleContent::Set(content) => content.list(list),
650 SimpleContent::DiffSet(content) => content.list(list),
651 }
652 }
653
654 pub fn next(&self, it: &mut ObjectMapIterator) -> BuckyResult<()> {
655 match &self.content {
656 SimpleContent::Map(content) => content.next(it),
657 SimpleContent::DiffMap(content) => content.next(it),
658 SimpleContent::Set(content) => content.next(it),
659 SimpleContent::DiffSet(content) => content.next(it),
660 }
661 }
662
663 pub(crate) fn diff(&self, other: &Self, diff: &mut ObjectMapDiff) {
664 match &self.content {
665 SimpleContent::Map(content) => content.diff(other.content.as_map(), diff),
666 SimpleContent::DiffMap(content) => content.diff(other.content.as_diff_map(), diff),
667 SimpleContent::Set(content) => content.diff(other.content.as_set(), diff),
668 SimpleContent::DiffSet(content) => content.diff(other.content.as_diff_set(), diff),
669 }
670 }
671
672 pub(crate) async fn visit(&self, visitor: &mut impl ObjectMapVisitor) -> BuckyResult<()> {
674 match &self.content {
675 SimpleContent::Map(content) => {
676 for (key, value) in &content.values {
677 visitor.visit_map_item(&key, value).await?;
678 }
679 }
680 SimpleContent::DiffMap(content) => {
681 for (key, value) in &content.values {
682 visitor.visit_diff_map_item(&key, value).await?;
683 }
684 }
685 SimpleContent::Set(content) => {
686 for value in &content.values {
687 visitor.visit_set_item(value).await?;
688 }
689 }
690 SimpleContent::DiffSet(content) => {
691 for value in &content.values {
692 visitor.visit_diff_set_item(value).await?;
693 }
694 }
695 }
696
697 Ok(())
698 }
699
700 pub fn get_by_key(&self, key: &str) -> BuckyResult<Option<ObjectId>> {
702 match &self.content {
703 SimpleContent::Map(content) => content.get_by_key(key),
704 _ => {
705 let msg = format!(
706 "unmatch objectmap content type: {:?}, key={}",
707 self.content.content_type(),
708 key
709 );
710 warn!("{}", msg);
711
712 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
713 }
714 }
715 }
716
717 pub fn insert_with_key(&mut self, key: &str, value: &ObjectId) -> BuckyResult<()> {
718 match &mut self.content {
719 SimpleContent::Map(content) => content.insert_with_key(key, value),
720 _ => {
721 let msg = format!(
722 "unmatch objectmap content type: {:?}, key={}",
723 self.content.content_type(),
724 key
725 );
726 warn!("{}", msg);
727
728 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
729 }
730 }
731 }
732
733 pub fn set_with_key(
734 &mut self,
735 key: &str,
736 value: &ObjectId,
737 prev_value: &Option<ObjectId>,
738 auto_insert: bool,
739 ) -> BuckyResult<Option<ObjectId>> {
740 match &mut self.content {
741 SimpleContent::Map(content) => {
742 content.set_with_key(key, value, prev_value, auto_insert)
743 }
744 _ => {
745 let msg = format!(
746 "unmatch objectmap content type: {:?}, key={}",
747 self.content.content_type(),
748 key
749 );
750 warn!("{}", msg);
751
752 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
753 }
754 }
755 }
756
757 pub fn remove_with_key(
758 &mut self,
759 key: &str,
760 prev_value: &Option<ObjectId>,
761 ) -> BuckyResult<Option<ObjectId>> {
762 match &mut self.content {
763 SimpleContent::Map(content) => content.remove_with_key(key, prev_value),
764 _ => {
765 let msg = format!(
766 "unmatch objectmap content type: {:?}, key={}",
767 self.content.content_type(),
768 key
769 );
770 warn!("{}", msg);
771
772 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
773 }
774 }
775 }
776
777 pub fn diff_get_by_key(&self, key: &str) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
779 match &self.content {
780 SimpleContent::DiffMap(content) => content.get_by_key(key),
781 _ => {
782 let msg = format!(
783 "unmatch objectmap content type: {:?}, key={}",
784 self.content.content_type(),
785 key
786 );
787 warn!("{}", msg);
788
789 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
790 }
791 }
792 }
793
794 pub fn diff_insert_with_key(
795 &mut self,
796 key: &str,
797 value: &ObjectMapDiffMapItem,
798 ) -> BuckyResult<()> {
799 match &mut self.content {
800 SimpleContent::DiffMap(content) => content.insert_with_key(key, value),
801 _ => {
802 let msg = format!(
803 "unmatch objectmap content type: {:?}, key={}",
804 self.content.content_type(),
805 key
806 );
807 warn!("{}", msg);
808
809 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
810 }
811 }
812 }
813
814 pub fn diff_set_with_key(
815 &mut self,
816 key: &str,
817 value: &ObjectMapDiffMapItem,
818 prev_value: &Option<ObjectMapDiffMapItem>,
819 auto_insert: bool,
820 ) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
821 match &mut self.content {
822 SimpleContent::DiffMap(content) => {
823 content.set_with_key(key, value, prev_value, auto_insert)
824 }
825 _ => {
826 let msg = format!(
827 "unmatch objectmap content type: {:?}, key={}",
828 self.content.content_type(),
829 key
830 );
831 warn!("{}", msg);
832
833 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
834 }
835 }
836 }
837
838 pub fn diff_remove_with_key(
839 &mut self,
840 key: &str,
841 prev_value: &Option<ObjectMapDiffMapItem>,
842 ) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
843 match &mut self.content {
844 SimpleContent::DiffMap(content) => content.remove_with_key(key, prev_value),
845 _ => {
846 let msg = format!(
847 "unmatch objectmap content type: {:?}, key={}",
848 self.content.content_type(),
849 key
850 );
851 warn!("{}", msg);
852
853 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
854 }
855 }
856 }
857
858 pub fn contains(&self, object_id: &ObjectId) -> BuckyResult<bool> {
860 match &self.content {
861 SimpleContent::Set(content) => content.contains(object_id),
862 _ => {
863 let msg = format!(
864 "unmatch objectmap content type: {:?}, object={}",
865 self.content.content_type(),
866 object_id,
867 );
868 warn!("{}", msg);
869
870 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
871 }
872 }
873 }
874
875 pub fn insert(&mut self, object_id: &ObjectId) -> BuckyResult<bool> {
876 match &mut self.content {
877 SimpleContent::Set(content) => content.insert(object_id),
878 _ => {
879 let msg = format!(
880 "unmatch objectmap content type: {:?}, object={}",
881 self.content.content_type(),
882 object_id,
883 );
884 warn!("{}", msg);
885
886 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
887 }
888 }
889 }
890
891 pub fn remove(&mut self, object_id: &ObjectId) -> BuckyResult<bool> {
892 match &mut self.content {
893 SimpleContent::Set(content) => content.remove(object_id),
894 _ => {
895 let msg = format!(
896 "unmatch objectmap content type: {:?}, object={}",
897 self.content.content_type(),
898 object_id,
899 );
900 warn!("{}", msg);
901
902 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
903 }
904 }
905 }
906
907 pub fn diff_contains(&self, object_id: &ObjectMapDiffSetItem) -> BuckyResult<bool> {
909 match &self.content {
910 SimpleContent::DiffSet(content) => content.contains(object_id),
911 _ => {
912 let msg = format!(
913 "unmatch objectmap content type: {:?}, object={}",
914 self.content.content_type(),
915 object_id,
916 );
917 warn!("{}", msg);
918
919 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
920 }
921 }
922 }
923
924 pub fn diff_insert(&mut self, object_id: &ObjectMapDiffSetItem) -> BuckyResult<bool> {
925 match &mut self.content {
926 SimpleContent::DiffSet(content) => content.insert(object_id),
927 _ => {
928 let msg = format!(
929 "unmatch objectmap content type: {:?}, object={}",
930 self.content.content_type(),
931 object_id,
932 );
933 warn!("{}", msg);
934
935 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
936 }
937 }
938 }
939
940 pub fn diff_remove(&mut self, object_id: &ObjectMapDiffSetItem) -> BuckyResult<bool> {
941 match &mut self.content {
942 SimpleContent::DiffSet(content) => content.remove(object_id),
943 _ => {
944 let msg = format!(
945 "unmatch objectmap content type: {:?}, object={}",
946 self.content.content_type(),
947 object_id,
948 );
949 warn!("{}", msg);
950
951 Err(BuckyError::new(BuckyErrorCode::NotSupport, msg))
952 }
953 }
954 }
955}
956
957#[derive(Clone, Debug, RawEncode, RawDecode, Serialize)]
958pub struct ObjectMapHubItem {
959 id: ObjectId,
960}
961
962#[derive(Clone, Debug, RawEncode, RawDecode)]
963pub struct ObjectMapHubContent {
964 depth: u8,
965 subs: BTreeMap<u16, ObjectMapHubItem>,
966
967 #[cyfs(skip)]
968 dirty: bool,
969}
970
971impl ObjectMapHubContent {
972 pub fn new(depth: u8) -> Self {
973 Self {
974 depth,
975 subs: BTreeMap::new(),
976 dirty: false,
977 }
978 }
979
980 pub fn subs(&self) -> &BTreeMap<u16, ObjectMapHubItem> {
981 &self.subs
982 }
983
984 pub fn is_dirty(&self) -> bool {
985 self.dirty
986 }
987
988 pub fn clear_dirty(&mut self) {
989 self.dirty = false;
990 }
991
992 fn hash_bytes(&self, key: &[u8]) -> u16 {
993 use std::collections::hash_map::DefaultHasher;
994 use std::hash::Hasher;
995
996 let mut hasher = DefaultHasher::new();
997 let mut sha256 = sha2::Sha256::new();
998 sha256.input(key);
999 sha256.input([self.depth]);
1000 hasher.write(&sha256.result());
1001 let index = (hasher.finish() % SUB_LIST_CONST_LENGTH) as u16;
1002
1003 index
1014 }
1015
1016 async fn get_sub(
1017 &self,
1018 cache: &ObjectMapOpEnvCacheRef,
1019 key: &[u8],
1020 ) -> BuckyResult<Option<ObjectMapRef>> {
1021 let index = self.hash_bytes(key);
1022 match self.subs.get(&index) {
1023 Some(sub) => cache.get_object_map(&sub.id).await,
1024 None => Ok(None),
1025 }
1026 }
1027
1028 async fn get_sub_mut(
1029 &mut self,
1030 builder: Option<&ObjectMapBuilder>,
1031 cache: &ObjectMapOpEnvCacheRef,
1032 key: &[u8],
1033 auto_create: bool,
1034 ) -> BuckyResult<Option<(&mut ObjectMapHubItem, ObjectMap)>> {
1035 let index = self.hash_bytes(key);
1036 match self.subs.entry(index) {
1037 Entry::Occupied(o) => {
1038 let sub = o.into_mut();
1039 match cache.get_object_map(&sub.id).await? {
1040 Some(item) => Ok(Some((sub, item.lock().await.clone()))),
1041 None => {
1042 let msg = format!("objectmap sub item exists but load from noc not found! sub={}, key={:?}, index={}", sub.id, key, index);
1043 error!("{}", msg);
1044 Err(BuckyError::new(BuckyErrorCode::NotFound, msg))
1045 }
1046 }
1047 }
1048 Entry::Vacant(v) => {
1049 if auto_create {
1050 let builder = builder.unwrap().clone().class(ObjectMapClass::Sub);
1052 let sub = builder.build();
1053 let id = sub.flush_id();
1054
1055 let item = ObjectMapHubItem { id };
1056 let solt = v.insert(item);
1057 self.dirty = true;
1058
1059 Ok(Some((solt, sub)))
1062 } else {
1063 Ok(None)
1064 }
1065 }
1066 }
1067 }
1068
1069 fn remove_sub(&mut self, _cache: &ObjectMapOpEnvCacheRef, key: &[u8]) -> Option<ObjectId> {
1070 let index = self.hash_bytes(key);
1071 match self.subs.remove(&index) {
1072 Some(sub) => Some(sub.id),
1073 None => None,
1074 }
1075 }
1076
1077 #[async_recursion::async_recursion]
1081 pub async fn get_or_create_child_object_map(
1082 &mut self,
1083 builder: &ObjectMapBuilder,
1084 cache: &ObjectMapOpEnvCacheRef,
1085 key: &str,
1086 auto_create: ObjectMapCreateStrategy,
1087 access: Option<AccessString>,
1088 ) -> BuckyResult<Option<ObjectMapRef>> {
1089 let sub_auto_create = match auto_create {
1090 ObjectMapCreateStrategy::NotCreate => false,
1091 _ => true,
1092 };
1093
1094 let sub = self
1095 .get_sub_mut(Some(builder), cache, key.as_bytes(), sub_auto_create)
1096 .await?;
1097 match sub {
1098 Some((solt, mut obj_map)) => {
1099 let ret = obj_map
1101 .get_or_create_child_object_map(cache, key, builder.content_type(), auto_create, access)
1102 .await?;
1103 let current_id = obj_map.cached_object_id();
1104 let new_id = obj_map.flush_id();
1105
1106 if current_id != Some(new_id) {
1108 cache.put_object_map(&new_id, obj_map, None)?;
1109 solt.id = new_id;
1110 self.dirty = true;
1111 }
1112 Ok(ret)
1113 }
1114 None => Ok(None),
1115 }
1116 }
1117
1118 #[async_recursion::async_recursion]
1119 pub async fn list(
1120 &self,
1121 cache: &ObjectMapOpEnvCacheRef,
1122 list: &mut ObjectMapContentList,
1123 ) -> BuckyResult<u64> {
1124 let mut total: u64 = 0;
1125 for (_key, sub) in &self.subs {
1126 let sub_map = cache.get_object_map(&sub.id).await?;
1127 if sub_map.is_none() {
1128 let msg = format!(
1129 "read objectmap to list but sub item not found: id={}",
1130 sub.id
1131 );
1132 error!("{}", msg);
1133 return Err(BuckyError::new(BuckyErrorCode::NotFound, msg));
1134 }
1135 let sub_map = sub_map.unwrap();
1136 let obj = sub_map.lock().await;
1137 total += obj.list(cache, list).await? as u64;
1138 }
1139
1140 Ok(total)
1141 }
1142
1143 #[async_recursion::async_recursion]
1144 pub async fn list_subs(
1145 &self,
1146 cache: &ObjectMapOpEnvCacheRef,
1147 list: &mut Vec<ObjectId>,
1148 ) -> BuckyResult<u64> {
1149 let mut total: u64 = 0;
1150 for (_key, sub) in &self.subs {
1151 list.push(sub.id.clone());
1152
1153 let sub_map = cache.get_object_map(&sub.id).await?;
1154 if sub_map.is_none() {
1155 let msg = format!(
1156 "read objectmap to list but sub item not found: id={}",
1157 sub.id
1158 );
1159 error!("{}", msg);
1160 return Err(BuckyError::new(BuckyErrorCode::NotFound, msg));
1161 }
1162 let sub_map = sub_map.unwrap();
1163 let obj = sub_map.lock().await;
1164 total += obj.list_subs(cache, list).await? as u64;
1165 }
1166
1167 Ok(total)
1168 }
1169
1170 #[async_recursion::async_recursion]
1171 pub async fn next(&self, it: &mut ObjectMapIterator) -> BuckyResult<()> {
1172 let pos = it.current_pos().into_hub();
1174 let depth = it.depth();
1175
1176 let begin = match pos {
1177 Some(key) => std::ops::Bound::Included(key),
1178 None => std::ops::Bound::Unbounded,
1179 };
1180
1181 let end = std::ops::Bound::Unbounded;
1182
1183 let range = self.subs.range((begin, end));
1184 for (key, sub) in range {
1185 let sub_map = it.cache.get_object_map(&sub.id).await?;
1186 if sub_map.is_none() {
1187 let msg = format!(
1188 "load sub object map from cache but not found! id={}",
1189 sub.id
1190 );
1191 error!("{}", msg);
1192 return Err(BuckyError::new(BuckyErrorCode::NotFound, msg));
1193 }
1194 let sub_map = sub_map.unwrap();
1195 {
1196 let obj = sub_map.lock().await;
1197 it.inc_depth(obj.mode(), obj.content_type());
1198
1199 obj.next(it).await?;
1200 }
1201 if it.is_enough() {
1202 it.update_pos(depth, IteratorPosition::Hub(Some(key.to_owned())));
1204
1205 return Ok(());
1206 }
1207
1208 it.dec_depth();
1210 }
1211
1212 assert!(!it.is_enough());
1213
1214 Ok(())
1215 }
1216
1217 pub(crate) fn diff(&self, other: &Self, diff: &mut ObjectMapDiff) {
1218 for (key, value) in &self.subs {
1219 if let Some(other_value) = other.subs.get(key) {
1220 if value.id != other_value.id {
1221 diff.pend_async_sub_alter(&value.id, &other_value.id);
1222 }
1223 } else {
1224 diff.pend_async_remove(&value.id);
1225 }
1226 }
1227
1228 for (key, value) in &other.subs {
1229 if let None = self.subs.get(key) {
1230 diff.pend_async_add(&value.id);
1231 }
1232 }
1233 }
1234
1235 pub async fn visit(&self, visitor: &mut impl ObjectMapVisitor) -> BuckyResult<()> {
1237 for (_key, value) in &self.subs {
1238 visitor.visit_hub_item(&value.id).await?;
1239 }
1240
1241 Ok(())
1242 }
1243
1244 #[async_recursion::async_recursion]
1246 pub async fn get_by_key(
1247 &self,
1248 cache: &ObjectMapOpEnvCacheRef,
1249 key: &str,
1250 ) -> BuckyResult<Option<ObjectId>> {
1251 let sub = self.get_sub(cache, key.as_bytes()).await?;
1252 match sub {
1253 Some(sub) => {
1254 let obj_map = sub.lock().await;
1255 obj_map.get_by_key(cache, key).await
1256 }
1257 None => Ok(None),
1258 }
1259 }
1260
1261 #[async_recursion::async_recursion]
1262 pub async fn insert_with_key(
1263 &mut self,
1264 builder: &ObjectMapBuilder,
1265 cache: &ObjectMapOpEnvCacheRef,
1266 key: &str,
1267 value: &ObjectId,
1268 ) -> BuckyResult<()> {
1269 let sub = self
1270 .get_sub_mut(Some(builder), cache, key.as_bytes(), true)
1271 .await?;
1272 match sub {
1273 Some((solt, mut obj_map)) => {
1274 obj_map.insert_with_key(&cache, &key, &value).await?;
1275
1276 let new_id = obj_map.flush_id();
1277 cache.put_object_map(&new_id, obj_map, None)?;
1279 solt.id = new_id;
1280 self.dirty = true;
1281 Ok(())
1282 }
1283 None => {
1284 unreachable!();
1285 }
1286 }
1287 }
1288
1289 #[async_recursion::async_recursion]
1290 pub async fn set_with_key(
1291 &mut self,
1292 builder: &ObjectMapBuilder,
1293 cache: &ObjectMapOpEnvCacheRef,
1294 key: &str,
1295 value: &ObjectId,
1296 prev_value: &Option<ObjectId>,
1297 auto_insert: bool,
1298 ) -> BuckyResult<Option<ObjectId>> {
1299 let sub = self
1300 .get_sub_mut(Some(builder), cache, key.as_bytes(), true)
1301 .await?;
1302 match sub {
1303 Some((solt, mut obj_map)) => {
1304 let ret = obj_map
1305 .set_with_key(cache, key, value, prev_value, auto_insert)
1306 .await?;
1307 let current_id = obj_map.cached_object_id();
1308 let new_id = obj_map.flush_id();
1309 if current_id != Some(new_id) {
1310 cache.put_object_map(&new_id, obj_map, None)?;
1311 solt.id = new_id;
1312 self.dirty = true;
1313 }
1314 Ok(ret)
1315 }
1316 None => {
1317 unreachable!();
1318 }
1319 }
1320 }
1321
1322 #[async_recursion::async_recursion]
1323 pub async fn remove_with_key(
1324 &mut self,
1325 cache: &ObjectMapOpEnvCacheRef,
1326 key: &str,
1327 prev_value: &Option<ObjectId>,
1328 ) -> BuckyResult<Option<ObjectId>> {
1329 let sub = self.get_sub_mut(None, cache, key.as_bytes(), false).await?;
1330 match sub {
1331 Some((solt, mut obj_map)) => {
1332 let ret = obj_map.remove_with_key(cache, key, prev_value).await?;
1333
1334 if ret.is_some() {
1335 if obj_map.count() > 0 {
1336 let new_id = obj_map.flush_id();
1337 cache.put_object_map(&new_id, obj_map, None)?;
1338 solt.id = new_id;
1339 } else {
1340 debug!(
1341 "sub objectmap is empty! now will remove: key={}, sub={}",
1342 key, solt.id
1343 );
1344 let sub_id = solt.id.clone();
1345 drop(solt);
1346 drop(obj_map);
1347
1348 let ret = self.remove_sub(cache, key.as_bytes());
1349 assert_eq!(ret, Some(sub_id));
1350 }
1351 self.dirty = true;
1352 }
1353 Ok(ret)
1354 }
1355 None => {
1356 unreachable!();
1357 }
1358 }
1359 }
1360
1361 #[async_recursion::async_recursion]
1363 pub async fn diff_get_by_key(
1364 &self,
1365 cache: &ObjectMapOpEnvCacheRef,
1366 key: &str,
1367 ) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
1368 let sub = self.get_sub(cache, key.as_bytes()).await?;
1369 match sub {
1370 Some(sub) => {
1371 let obj_map = sub.lock().await;
1372 obj_map.diff_get_by_key(cache, key).await
1373 }
1374 None => Ok(None),
1375 }
1376 }
1377
1378 #[async_recursion::async_recursion]
1379 pub async fn diff_insert_with_key(
1380 &mut self,
1381 builder: &ObjectMapBuilder,
1382 cache: &ObjectMapOpEnvCacheRef,
1383 key: &str,
1384 value: &ObjectMapDiffMapItem,
1385 ) -> BuckyResult<()> {
1386 let sub = self
1387 .get_sub_mut(Some(builder), cache, key.as_bytes(), true)
1388 .await?;
1389 match sub {
1390 Some((solt, mut obj_map)) => {
1391 obj_map.diff_insert_with_key(&cache, &key, &value).await?;
1392
1393 let new_id = obj_map.flush_id();
1394 cache.put_object_map(&new_id, obj_map, None)?;
1396 solt.id = new_id;
1397 self.dirty = true;
1398 Ok(())
1399 }
1400 None => {
1401 unreachable!();
1402 }
1403 }
1404 }
1405
1406 #[async_recursion::async_recursion]
1407 pub async fn diff_set_with_key(
1408 &mut self,
1409 builder: &ObjectMapBuilder,
1410 cache: &ObjectMapOpEnvCacheRef,
1411 key: &str,
1412 value: &ObjectMapDiffMapItem,
1413 prev_value: &Option<ObjectMapDiffMapItem>,
1414 auto_insert: bool,
1415 ) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
1416 let sub = self
1417 .get_sub_mut(Some(builder), cache, key.as_bytes(), true)
1418 .await?;
1419 match sub {
1420 Some((solt, mut obj_map)) => {
1421 let ret = obj_map
1422 .diff_set_with_key(cache, key, value, prev_value, auto_insert)
1423 .await?;
1424 let current_id = obj_map.cached_object_id();
1425 let new_id = obj_map.flush_id();
1426 if current_id != Some(new_id) {
1427 cache.put_object_map(&new_id, obj_map, None)?;
1428 solt.id = new_id;
1429 self.dirty = true;
1430 }
1431 Ok(ret)
1432 }
1433 None => {
1434 unreachable!();
1435 }
1436 }
1437 }
1438
1439 #[async_recursion::async_recursion]
1440 pub async fn diff_remove_with_key(
1441 &mut self,
1442 cache: &ObjectMapOpEnvCacheRef,
1443 key: &str,
1444 prev_value: &Option<ObjectMapDiffMapItem>,
1445 ) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
1446 let sub = self.get_sub_mut(None, cache, key.as_bytes(), false).await?;
1447 match sub {
1448 Some((solt, mut obj_map)) => {
1449 let ret = obj_map.diff_remove_with_key(cache, key, prev_value).await?;
1450
1451 if ret.is_some() {
1452 if obj_map.count() > 0 {
1453 let new_id = obj_map.flush_id();
1454 cache.put_object_map(&new_id, obj_map, None)?;
1455 solt.id = new_id;
1456 } else {
1457 debug!(
1458 "sub objectmap is empty! now will remove: key={}, sub={}",
1459 key, solt.id
1460 );
1461 let sub_id = solt.id.clone();
1462 drop(solt);
1463 drop(obj_map);
1464
1465 let ret = self.remove_sub(cache, key.as_bytes());
1466 assert_eq!(ret, Some(sub_id));
1467 }
1468 self.dirty = true;
1469 }
1470 Ok(ret)
1471 }
1472 None => {
1473 unreachable!();
1474 }
1475 }
1476 }
1477
1478 #[async_recursion::async_recursion]
1480 pub async fn contains(
1481 &self,
1482 cache: &ObjectMapOpEnvCacheRef,
1483 object_id: &ObjectId,
1484 ) -> BuckyResult<bool> {
1485 let sub = self.get_sub(cache, object_id.as_ref().as_slice()).await?;
1486 match sub {
1487 Some(sub) => {
1488 let obj_map = sub.lock().await;
1489 obj_map.contains(cache, object_id).await
1490 }
1491 None => Ok(false),
1492 }
1493 }
1494
1495 #[async_recursion::async_recursion]
1496 pub async fn insert(
1497 &mut self,
1498 builder: &ObjectMapBuilder,
1499 cache: &ObjectMapOpEnvCacheRef,
1500 object_id: &ObjectId,
1501 ) -> BuckyResult<bool> {
1502 let sub = self
1503 .get_sub_mut(Some(builder), cache, object_id.as_ref().as_slice(), true)
1504 .await?;
1505 match sub {
1506 Some((solt, mut obj_map)) => {
1507 let ret = obj_map.insert(cache, object_id).await?;
1508 if ret {
1509 let new_id = obj_map.flush_id();
1510 cache.put_object_map(&new_id, obj_map, None)?;
1511 solt.id = new_id;
1512 self.dirty = true;
1513 }
1514
1515 Ok(ret)
1516 }
1517 None => {
1518 unreachable!();
1519 }
1520 }
1521 }
1522
1523 #[async_recursion::async_recursion]
1524 pub async fn remove(
1525 &mut self,
1526 cache: &ObjectMapOpEnvCacheRef,
1527 object_id: &ObjectId,
1528 ) -> BuckyResult<bool> {
1529 let sub = self
1530 .get_sub_mut(None, cache, object_id.as_ref().as_slice(), false)
1531 .await?;
1532 match sub {
1533 Some((solt, mut obj_map)) => {
1534 let ret = obj_map.remove(cache, object_id).await?;
1535 if ret {
1536 if obj_map.count() > 0 {
1537 let new_id = obj_map.flush_id();
1538 cache.put_object_map(&new_id, obj_map, None)?;
1539 solt.id = new_id;
1540 } else {
1541 debug!(
1542 "sub objectmap is empty! now will remove: value={}, sub={}",
1543 object_id, solt.id
1544 );
1545 drop(solt);
1546 drop(obj_map);
1547
1548 let _ret = self.remove_sub(cache, object_id.as_ref().as_slice());
1549 }
1550 self.dirty = true;
1551 }
1552
1553 Ok(ret)
1554 }
1555 None => {
1556 let msg = format!(
1557 "remove object from objectmap with set content but sub obj not found! object={}",
1558 object_id
1559 );
1560 warn!("{}", msg);
1561
1562 Err(BuckyError::new(BuckyErrorCode::NotFound, msg))
1563 }
1564 }
1565 }
1566
1567 #[async_recursion::async_recursion]
1569 pub async fn diff_contains(
1570 &self,
1571 cache: &ObjectMapOpEnvCacheRef,
1572 object_id: &ObjectMapDiffSetItem,
1573 ) -> BuckyResult<bool> {
1574 let sub = self.get_sub(cache, object_id.as_slice()).await?;
1575 match sub {
1576 Some(sub) => {
1577 let obj_map = sub.lock().await;
1578 obj_map.diff_contains(cache, object_id).await
1579 }
1580 None => Ok(false),
1581 }
1582 }
1583
1584 #[async_recursion::async_recursion]
1585 pub async fn diff_insert(
1586 &mut self,
1587 builder: &ObjectMapBuilder,
1588 cache: &ObjectMapOpEnvCacheRef,
1589 object_id: &ObjectMapDiffSetItem,
1590 ) -> BuckyResult<bool> {
1591 let sub = self
1592 .get_sub_mut(Some(builder), cache, object_id.as_slice(), true)
1593 .await?;
1594 match sub {
1595 Some((solt, mut obj_map)) => {
1596 let ret = obj_map.diff_insert(cache, object_id).await?;
1597 if ret {
1598 let new_id = obj_map.flush_id();
1599 cache.put_object_map(&new_id, obj_map, None)?;
1600 solt.id = new_id;
1601 self.dirty = true;
1602 }
1603
1604 Ok(ret)
1605 }
1606 None => {
1607 unreachable!();
1608 }
1609 }
1610 }
1611
1612 #[async_recursion::async_recursion]
1613 pub async fn diff_remove(
1614 &mut self,
1615 cache: &ObjectMapOpEnvCacheRef,
1616 object_id: &ObjectMapDiffSetItem,
1617 ) -> BuckyResult<bool> {
1618 let sub = self
1619 .get_sub_mut(None, cache, object_id.as_slice(), false)
1620 .await?;
1621 match sub {
1622 Some((solt, mut obj_map)) => {
1623 let ret = obj_map.diff_remove(cache, object_id).await?;
1624 if ret {
1625 if obj_map.count() > 0 {
1626 let new_id = obj_map.flush_id();
1627 cache.put_object_map(&new_id, obj_map, None)?;
1628 solt.id = new_id;
1629 } else {
1630 debug!(
1631 "sub objectmap is empty! now will remove: value={}, sub={}",
1632 object_id, solt.id
1633 );
1634 drop(solt);
1635 drop(obj_map);
1636
1637 let _ret = self.remove_sub(cache, object_id.as_slice());
1638 }
1639 self.dirty = true;
1640 }
1641
1642 Ok(ret)
1643 }
1644 None => {
1645 let msg = format!(
1646 "remove object from objectmap with set content but sub obj not found! object={}",
1647 object_id
1648 );
1649 warn!("{}", msg);
1650
1651 Err(BuckyError::new(BuckyErrorCode::NotFound, msg))
1652 }
1653 }
1654 }
1655}
1656
1657#[derive(Clone, Debug, Copy, RawEncode, RawDecode, Eq, PartialEq)]
1658pub enum ObjectMapSimpleContentType {
1659 Map,
1660 DiffMap,
1661 Set,
1662 DiffSet,
1663}
1664
1665impl ObjectMapSimpleContentType {
1666 pub fn get_diff_type(&self) -> Option<ObjectMapSimpleContentType> {
1667 match &self {
1668 Self::Map => Some(Self::DiffMap),
1669 Self::Set => Some(Self::DiffSet),
1670 _ => {
1671 None
1673 }
1674 }
1675 }
1676
1677 pub fn is_diff_match(&self, diff_content_type: &Self) -> bool {
1678 match self.get_diff_type() {
1679 Some(diff_type) => diff_type == *diff_content_type,
1680 None => false,
1681 }
1682 }
1683
1684 pub fn as_str(&self) -> &str {
1685 match self {
1686 Self::Map => "map",
1687 Self::DiffMap => "diffmap",
1688 Self::Set => "set",
1689 Self::DiffSet => "diffset",
1690 }
1691 }
1692
1693 pub fn is_map(&self) -> bool {
1694 match self {
1695 Self::Map => true,
1696 _ => false,
1697 }
1698 }
1699
1700 pub fn is_set(&self) -> bool {
1701 match self {
1702 Self::Set => true,
1703 _ => false,
1704 }
1705 }
1706}
1707
1708impl ToString for ObjectMapSimpleContentType {
1709 fn to_string(&self) -> String {
1710 self.as_str().to_owned()
1711 }
1712}
1713
1714impl std::str::FromStr for ObjectMapSimpleContentType {
1715 type Err = BuckyError;
1716
1717 fn from_str(value: &str) -> Result<Self, Self::Err> {
1718 let ret = match value {
1719 "map" => Self::Map,
1720 "diffmap" => Self::DiffMap,
1721 "set" => Self::Set,
1722 "diffset" => Self::DiffSet,
1723
1724 v @ _ => {
1725 let msg = format!("unknown simple content type: {}", v);
1726 error!("{}", msg);
1727
1728 return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg));
1729 }
1730 };
1731
1732 Ok(ret)
1733 }
1734}
1735
1736#[derive(Debug, Clone, Copy, Eq, PartialEq)]
1737pub enum ObjectMapContentMode {
1738 Simple,
1739 Hub,
1740}
1741
1742impl ToString for ObjectMapContentMode {
1743 fn to_string(&self) -> String {
1744 match *self {
1745 Self::Simple => "simple",
1746 Self::Hub => "hub",
1747 }
1748 .to_owned()
1749 }
1750}
1751
1752impl std::str::FromStr for ObjectMapContentMode {
1753 type Err = BuckyError;
1754
1755 fn from_str(value: &str) -> Result<Self, Self::Err> {
1756 let ret = match value {
1757 "simple" => Self::Simple,
1758 "hub" => Self::Hub,
1759
1760 v @ _ => {
1761 let msg = format!("unknown ObjectMapContentMode value: {}", v);
1762 error!("{}", msg);
1763
1764 return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg));
1765 }
1766 };
1767
1768 Ok(ret)
1769 }
1770}
1771
1772#[derive(Clone, Debug, RawEncode, RawDecode)]
1773pub enum ObjectMapContent {
1774 Simple(ObjectMapSimpleContent),
1775 Hub(ObjectMapHubContent),
1776}
1777
1778impl ObjectMapContent {
1779 pub fn mode(&self) -> ObjectMapContentMode {
1780 match self {
1781 Self::Simple(_) => ObjectMapContentMode::Simple,
1782 Self::Hub(_) => ObjectMapContentMode::Hub,
1783 }
1784 }
1785
1786 pub fn new_simple(content_type: ObjectMapSimpleContentType, depth: u8) -> Self {
1787 ObjectMapContent::Simple(ObjectMapSimpleContent::new(content_type, depth))
1788 }
1789
1790 pub fn new_hub(depth: u8) -> Self {
1791 ObjectMapContent::Hub(ObjectMapHubContent::new(depth))
1792 }
1793
1794 pub fn is_dirty(&self) -> bool {
1795 match self {
1796 Self::Simple(content) => content.is_dirty(),
1797 Self::Hub(content) => content.is_dirty(),
1798 }
1799 }
1800
1801 pub fn clear_dirty(&mut self) {
1802 match self {
1803 Self::Simple(content) => content.clear_dirty(),
1804 Self::Hub(content) => content.clear_dirty(),
1805 }
1806 }
1807
1808 pub fn into_simple(self) -> ObjectMapSimpleContent {
1820 match self {
1821 Self::Simple(content) => content,
1822 Self::Hub(_) => unreachable!(),
1823 }
1824 }
1825
1826 pub async fn convert_to_hub(
1827 self,
1828 builder: &ObjectMapBuilder,
1829 cache: &ObjectMapOpEnvCacheRef,
1830 ) -> BuckyResult<Self> {
1831 match self {
1832 Self::Simple(content) => {
1833 let mut hub = ObjectMapHubContent::new(content.depth);
1834 match content.content {
1835 SimpleContent::Map(values) => {
1836 for (key, value) in values.into_values().into_iter() {
1837 hub.insert_with_key(builder, cache, &key, &value).await?;
1838 }
1839 }
1840 SimpleContent::DiffMap(values) => {
1841 for (key, value) in values.into_values().into_iter() {
1842 hub.diff_insert_with_key(builder, cache, &key, &value)
1843 .await?;
1844 }
1845 }
1846 SimpleContent::Set(values) => {
1847 for value in values.into_values().into_iter() {
1848 hub.insert(builder, cache, &value).await?;
1849 }
1850 }
1851 SimpleContent::DiffSet(values) => {
1852 for value in values.into_values().into_iter() {
1853 hub.diff_insert(builder, cache, &value).await?;
1854 }
1855 }
1856 }
1857 let ret = Self::Hub(hub);
1858 Ok(ret)
1859 }
1860 Self::Hub(_) => Ok(self),
1861 }
1862 }
1863
1864 #[async_recursion::async_recursion]
1865 pub async fn convert_to_simple(
1866 self,
1867 cache: &ObjectMapOpEnvCacheRef,
1868 content_type: ObjectMapSimpleContentType,
1869 ) -> BuckyResult<Self> {
1870 match self {
1871 Self::Hub(content) => {
1872 let mut new_content = ObjectMapSimpleContent::new(content_type, content.depth);
1873
1874 for (_, sub) in content.subs.iter() {
1876 let sub_obj = cache.get_object_map(&sub.id).await?;
1877 if sub_obj.is_none() {
1878 let msg = format!(
1879 "convert object map to simple failed, sub obj not found! obj={}",
1880 sub.id
1881 );
1882 error!("{}", msg);
1883 return Err(BuckyError::new(BuckyErrorCode::NotFound, msg));
1884 }
1885
1886 let sub_obj = sub_obj.unwrap();
1887 let simple_content;
1888 {
1889 let mut obj = sub_obj.lock().await.clone();
1890 obj.convert_to_simple(cache).await?;
1891 simple_content = obj.into_simple();
1892 }
1893 new_content.merge(simple_content)?;
1894 }
1895
1896 let ret = Self::Simple(new_content);
1897 Ok(ret)
1898 }
1899 Self::Simple(_) => Ok(self),
1900 }
1901 }
1902
1903 pub async fn visit(&self, visitor: &mut impl ObjectMapVisitor) -> BuckyResult<()> {
1905 match &self {
1906 Self::Simple(content) => content.visit(visitor).await,
1907 Self::Hub(content) => content.visit(visitor).await,
1908 }
1909 }
1910}
1911
1912#[derive(Debug, Clone)]
1914struct ObjectMapContentHashCacheImpl {
1915 dirty: bool,
1916
1917 object_id: Option<ObjectId>,
1923}
1924
1925impl ObjectMapContentHashCacheImpl {
1926 pub fn new(object_id: ObjectId) -> Self {
1927 Self {
1928 dirty: false,
1929 object_id: Some(object_id),
1930 }
1931 }
1932
1933 pub fn new_empty() -> Self {
1934 Self {
1935 dirty: true,
1936 object_id: None,
1937 }
1938 }
1939
1940 fn mark_dirty(&mut self) -> bool {
1942 let ret = self.dirty;
1943 self.dirty = true;
1944 ret
1945 }
1946}
1947
1948struct ObjectMapContentHashCache(Mutex<ObjectMapContentHashCacheImpl>);
1949
1950impl Clone for ObjectMapContentHashCache {
1951 fn clone(&self) -> Self {
1952 let value = self.0.lock().unwrap().clone();
1953 Self(Mutex::new(value))
1954 }
1955}
1956
1957impl std::fmt::Debug for ObjectMapContentHashCache {
1958 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1959 let value = self.0.lock().unwrap();
1960 value.fmt(f)
1961 }
1962}
1963
1964impl ObjectMapContentHashCache {
1965 pub fn new(object_id: ObjectId) -> Self {
1966 Self(Mutex::new(ObjectMapContentHashCacheImpl::new(object_id)))
1967 }
1968
1969 pub fn new_empty() -> Self {
1970 Self(Mutex::new(ObjectMapContentHashCacheImpl::new_empty()))
1971 }
1972
1973 pub fn mark_dirty(&self) -> bool {
1974 self.0.lock().unwrap().mark_dirty()
1975 }
1976
1977 pub fn object_id(&self) -> Option<ObjectId> {
1978 self.0.lock().unwrap().object_id.clone()
1979 }
1980
1981 pub fn need_flush_id(&self) -> Option<ObjectId> {
1982 let cache = self.0.lock().unwrap();
1983 if !cache.dirty {
1984 assert!(cache.object_id.is_some());
1985 Some(cache.object_id.as_ref().unwrap().to_owned())
1986 } else {
1987 None
1988 }
1989 }
1990
1991 pub fn update_id(&self, object_id: &ObjectId) {
1992 let mut cache = self.0.lock().unwrap();
1993 cache.object_id = Some(object_id.clone());
1994 cache.dirty = false;
1995 }
1996
1997 pub fn direct_set_id_on_init(&self, object_id: ObjectId) {
1998 let mut cache = self.0.lock().unwrap();
1999 assert!(cache.dirty);
2000 assert!(cache.object_id.is_none());
2001
2002 cache.object_id = Some(object_id);
2003 cache.dirty = false;
2004 }
2005}
2006
2007#[repr(u8)]
2009#[derive(Debug, Clone, Copy, Eq, PartialEq)]
2010pub enum ObjectMapClass {
2011 Root = 0,
2013
2014 Sub = 1,
2016
2017 DecRoot = 2,
2019
2020 GlobalRoot = 3,
2022}
2023
2024impl ObjectMapClass {
2025 pub fn as_str(&self) -> &str {
2026 match self {
2027 Self::Root => "root",
2028 Self::Sub => "sub",
2029 Self::DecRoot => "dec-root",
2030 Self::GlobalRoot => "global-root",
2031 }
2032 }
2033}
2034
2035impl Into<u8> for ObjectMapClass {
2036 fn into(self) -> u8 {
2037 unsafe { std::mem::transmute(self as u8) }
2038 }
2039}
2040
2041use std::convert::TryFrom;
2042
2043impl TryFrom<u8> for ObjectMapClass {
2044 type Error = BuckyError;
2045 fn try_from(value: u8) -> Result<Self, Self::Error> {
2046 let ret = match value {
2047 0 => Self::Root,
2048 1 => Self::Sub,
2049 2 => Self::DecRoot,
2050 3 => Self::GlobalRoot,
2051
2052 _ => {
2053 let msg = format!("unknown objectmap class: {}", value);
2054 error!("{}", msg);
2055 return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg));
2056 }
2057 };
2058
2059 Ok(ret)
2060 }
2061}
2062
2063pub struct ObjectMapMetaData {
2064 pub content_mode: ObjectMapContentMode,
2065 pub content_type: ObjectMapSimpleContentType,
2066 pub count: u64,
2067 pub size: u64,
2068 pub depth: u8,
2069}
2070
2071fn raw_encode_size(t: &(impl RawEncode + ?Sized)) -> u64 {
2072 t.raw_measure(&None).unwrap() as u64
2073}
2074
2075#[derive(Clone, Debug)]
2077pub struct ObjectMapDescContent {
2078 class: ObjectMapClass,
2080
2081 total: u64,
2083
2084 size: u64,
2086
2087 depth: u8,
2089
2090 content_type: ObjectMapSimpleContentType,
2091 content: ObjectMapContent,
2092
2093 hash_cache: ObjectMapContentHashCache,
2094}
2095
2096impl ObjectMapDescContent {
2097 pub fn new(class: ObjectMapClass, content_type: ObjectMapSimpleContentType, depth: u8) -> Self {
2098 Self {
2099 class,
2100 total: 0,
2101 size: 0,
2102 depth,
2103 content_type: content_type.clone(),
2104 content: ObjectMapContent::new_simple(content_type, depth),
2105 hash_cache: ObjectMapContentHashCache::new_empty(),
2106 }
2107 }
2108
2109 fn mark_dirty(&mut self) -> bool {
2110 self.content.clear_dirty();
2112
2113 self.hash_cache.mark_dirty()
2115 }
2116
2117 pub fn count(&self) -> u64 {
2118 self.total
2119 }
2120
2121 pub fn size(&self) -> u64 {
2122 self.size
2123 }
2124
2125 pub fn depth(&self) -> u8 {
2126 self.depth
2127 }
2128
2129 pub fn object_id(&self) -> Option<ObjectId> {
2130 self.hash_cache.object_id()
2131 }
2132
2133 pub fn content_type(&self) -> &ObjectMapSimpleContentType {
2134 &self.content_type
2135 }
2136
2137 pub fn mode(&self) -> ObjectMapContentMode {
2138 self.content.mode()
2139 }
2140
2141 pub fn class(&self) -> ObjectMapClass {
2142 self.class.clone()
2143 }
2144
2145 pub fn set_class(&mut self, class: ObjectMapClass) {
2146 if self.class != class {
2147 self.class = class;
2148 self.mark_dirty();
2149 }
2150 }
2151
2152 pub fn content(&self) -> &ObjectMapContent {
2153 &self.content
2154
2155 }
2156 pub fn metadata(&self) -> ObjectMapMetaData {
2157 ObjectMapMetaData {
2158 content_type: self.content_type.clone(),
2159 content_mode: self.content.mode(),
2160 count: self.total,
2161 size: self.size,
2162 depth: self.depth,
2163 }
2164 }
2165
2166 pub fn into_simple(self) -> ObjectMapSimpleContent {
2168 self.content.into_simple()
2169 }
2170
2171 pub async fn convert_to_simple(&mut self, cache: &ObjectMapOpEnvCacheRef) -> BuckyResult<()> {
2172 let mut content = ObjectMapContent::new_simple(self.content_type.clone(), self.depth);
2173 std::mem::swap(&mut self.content, &mut content);
2174
2175 self.content = content
2176 .convert_to_simple(cache, self.content_type().clone())
2177 .await?;
2178
2179 self.mark_dirty();
2180
2181 Ok(())
2182 }
2183
2184 pub async fn convert_to_hub(
2185 &mut self,
2186 builder: &ObjectMapBuilder,
2187 cache: &ObjectMapOpEnvCacheRef,
2188 ) -> BuckyResult<()> {
2189 let mut content = ObjectMapContent::new_hub(self.depth);
2191 std::mem::swap(&mut self.content, &mut content);
2192
2193 self.content = content.convert_to_hub(builder, cache).await?;
2194 self.mark_dirty();
2195
2196 Ok(())
2199 }
2200
2201 pub async fn inflate_check_point(
2203 &mut self,
2204 builder: &ObjectMapBuilder,
2205 cache: &ObjectMapOpEnvCacheRef,
2206 ) -> BuckyResult<()> {
2207 match &self.content {
2208 ObjectMapContent::Simple(_) => {
2209 if self.size > OBJECT_MAP_CONTENT_MAX_ENCODE_SIZE {
2211 info!("object map simple content extend limit, now will convert to hub mode! id={:?}, size={}, count={}",
2212 self.object_id(), self.size, self.total);
2213 self.convert_to_hub(builder, cache).await?;
2214 }
2215 }
2216 ObjectMapContent::Hub(_) => {
2217 assert!(self.size > OBJECT_MAP_CONTENT_MAX_ENCODE_SIZE);
2218 }
2219 }
2220
2221 Ok(())
2222 }
2223
2224 pub async fn deflate_check_point(&mut self, cache: &ObjectMapOpEnvCacheRef) -> BuckyResult<()> {
2226 match &self.content {
2227 ObjectMapContent::Simple(_) => {
2228 assert!(self.size <= OBJECT_MAP_CONTENT_MAX_ENCODE_SIZE);
2229 }
2230 ObjectMapContent::Hub(_) => {
2231 if self.size <= OBJECT_MAP_CONTENT_MAX_ENCODE_SIZE {
2232 info!("object map hub content in limit, now will convert back to simple mode! count={}", self.total);
2234 self.convert_to_simple(cache).await?;
2235 }
2236 }
2237 }
2238
2239 Ok(())
2240 }
2241
2242 pub async fn get_or_create_child_object_map(
2244 &mut self,
2245 builder: &ObjectMapBuilder,
2246 cache: &ObjectMapOpEnvCacheRef,
2247 key: &str,
2248 auto_create: ObjectMapCreateStrategy,
2249 access: Option<AccessString>,
2250 ) -> BuckyResult<Option<ObjectMapRef>> {
2251 assert!(!self.content.is_dirty());
2252
2253 let ret = match &mut self.content {
2254 ObjectMapContent::Simple(content) => {
2255 content
2256 .get_or_create_child_object_map(builder, cache, key, auto_create, access)
2257 .await
2258 }
2259 ObjectMapContent::Hub(content) => {
2260 content
2261 .get_or_create_child_object_map(builder, cache, key, auto_create, access)
2262 .await
2263 }
2264 }?;
2265
2266 if self.content.is_dirty() {
2268 self.size += raw_encode_size(key) + ObjectId::raw_bytes().unwrap() as u64;
2269 self.total += 1;
2270 self.inflate_check_point(builder, cache).await?;
2271 self.mark_dirty();
2272 }
2273
2274 Ok(ret)
2275 }
2276
2277 pub async fn list(
2279 &self,
2280 cache: &ObjectMapOpEnvCacheRef,
2281 list: &mut ObjectMapContentList,
2282 ) -> BuckyResult<u64> {
2283 match &self.content {
2284 ObjectMapContent::Simple(content) => content.list(list).map(|v| v as u64),
2285 ObjectMapContent::Hub(content) => content.list(cache, list).await,
2286 }
2287 }
2288
2289 pub async fn list_subs(
2290 &self,
2291 cache: &ObjectMapOpEnvCacheRef,
2292 list: &mut Vec<ObjectId>,
2293 ) -> BuckyResult<u64> {
2294 match &self.content {
2295 ObjectMapContent::Simple(_content) => Ok(0),
2296 ObjectMapContent::Hub(content) => content.list_subs(cache, list).await,
2297 }
2298 }
2299
2300 pub async fn next(&self, it: &mut ObjectMapIterator) -> BuckyResult<()> {
2302 match &self.content {
2303 ObjectMapContent::Simple(content) => content.next(it),
2304 ObjectMapContent::Hub(content) => content.next(it).await,
2305 }
2306 }
2307
2308 pub(crate) fn diff(&self, other: &Self, diff: &mut ObjectMapDiff) {
2309 match &self.content {
2310 ObjectMapContent::Simple(content) => match &other.content {
2311 ObjectMapContent::Simple(other) => {
2312 content.diff(other, diff);
2314 }
2315 ObjectMapContent::Hub(_) => {
2316 unreachable!();
2317 }
2318 },
2319 ObjectMapContent::Hub(content) => match &other.content {
2320 ObjectMapContent::Simple(_) => {
2321 unreachable!();
2322 }
2323 ObjectMapContent::Hub(other) => {
2324 content.diff(other, diff);
2326 }
2327 },
2328 }
2329 }
2330
2331 pub async fn get_by_key(
2333 &self,
2334 cache: &ObjectMapOpEnvCacheRef,
2335 key: &str,
2336 ) -> BuckyResult<Option<ObjectId>> {
2337 match &self.content {
2338 ObjectMapContent::Simple(content) => content.get_by_key(key),
2339 ObjectMapContent::Hub(content) => content.get_by_key(cache, key).await,
2340 }
2341 }
2342
2343 pub async fn insert_with_key(
2344 &mut self,
2345 builder: &ObjectMapBuilder,
2346 cache: &ObjectMapOpEnvCacheRef,
2347 key: &str,
2348 value: &ObjectId,
2349 ) -> BuckyResult<()> {
2350 match &mut self.content {
2351 ObjectMapContent::Simple(content) => content.insert_with_key(key, value),
2352 ObjectMapContent::Hub(content) => {
2353 content.insert_with_key(builder, cache, key, value).await
2354 }
2355 }?;
2356
2357 self.size += raw_encode_size(key) + raw_encode_size(value);
2358 self.total += 1;
2359 self.inflate_check_point(builder, cache).await?;
2360 self.mark_dirty();
2361
2362 debug!(
2363 "objectmap insert_with_key, total={}, {}={}",
2364 self.total, key, value
2365 );
2366
2367 Ok(())
2368 }
2369
2370 pub async fn set_with_key(
2371 &mut self,
2372 builder: &ObjectMapBuilder,
2373 cache: &ObjectMapOpEnvCacheRef,
2374 key: &str,
2375 value: &ObjectId,
2376 prev_value: &Option<ObjectId>,
2377 auto_insert: bool,
2378 ) -> BuckyResult<Option<ObjectId>> {
2379 let ret = match &mut self.content {
2380 ObjectMapContent::Simple(content) => {
2381 content.set_with_key(key, value, prev_value, auto_insert)
2382 }
2383 ObjectMapContent::Hub(content) => {
2384 content
2385 .set_with_key(builder, cache, key, value, prev_value, auto_insert)
2386 .await
2387 }
2388 }?;
2389
2390 debug!(
2391 "objectmap set_with_key: key={}, value={}, prev={:?}, auto_insert={}, ret={:?}",
2392 key, value, prev_value, auto_insert, ret
2393 );
2394
2395 if ret.is_none() {
2396 self.size += raw_encode_size(key) + raw_encode_size(value);
2398 self.total += 1;
2399 self.inflate_check_point(builder, cache).await?;
2400 self.mark_dirty();
2401 } else {
2402 if self.content.is_dirty() {
2404 self.mark_dirty();
2405 }
2406 }
2407
2408 Ok(ret)
2409 }
2410
2411 pub async fn remove_with_key(
2412 &mut self,
2413 cache: &ObjectMapOpEnvCacheRef,
2414 key: &str,
2415 prev_value: &Option<ObjectId>,
2416 ) -> BuckyResult<Option<ObjectId>> {
2417 let ret = match &mut self.content {
2418 ObjectMapContent::Simple(content) => content.remove_with_key(key, prev_value),
2419 ObjectMapContent::Hub(content) => content.remove_with_key(cache, key, prev_value).await,
2420 }?;
2421
2422 if ret.is_some() {
2423 assert!(self.total > 0);
2424 self.total -= 1;
2425
2426 let size = raw_encode_size(key) + raw_encode_size(ret.as_ref().unwrap());
2427 assert!(size <= self.size);
2428 self.size -= size;
2429
2430 self.deflate_check_point(cache).await?;
2431 self.mark_dirty();
2432 }
2433
2434 debug!(
2435 "objectmap remove_with_key, key={}, prev={:?}, ret={:?}",
2436 key, prev_value, ret
2437 );
2438
2439 Ok(ret)
2440 }
2441
2442 pub async fn diff_get_by_key(
2444 &self,
2445 cache: &ObjectMapOpEnvCacheRef,
2446 key: &str,
2447 ) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
2448 match &self.content {
2449 ObjectMapContent::Simple(content) => content.diff_get_by_key(key),
2450 ObjectMapContent::Hub(content) => content.diff_get_by_key(cache, key).await,
2451 }
2452 }
2453
2454 pub async fn diff_insert_with_key(
2455 &mut self,
2456 builder: &ObjectMapBuilder,
2457 cache: &ObjectMapOpEnvCacheRef,
2458 key: &str,
2459 value: &ObjectMapDiffMapItem,
2460 ) -> BuckyResult<()> {
2461 match &mut self.content {
2462 ObjectMapContent::Simple(content) => content.diff_insert_with_key(key, value),
2463 ObjectMapContent::Hub(content) => {
2464 content
2465 .diff_insert_with_key(builder, cache, key, value)
2466 .await
2467 }
2468 }?;
2469
2470 self.size += raw_encode_size(key) + raw_encode_size(value);
2471 self.total += 1;
2472 self.inflate_check_point(builder, cache).await?;
2473 self.mark_dirty();
2474
2475 debug!(
2476 "objectmap diff_insert_with_key, total={}, {}={}",
2477 self.total, key, value
2478 );
2479
2480 Ok(())
2481 }
2482
2483 pub async fn diff_set_with_key(
2484 &mut self,
2485 builder: &ObjectMapBuilder,
2486 cache: &ObjectMapOpEnvCacheRef,
2487 key: &str,
2488 value: &ObjectMapDiffMapItem,
2489 prev_value: &Option<ObjectMapDiffMapItem>,
2490 auto_insert: bool,
2491 ) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
2492 let ret = match &mut self.content {
2493 ObjectMapContent::Simple(content) => {
2494 content.diff_set_with_key(key, value, &prev_value, auto_insert)
2495 }
2496 ObjectMapContent::Hub(content) => {
2497 content
2498 .diff_set_with_key(builder, cache, key, value, prev_value, auto_insert)
2499 .await
2500 }
2501 }?;
2502
2503 debug!(
2504 "objectmap diff_set_with_key: key={}, value={}, prev={:?}, auto_insert={}, ret={:?}",
2505 key, value, prev_value, auto_insert, ret
2506 );
2507
2508 if ret.is_none() {
2509 self.size += raw_encode_size(key) + raw_encode_size(value);
2511 self.total += 1;
2512 self.inflate_check_point(builder, cache).await?;
2513 self.mark_dirty();
2514 } else {
2515 let current = self.size;
2517 self.size += raw_encode_size(value);
2518 self.size -= raw_encode_size(ret.as_ref().unwrap());
2519
2520 if self.size > current {
2521 self.inflate_check_point(builder, cache).await?;
2522 } else if self.size < current {
2523 self.deflate_check_point(cache).await?;
2524 }
2525
2526 if self.content.is_dirty() {
2527 self.mark_dirty();
2528 }
2529 }
2530
2531 Ok(ret)
2532 }
2533
2534 pub async fn diff_remove_with_key(
2535 &mut self,
2536 cache: &ObjectMapOpEnvCacheRef,
2537 key: &str,
2538 prev_value: &Option<ObjectMapDiffMapItem>,
2539 ) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
2540 let ret = match &mut self.content {
2541 ObjectMapContent::Simple(content) => content.diff_remove_with_key(key, &prev_value),
2542 ObjectMapContent::Hub(content) => {
2543 content.diff_remove_with_key(cache, key, prev_value).await
2544 }
2545 }?;
2546
2547 debug!(
2548 "objectmap diff_remove_with_key, key={}, prev={:?}, ret={:?}",
2549 key, prev_value, ret
2550 );
2551
2552 if ret.is_some() {
2553 assert!(self.total > 0);
2554 self.total -= 1;
2555
2556 let size = raw_encode_size(key) + raw_encode_size(ret.as_ref().unwrap());
2557 assert!(size <= self.size);
2558 self.size -= size;
2559
2560 self.deflate_check_point(cache).await?;
2561 self.mark_dirty();
2562 }
2563
2564 Ok(ret)
2565 }
2566
2567 pub async fn contains(
2569 &self,
2570 cache: &ObjectMapOpEnvCacheRef,
2571 object_id: &ObjectId,
2572 ) -> BuckyResult<bool> {
2573 match &self.content {
2574 ObjectMapContent::Simple(content) => content.contains(object_id),
2575 ObjectMapContent::Hub(content) => content.contains(cache, object_id).await,
2576 }
2577 }
2578
2579 pub async fn insert(
2580 &mut self,
2581 builder: &ObjectMapBuilder,
2582 cache: &ObjectMapOpEnvCacheRef,
2583 object_id: &ObjectId,
2584 ) -> BuckyResult<bool> {
2585 let ret = match &mut self.content {
2586 ObjectMapContent::Simple(content) => content.insert(object_id),
2587 ObjectMapContent::Hub(content) => content.insert(builder, cache, object_id).await,
2588 }?;
2589
2590 if ret {
2591 self.total += 1;
2592 self.size += raw_encode_size(object_id);
2593 self.inflate_check_point(builder, cache).await?;
2594 self.mark_dirty();
2595 }
2596
2597 debug!(
2598 "objectmap insert, value={}, count={}, ret={}",
2599 object_id, self.total, ret
2600 );
2601
2602 Ok(ret)
2603 }
2604
2605 pub async fn remove(
2606 &mut self,
2607 cache: &ObjectMapOpEnvCacheRef,
2608 object_id: &ObjectId,
2609 ) -> BuckyResult<bool> {
2610 let ret = match &mut self.content {
2611 ObjectMapContent::Simple(content) => content.remove(object_id),
2612 ObjectMapContent::Hub(content) => content.remove(cache, object_id).await,
2613 }?;
2614
2615 if ret {
2616 assert!(self.total > 0);
2617 self.total -= 1;
2618 let size = raw_encode_size(object_id);
2619 assert!(size <= self.size);
2620 self.size -= size;
2621
2622 self.deflate_check_point(cache).await?;
2623 self.mark_dirty();
2624 }
2625
2626 debug!(
2627 "objectmap remove, value={}, count={}, ret={}",
2628 object_id, self.total, ret
2629 );
2630
2631 Ok(ret)
2632 }
2633
2634 pub async fn diff_contains(
2636 &self,
2637 cache: &ObjectMapOpEnvCacheRef,
2638 object_id: &ObjectMapDiffSetItem,
2639 ) -> BuckyResult<bool> {
2640 match &self.content {
2641 ObjectMapContent::Simple(content) => content.diff_contains(object_id),
2642 ObjectMapContent::Hub(content) => content.diff_contains(cache, object_id).await,
2643 }
2644 }
2645
2646 pub async fn diff_insert(
2647 &mut self,
2648 builder: &ObjectMapBuilder,
2649 cache: &ObjectMapOpEnvCacheRef,
2650 object_id: &ObjectMapDiffSetItem,
2651 ) -> BuckyResult<bool> {
2652 let ret = match &mut self.content {
2653 ObjectMapContent::Simple(content) => content.diff_insert(object_id),
2654 ObjectMapContent::Hub(content) => content.diff_insert(builder, cache, object_id).await,
2655 }?;
2656
2657 if ret {
2658 self.total += 1;
2659 self.size += raw_encode_size(object_id);
2660 self.inflate_check_point(builder, cache).await?;
2661 self.mark_dirty();
2662 }
2663
2664 debug!(
2665 "objectmap diff_insert, value={}, count={}, ret={}",
2666 object_id, self.total, ret
2667 );
2668
2669 Ok(ret)
2670 }
2671
2672 pub async fn diff_remove(
2673 &mut self,
2674 cache: &ObjectMapOpEnvCacheRef,
2675 object_id: &ObjectMapDiffSetItem,
2676 ) -> BuckyResult<bool> {
2677 let ret = match &mut self.content {
2678 ObjectMapContent::Simple(content) => content.diff_remove(object_id),
2679 ObjectMapContent::Hub(content) => content.diff_remove(cache, object_id).await,
2680 }?;
2681
2682 if ret {
2683 assert!(self.total > 0);
2684 self.total -= 1;
2685 let size = raw_encode_size(object_id);
2686 assert!(size >= self.size);
2687 self.size -= size;
2688
2689 self.deflate_check_point(cache).await?;
2690 self.mark_dirty();
2691 }
2692
2693 debug!(
2694 "objectmap diff_remove, value={}, count={}, ret={}",
2695 object_id, self.total, ret
2696 );
2697
2698 Ok(ret)
2699 }
2700
2701 pub async fn visit(&self, visitor: &mut impl ObjectMapVisitor) -> BuckyResult<()> {
2703 match &self.content {
2704 ObjectMapContent::Simple(content) => content.visit(visitor).await,
2705 ObjectMapContent::Hub(content) => content.visit(visitor).await,
2706 }
2707 }
2708}
2709
2710impl RawEncode for ObjectMapDescContent {
2711 fn raw_measure(&self, purpose: &Option<RawEncodePurpose>) -> BuckyResult<usize> {
2712 let ret = u8::raw_bytes().unwrap() + self.total.raw_measure(purpose)?
2714 + self.size.raw_measure(purpose)?
2715 + self.depth.raw_measure(purpose)?
2716 + self.content_type.raw_measure(purpose)?
2717 + self.content.raw_measure(purpose)?;
2718
2719 Ok(ret)
2723 }
2724
2725 fn raw_encode<'a>(
2726 &self,
2727 buf: &'a mut [u8],
2728 purpose: &Option<RawEncodePurpose>,
2729 ) -> BuckyResult<&'a mut [u8]> {
2730 let class: u8 = self.class.clone().into();
2731 let buf = class.raw_encode(buf, purpose)?;
2732
2733 let buf = self.total.raw_encode(buf, purpose)?;
2734 let buf = self.size.raw_encode(buf, purpose)?;
2735 let buf = self.depth.raw_encode(buf, purpose)?;
2736 let buf = self.content_type.raw_encode(buf, purpose)?;
2737 let buf = self.content.raw_encode(buf, purpose)?;
2738
2739 Ok(buf)
2740 }
2741}
2742
2743impl RawDecode<'_> for ObjectMapDescContent {
2744 fn raw_decode(buf: &[u8]) -> BuckyResult<(Self, &[u8])> {
2745 let (class, buf) = u8::raw_decode(buf).map_err(|e| {
2746 error!("ObjectMapDescContent::raw_decode/class error:{}", e);
2747 e
2748 })?;
2749
2750 let class = ObjectMapClass::try_from(class)?;
2751
2752 let (total, buf) = u64::raw_decode(buf).map_err(|e| {
2753 error!("ObjectMapDescContent::raw_decode/total error:{}", e);
2754 e
2755 })?;
2756
2757 let (size, buf) = u64::raw_decode(buf).map_err(|e| {
2758 error!("ObjectMapDescContent::raw_decode/size error:{}", e);
2759 e
2760 })?;
2761
2762 let (depth, buf) = u8::raw_decode(buf).map_err(|e| {
2763 error!("ObjectMapDescContent::raw_decode/depth error:{}", e);
2764 e
2765 })?;
2766
2767 let (content_type, buf) = ObjectMapSimpleContentType::raw_decode(buf).map_err(|e| {
2768 error!("ObjectMapDescContent::raw_decode/content_type error:{}", e);
2769 e
2770 })?;
2771
2772 let (content, buf) = ObjectMapContent::raw_decode(buf).map_err(|e| {
2773 error!("ObjectMapDescContent::raw_decode/content error:{}", e);
2774 e
2775 })?;
2776
2777 let ret = Self {
2779 class,
2780 total,
2781 size,
2782 depth,
2783 content_type,
2784 content,
2785
2786 hash_cache: ObjectMapContentHashCache::new_empty(),
2787 };
2788
2789 Ok((ret, buf))
2790 }
2791}
2792
2793impl DescContent for ObjectMapDescContent {
2794 fn obj_type() -> u16 {
2795 ObjectTypeCode::ObjectMap.into()
2796 }
2797
2798 type OwnerType = Option<ObjectId>;
2799 type AreaType = SubDescNone;
2800 type AuthorType = SubDescNone;
2801 type PublicKeyType = SubDescNone;
2802}
2803
2804#[derive(Clone, Debug, RawEncode, RawDecode)]
2805pub struct ObjectMapBodyContent;
2806
2807impl BodyContent for ObjectMapBodyContent {}
2808
2809pub type ObjectMapType = NamedObjType<ObjectMapDescContent, ObjectMapBodyContent>;
2810pub type ObjectMapBuilder = NamedObjectBuilder<ObjectMapDescContent, ObjectMapBodyContent>;
2811
2812pub type ObjectMapDesc = NamedObjectDesc<ObjectMapDescContent>;
2813pub type ObjectMapId = NamedObjectId<ObjectMapType>;
2814pub type ObjectMap = NamedObjectBase<ObjectMapType>;
2815
2816impl ObjectMapBuilder {
2817 pub fn content_type(&self) -> ObjectMapSimpleContentType {
2818 self.desc_builder().desc_content().content_type.clone()
2819 }
2820
2821 pub fn class(mut self, class: ObjectMapClass) -> Self {
2822 self.mut_desc_builder().mut_desc_content().class = class;
2823 self
2824 }
2825}
2826
2827impl ObjectMap {
2828 pub fn new(
2829 content_type: ObjectMapSimpleContentType,
2830 owner: Option<ObjectId>,
2831 dec_id: Option<ObjectId>,
2832 ) -> ObjectMapBuilder {
2833 let desc_content = ObjectMapDescContent::new(ObjectMapClass::Root, content_type, 0);
2834 let body_content = ObjectMapBodyContent {};
2835
2836 ObjectMapBuilder::new(desc_content, body_content)
2837 .option_owner(owner)
2838 .option_dec_id(dec_id)
2839 .no_create_time()
2840 }
2841
2842 fn new_sub_builder(
2843 &self,
2844 content_type: Option<ObjectMapSimpleContentType>,
2845 ) -> BuckyResult<ObjectMapBuilder> {
2846 let content_type = match content_type {
2847 Some(content_type) => content_type,
2848 None => self.desc().content().content_type().to_owned(),
2849 };
2850
2851 let depth = self.depth();
2853 if depth == u8::MAX {
2854 let msg = format!("object map depth extend max limit! max={}", u8::MAX);
2855 error!("{}", msg);
2856 return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
2857 }
2858
2859 let desc_content = ObjectMapDescContent::new(ObjectMapClass::Sub, content_type, depth + 1);
2860 let body_content = ObjectMapBodyContent {};
2861
2862 let builder = ObjectMapBuilder::new(desc_content, body_content)
2863 .option_owner(self.desc().owner().to_owned())
2864 .option_dec_id(self.desc().dec_id().to_owned())
2865 .no_create_time();
2866
2867 Ok(builder)
2868 }
2869
2870 pub fn count(&self) -> u64 {
2871 self.desc().content().count()
2872 }
2873
2874 pub fn object_id(&self) -> ObjectId {
2875 self.flush_id()
2876 }
2877
2878 pub fn content_type(&self) -> ObjectMapSimpleContentType {
2879 self.desc().content().content_type().to_owned()
2880 }
2881
2882 pub fn mode(&self) -> ObjectMapContentMode {
2883 self.desc().content().mode()
2884 }
2885
2886 pub fn class(&self) -> ObjectMapClass {
2887 self.desc().content().class()
2888 }
2889
2890 pub fn depth(&self) -> u8 {
2891 self.desc().content().depth
2892 }
2893
2894 pub fn metadata(&self) -> ObjectMapMetaData {
2895 self.desc().content().metadata()
2896 }
2897 pub fn cached_object_id(&self) -> Option<ObjectId> {
2899 self.desc().content().hash_cache.object_id()
2900 }
2901
2902 pub fn direct_set_object_id_on_init(&self, object_id: &ObjectId) {
2904 #[cfg(debug_assertions)]
2905 {
2906 let real_id = self.flush_id_without_cache();
2907 assert_eq!(real_id, *object_id);
2908 }
2909
2910 self.desc()
2911 .content()
2912 .hash_cache
2913 .direct_set_id_on_init(object_id.to_owned());
2914 }
2915
2916 pub fn flush_id(&self) -> ObjectId {
2918 if let Some(object_id) = self.desc().content().hash_cache.need_flush_id() {
2920 return object_id;
2921 }
2922
2923 let id = self.desc().calculate_id();
2925
2926 self.desc().content().hash_cache.update_id(&id);
2928
2929 id
2930 }
2931
2932 pub fn flush_id_without_cache(&self) -> ObjectId {
2934 self.desc().calculate_id()
2935 }
2936
2937 pub async fn convert_to_simple(&mut self, cache: &ObjectMapOpEnvCacheRef) -> BuckyResult<()> {
2940 self.desc_mut().content_mut().convert_to_simple(cache).await
2941 }
2942
2943 pub async fn convert_to_hub(&mut self, cache: &ObjectMapOpEnvCacheRef) -> BuckyResult<()> {
2944 let builder = self.new_sub_builder(None)?;
2945
2946 self.desc_mut()
2947 .content_mut()
2948 .convert_to_hub(&builder, cache)
2949 .await
2950 }
2951
2952 pub fn into_simple(self) -> ObjectMapSimpleContent {
2953 self.into_desc().into_content().into_simple()
2954 }
2955
2956 pub async fn get_or_create_child_object_map(
2958 &mut self,
2959 cache: &ObjectMapOpEnvCacheRef,
2960 key: &str,
2961 content_type: ObjectMapSimpleContentType,
2962 auto_create: ObjectMapCreateStrategy,
2963 access: Option<AccessString>,
2964 ) -> BuckyResult<Option<ObjectMapRef>> {
2965 let builder = self.new_sub_builder(Some(content_type))?;
2966 self.desc_mut()
2967 .content_mut()
2968 .get_or_create_child_object_map(&builder, cache, key, auto_create, access)
2969 .await
2970 }
2971
2972 pub async fn list(
2974 &self,
2975 cache: &ObjectMapOpEnvCacheRef,
2976 list: &mut ObjectMapContentList,
2977 ) -> BuckyResult<u64> {
2978 self.desc().content().list(cache, list).await
2979 }
2980
2981 pub async fn list_direct(
2982 &self,
2983 cache: &ObjectMapOpEnvCacheRef,
2984 ) -> BuckyResult<ObjectMapContentList> {
2985 let mut list = ObjectMapContentList::new(self.count() as usize);
2986 self.desc().content().list(cache, &mut list).await?;
2987 Ok(list)
2988 }
2989
2990 pub async fn list_subs(
2992 &self,
2993 cache: &ObjectMapOpEnvCacheRef,
2994 list: &mut Vec<ObjectId>,
2995 ) -> BuckyResult<u64> {
2996 self.desc().content().list_subs(cache, list).await
2997 }
2998
2999 pub async fn next(&self, it: &mut ObjectMapIterator) -> BuckyResult<()> {
3001 self.desc().content().next(it).await
3002 }
3003
3004 pub(crate) fn diff(&self, other: &Self, diff: &mut ObjectMapDiff) {
3006 assert_eq!(self.content_type(), other.content_type());
3007
3008 match self.mode() {
3009 ObjectMapContentMode::Hub => match other.mode() {
3010 ObjectMapContentMode::Hub => {
3011 self.desc().content().diff(other.desc().content(), diff);
3012 }
3013 ObjectMapContentMode::Simple => {
3014 diff.pend_async_alter(
3015 self.cached_object_id().unwrap(),
3016 other.cached_object_id().unwrap(),
3017 );
3018 }
3019 },
3020 ObjectMapContentMode::Simple => match other.mode() {
3021 ObjectMapContentMode::Hub => {
3022 diff.pend_async_alter(
3023 self.cached_object_id().unwrap(),
3024 other.cached_object_id().unwrap(),
3025 );
3026 }
3027 ObjectMapContentMode::Simple => {
3028 self.desc().content().diff(other.desc().content(), diff);
3029 }
3030 },
3031 }
3032 }
3033
3034 pub async fn get_by_key(
3036 &self,
3037 cache: &ObjectMapOpEnvCacheRef,
3038 key: &str,
3039 ) -> BuckyResult<Option<ObjectId>> {
3040 self.desc().content().get_by_key(cache, key).await
3041 }
3042
3043 pub async fn insert_with_key(
3044 &mut self,
3045 cache: &ObjectMapOpEnvCacheRef,
3046 key: &str,
3047 value: &ObjectId,
3048 ) -> BuckyResult<()> {
3049 let builder = self.new_sub_builder(None)?;
3050 self.desc_mut()
3051 .content_mut()
3052 .insert_with_key(&builder, cache, key, value)
3053 .await
3054 }
3055
3056 pub async fn set_with_key(
3057 &mut self,
3058 cache: &ObjectMapOpEnvCacheRef,
3059 key: &str,
3060 value: &ObjectId,
3061 prev_value: &Option<ObjectId>,
3062 auto_insert: bool,
3063 ) -> BuckyResult<Option<ObjectId>> {
3064 let builder = self.new_sub_builder(None)?;
3065 self.desc_mut()
3066 .content_mut()
3067 .set_with_key(&builder, cache, key, value, prev_value, auto_insert)
3068 .await
3069 }
3070
3071 pub async fn remove_with_key(
3072 &mut self,
3073 cache: &ObjectMapOpEnvCacheRef,
3074 key: &str,
3075 prev_value: &Option<ObjectId>,
3076 ) -> BuckyResult<Option<ObjectId>> {
3077 self.desc_mut()
3078 .content_mut()
3079 .remove_with_key(cache, key, prev_value)
3080 .await
3081 }
3082
3083 pub async fn diff_get_by_key(
3085 &self,
3086 cache: &ObjectMapOpEnvCacheRef,
3087 key: &str,
3088 ) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
3089 self.desc().content().diff_get_by_key(cache, key).await
3090 }
3091
3092 pub async fn diff_insert_with_key(
3093 &mut self,
3094 cache: &ObjectMapOpEnvCacheRef,
3095 key: &str,
3096 value: &ObjectMapDiffMapItem,
3097 ) -> BuckyResult<()> {
3098 let builder = self.new_sub_builder(None)?;
3099 self.desc_mut()
3100 .content_mut()
3101 .diff_insert_with_key(&builder, cache, key, value)
3102 .await
3103 }
3104
3105 pub async fn diff_set_with_key(
3106 &mut self,
3107 cache: &ObjectMapOpEnvCacheRef,
3108 key: &str,
3109 value: &ObjectMapDiffMapItem,
3110 prev_value: &Option<ObjectMapDiffMapItem>,
3111 auto_insert: bool,
3112 ) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
3113 let builder = self.new_sub_builder(None)?;
3114 self.desc_mut()
3115 .content_mut()
3116 .diff_set_with_key(&builder, cache, key, value, prev_value, auto_insert)
3117 .await
3118 }
3119
3120 pub async fn diff_remove_with_key(
3121 &mut self,
3122 cache: &ObjectMapOpEnvCacheRef,
3123 key: &str,
3124 prev_value: &Option<ObjectMapDiffMapItem>,
3125 ) -> BuckyResult<Option<ObjectMapDiffMapItem>> {
3126 self.desc_mut()
3127 .content_mut()
3128 .diff_remove_with_key(cache, key, prev_value)
3129 .await
3130 }
3131
3132 pub async fn contains(
3134 &self,
3135 cache: &ObjectMapOpEnvCacheRef,
3136 object_id: &ObjectId,
3137 ) -> BuckyResult<bool> {
3138 self.desc().content().contains(cache, object_id).await
3139 }
3140
3141 pub async fn insert(
3142 &mut self,
3143 cache: &ObjectMapOpEnvCacheRef,
3144 object_id: &ObjectId,
3145 ) -> BuckyResult<bool> {
3146 let builder = self.new_sub_builder(None)?;
3147 self.desc_mut()
3148 .content_mut()
3149 .insert(&builder, cache, object_id)
3150 .await
3151 }
3152
3153 pub async fn remove(
3154 &mut self,
3155 cache: &ObjectMapOpEnvCacheRef,
3156 object_id: &ObjectId,
3157 ) -> BuckyResult<bool> {
3158 self.desc_mut().content_mut().remove(cache, object_id).await
3159 }
3160
3161 pub async fn diff_contains(
3163 &self,
3164 cache: &ObjectMapOpEnvCacheRef,
3165 object_id: &ObjectMapDiffSetItem,
3166 ) -> BuckyResult<bool> {
3167 self.desc().content().diff_contains(cache, object_id).await
3168 }
3169
3170 pub async fn diff_insert(
3171 &mut self,
3172 cache: &ObjectMapOpEnvCacheRef,
3173 object_id: &ObjectMapDiffSetItem,
3174 ) -> BuckyResult<bool> {
3175 let builder = self.new_sub_builder(None)?;
3176 self.desc_mut()
3177 .content_mut()
3178 .diff_insert(&builder, cache, object_id)
3179 .await
3180 }
3181
3182 pub async fn diff_remove(
3183 &mut self,
3184 cache: &ObjectMapOpEnvCacheRef,
3185 object_id: &ObjectMapDiffSetItem,
3186 ) -> BuckyResult<bool> {
3187 self.desc_mut()
3188 .content_mut()
3189 .diff_remove(cache, object_id)
3190 .await
3191 }
3192
3193 pub async fn visit(&self, visitor: &mut impl ObjectMapVisitor) -> BuckyResult<()> {
3194 self.desc().content().visit(visitor).await
3195 }
3196}
3197
3198#[cfg(test)]
3199mod test_desc_limit {
3200 use super::*;
3201
3202 struct ObjectMapSlim {
3203 class: ObjectMapClass,
3205
3206 total: u64,
3208
3209 size: u64,
3211
3212 depth: u8,
3214
3215 content_type: ObjectMapSimpleContentType,
3216 }
3217
3218 impl RawEncode for ObjectMapSlim {
3219 fn raw_measure(&self, purpose: &Option<RawEncodePurpose>) -> BuckyResult<usize> {
3220 let ret = u8::raw_bytes().unwrap() + self.total.raw_measure(purpose)?
3222 + self.size.raw_measure(purpose)?
3223 + self.depth.raw_measure(purpose)?
3224 + self.content_type.raw_measure(purpose)?;
3225
3226 Ok(ret)
3230 }
3231
3232 fn raw_encode<'a>(
3233 &self,
3234 _buf: &'a mut [u8],
3235 _purpose: &Option<RawEncodePurpose>,
3236 ) -> BuckyResult<&'a mut [u8]> {
3237 unimplemented!();
3238 }
3239 }
3240
3241 #[test]
3242 fn object_map_desc_max_size() {
3243 let slim = ObjectMapSlim {
3244 class: ObjectMapClass::Root,
3245 total: 1024,
3246 size: 1024,
3247 depth: 0,
3248 content_type: ObjectMapSimpleContentType::Map,
3249 };
3250
3251 let size = slim.raw_measure(&None).unwrap();
3252 println!("{}", size);
3253 }
3254}
3255
3256#[cfg(test)]
3257mod test {
3258 use super::super::cache::*;
3259 use super::*;
3260 use crate::*;
3261
3262 use rand::distributions::Alphanumeric;
3263 use rand::{thread_rng, Rng};
3264
3265 fn gen_random_key(len: usize) -> String {
3266 let rand_string: String = thread_rng()
3267 .sample_iter(&Alphanumeric)
3268 .take(len)
3269 .map(char::from)
3270 .collect();
3271
3272 println!("{}", rand_string);
3273 rand_string
3274 }
3275
3276 async fn test_map() {
3277 let noc = ObjectMapMemoryNOCCache::new();
3278 let root_cache = ObjectMapRootMemoryCache::new_default_ref(None, noc);
3279 let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone());
3280
3281 let owner = ObjectId::default();
3282 let mut map = ObjectMap::new(
3283 ObjectMapSimpleContentType::Map,
3284 Some(owner.clone()),
3285 Some(owner.clone()),
3286 )
3287 .no_create_time()
3288 .build();
3289 for i in 0..10000 {
3290 let key = format!("test_map_{}", i);
3291 let object_id = ObjectId::default();
3292 map.insert_with_key(&cache, &key, &object_id).await.unwrap();
3293 }
3294
3295 let mut subs = vec![];
3296 map.list_subs(&cache, &mut subs).await.unwrap();
3297 info!("subs: {:?}", subs);
3298
3299 let object_id = ObjectId::default();
3300 for i in 0..10000 {
3301 let key = format!("test_map_{}", i);
3302 let ret = map.get_by_key(&cache, &key).await.unwrap();
3303 assert_eq!(ret, Some(object_id));
3304 }
3305
3306 let id = map.flush_id();
3317 info!("obj map id={}", id);
3318
3319 cache.put_object_map(&id, map, None).unwrap();
3320 cache.gc(true, &id).await.unwrap();
3321 }
3322
3323 async fn test_set() {
3324 let noc = ObjectMapMemoryNOCCache::new();
3325 let root_cache = ObjectMapRootMemoryCache::new_default_ref(None, noc);
3326 let cache = ObjectMapOpEnvMemoryCache::new_ref(root_cache.clone());
3327
3328 let owner = ObjectId::default();
3329 let mut map = ObjectMap::new(
3330 ObjectMapSimpleContentType::Set,
3331 Some(owner.clone()),
3332 Some(owner.clone()),
3333 )
3334 .no_create_time()
3335 .build();
3336
3337 fn object_id_from_index(index: i32) -> ObjectId {
3338 let key = format!("test_set_{}", index);
3339 let chunk_id = ChunkId::calculate_sync(key.as_bytes()).unwrap();
3340 let object_id = chunk_id.object_id();
3341 object_id
3342 }
3343
3344 for i in 0..10000 {
3345 let object_id = object_id_from_index(i);
3346 let ret = map.insert(&cache, &object_id).await.unwrap();
3347 assert!(ret);
3348
3349 let ret = map.insert(&cache, &object_id).await.unwrap();
3350 assert!(!ret);
3351 }
3352
3353 for i in 0..10000 {
3354 let object_id = object_id_from_index(i);
3355 let ret = map.contains(&cache, &object_id).await.unwrap();
3356 assert!(ret);
3357 }
3358
3359 for i in 0..10000 {
3360 let object_id = object_id_from_index(i);
3361 let ret = map.remove(&cache, &object_id).await.unwrap();
3362 assert!(ret);
3363 }
3364
3365 assert_eq!(map.count(), 0);
3366
3367 let id = map.flush_id();
3368 info!("obj map id={}", id);
3369 }
3370
3371 #[test]
3372 fn test() {
3373 crate::init_simple_log("test-object-map", Some("debug"));
3374 async_std::task::block_on(async move {
3375 test_map().await;
3377 });
3378 }
3379
3380 #[test]
3381 fn test_path_string() {
3382 let path = "/a/b/c";
3383 let parts = path.split("/").skip(1);
3384 for part in parts {
3385 println!("part={}", part);
3386 }
3387 }
3388
3389 #[test]
3390 fn test_hub_fix_limit() {
3391 let mut content = ObjectMapHubContent {
3392 depth: 0,
3393 subs: BTreeMap::new(),
3394 dirty: false,
3395 };
3396
3397 let mut index = 0;
3398 let object_id = ObjectId::default();
3399 loop {
3400 let item = ObjectMapHubItem {
3401 id: object_id.clone(),
3402 };
3403 content.subs.insert(index, item);
3404 let len = content.raw_measure(&None).unwrap();
3405 if len > u16::MAX as usize {
3406 println!("touch desc limit! index ={}", index);
3407 break;
3408 }
3409 index += 1;
3410 }
3411 }
3412
3413 #[test]
3414 fn test_simple_map_limit() {
3415 use std::str::FromStr;
3416
3417 let object_id = ObjectId::default();
3418 let object_id = ObjectId::from_str("95RvaS5Wy2UZC4Pzy7A6PZTs47bsWLCPtZe834oVvbQ4").unwrap();
3419 let s = object_id.to_string();
3420 let len = object_id.raw_measure(&None).unwrap() + s.raw_measure(&None).unwrap();
3421 println!("len={}", len);
3422
3423 let mut content = ObjectMapSimpleContent::new(ObjectMapSimpleContentType::Map, 0);
3424 let object_id = ObjectId::default();
3425 let mut index = 0;
3426 loop {
3427 let key = gen_random_key(OBJECT_MAP_KEY_MAX_LEN);
3428 content.insert_with_key(&key, &object_id).unwrap();
3429 let len = content.raw_measure(&None).unwrap();
3430 if len > u16::MAX as usize {
3431 println!("touch simple map limit! index ={}", index);
3432 break;
3433 }
3434
3435 index += 1;
3436 }
3437 }
3438
3439 #[test]
3440 fn test_simple_set_limit() {
3441 use cyfs_base::*;
3442
3443 let mut content = ObjectMapSimpleContent::new(ObjectMapSimpleContentType::Set, 0);
3444
3445 let mut index: i32 = 0;
3446 loop {
3447 let chunk_id = ChunkId::calculate_sync(&index.to_be_bytes()).unwrap();
3448 let object_id = chunk_id.object_id();
3449 let ret = content.insert(&object_id).unwrap();
3450 assert!(ret);
3451
3452 let len = content.raw_measure(&None).unwrap();
3453 if len > u16::MAX as usize {
3454 println!("touch simple set limit! index ={}", index);
3455 break;
3456 }
3457
3458 index += 1;
3459 }
3460 }
3461
3462 fn hash_bytes(key: &[u8]) -> u64 {
3463 use std::collections::hash_map::DefaultHasher;
3464 use std::hash::Hasher;
3465
3466 let mut hasher = DefaultHasher::new();
3467 let mut sha256 = sha2::Sha256::new();
3468 sha256.input(key);
3469 hasher.write(&sha256.result());
3470 hasher.finish()
3471 }
3472
3473 #[test]
3474 fn test_hash() {
3475 let ret = hash_bytes("abc".as_bytes());
3476 println!("hash={}", ret);
3477 }
3478}