Skip to content

Commit

Permalink
refactor: use dep hashmaps from ZhenyaUsenko
Browse files Browse the repository at this point in the history
  • Loading branch information
cybrowl committed Apr 15, 2023
1 parent dfdf7c1 commit 904a3e8
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 59 deletions.
37 changes: 16 additions & 21 deletions package-set.dhall
@@ -1,25 +1,20 @@
let upstream = https://github.com/dfinity/vessel-package-set/releases/download/mo-0.8.2-20230217/package-set.dhall sha256:0a6f87bdacb4032f4b273d936225735ca4a0b0378de1f81e4bc4c6b4c5bad8a5
let upstream = https://github.com/internet-computer/base-package-set/releases/download/moc-0.8.6/package-set.dhall sha256:4a7734568f1c7e5dfe91d2ba802c9b6f218d7836904dea5a999a3096f6ef0d3c
let Package =
{ name : Text, version : Text, repo : Text, dependencies : List Text }

let
-- This is where you can add your own packages to the package-set
additions =
[] : List Package
let additions = [
{
name = "base",
repo = "https://github.com/dfinity/motoko-base",
version = "master",
dependencies = [] : List Text
},
{
name = "hashmap",
repo = "https://github.com/ZhenyaUsenko/motoko-hash-map",
version = "master",
dependencies = [] : List Text
},
] : List Package

let
{- This is where you can override existing packages in the package-set
For example, if you wanted to use version `v2.0.0` of the foo library:
let overrides = [
{ name = "foo"
, version = "v2.0.0"
, repo = "https://github.com/bar/foo"
, dependencies = [] : List Text
}
]
-}
overrides =
[] : List Package

