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