Browse Source

runtime: storage add data_directory::inject_data_objects()

Mokhtar Naamani 4 years ago
parent
commit
d9a5f597d3

+ 50 - 6
runtime-modules/storage/src/data_directory.rs

@@ -22,6 +22,7 @@
 //#![warn(missing_docs)]
 
 use codec::{Decode, Encode};
+use rstd::collections::btree_map::BTreeMap;
 use rstd::prelude::*;
 use sr_primitives::traits::{MaybeSerialize, Member};
 use srml_support::{decl_error, decl_event, decl_module, decl_storage, ensure, Parameter};
@@ -75,6 +76,9 @@ decl_error! {
 
         /// Require root origin in extrinsics.
         RequireRootOrigin,
+
+        /// DataObject Injection Failed. Invalid Input
+        DataObjectsInjectionFailed
     }
 }
 
@@ -116,23 +120,32 @@ impl Default for LiaisonJudgement {
     }
 }
 
+/// Alias for DataObjectInternal
+pub type DataObject<T> = DataObjectInternal<
+    MemberId<T>,
+    <T as system::Trait>::BlockNumber,
+    <T as timestamp::Trait>::Moment,
+    <T as data_object_type_registry::Trait>::DataObjectTypeId,
+    StorageProviderId<T>,
+>;
+
 /// Manages content ids, type and storage provider decision about it.
 #[derive(Clone, Encode, Decode, PartialEq, Debug)]
-pub struct DataObject<T: Trait> {
+pub struct DataObjectInternal<MemberId, BlockNumber, Moment, DataObjectTypeId, StorageProviderId> {
     /// Content owner.
-    pub owner: MemberId<T>,
+    pub owner: MemberId,
 
     /// Content added at.
-    pub added_at: BlockAndTime<T::BlockNumber, T::Moment>,
+    pub added_at: BlockAndTime<BlockNumber, Moment>,
 
     /// Content type id.
-    pub type_id: <T as data_object_type_registry::Trait>::DataObjectTypeId,
+    pub type_id: DataObjectTypeId,
 
     /// Content size in bytes.
     pub size: u64,
 
     /// Storage provider id of the liaison.
-    pub liaison: StorageProviderId<T>,
+    pub liaison: StorageProviderId,
 
     /// Storage provider as liaison judgment.
     pub liaison_judgement: LiaisonJudgement,
@@ -141,6 +154,9 @@ pub struct DataObject<T: Trait> {
     pub ipfs_content_id: Vec<u8>,
 }
 
+/// A map collection of unique DataObjects keyed by the ContentId
+pub type DataObjectsMap<T> = BTreeMap<<T as Trait>::ContentId, DataObject<T>>;
+
 decl_storage! {
     trait Store for Module<T: Trait> as DataDirectory {
         /// List of ids known to the system.
@@ -213,7 +229,7 @@ decl_module! {
             let liaison = T::StorageProviderHelper::get_random_storage_provider()?;
 
             // Let's create the entry then
-            let data: DataObject<T> = DataObject {
+            let data: DataObject<T> = DataObjectInternal {
                 type_id,
                 size,
                 added_at: common::current_block_time::<T>(),
@@ -278,6 +294,34 @@ decl_module! {
                 .collect();
             <KnownContentIds<T>>::put(upd_content_ids);
         }
+
+        /// Injects a set of data objects and their corresponding content id into the directory.
+        /// The operation is "silent" - no events will be emitted as objects are added.
+        /// The number of objects that can be added per call is limited to prevent the dispatch
+        /// from causing the block production to fail if it takes too much time to process.
+        /// Existing data objects will be overwritten.
+        fn inject_data_objects(origin, objects: DataObjectsMap<T>) {
+            ensure_root(origin)?;
+
+            // limit size - do some benchmarking to test how much we can allow per call.
+            const MAX_OBJECTS: usize = 20;
+
+            // Must provide something to inject
+            ensure!(objects.len() <= MAX_OBJECTS, Error::DataObjectsInjectionFailed);
+
+            for (id, object) in objects.into_iter() {
+                // append to known content ids
+                // duplicates will be removed at the end
+                <KnownContentIds<T>>::mutate(|ids| ids.push(id));
+                <DataObjectByContentId<T>>::insert(id, object);
+            }
+
+            // remove duplicate ids
+            <KnownContentIds<T>>::mutate(|ids| {
+                ids.sort();
+                ids.dedup();
+            });
+        }
     }
 }
 

+ 1 - 1
runtime-modules/storage/src/tests/mock.rs

@@ -63,7 +63,7 @@ impl ContentIdExists<Test> for MockContent {
         which: &<Test as data_directory::Trait>::ContentId,
     ) -> Result<data_directory::DataObject<Test>, &'static str> {
         match *which {
-            TEST_MOCK_EXISTING_CID => Ok(data_directory::DataObject {
+            TEST_MOCK_EXISTING_CID => Ok(data_directory::DataObjectInternal {
                 type_id: 1,
                 size: 1234,
                 added_at: data_directory::BlockAndTime {

+ 4 - 3
types/src/media.ts

@@ -1,4 +1,4 @@
-import { Enum, Struct, Option, Vec as Vector, H256 } from '@polkadot/types';
+import { Enum, Struct, Option, Vec as Vector, H256, BTreeMap } from '@polkadot/types';
 import { getTypeRegistry, u64, bool, Text } from '@polkadot/types';
 import { BlockAndTime } from './common';
 import { MemberId } from './members';
@@ -127,11 +127,11 @@ export class DataObjectType extends Struct {
   }
 }
 
+export class DataObjectsMap extends BTreeMap.with(ContentId, DataObject) {}
+
 export function registerMediaTypes () {
   try {
     getTypeRegistry().register({
-      '::ContentId': ContentId,
-      '::DataObjectTypeId': DataObjectTypeId,
       ContentId,
       LiaisonJudgement,
       DataObject,
@@ -139,6 +139,7 @@ export function registerMediaTypes () {
       DataObjectStorageRelationship,
       DataObjectTypeId,
       DataObjectType,
+      DataObjectsMap
     });
   } catch (err) {
     console.error('Failed to register custom types of media module', err);