filestore 0.0.14 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|