in upstream # additions # overrides
in upstream # additions
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "upload-file",
"version": "0.1.0",
"version": "0.2.0",
"type": "module",
"scripts": {
"gen_can_test_interface": "bash ./scripts/gen_can_test_interface.sh",
Expand Down
54 changes: 23 additions & 31 deletions src/FileStorage.mo
Expand Up @@ -5,6 +5,7 @@ import Float "mo:base/Float";
import Hash "mo:base/Hash";
import HashMap "mo:base/HashMap";
import Iter "mo:base/Iter";
import Map "mo:hashmap/Map";
import Nat "mo:base/Nat";
import Nat32 "mo:base/Nat32";
import Option "mo:base/Option";
Expand Down Expand Up @@ -37,19 +38,14 @@ actor class FileStorage() = this {
// change me when in production
let IS_PROD : Bool = false;

private var assets : HashMap.HashMap<Asset_ID, Asset> = HashMap.HashMap<Asset_ID, Asset>(
0,
Text.equal,
Text.hash,
);
let { nhash; thash } = Map;

private var assets = Map.new<Asset_ID, Asset>(thash);
private var chunks = Map.new<Chunk_ID, AssetChunk>(nhash);

stable var assets_stable_storage : [(Asset_ID, Asset)] = [];

private var chunk_id_count : Chunk_ID = 0;
private var chunks : HashMap.HashMap<Chunk_ID, AssetChunk> = HashMap.HashMap<Chunk_ID, AssetChunk>(
0,
Nat.equal,
Hash.hash,
);

private func compare(a : AssetChunk, b : AssetChunk) : Order.Order {
if (a.order < b.order) {
Expand Down Expand Up @@ -79,7 +75,7 @@ actor class FileStorage() = this {
owner = caller;
};

chunks.put(chunk_id_count, asset_chunk);
ignore Map.put(chunks, nhash, chunk_id_count, asset_chunk);

return chunk_id_count;
};
Expand All @@ -94,7 +90,7 @@ actor class FileStorage() = this {
var asset_checksum : Nat32 = 0;
let modulo_value : Nat32 = 400_000_000;

for (chunk in chunks.vals()) {
for (chunk in Map.vals(chunks)) {
if (chunk.batch_id == batch_id) {
if (chunk.owner != caller) {
return #err("Not Owner of Chunk");
Expand All @@ -119,7 +115,7 @@ actor class FileStorage() = this {
};

for (chunk in chunks_to_commit.vals()) {
chunks.delete(chunk.id);
Map.delete(chunks, nhash, chunk.id);
};

let asset : Types.Asset = {
Expand All @@ -140,16 +136,17 @@ actor class FileStorage() = this {
owner = Principal.toText(caller);
};

assets.put(ASSET_ID, asset);
ignore Map.put(assets, thash, ASSET_ID, asset);

return #ok(asset.id);
};

public shared ({ caller }) func delete_asset(id : Asset_ID) : async Result.Result<Text, Text> {
switch (assets.get(id)) {
switch (Map.get(assets, thash, id)) {
case (?asset) {
if (asset.owner == Principal.toText(caller)) {
assets.delete(id);
Map.delete(assets, thash, id);

return #ok("Asset deleted successfully.");
} else {
return #err("Permission denied: You are not the owner of this asset.");
Expand All @@ -165,10 +162,9 @@ actor class FileStorage() = this {
let currentTime = Time.now();
let fiveMinutes = 5 * 60 * 1000000000; // Convert 5 minutes to nanoseconds

let filteredChunks = HashMap.mapFilter<Chunk_ID, AssetChunk, AssetChunk>(
let filteredChunks = Map.mapFilter<Chunk_ID, AssetChunk, AssetChunk>(
chunks,
Nat.equal,
Hash.hash,
nhash,
func(key : Chunk_ID, assetChunk : AssetChunk) : ?AssetChunk {
let age = currentTime - assetChunk.created;
if (age <= fiveMinutes) {
Expand All @@ -185,7 +181,7 @@ actor class FileStorage() = this {
public query func assets_list() : async Result.Result<[Asset], Text> {
var assets_list = Buffer.Buffer<Asset>(0);

for (asset in assets.vals()) {
for (asset in Map.vals(assets)) {
let asset_without_content : Asset = {
asset with content = null;
};
Expand All @@ -197,7 +193,7 @@ actor class FileStorage() = this {
};

public query func get(id : Asset_ID) : async Result.Result<Asset, Text> {
switch (assets.get(id)) {
switch (Map.get(assets, thash, id)) {
case (?asset) {
let asset_without_content : Asset = {
asset with content = null;
Expand All @@ -212,7 +208,7 @@ actor class FileStorage() = this {
};

public query func chunks_size() : async Nat {
return chunks.size();
return Map.size(chunks);
};

public query func is_full() : async Bool {
Expand All @@ -235,7 +231,7 @@ actor class FileStorage() = this {

let asset_id = Utils.get_asset_id(request.url);

switch (assets.get(asset_id)) {
switch (Map.get(assets, thash, asset_id)) {
case (?asset) {
let filename = Text.concat("attachment; filename=", asset.filename);

Expand Down Expand Up @@ -301,7 +297,7 @@ actor class FileStorage() = this {
public shared query ({ caller }) func http_request_streaming_callback(
st : Types.StreamingCallbackToken
) : async Types.StreamingCallbackHttpResponse {
switch (assets.get(st.asset_id)) {
switch (Map.get(assets, thash, st.asset_id)) {
case (null) throw Error.reject("asset_id not found: " # st.asset_id);
case (?asset) {
return {
Expand Down Expand Up @@ -341,16 +337,12 @@ actor class FileStorage() = this {

// ------------------------- System Methods -------------------------
system func preupgrade() {
assets_stable_storage := Iter.toArray(assets.entries());
assets_stable_storage := Iter.toArray(Map.entries(assets));
};

system func postupgrade() {
assets := HashMap.fromIter<Asset_ID, Asset>(
assets_stable_storage.vals(),
0,
Text.equal,
Text.hash,
);
assets := Map.fromIter<Asset_ID, Asset>(assets_stable_storage.vals(), thash);

assets_stable_storage := [];
};
};
11 changes: 9 additions & 2 deletions src/utils.mo
Expand Up @@ -3,6 +3,7 @@ import Debug "mo:base/Debug";
import Hash "mo:base/Hash";
import Int "mo:base/Int";
import Iter "mo:base/Iter";
import Map "mo:hashmap/Map";
import Nat "mo:base/Nat";
import Nat32 "mo:base/Nat32";
import Option "mo:base/Option";
Expand All @@ -16,6 +17,8 @@ module {
is_prod : Bool;
};

let { hashNat } = Map;

public func get_asset_id(url : Text) : Text {
let urlSplitByPath : [Text] = Iter.toArray(Text.tokens(url, #char '/'));
let lastElem : Text = urlSplitByPath[urlSplitByPath.size() - 1];
Expand Down Expand Up @@ -43,14 +46,18 @@ module {
public func random_from_time() : [Nat] {
var randomness = Buffer<Nat>(0);

let seed = Nat32.toNat(Hash.hash(Int.abs(Time.now())));
let hash : Nat32 = hashNat(Int.abs(Time.now()));

let seed = Nat32.toNat(hash);

for (i in Iter.range(0, 32)) {
if (i == 0) {
randomness.add(seed);
} else {
let prev = randomness.get(i - 1);
let next = Nat32.toNat(Hash.hash(prev));
let hash_prev : Nat32 = hashNat(prev);

let next = Nat32.toNat(hash_prev);
randomness.add(next);
};
};
Expand Down
2 changes: 0 additions & 2 deletions tests/file_storage.test.cjs
Expand Up @@ -216,8 +216,6 @@ test("FileStorage[motoko].commit_batch(): should start formation of asset to be
test("FileStorage[motoko].assets_list(): should return all assets without file content data since it would be too large", async function (t) {
const { ok: asset_list } = await file_storage_actors.motoko.assets_list();

console.log("asset_list: ", asset_list);

const hasAssets = asset_list.length > 1;

t.equal(hasAssets, true);
Expand Down
4 changes: 2 additions & 2 deletions vessel.dhall
@@ -1,4 +1,4 @@
{
dependencies = [ "base" ],
compiler = None Text
dependencies = [ "base", "hashmap" ],
compiler = Some "0.8.6"
}

0 comments on commit 904a3e8

Please sign in to comment.