filestore 0.0.14 → 0.0.19
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/filestore/factory.rb +211 -0
- data/lib/filestore/memory_meta.rb +34 -28
- data/lib/filestore/meta_manager.rb +5 -0
- data/lib/filestore/multitenant_store.rb +21 -60
- data/lib/filestore/observer.rb +4 -4
- data/lib/filestore/simple_store.rb +42 -156
- data/lib/filestore.rb +11 -3
- data/test/classes.rb +12 -6
- data/test/tc_filestore.rb +6 -11
- data/test/tc_meta.rb +14 -11
- data/test/tc_module.rb +6 -1
- data/test/tc_multitenant.rb +34 -16
- metadata +2 -1
@@ -0,0 +1,211 @@
|
|
1
|
+
#
|
2
|
+
# store_factory.rb
|
3
|
+
#
|
4
|
+
# author: Thomas Stätter
|
5
|
+
# date: 2014/01/06
|
6
|
+
#
|
7
|
+
module FileStore
|
8
|
+
#
|
9
|
+
# Base factory class
|
10
|
+
#
|
11
|
+
class BaseFactory
|
12
|
+
#
|
13
|
+
# Creates a new instance of the given class
|
14
|
+
#
|
15
|
+
# Arguments:
|
16
|
+
# klass: The class to be instantiated
|
17
|
+
# path: The path to be used wether for stores or managers
|
18
|
+
# observable (optional): Determines wether this instance should support observation
|
19
|
+
# logger (optional): The logging facility
|
20
|
+
#
|
21
|
+
# Returns:
|
22
|
+
# A new instance of 'klass'
|
23
|
+
#
|
24
|
+
def self.create(klass, path, observable = false, logger = StdoutLogger)
|
25
|
+
logger.debug "Creating new instance of class #{klass} with path '#{path}'"
|
26
|
+
obj = klass.new path
|
27
|
+
|
28
|
+
obj.logger = logger if not logger.nil?
|
29
|
+
|
30
|
+
if observable then
|
31
|
+
logger.debug "Extending instance with module 'ObservedSubject'"
|
32
|
+
|
33
|
+
obj.extend ObservedSubject
|
34
|
+
obj.initialize_obs
|
35
|
+
end
|
36
|
+
|
37
|
+
return obj
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
#
|
42
|
+
# MetaManager factory class
|
43
|
+
#
|
44
|
+
class MemoryMetaFactory < BaseFactory
|
45
|
+
#
|
46
|
+
# Creates a memory meta-manager instance
|
47
|
+
#
|
48
|
+
# Arguments:
|
49
|
+
# persist_file: The file where the manager will be persistet
|
50
|
+
# observable (optional): Determines wether this instance should support observation
|
51
|
+
# logger (optional): The logging facility
|
52
|
+
#
|
53
|
+
# Returns:
|
54
|
+
# A new instance of MemoryMetaManager
|
55
|
+
#
|
56
|
+
def self.create(persist_file = MemoryMetaManager::FILE, observable = false, logger = StdoutLogger)
|
57
|
+
return super(MemoryMetaManager, persist_file, observable, logger)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
#
|
61
|
+
# MultiTenantFileStore factory class
|
62
|
+
#
|
63
|
+
class MultiTenantStoreFactory < BaseFactory
|
64
|
+
#
|
65
|
+
# Creates a multi tenant store instance
|
66
|
+
#
|
67
|
+
# Arguments:
|
68
|
+
# base_path: The directory of the multitenant store
|
69
|
+
# observable (optional): Determines wether this instance should support observation
|
70
|
+
# logger (optional): The logging facility
|
71
|
+
#
|
72
|
+
# Returns:
|
73
|
+
# A new instance of MultiTenantStore
|
74
|
+
#
|
75
|
+
def self.create(base_path, observable = false, logger = StdoutLogger)
|
76
|
+
logger.debug "Creating new MultiTenantFileStore"
|
77
|
+
multi_store = super MultiTenantFileStore, base_path, observable, logger
|
78
|
+
|
79
|
+
multi_store.stores = MultiTenantStoreFactory::recover_tenant_stores(base_path, observable, logger) if File.exists?(base_path)
|
80
|
+
|
81
|
+
return multi_store
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# Recovers a multitenant store
|
86
|
+
#
|
87
|
+
# Arguments:
|
88
|
+
# rootPath: The base path of the multitenant store
|
89
|
+
# logger (optional): The logging facility
|
90
|
+
#
|
91
|
+
# Returns:
|
92
|
+
# A hashset of file stores (with the user ID as key) recovered
|
93
|
+
# from the given directory
|
94
|
+
#
|
95
|
+
def self.recover_tenant_stores(root_path, observable, logger)
|
96
|
+
raise FileStoreException, "Root path #{rootPath} isn't a valid multitenant store" if not File.directory?(root_path)
|
97
|
+
|
98
|
+
stores = {}
|
99
|
+
|
100
|
+
logger.debug "Trying to recover tenant stores"
|
101
|
+
|
102
|
+
Dir.glob(File.join(root_path, "*")).each do |e|
|
103
|
+
begin
|
104
|
+
if File.directory?(e) then
|
105
|
+
tenant = File.basename(e)
|
106
|
+
tenant_path = File.absolute_path e
|
107
|
+
|
108
|
+
logger.debug "Restoring tenant store in directory #{tenant_path}"
|
109
|
+
|
110
|
+
sfs = SimpleStoreFactory::create tenant_path, observable, logger
|
111
|
+
|
112
|
+
stores[tenant] = sfs
|
113
|
+
end
|
114
|
+
rescue Exception => e
|
115
|
+
logger.error "Couldn't create store for tenant #{tenant}.\n#{e}"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
return stores
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
#
|
124
|
+
# SimpleFileStore factory class
|
125
|
+
#
|
126
|
+
class SimpleStoreFactory < BaseFactory
|
127
|
+
#
|
128
|
+
# Creates a simple file-store instance
|
129
|
+
#
|
130
|
+
# Arguments:
|
131
|
+
# base_path: The base path directory
|
132
|
+
# observable (optional): Determines wether this instance should support observation
|
133
|
+
# logger (optional): The logging facility
|
134
|
+
#
|
135
|
+
# Returns:
|
136
|
+
# A new instance of SimpleFileStore
|
137
|
+
#
|
138
|
+
def self.create(base_path, observable = false, logger = StdoutLogger)
|
139
|
+
store = super(SimpleFileStore, base_path, observable, logger)
|
140
|
+
mm = MemoryMetaFactory.create File.join(base_path, MemoryMetaManager::FILE), observable, logger
|
141
|
+
|
142
|
+
store.meta_manager = mm
|
143
|
+
|
144
|
+
begin
|
145
|
+
SimpleStoreFactory.recover_store(store)
|
146
|
+
rescue FileStoreException => e
|
147
|
+
logger.debug "Couldn't recover store.\nReason: #{e.message}\nTrying to create the store"
|
148
|
+
SimpleStoreFactory.create_store(store)
|
149
|
+
end
|
150
|
+
|
151
|
+
return store
|
152
|
+
end
|
153
|
+
|
154
|
+
#
|
155
|
+
# Setup for a new file store directory
|
156
|
+
#
|
157
|
+
# Arguments:
|
158
|
+
# store: The file store instance to set up
|
159
|
+
#
|
160
|
+
def self.create_store(store)
|
161
|
+
# Try to create needed directories
|
162
|
+
begin
|
163
|
+
FileUtils.mkdir [store.store_path, store.deleted_path, store.rollback_path]
|
164
|
+
rescue Errno::ENOENT => e
|
165
|
+
raise FileStoreException, "One ore more system directories couldn't be created.\n#{e.message}"
|
166
|
+
end
|
167
|
+
#
|
168
|
+
# Try to create hidden meta file
|
169
|
+
#
|
170
|
+
begin
|
171
|
+
meta = {
|
172
|
+
:created_at => Date.today.strftime('%d.%m.%Y %H:%M:%S:%L'),
|
173
|
+
:store_path => store.store_path,
|
174
|
+
:deleted_path => store.deleted_path,
|
175
|
+
:rollback_path => store.rollback_path,
|
176
|
+
:created_by => Etc.getlogin
|
177
|
+
}
|
178
|
+
|
179
|
+
File.open(store.meta_file, "wb+") do |fh|
|
180
|
+
YAML.dump(meta, fh)
|
181
|
+
end
|
182
|
+
#
|
183
|
+
# Creation was successful
|
184
|
+
#
|
185
|
+
rescue Exception => e
|
186
|
+
raise FileStoreException, "Store meta file #{store.meta_file} couldn't be created.\n#{e.message}"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
#
|
190
|
+
# Recover an existing file store
|
191
|
+
#
|
192
|
+
# Arguments:
|
193
|
+
# store: The file store instance to recover
|
194
|
+
#
|
195
|
+
def self.recover_store(store)
|
196
|
+
# trying to recover existing file store
|
197
|
+
begin
|
198
|
+
meta = YAML.load_file(store.meta_file)
|
199
|
+
|
200
|
+
raise FileStoreException, "Store directory not found" if not File.directory?(meta[:store_path])
|
201
|
+
raise FileStoreException, "Deleted directory not found" if not File.directory?(meta[:deleted_path])
|
202
|
+
raise FileStoreException, "Rollback directory not found" if not File.directory?(meta[:rollback_path])
|
203
|
+
#
|
204
|
+
# Recovery was successful
|
205
|
+
#
|
206
|
+
rescue Exception => e
|
207
|
+
raise FileStoreException, "Unable to recover file store from path #{store.root_path}.\n#{e.message}"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -8,10 +8,9 @@ module FileStore
|
|
8
8
|
#
|
9
9
|
# Class implementing a memory based MetaManager
|
10
10
|
#
|
11
|
-
class MemoryMetaManager
|
11
|
+
class MemoryMetaManager
|
12
12
|
include Logger
|
13
|
-
|
14
|
-
|
13
|
+
|
15
14
|
# Constant defining the default file path
|
16
15
|
FILE = 'meta.yaml'
|
17
16
|
# Accessor for the file to store data to
|
@@ -21,14 +20,13 @@ module FileStore
|
|
21
20
|
#
|
22
21
|
# Arguments:
|
23
22
|
# persistentFile: The file where the manager class is persisted to
|
23
|
+
# logger: The logging facility
|
24
24
|
#
|
25
|
-
def initialize(
|
25
|
+
def initialize(persistent_file = MemoryMetaManager::FILE, logger = StdoutLogger)
|
26
26
|
@logger = logger
|
27
27
|
@data = Hash.new
|
28
28
|
@removed = Hash.new
|
29
|
-
@file = (
|
30
|
-
|
31
|
-
self.initialize_obs
|
29
|
+
@file = (persistent_file.nil? or persistent_file == '') ? MemoryMetaManager::FILE : persistent_file
|
32
30
|
|
33
31
|
begin
|
34
32
|
if File.exists?(@file)
|
@@ -62,8 +60,8 @@ module FileStore
|
|
62
60
|
|
63
61
|
@data[id] = (@data.key?(id) ? @data[id].merge!(metaData) : @data[id] = metaData)
|
64
62
|
|
65
|
-
|
66
|
-
:objects => [id, metaData], :msg => "Added/Updated file to meta store")
|
63
|
+
inform ObserverAction.new(:type => ObserverAction::TYPE_META_ADD,
|
64
|
+
:objects => [id, metaData], :msg => "Added/Updated file to meta store") if self.is_a?(ObservedSubject)
|
67
65
|
end
|
68
66
|
#
|
69
67
|
# see: MetaManager::remove
|
@@ -75,8 +73,8 @@ module FileStore
|
|
75
73
|
@removed[id] = @data[id]
|
76
74
|
@data.delete(id)
|
77
75
|
|
78
|
-
|
79
|
-
:objects => [id], :msg => "Removed file to meta store")
|
76
|
+
inform ObserverAction.new(:type => ObserverAction::TYPE_META_REMOVE,
|
77
|
+
:objects => [id], :msg => "Removed file to meta store") if self.is_a?(ObservedSubject)
|
80
78
|
end
|
81
79
|
#
|
82
80
|
# see: MetaManager::restore
|
@@ -88,26 +86,34 @@ module FileStore
|
|
88
86
|
@data[id] = @removed[id]
|
89
87
|
@removed.delete(id)
|
90
88
|
|
91
|
-
|
92
|
-
:objects => [id], :msg => "Restored file in meta store")
|
89
|
+
inform ObserverAction.new(:type => ObserverAction::TYPE_META_RESTORE,
|
90
|
+
:objects => [id], :msg => "Restored file in meta store") if self.is_a?(ObservedSubject)
|
93
91
|
end
|
94
92
|
#
|
95
|
-
# see: MetaManager::
|
93
|
+
# see: MetaManager::save
|
96
94
|
#
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
:msg => "
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
95
|
+
def save
|
96
|
+
begin
|
97
|
+
@logger.info "Persisting meta store to #{@file}"
|
98
|
+
|
99
|
+
File.open(@file, "wb+") do |fh|
|
100
|
+
YAML.dump({:current => @data, :removed => @removed}, fh)
|
101
|
+
end
|
102
|
+
|
103
|
+
inform ObserverAction.new(:type => ObserverAction::TYPE_META_SHUTDOWN,
|
104
|
+
:msg => "Shut down meta manager") if self.is_a?(ObservedSubject)
|
105
|
+
rescue Exception => e
|
106
|
+
raise FileStoreException, "Couldn't persist meta manager to file #{@file}.\n#{e.message}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
#
|
110
|
+
# see: MetaManager::shutdown
|
111
|
+
#
|
112
|
+
def shutdown
|
113
|
+
save
|
114
|
+
|
115
|
+
@data = @removed = nil
|
116
|
+
end
|
111
117
|
#
|
112
118
|
# see: MetaManager::has_id?
|
113
119
|
#
|
@@ -4,40 +4,22 @@
|
|
4
4
|
# author: Thomas Stätter
|
5
5
|
# date: 2012/11/21
|
6
6
|
#
|
7
|
-
require 'filestore'
|
8
|
-
|
9
7
|
module FileStore
|
10
8
|
#
|
11
|
-
#
|
9
|
+
# Class implementing a multitenant file store
|
12
10
|
#
|
13
11
|
class MultiTenantFileStore
|
14
12
|
include Logger
|
15
|
-
include OberservedSubject
|
16
|
-
# Make this class a singleton class
|
17
|
-
include Singleton
|
18
13
|
# Accessors
|
19
|
-
attr_reader :
|
14
|
+
attr_reader :rootPath
|
15
|
+
attr_accessor :stores
|
20
16
|
#
|
21
17
|
# Initializes a new instance of MultiTenantFileStore
|
22
18
|
#
|
23
|
-
def initialize()
|
24
|
-
@rootPath =
|
19
|
+
def initialize(root_path = ".", logger = StdoutLogger)
|
20
|
+
@rootPath = root_path
|
25
21
|
@stores = {}
|
26
|
-
|
27
|
-
self.initialize_obs
|
28
|
-
end
|
29
|
-
#
|
30
|
-
# Sets the root path of the multitenant store. As FileStore::MultiTenantFileStore
|
31
|
-
# is a singleton class, this method must be used before any other
|
32
|
-
#
|
33
|
-
# Arguments:
|
34
|
-
# rootPath: The path to be used
|
35
|
-
#
|
36
|
-
def set_root_path(rootPath)
|
37
|
-
raise FileStoreException, "Root path #{rootPath} doesn't exist" if not File.exists?(rootPath)
|
38
|
-
|
39
|
-
@rootPath = rootPath
|
40
|
-
@stores = MultiTenantFileStore.recover(rootPath, @logger)
|
22
|
+
@logger = logger
|
41
23
|
end
|
42
24
|
#
|
43
25
|
# Creates a new file store for a tenant
|
@@ -55,13 +37,12 @@ module FileStore
|
|
55
37
|
begin
|
56
38
|
path = File.join(@rootPath, id)
|
57
39
|
FileUtils.mkdir path if not File.directory?(path)
|
58
|
-
|
59
|
-
sfs = SimpleFileStore.new mm, path, @logger
|
40
|
+
sfs = SimpleStoreFactory::create path, self.is_a?(ObservedSubject), @logger
|
60
41
|
|
61
42
|
@stores[id] = sfs
|
62
43
|
|
63
|
-
|
64
|
-
:msg => "Created new tenant store")
|
44
|
+
inform ObserverAction.new(:type => ObserverAction::TYPE_MSTORE_CREATE,
|
45
|
+
:msg => "Created new tenant store") if self.is_a?(ObservedSubject)
|
65
46
|
rescue Exception => e
|
66
47
|
raise FileStoreException, "Couldn't create multitenant store.\n#{e.message}"
|
67
48
|
end
|
@@ -106,13 +87,18 @@ module FileStore
|
|
106
87
|
# file: The file to be added
|
107
88
|
# md: Optional meta data
|
108
89
|
#
|
90
|
+
# Returns:
|
91
|
+
# The file ID
|
92
|
+
#
|
109
93
|
def add_to_tenant(tenant, file, md = {})
|
110
94
|
raise FileStoreException, "Tenant #{tenant} not registered. File #{file} can't be added." if not @stores.key?(tenant)
|
111
95
|
|
112
|
-
@stores[tenant].add(file, md)
|
96
|
+
f_id = @stores[tenant].add(file, md)
|
113
97
|
|
114
|
-
|
115
|
-
:objects => [tenant, file], :msg => "Added file to tenant")
|
98
|
+
inform ObserverAction.new(:type => ObserverAction::TYPE_MSTORE_ADD,
|
99
|
+
:objects => [tenant, file, f_id], :msg => "Added file to tenant #{tenant} with ID #{f_id}") if self.is_a?(ObservedSubject)
|
100
|
+
|
101
|
+
return f_id
|
116
102
|
end
|
117
103
|
#
|
118
104
|
# Removes a file from the tenant's store
|
@@ -156,39 +142,14 @@ module FileStore
|
|
156
142
|
#
|
157
143
|
def shutdown
|
158
144
|
# Shut down any tenant store
|
159
|
-
@stores.
|
160
|
-
|
145
|
+
@stores.each do |id, store|
|
146
|
+
@logger.info "Shutting down file store for tenant #{id}"
|
147
|
+
store.shutdown
|
161
148
|
end
|
162
149
|
end
|
163
150
|
|
164
151
|
private
|
165
|
-
|
166
|
-
# Recovers a multitenant store
|
167
|
-
#
|
168
|
-
# Arguments:
|
169
|
-
# rootPath: The base path of the multitenant store
|
170
|
-
#
|
171
|
-
def self.recover(rootPath, logger)
|
172
|
-
raise FileStoreException, "Root path #{rootPath} isn't a valid multitenant store" if not File.directory?(rootPath)
|
173
|
-
|
174
|
-
stores = {}
|
175
|
-
|
176
|
-
Dir.glob(File.join(rootPath, "*")).each { |e|
|
177
|
-
begin
|
178
|
-
if File.directory?(e)
|
179
|
-
tenant = File.basename(e)
|
180
|
-
mm = MemoryMetaManager.new File.join(e, MemoryMetaManager::FILE), logger
|
181
|
-
sfs = SimpleFileStore.new mm, e, @logger
|
182
|
-
|
183
|
-
stores[tenant] = sfs
|
184
|
-
end
|
185
|
-
rescue Exception => e
|
186
|
-
logger.error "Couldn't create store for tenant #{tenant}.\n#{e.message}"
|
187
|
-
end
|
188
|
-
}
|
189
|
-
|
190
|
-
return stores
|
191
|
-
end
|
152
|
+
|
192
153
|
end
|
193
154
|
|
194
155
|
end
|
data/lib/filestore/observer.rb
CHANGED
@@ -50,10 +50,10 @@ module FileStore
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
#
|
53
|
-
# Module FileStore::
|
53
|
+
# Module FileStore::ObservedSubject can be mixed in to implement an
|
54
54
|
# observed object.
|
55
55
|
#
|
56
|
-
module
|
56
|
+
module ObservedSubject
|
57
57
|
#
|
58
58
|
# Reader for collection of observers
|
59
59
|
#
|
@@ -82,7 +82,7 @@ module FileStore
|
|
82
82
|
def register(obj)
|
83
83
|
if obj.is_a?(Observer) and not obj.nil? and not @observers.include?(obj) then
|
84
84
|
@observers << obj
|
85
|
-
|
85
|
+
@logger.debug "Added #{obj} to observers" if not self.logger.nil?
|
86
86
|
else
|
87
87
|
raise FileStoreException, "Only instances of FileStore::Observer can be registered"
|
88
88
|
end
|
@@ -97,7 +97,7 @@ module FileStore
|
|
97
97
|
def unregister(obj)
|
98
98
|
if @observers.include?(obj) then
|
99
99
|
@observers.delete_at(@observers.index(obj))
|
100
|
-
|
100
|
+
@logger.debug "Removed observing object #{obj} from the list" if not self.logger.nil?
|
101
101
|
else
|
102
102
|
raise FileStoreException, "Object #{obj} isn't a registered observer"
|
103
103
|
end
|
@@ -5,21 +5,13 @@
|
|
5
5
|
# date: 2012/11/07
|
6
6
|
#
|
7
7
|
module FileStore
|
8
|
-
#
|
9
|
-
# Base exception class used for errors occurring in this module
|
10
|
-
#
|
11
|
-
class FileStoreException < Exception
|
12
|
-
end
|
13
8
|
#
|
14
9
|
# Main library class implementing a simple file store used for storing and managing
|
15
10
|
# arbitrary files
|
16
11
|
#
|
17
12
|
class SimpleFileStore
|
18
13
|
include Logger
|
19
|
-
include OberservedSubject
|
20
14
|
|
21
|
-
# Name of the lock file
|
22
|
-
STORE_LOCK_FILE = ".locked"
|
23
15
|
# Name of the meta file describing the current file store
|
24
16
|
META_FILE = "filestore.yaml"
|
25
17
|
# The base name of the file store directory
|
@@ -32,41 +24,28 @@ module FileStore
|
|
32
24
|
#
|
33
25
|
# Accessors for important properties
|
34
26
|
#
|
35
|
-
|
27
|
+
attr_accessor :meta_manager
|
28
|
+
attr_reader :root_path, :store_path, :deleted_path, :meta_file
|
29
|
+
#
|
30
|
+
# Rollback path will be used in future versions
|
31
|
+
#
|
32
|
+
attr_reader :rollback_path
|
36
33
|
#
|
37
34
|
# Initializes a new instance of SimpleFileStore
|
38
35
|
#
|
39
36
|
# Arguments:
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
def initialize(
|
44
|
-
raise FileStoreException, "
|
45
|
-
raise FileStoreException, "FileStore root path #{
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
@storePath = File.join(@rootPath, STORE_ROOT)
|
53
|
-
@deletedPath = File.join(@rootPath, DELETED_ROOT)
|
54
|
-
@rollbackPath = File.join(@rootPath, ROLLBACK_ROOT)
|
55
|
-
@metaFile = File.join(@rootPath, META_FILE)
|
56
|
-
@locked = false
|
57
|
-
@logger = logger
|
58
|
-
|
59
|
-
self.initialize_obs
|
60
|
-
|
61
|
-
begin
|
62
|
-
# Try to recover existing store
|
63
|
-
SimpleFileStore.recover_store(self)
|
64
|
-
rescue FileStoreException => e
|
65
|
-
# Recovery failed, trying to create the store
|
66
|
-
SimpleFileStore.create_store(self)
|
67
|
-
end
|
68
|
-
|
69
|
-
lock
|
37
|
+
# root_path: The path where the file store resides
|
38
|
+
# logger: The logging facility
|
39
|
+
#
|
40
|
+
def initialize(root_path, logger = StdoutLogger)
|
41
|
+
raise FileStoreException, "FileStore root path #{root_path} doesn't exist" if not File.directory?(root_path)
|
42
|
+
raise FileStoreException, "FileStore root path #{root_path} isn't writable" if not File.writable?(root_path)
|
43
|
+
|
44
|
+
@root_path = root_path
|
45
|
+
@store_path = File.join(@root_path, STORE_ROOT)
|
46
|
+
@deleted_path = File.join(@root_path, DELETED_ROOT)
|
47
|
+
@rollback_path = File.join(@root_path, ROLLBACK_ROOT)
|
48
|
+
@meta_file = File.join(@root_path, SimpleFileStore::META_FILE)
|
70
49
|
end
|
71
50
|
#
|
72
51
|
# Adds a file to the store
|
@@ -88,7 +67,7 @@ module FileStore
|
|
88
67
|
id = ""
|
89
68
|
|
90
69
|
begin
|
91
|
-
dir = SimpleFileStore.get_daily_directory(@
|
70
|
+
dir = SimpleFileStore.get_daily_directory(@store_path)
|
92
71
|
@logger.info "Adding file #{file} to directory #{dir}"
|
93
72
|
id = SimpleFileStore.get_id(self)
|
94
73
|
@logger.info "Using file id #{id}"
|
@@ -98,14 +77,14 @@ module FileStore
|
|
98
77
|
shouldMove ? (@logger.info("Moving file"); FileUtils.mv(file, dstPath)) :
|
99
78
|
(@logger.info("Copying file"); FileUtils.copy_file(file, dstPath))
|
100
79
|
|
101
|
-
|
102
|
-
:objects => [file, meta], :msg => "Added file to file store")
|
80
|
+
inform ObserverAction.new(:type => ObserverAction::TYPE_STORE_ADD,
|
81
|
+
:objects => [file, meta], :msg => "Added file to file store") if self.is_a?(ObservedSubject)
|
103
82
|
rescue Exception => e
|
104
83
|
raise FileStoreException, "Couldn't add file #{file} to store.", e.backtrace
|
105
84
|
end
|
106
85
|
|
107
86
|
meta[:path] = dstPath
|
108
|
-
@
|
87
|
+
@meta_manager.add_or_update(id, meta)
|
109
88
|
|
110
89
|
return id
|
111
90
|
end
|
@@ -121,15 +100,15 @@ module FileStore
|
|
121
100
|
#
|
122
101
|
def get(id)
|
123
102
|
raise FileStoreException, "No ID given" if id.nil? or id == ''
|
124
|
-
raise FileStoreException, "No file for ID #{id} found" if not @
|
103
|
+
raise FileStoreException, "No file for ID #{id} found" if not @meta_manager.has_id?(id)
|
125
104
|
|
126
|
-
md = @
|
105
|
+
md = @meta_manager.get_data(id)
|
127
106
|
path = md[:path]
|
128
107
|
|
129
108
|
raise FileStoreException, "No valid meta data found for ID #{id}" if md.nil? or not File.exists?(path)
|
130
109
|
|
131
|
-
|
132
|
-
:objects => [id], :msg => "Returning file from file store"
|
110
|
+
inform ObserverAction.new(:type => ObserverAction::TYPE_STORE_GET,
|
111
|
+
:objects => [id], :msg => "Returning file from file store") if self.is_a?(ObservedSubject)
|
133
112
|
|
134
113
|
return { :path => File.new(path), :data => md }
|
135
114
|
end
|
@@ -141,20 +120,20 @@ module FileStore
|
|
141
120
|
#
|
142
121
|
def remove(id)
|
143
122
|
raise FileStoreException, "No file ID given for removal" if id == '' or id.nil?
|
144
|
-
raise FileStoreException, "File ID for removal not found in store" if not @
|
123
|
+
raise FileStoreException, "File ID for removal not found in store" if not @meta_manager.has_id?(id)
|
145
124
|
|
146
|
-
file = @
|
125
|
+
file = @meta_manager.get_data(id)[:path]
|
147
126
|
|
148
127
|
begin
|
149
|
-
@
|
128
|
+
@meta_manager.remove(id)
|
150
129
|
|
151
|
-
dir = SimpleFileStore.get_daily_directory(@
|
130
|
+
dir = SimpleFileStore.get_daily_directory(@deleted_path)
|
152
131
|
dstPath = File.join(dir, id)
|
153
132
|
|
154
133
|
FileUtils.move(file, dstPath)
|
155
134
|
|
156
|
-
|
157
|
-
:objects => [id], :msg => "Deleted file from store"
|
135
|
+
inform ObserverAction.new(:type => ObserverAction::TYPE_STORE_REMOVE,
|
136
|
+
:objects => [id], :msg => "Deleted file from store") if self.is_a?(ObservedSubject)
|
158
137
|
rescue Exception => e
|
159
138
|
raise FileStoreException, "Couldn't move file #{file} to deleted store.\n#{e.message}"
|
160
139
|
end
|
@@ -169,74 +148,36 @@ module FileStore
|
|
169
148
|
raise FileStoreException, "No file ID given for restore" if id == '' or id.nil?
|
170
149
|
|
171
150
|
begin
|
172
|
-
md = @
|
151
|
+
md = @meta_manager.restore id
|
173
152
|
@logger.debug "Restoring meta data #{md}"
|
174
153
|
file = md[:path]
|
175
154
|
|
176
|
-
dir = SimpleFileStore.get_daily_directory(@
|
155
|
+
dir = SimpleFileStore.get_daily_directory(@store_path)
|
177
156
|
dstPath = File.join(dir, id)
|
178
157
|
|
179
158
|
FileUtils.move(file, dstPath)
|
180
159
|
|
181
|
-
|
182
|
-
:objects => [id], :msg => "Restored file from store"
|
160
|
+
inform ObserverAction.new(:type => ObserverAction::TYPE_STORE_RESTORE,
|
161
|
+
:objects => [id], :msg => "Restored file from store") if self.is_a?(ObservedSubject)
|
183
162
|
rescue Exception => e
|
184
163
|
raise FileStoreException, "Couldn't restore file #{file} from deleted store.\n#{e.message}"
|
185
164
|
#
|
186
165
|
# Delete restored entry from metaManager
|
187
|
-
|
166
|
+
#
|
167
|
+
@meta_manager.delete(id)
|
188
168
|
end
|
189
169
|
end
|
190
170
|
#
|
191
171
|
# Shuts down the file store
|
192
172
|
#
|
193
173
|
def shutdown
|
194
|
-
@
|
195
|
-
|
196
|
-
release_lock
|
174
|
+
@meta_manager.shutdown
|
197
175
|
|
198
|
-
|
199
|
-
:msg => "File store shutdown"
|
200
|
-
end
|
201
|
-
#
|
202
|
-
# Determines wether this store is locked
|
203
|
-
#
|
204
|
-
def locked?
|
205
|
-
return @locked
|
176
|
+
inform ObserverAction.new(:type => ObserverAction::TYPE_STORE_SHUTDOWN,
|
177
|
+
:msg => "File store shutdown") if self.is_a?(ObservedSubject)
|
206
178
|
end
|
207
179
|
|
208
180
|
private
|
209
|
-
|
210
|
-
#
|
211
|
-
# Release the lock from the store
|
212
|
-
#
|
213
|
-
def release_lock
|
214
|
-
begin
|
215
|
-
File.delete File.join(@rootPath, STORE_LOCK_FILE)
|
216
|
-
@locked = false
|
217
|
-
rescue Exception => e
|
218
|
-
raise FileStoreException, "Couldn't release lock from #{@storePath}.\n#{e.message}"
|
219
|
-
end
|
220
|
-
end
|
221
|
-
#
|
222
|
-
# Locks the current instance of file store as well as the corresponding path on
|
223
|
-
# the file system using a hidden file
|
224
|
-
#
|
225
|
-
def lock
|
226
|
-
begin
|
227
|
-
FileUtils.touch File.join(@rootPath, STORE_LOCK_FILE)
|
228
|
-
@locked = true
|
229
|
-
rescue Exception => e
|
230
|
-
raise FileStoreException, "Couldn't lock the store in path #{@storePath}.\n#{e.message}"
|
231
|
-
end
|
232
|
-
end
|
233
|
-
#
|
234
|
-
# Determines wether the store path is already locked by another instance
|
235
|
-
# of SimpleFileStore
|
236
|
-
#
|
237
|
-
def self.is_directory_locked?(rootPath)
|
238
|
-
return File.exists?(File.join(rootPath, SimpleFileStore::STORE_LOCK_FILE))
|
239
|
-
end
|
240
181
|
#
|
241
182
|
# Creates a new file ID
|
242
183
|
#
|
@@ -247,7 +188,7 @@ module FileStore
|
|
247
188
|
for i in 0..2 do
|
248
189
|
id = UUIDTools::UUID.random_create.to_s
|
249
190
|
|
250
|
-
return id if not store.
|
191
|
+
return id if not store.meta_manager.has_id?(id)
|
251
192
|
end
|
252
193
|
|
253
194
|
raise FileStoreException, "Couldn't find unique ID"
|
@@ -268,61 +209,6 @@ module FileStore
|
|
268
209
|
raise FileStoreException, "Daily directory #{dir} isn't writable" if not File.writable?(dir)
|
269
210
|
return dir
|
270
211
|
end
|
271
|
-
#
|
272
|
-
# Setup for a new file store directory
|
273
|
-
#
|
274
|
-
# Arguments:
|
275
|
-
# store: The file store instance to set up
|
276
|
-
#
|
277
|
-
def self.create_store(store)
|
278
|
-
# Try to create needed directories
|
279
|
-
begin
|
280
|
-
FileUtils.mkdir [store.storePath, store.deletedPath, store.rollbackPath]
|
281
|
-
rescue Errno::ENOENT => e
|
282
|
-
raise FileStoreException, "One ore more system directories couldn't be created.\n#{e.message}"
|
283
|
-
end
|
284
|
-
# Try to create hidden meta file
|
285
|
-
begin
|
286
|
-
meta = { :created_at => Date.today.strftime('%d.%m.%Y %H:%M:%S:%L'),
|
287
|
-
:storePath => store.storePath,
|
288
|
-
:deletedPath => store.deletedPath,
|
289
|
-
:rollbackPath => store.rollbackPath,
|
290
|
-
:created_by => Etc.getlogin
|
291
|
-
}
|
292
|
-
|
293
|
-
File.open(store.metaFile, "w+") do |fh|
|
294
|
-
YAML.dump(meta, fh)
|
295
|
-
end
|
296
|
-
|
297
|
-
#
|
298
|
-
# Creation was successful
|
299
|
-
#
|
300
|
-
rescue Exception => e
|
301
|
-
raise FileStoreException, "Meta file #{store.metaFile} couldn't be created.\n#{e.message}"
|
302
|
-
end
|
303
|
-
end
|
304
|
-
#
|
305
|
-
# Recover an existing file store
|
306
|
-
#
|
307
|
-
# Arguments:
|
308
|
-
# store: The file store instance to recover
|
309
|
-
#
|
310
|
-
def self.recover_store(store)
|
311
|
-
# trying to recover existing file store
|
312
|
-
begin
|
313
|
-
meta = YAML.load_file(store.metaFile)
|
314
|
-
|
315
|
-
raise FileStoreException, "Store directory not found" if not File.directory?(meta[:storePath])
|
316
|
-
raise FileStoreException, "Deleted directory not found" if not File.directory?(meta[:deletedPath])
|
317
|
-
raise FileStoreException, "Rollback directory not found" if not File.directory?(meta[:rollbackPath])
|
318
|
-
|
319
|
-
#
|
320
|
-
# Recovery was successful
|
321
|
-
#
|
322
|
-
rescue Exception => e
|
323
|
-
raise FileStoreException, "Unable to recover file store from path #{store.rootPath}.\n#{e.message}"
|
324
|
-
end
|
325
|
-
end
|
326
212
|
|
327
213
|
end
|
328
214
|
|
data/lib/filestore.rb
CHANGED
@@ -4,6 +4,14 @@
|
|
4
4
|
# @date 2012/11/26
|
5
5
|
# @description
|
6
6
|
#
|
7
|
+
module FileStore
|
8
|
+
#
|
9
|
+
# Base exception class used for errors occurring in this module
|
10
|
+
#
|
11
|
+
class FileStoreException < Exception
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
7
15
|
LIBS = [
|
8
16
|
#
|
9
17
|
# Required 3rd party libs
|
@@ -11,8 +19,7 @@ LIBS = [
|
|
11
19
|
'uuidtools',
|
12
20
|
'fileutils',
|
13
21
|
'yaml',
|
14
|
-
'etc'
|
15
|
-
'singleton'
|
22
|
+
'etc'
|
16
23
|
]
|
17
24
|
FILESTORE_FILES = [
|
18
25
|
#
|
@@ -23,7 +30,8 @@ FILESTORE_FILES = [
|
|
23
30
|
'log',
|
24
31
|
'memory_meta',
|
25
32
|
'simple_store',
|
26
|
-
'multitenant_store'
|
33
|
+
'multitenant_store',
|
34
|
+
'factory'
|
27
35
|
]
|
28
36
|
#
|
29
37
|
# Loads required 3rd party libs as defined in FileStore::LIBS
|
data/test/classes.rb
CHANGED
@@ -12,16 +12,22 @@ class FileStoreTest < Test::Unit::TestCase
|
|
12
12
|
|
13
13
|
def setup
|
14
14
|
# create test directory and file
|
15
|
-
@
|
16
|
-
@
|
15
|
+
@uid = Etc.getlogin
|
16
|
+
@basePathSimple = "#{Dir.getwd}/simple_store_test"
|
17
|
+
@basePathMulti = "#{Dir.getwd}/multi_store_test"
|
18
|
+
@testFileSimple = File.join(@basePathSimple, "testfile.txt")
|
19
|
+
@testFileMulti = File.join(@basePathMulti, "testfile.txt")
|
17
20
|
|
18
|
-
FileUtils.mkdir(@
|
19
|
-
FileUtils.
|
21
|
+
FileUtils.mkdir(@basePathSimple) if not File.exists?(@basePathSimple)
|
22
|
+
FileUtils.mkdir(@basePathMulti) if not File.exists?(@basePathMulti)
|
23
|
+
FileUtils.touch(@testFileSimple)
|
24
|
+
FileUtils.touch(@testFileMulti)
|
20
25
|
end
|
21
26
|
|
22
27
|
def teardown
|
23
|
-
# remove test
|
24
|
-
FileUtils.remove_dir(@
|
28
|
+
# remove test directories and file
|
29
|
+
FileUtils.remove_dir(@basePathSimple, true) if File.exists?(@basePathSimple)
|
30
|
+
FileUtils.remove_dir(@basePathMulti, true) if File.exists?(@basePathMulti)
|
25
31
|
end
|
26
32
|
|
27
33
|
end
|
data/test/tc_filestore.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
# @author Thomas Stätter
|
4
4
|
# @date 2012/11/14
|
5
5
|
#
|
6
|
-
# require 'filestore'
|
7
6
|
require './classes.rb'
|
8
7
|
require 'test/unit'
|
9
8
|
|
@@ -16,14 +15,12 @@ class TestFileStore < FileStoreTest
|
|
16
15
|
puts "TestFileStore::test_init_shutdown"
|
17
16
|
puts "=" * 80
|
18
17
|
|
19
|
-
mm = MemoryMetaManager.new File.join(@basePath, "meta.yaml"), StdoutLogger
|
20
|
-
sfs = nil
|
21
|
-
|
22
18
|
assert_nothing_raised(FileStoreException) {
|
23
|
-
|
19
|
+
SimpleStoreFactory::create @basePathSimple
|
24
20
|
}
|
25
|
-
assert_not_nil(
|
21
|
+
assert_not_nil(SimpleStoreFactory::create @basePathSimple)
|
26
22
|
assert_nothing_raised(FileStoreException) {
|
23
|
+
sfs = SimpleStoreFactory::create @basePathSimple
|
27
24
|
sfs.shutdown
|
28
25
|
}
|
29
26
|
end
|
@@ -33,8 +30,7 @@ class TestFileStore < FileStoreTest
|
|
33
30
|
puts "TestFileStorage::test_registration_observer"
|
34
31
|
puts "=" * 80
|
35
32
|
|
36
|
-
|
37
|
-
sfs = SimpleFileStore.new mm, @basePath, StdoutLogger
|
33
|
+
sfs = SimpleStoreFactory::create @basePathSimple, true
|
38
34
|
o1 = OtherObserverClass.new
|
39
35
|
o2 = ObserverClass.new
|
40
36
|
|
@@ -56,14 +52,13 @@ class TestFileStore < FileStoreTest
|
|
56
52
|
|
57
53
|
o1 = ObserverClass.new
|
58
54
|
o1.logger = StdoutLogger
|
59
|
-
|
60
|
-
sfs = SimpleFileStore.new mm, @basePath, StdoutLogger
|
55
|
+
sfs = SimpleStoreFactory::create @basePathSimple, true
|
61
56
|
id = nil
|
62
57
|
|
63
58
|
sfs.register o1
|
64
59
|
|
65
60
|
assert_nothing_raised(FileStoreException) {
|
66
|
-
id = sfs.add @
|
61
|
+
id = sfs.add @testFileSimple, { :original_file => @testFileSimple }, false
|
67
62
|
}
|
68
63
|
assert_nothing_raised(FileStoreException) { file = sfs.get id }
|
69
64
|
assert_not_nil(sfs.get(id))
|
data/test/tc_meta.rb
CHANGED
@@ -14,11 +14,13 @@ class TestMetaManager < FileStoreTest
|
|
14
14
|
puts "=" * 80
|
15
15
|
puts "TestMetaManager::test_init_shutdown"
|
16
16
|
puts "=" * 80
|
17
|
+
|
17
18
|
assert_nothing_raised(FileStoreException) {
|
18
|
-
|
19
|
+
mm = MemoryMetaFactory::create File.join(@basePathSimple, MemoryMetaManager::FILE)
|
19
20
|
}
|
21
|
+
assert_not_nil(MemoryMetaFactory::create File.join(@basePathSimple, MemoryMetaManager::FILE))
|
20
22
|
assert_nothing_raised(FileStoreException) {
|
21
|
-
mm =
|
23
|
+
mm = MemoryMetaFactory::create File.join(@basePathSimple, MemoryMetaManager::FILE)
|
22
24
|
|
23
25
|
mm.shutdown
|
24
26
|
}
|
@@ -35,19 +37,19 @@ class TestMetaManager < FileStoreTest
|
|
35
37
|
o1.logger = StdoutLogger
|
36
38
|
o2.logger = StdoutLogger
|
37
39
|
|
38
|
-
mm =
|
40
|
+
mm = MemoryMetaFactory::create File.join(@basePathSimple, MemoryMetaManager::FILE), true
|
39
41
|
|
40
42
|
assert_nothing_raised(FileStoreException) {
|
41
43
|
mm.register o1
|
42
44
|
mm.register o2
|
43
45
|
}
|
44
|
-
assert_raise(FileStoreException) { mm.register
|
46
|
+
assert_raise(FileStoreException) { mm.register "" }
|
45
47
|
assert_nothing_raised(FileStoreException) {
|
46
48
|
mm.unregister(o1)
|
47
49
|
mm.unregister(o2)
|
48
50
|
}
|
49
51
|
end
|
50
|
-
|
52
|
+
|
51
53
|
def test_actions_with_observer
|
52
54
|
puts "=" * 80
|
53
55
|
puts "TestMetaManager::test_actions_with_observer"
|
@@ -55,14 +57,15 @@ class TestMetaManager < FileStoreTest
|
|
55
57
|
|
56
58
|
o1 = ObserverClass.new
|
57
59
|
o1.logger = StdoutLogger
|
58
|
-
mm =
|
60
|
+
mm = MemoryMetaFactory::create File.join(@basePathSimple, MemoryMetaManager::FILE), true
|
59
61
|
|
60
62
|
mm.register o1
|
61
63
|
|
62
|
-
assert_nothing_raised(
|
63
|
-
assert_nothing_raised(
|
64
|
-
assert_nothing_raised(
|
65
|
-
assert_nothing_raised(
|
66
|
-
assert_nothing_raised(
|
64
|
+
assert_nothing_raised(FileStoreException) { mm.add_or_update "1", {} }
|
65
|
+
assert_nothing_raised(FileStoreException) { mm.add_or_update "1", {} }
|
66
|
+
assert_nothing_raised(FileStoreException) { mm.remove "1" }
|
67
|
+
assert_nothing_raised(FileStoreException) { mm.restore "1" }
|
68
|
+
assert_nothing_raised(FileStoreException) { mm.shutdown }
|
67
69
|
end
|
70
|
+
|
68
71
|
end
|
data/test/tc_module.rb
CHANGED
@@ -12,13 +12,18 @@ class TestModule < Test::Unit::TestCase
|
|
12
12
|
puts "=" * 80
|
13
13
|
puts "TestModule::test_inclusion"
|
14
14
|
puts "=" * 80
|
15
|
+
|
15
16
|
assert_nothing_raised(NameError) { ObserverAction }
|
16
|
-
assert_nothing_raised(NameError) {
|
17
|
+
assert_nothing_raised(NameError) { ObservedSubject }
|
17
18
|
assert_nothing_raised(NameError) { Observer }
|
18
19
|
assert_nothing_raised(NameError) { SimpleFileStore }
|
19
20
|
assert_nothing_raised(NameError) { MultiTenantFileStore }
|
20
21
|
assert_nothing_raised(NameError) { MemoryMetaManager }
|
21
22
|
assert_nothing_raised(NameError) { MetaManager }
|
22
23
|
assert_nothing_raised(NameError) { FileStoreException }
|
24
|
+
assert_nothing_raised(NameError) { BaseFactory }
|
25
|
+
assert_nothing_raised(NameError) { MemoryMetaFactory }
|
26
|
+
assert_nothing_raised(NameError) { MultiTenantStoreFactory }
|
27
|
+
assert_nothing_raised(NameError) { SimpleStoreFactory }
|
23
28
|
end
|
24
29
|
end
|
data/test/tc_multitenant.rb
CHANGED
@@ -12,38 +12,56 @@ include FileStore
|
|
12
12
|
|
13
13
|
class TestMultiTenantFileStore < FileStoreTest
|
14
14
|
|
15
|
-
def
|
15
|
+
def test_init_shutdown
|
16
16
|
puts "=" * 80
|
17
|
-
puts "TestMultiTenantFileStore::
|
17
|
+
puts "TestMultiTenantFileStore::test_init"
|
18
18
|
puts "=" * 80
|
19
19
|
|
20
|
-
MultiTenantFileStore.instance.set_root_path @basePath
|
21
|
-
MultiTenantFileStore.instance.logger = StdoutLogger
|
22
|
-
tenant = MultiTenantFileStore.instance.create_tenant_store
|
23
|
-
o1 = OtherObserverClass.new
|
24
|
-
o2 = ObserverClass.new
|
25
|
-
|
26
20
|
assert_nothing_raised(FileStoreException) {
|
27
|
-
|
28
|
-
|
21
|
+
MultiTenantStoreFactory::create @basePathMulti
|
22
|
+
}
|
23
|
+
assert_not_nil(MultiTenantStoreFactory::create @basePathMulti)
|
24
|
+
assert(MultiTenantStoreFactory::create(@basePathMulti).is_a?(MultiTenantFileStore))
|
25
|
+
assert_nothing_raised(FileStoreException) {
|
26
|
+
m_store = MultiTenantStoreFactory::create @basePathMulti
|
27
|
+
|
28
|
+
m_store.shutdown
|
29
29
|
}
|
30
30
|
end
|
31
31
|
|
32
|
+
def test_observer_registration
|
33
|
+
puts "=" * 80
|
34
|
+
puts "TestMultiTenantFileStore::test_observer_registration"
|
35
|
+
puts "=" * 80
|
36
|
+
|
37
|
+
assert_nothing_raised(Exception) {
|
38
|
+
o1 = ObserverClass.new
|
39
|
+
o1.logger = StdoutLogger
|
40
|
+
m_store = MultiTenantStoreFactory::create @basePathMulti, true
|
41
|
+
|
42
|
+
m_store.register o1
|
43
|
+
m_store.inform "Some test message"
|
44
|
+
m_store.shutdown
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
32
48
|
def test_actions_with_observer
|
33
49
|
puts "=" * 80
|
34
50
|
puts "TestMultiTenantFileStore::test_actions_with_observer"
|
35
51
|
puts "=" * 80
|
36
52
|
|
37
|
-
MultiTenantFileStore.instance.set_root_path @basePath
|
38
|
-
MultiTenantFileStore.instance.logger = StdoutLogger
|
39
53
|
o1 = OtherObserverClass.new
|
40
54
|
o1.logger = StdoutLogger
|
41
|
-
|
55
|
+
|
56
|
+
m_store = MultiTenantStoreFactory::create @basePathMulti, true
|
57
|
+
m_store.register o1
|
42
58
|
|
43
59
|
assert_nothing_raised(FileStoreException) {
|
44
|
-
|
45
|
-
|
46
|
-
@
|
60
|
+
tenant_id = m_store.create_tenant_store @uid
|
61
|
+
f_id = m_store.add_to_tenant tenant_id,
|
62
|
+
@testFileMulti, { :original_file => @testFileMulti }
|
63
|
+
m_store.remove_from_tenant tenant_id, f_id
|
64
|
+
m_store.shutdown
|
47
65
|
}
|
48
66
|
end
|
49
67
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: filestore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.19
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -39,6 +39,7 @@ executables: []
|
|
39
39
|
extensions: []
|
40
40
|
extra_rdoc_files: []
|
41
41
|
files:
|
42
|
+
- lib/filestore/factory.rb
|
42
43
|
- lib/filestore/log.rb
|
43
44
|
- lib/filestore/memory_meta.rb
|
44
45
|
- lib/filestore/meta_manager.rb
|