rewrite: include JSON::Serializable

dev
Philippe PITTOLI 2020-01-29 15:56:49 +01:00
parent f5f75dda7b
commit d02de92d24
4 changed files with 105 additions and 91 deletions

View File

@ -31,14 +31,11 @@ module FileStorage
end end
class Chunk class Chunk
JSON.mapping({ include JSON::Serializable
# chunk's number
n: Int32, property n : Int32 # chunk's number
# number of chunks property on : Int32 # number of chunks
on: Int32, property digest : String # digest of the current chunk
# digest of the current chunk
digest: String
})
def initialize(@n, @on, data) def initialize(@n, @on, data)
@digest = FileStorage.data_digest data.to_slice @digest = FileStorage.data_digest data.to_slice
@ -50,10 +47,10 @@ module FileStorage
# arbitrary parts of each file. # arbitrary parts of each file.
class Token class Token
JSON.mapping({ include JSON::Serializable
uid: Int32,
login: String property uid : Int32
}) property login : String
def initialize(@uid, @login) def initialize(@uid, @login)
end end
@ -69,23 +66,23 @@ module FileStorage
# A file has a name, a size and tags. # A file has a name, a size and tags.
class FileInfo class FileInfo
JSON.mapping({ include JSON::Serializable
name: String,
size: UInt64,
nb_chunks: Int32,
# SHA256 file digest
digest: String,
# list of SHA256, if we are on UDP property name : String
# chunks: Array(SHA256), property size : UInt64
tags: Array(String)? property nb_chunks : Int32
}) property digest : String
def initialize(file : File, @tags = nil) # list of SHA256, if we are on UDP
# chunks: Array(SHA256),
property tags : Array(String)
def initialize(file : File, tags = nil)
@name = File.basename file.path @name = File.basename file.path
@size = file.size @size = file.size
@digest = FileStorage.file_digest file @digest = FileStorage.file_digest file
@nb_chunks = (@size / FileStorage.message_buffer_size).ceil.to_i @nb_chunks = (@size / FileStorage.message_buffer_size).ceil.to_i
@tags = tags || [] of String
end end
end end
@ -95,11 +92,10 @@ module FileStorage
alias Request = UploadRequest | DownloadRequest alias Request = UploadRequest | DownloadRequest
class UploadRequest < Message class UploadRequest < Message
JSON.mapping({ include JSON::Serializable
# autogenerated
mid: String, property mid : String # autogenerated
file: FileInfo property file : FileInfo
})
def initialize(@file) def initialize(@file)
@mid = UUID.random.to_s @mid = UUID.random.to_s
@ -109,28 +105,25 @@ module FileStorage
# WIP # WIP
class DownloadRequest < Message class DownloadRequest < Message
JSON.mapping({ include JSON::Serializable
# autogenerated
mid: String,
# SHA256 digest of the file, used as ID
uuid: String?,
name: String?,
tags: Array(String)?
})
def initialize(@uuid = nil, @name = nil, @tags = nil) property mid : String # autogenerated
property filedigest : String? # SHA256 digest of the file, used as ID
property name : String?
property tags : Array(String)?
def initialize(@filedigest = nil, @name = nil, @tags = nil)
@mid = UUID.random.to_s @mid = UUID.random.to_s
end end
end end
class Authentication < Message class Authentication < Message
JSON.mapping({ include JSON::Serializable
# autogenerated
mid: String, property mid : String # autogenerated
token: Token, property token : Token
uploads: Array(UploadRequest), property uploads : Array(UploadRequest)
downloads: Array(DownloadRequest) property downloads : Array(DownloadRequest)
})
def initialize(@token, @uploads = Array(UploadRequest).new, @downloads = Array(DownloadRequest).new) def initialize(@token, @uploads = Array(UploadRequest).new, @downloads = Array(DownloadRequest).new)
@mid = UUID.random.to_s @mid = UUID.random.to_s
@ -138,52 +131,46 @@ module FileStorage
end end
class Response < Message class Response < Message
JSON.mapping({ include JSON::Serializable
mid: String,
response: String, property mid : String
reason: String? property response : String
}) property reason : String?
def initialize(@mid, @response, @reason = nil) def initialize(@mid, @response, @reason = nil)
end end
end end
class Error < Message class Error < Message
JSON.mapping({ include JSON::Serializable
mid: String,
# a response for each request property mid : String
response: String, property response : String # a response for each request
reason: String? property reason : String?
})
def initialize(@mid, @response, @reason = nil) def initialize(@mid, @response, @reason = nil)
end end
end end
class Responses < Message class Responses < Message
JSON.mapping({ include JSON::Serializable
mid: String,
# a response for each request property mid : String
responses: Array(Response), property responses : Array(Response) # a response for each request
response: String, property response : String
reason: String? property reason : String?
})
def initialize(@mid, @response, @responses, @reason = nil) def initialize(@mid, @response, @responses, @reason = nil)
end end
end end
class Transfer < Message class Transfer < Message
JSON.mapping({ include JSON::Serializable
# autogenerated
mid: String, property mid : String # autogenerated
# SHA256 digest of the entire file property filedigest : String # SHA256 digest of the entire file
filedigest: String, property chunk : Chunk # For now, just the counter in a string
# For now, just the counter in a string property data : String # base64 slice
chunk: Chunk,
# base64 slice
data: String,
})
def initialize(file_info : FileInfo, count, bindata) def initialize(file_info : FileInfo, count, bindata)
# count: chunk number # count: chunk number

