rewrite: include JSON::Serializable
This commit is contained in:
parent
f5f75dda7b
commit
d02de92d24
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
21
src/tests/context-tests.cr
Normal file
21
src/tests/context-tests.cr
Normal 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
|
Loading…
Reference in New Issue
Block a user