View File

@ -1,4 +1,5 @@
require "dodb"
require "json" require "json"
# keep track of connected users and their requests # keep track of connected users and their requests
@ -20,31 +21,35 @@ class TransferInfo
include JSON::Serializable include JSON::Serializable
property owner : Int32 property owner : Int32
property file_info : FileInfo property file_info : FileStorage::FileInfo
property chunks : Hash(Int32, Bool) property chunks : Array(Int32)
def initialize(@owner, @file_info) def initialize(@owner, @file_info)
@chunks = Hash(Int32, Bool).new @chunks = [0...@file_info.nb_chunks]
@file_info.nb_chunks.times do |n|
@chunks[n] = false
end
end end
end end
class Context class Context
class_property service_name = "filestorage" class_property service_name = "filestorage"
class_property storage_directory = "./storage" class_property storage_directory = "./storage"
class_property file_info_directory = "./file-infos" class_property file_info_directory = "./file-infos"
class_property db : DODB::DataBase(TransferInfo) = self.init_db class_property db = DODB::DataBase(TransferInfo).new @@file_info_directory
# search file informations by their index, owner and tags
class_property db_by_filedigest : DODB::Index(TransferInfo) = @@db.new_index "filedigest", &.file_info.digest
class_property db_by_owner : DODB::Partition(TransferInfo) = @@db.new_partition "owner", &.owner.to_s
class_property db_by_tags : DODB::Tags(TransferInfo) = @@db.new_tags "tags", &.file_info.tags
def self.db_reconnect
# In case file_info_directory changes: database reinstanciation
def init_db
@@db = DODB::DataBase(TransferInfo).new @@file_info_directory @@db = DODB::DataBase(TransferInfo).new @@file_info_directory
# init index, partitions and tags # recreate indexes, partitions and tags objects, too
Context.db.new_index "filedigest", &.file_info.digest @@db_by_filedigest = @@db.new_index "filedigest", &.file_info.digest
Context.db.new_partition "owner", &.owner @@db_by_owner = @@db.new_partition "owner", &.owner.to_s
Context.db.new_tags "tags", &.tags @@db_by_tags = @@db.new_tags "tags", &.file_info.tags
end end
# list of connected users (fd => uid) # list of connected users (fd => uid)

View File

@ -3,10 +3,9 @@ require "dodb"
require "base64" require "base64"
# reception of a file chunk # reception of a file chunk
def hdl_transfer(message : FileStorage::Transfer, def hdl_transfer(message : FileStorage::Transfer, user : User) : FileStorage::Response
user : User,
event : IPC::Event::Message) : FileStorage::Response # We received a message containing a chunk of file.
puts "receiving a file"
mid = message.mid mid = message.mid
mid ||= "no message id" mid ||= "no message id"
@ -30,7 +29,9 @@ def hdl_transfer(message : FileStorage::Transfer,
# Get the transfer info from the db # Get the transfer info from the db
# is the file info recorded? # is the file info recorded?
by_digest = Context.db.get_index "filedigest" by_digest = Context.db.get_index "filedigest"
transfer_info = by_digest.get? message.filedigest transfer_info = by_digest.get message.filedigest
if
by_owner = Context.db.get_partition "owner" by_owner = Context.db.get_partition "owner"
pp! by_owner pp! by_owner

View File

@ -0,0 +1,21 @@
require "../common/filestorage.cr"
require "ipc"
require "option_parser"
filename = "./README.md"
OptionParser.parse do |parser|
parser.on "-f file-to-transfer",
"--file to-transfer",
"File to transfer (simulation)." do |opt|
filename = opt
end
parser.unknown_args do |args|
pp! args
end
end
require "../server/context.cr"
pp! Context