filestore 0.0.7 → 0.0.8
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.rb +35 -18
- data/lib/log.rb +40 -24
- data/lib/memory_meta.rb +24 -9
- data/lib/multitenant_filestore.rb +14 -11
- data/lib/observer.rb +147 -0
- data/module.rb +40 -0
- data/test/classes.rb +43 -0
- data/test/tc_filestore.rb +65 -23
- data/test/tc_meta.rb +69 -0
- data/test/tc_module.rb +26 -0
- data/test/tc_multitenant.rb +42 -20
- data/test/ts_all.rb +12 -0
- metadata +12 -5
- data/filestore.rb +0 -15
- data/test/testfile.txt +0 -0
data/lib/filestore.rb
CHANGED
|
@@ -4,15 +4,12 @@
|
|
|
4
4
|
# author: Thomas Stätter
|
|
5
5
|
# date: 2012/11/07
|
|
6
6
|
#
|
|
7
|
+
require "../module.rb"
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
require 'log.rb'
|
|
10
|
-
require 'etc'
|
|
11
|
-
require 'yaml'
|
|
12
|
-
require 'fileutils'
|
|
13
|
-
require 'uuidtools'
|
|
9
|
+
include FileStore
|
|
14
10
|
|
|
15
11
|
module FileStore
|
|
12
|
+
include OberservedSubject
|
|
16
13
|
#
|
|
17
14
|
# Base exception class used for errors occurring in this module
|
|
18
15
|
#
|
|
@@ -23,6 +20,9 @@ module FileStore
|
|
|
23
20
|
# arbitrary files
|
|
24
21
|
#
|
|
25
22
|
class SimpleFileStore
|
|
23
|
+
include Logger
|
|
24
|
+
include OberservedSubject
|
|
25
|
+
|
|
26
26
|
# Name of the lock file
|
|
27
27
|
STORE_LOCK_FILE = ".locked"
|
|
28
28
|
# Name of the meta file describing the current file store
|
|
@@ -45,7 +45,7 @@ module FileStore
|
|
|
45
45
|
# metaManager: The meta data manager instance to be used by this store
|
|
46
46
|
# rootPath: The path where the file store resides
|
|
47
47
|
#
|
|
48
|
-
def initialize(metaManager, rootPath = '.')
|
|
48
|
+
def initialize(metaManager, rootPath = '.', logger)
|
|
49
49
|
raise FileStoreException, "Root path already locked" if SimpleFileStore.is_directory_locked?(rootPath)
|
|
50
50
|
raise FileStoreException, "FileStore root path #{rootPath} doesn't exist" if not File.directory?(rootPath)
|
|
51
51
|
raise FileStoreException, "FileStore root path #{rootPath} isn't writable" if not File.writable?(rootPath)
|
|
@@ -59,6 +59,9 @@ module FileStore
|
|
|
59
59
|
@rollbackPath = File.join(@rootPath, ROLLBACK_ROOT)
|
|
60
60
|
@metaFile = File.join(@rootPath, META_FILE)
|
|
61
61
|
@locked = false
|
|
62
|
+
@logger = logger
|
|
63
|
+
|
|
64
|
+
self.initialize_obs
|
|
62
65
|
|
|
63
66
|
begin
|
|
64
67
|
# Try to recover existing store
|
|
@@ -79,7 +82,7 @@ module FileStore
|
|
|
79
82
|
# shouldMove: Determines wether to original file should be deleted
|
|
80
83
|
#
|
|
81
84
|
# Returns:
|
|
82
|
-
#
|
|
85
|
+
# The newly created ID for the file
|
|
83
86
|
#
|
|
84
87
|
def add(file, meta = {}, shouldMove = true)
|
|
85
88
|
raise FileStoreException, "File #{file} not found" if not File.exists?(file)
|
|
@@ -91,14 +94,17 @@ module FileStore
|
|
|
91
94
|
|
|
92
95
|
begin
|
|
93
96
|
dir = SimpleFileStore.get_daily_directory(@storePath)
|
|
94
|
-
|
|
97
|
+
@logger.info "Adding file #{file} to directory #{dir}"
|
|
95
98
|
id = SimpleFileStore.get_id(self)
|
|
96
|
-
|
|
99
|
+
@logger.info "Using file id #{id}"
|
|
97
100
|
dstPath = File.join(dir, id)
|
|
98
|
-
|
|
101
|
+
@logger.info "Created destination path #{dstPath}"
|
|
102
|
+
|
|
103
|
+
shouldMove ? (@logger.info("Moving file"); FileUtils.mv(file, dstPath)) :
|
|
104
|
+
(@logger.info("Copying file"); FileUtils.copy_file(file, dstPath))
|
|
99
105
|
|
|
100
|
-
|
|
101
|
-
|
|
106
|
+
self.inform ObserverAction.new(:type => ObserverAction::TYPE_STORE_ADD,
|
|
107
|
+
:objects => [file, meta], :msg => "Added file to file store")
|
|
102
108
|
rescue Exception => e
|
|
103
109
|
raise FileStoreException, "Couldn't add file #{file} to store.", e.backtrace
|
|
104
110
|
end
|
|
@@ -127,6 +133,9 @@ module FileStore
|
|
|
127
133
|
|
|
128
134
|
raise FileStoreException, "No valid meta data found for ID #{id}" if md.nil? or not File.exists?(path)
|
|
129
135
|
|
|
136
|
+
self.inform ObserverAction.new :type => ObserverAction::TYPE_STORE_GET,
|
|
137
|
+
:objects => [id], :msg => "Returning file from file store"
|
|
138
|
+
|
|
130
139
|
return { :path => File.new(path), :data => md }
|
|
131
140
|
end
|
|
132
141
|
#
|
|
@@ -148,6 +157,9 @@ module FileStore
|
|
|
148
157
|
dstPath = File.join(dir, id)
|
|
149
158
|
|
|
150
159
|
FileUtils.move(file, dstPath)
|
|
160
|
+
|
|
161
|
+
self.inform ObserverAction.new :type => ObserverAction::TYPE_STORE_REMOVE,
|
|
162
|
+
:objects => [id], :msg => "Deleted file from store"
|
|
151
163
|
rescue Exception => e
|
|
152
164
|
raise FileStoreException, "Couldn't move file #{file} to deleted store.\n#{e.message}"
|
|
153
165
|
end
|
|
@@ -161,14 +173,18 @@ module FileStore
|
|
|
161
173
|
def restore(id)
|
|
162
174
|
raise FileStoreException, "No file ID given for restore" if id == '' or id.nil?
|
|
163
175
|
|
|
164
|
-
md = @metaManager.restore(id)
|
|
165
|
-
file = md[:path]
|
|
166
|
-
|
|
167
176
|
begin
|
|
177
|
+
md = @metaManager.restore id
|
|
178
|
+
@logger.debug "Restoring meta data #{md}"
|
|
179
|
+
file = md[:path]
|
|
180
|
+
|
|
168
181
|
dir = SimpleFileStore.get_daily_directory(@storePath)
|
|
169
182
|
dstPath = File.join(dir, id)
|
|
170
183
|
|
|
171
184
|
FileUtils.move(file, dstPath)
|
|
185
|
+
|
|
186
|
+
self.inform ObserverAction.new :type => ObserverAction::TYPE_STORE_RESTORE,
|
|
187
|
+
:objects => [id], :msg => "Restored file from store"
|
|
172
188
|
rescue Exception => e
|
|
173
189
|
raise FileStoreException, "Couldn't restore file #{file} from deleted store.\n#{e.message}"
|
|
174
190
|
#
|
|
@@ -183,6 +199,9 @@ module FileStore
|
|
|
183
199
|
@metaManager.shutdown
|
|
184
200
|
|
|
185
201
|
release_lock
|
|
202
|
+
|
|
203
|
+
self.inform ObserverAction.new :type => ObserverAction::TYPE_STORE_SHUTDOWN,
|
|
204
|
+
:msg => "File store shutdown"
|
|
186
205
|
end
|
|
187
206
|
#
|
|
188
207
|
# Determines wether this store is locked
|
|
@@ -261,7 +280,6 @@ module FileStore
|
|
|
261
280
|
# store: The file store instance to set up
|
|
262
281
|
#
|
|
263
282
|
def self.create_store(store)
|
|
264
|
-
Logger.instance.logger.info "Trying to create store in #{store.storePath}"
|
|
265
283
|
# Try to create needed directories
|
|
266
284
|
begin
|
|
267
285
|
FileUtils.mkdir [store.storePath, store.deletedPath, store.rollbackPath]
|
|
@@ -297,7 +315,6 @@ module FileStore
|
|
|
297
315
|
def self.recover_store(store)
|
|
298
316
|
# trying to recover existing file store
|
|
299
317
|
begin
|
|
300
|
-
Logger.instance.logger.info "Trying to recover store from #{store.metaFile}"
|
|
301
318
|
meta = YAML.load_file(store.metaFile)
|
|
302
319
|
|
|
303
320
|
raise FileStoreException, "Store directory not found" if not File.directory?(meta[:storePath])
|
data/lib/log.rb
CHANGED
|
@@ -1,29 +1,45 @@
|
|
|
1
1
|
#
|
|
2
2
|
# log.rb
|
|
3
|
+
# @author Thomas Stätter
|
|
4
|
+
# @date 2012/11/26
|
|
5
|
+
# @description
|
|
3
6
|
#
|
|
4
|
-
# author: Thomas Stätter
|
|
5
|
-
# date: 2012/11/07
|
|
6
|
-
#
|
|
7
|
-
require 'date'
|
|
8
|
-
require 'log4r'
|
|
9
|
-
require 'singleton'
|
|
10
|
-
|
|
11
7
|
module FileStore
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
8
|
+
#
|
|
9
|
+
# Mix-in module for logging capabilities
|
|
10
|
+
#
|
|
11
|
+
module Logger
|
|
12
|
+
#
|
|
13
|
+
# Accessor for the logging facility. Any logging facility must
|
|
14
|
+
# implement the methods 'info', 'warn', 'error' and 'debug'
|
|
15
|
+
#
|
|
16
|
+
attr_accessor :logger
|
|
17
|
+
end
|
|
18
|
+
#
|
|
19
|
+
# Simple logger class for stdout logging
|
|
20
|
+
#
|
|
21
|
+
class StdoutLogger
|
|
22
|
+
|
|
23
|
+
def StdoutLogger.log(level, msg)
|
|
24
|
+
puts "[#{level}] #{msg}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def StdoutLogger.info(msg)
|
|
28
|
+
StdoutLogger::log("INFO", msg)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def StdoutLogger.warn(msg)
|
|
32
|
+
StdoutLogger::log("WARN", msg)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def StdoutLogger.error(msg)
|
|
36
|
+
StdoutLogger::log("ERROR", msg)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def StdoutLogger.debug(msg)
|
|
40
|
+
StdoutLogger::log("DEBUG", msg)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
29
45
|
end
|
data/lib/memory_meta.rb
CHANGED
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
# author: Thomas Stätter
|
|
5
5
|
# date: 2012/11/08
|
|
6
6
|
#
|
|
7
|
-
require
|
|
8
|
-
require 'filestore.rb'
|
|
9
|
-
require 'meta_manager.rb'
|
|
10
|
-
require 'log.rb'
|
|
7
|
+
require "../module.rb"
|
|
11
8
|
|
|
12
9
|
module FileStore
|
|
13
10
|
#
|
|
14
11
|
# Class implementing a memory based MetaManager
|
|
15
12
|
#
|
|
16
13
|
class MemoryMetaManager < MetaManager
|
|
14
|
+
include Logger
|
|
15
|
+
include OberservedSubject
|
|
16
|
+
|
|
17
17
|
# Constant defining the default file path
|
|
18
18
|
FILE = 'meta.yaml'
|
|
19
19
|
# Accessor for the file to store data to
|
|
@@ -24,23 +24,26 @@ module FileStore
|
|
|
24
24
|
# Arguments:
|
|
25
25
|
# persistentFile: The file where the manager class is persisted to
|
|
26
26
|
#
|
|
27
|
-
def initialize(persistentFile = '')
|
|
27
|
+
def initialize(persistentFile = '', logger)
|
|
28
|
+
@logger = logger
|
|
28
29
|
@data = Hash.new
|
|
29
30
|
@removed = Hash.new
|
|
30
31
|
@file = (persistentFile.nil? or persistentFile == '')? MemoryMetaManager::FILE : persistentFile
|
|
31
32
|
|
|
33
|
+
self.initialize_obs
|
|
34
|
+
|
|
32
35
|
begin
|
|
33
36
|
if File.exists?(@file)
|
|
34
|
-
|
|
37
|
+
@logger.info "loading meta yaml from #{@file}"
|
|
35
38
|
@mm = YAML.load_file(@file) if File.exists?(@file)
|
|
36
|
-
|
|
39
|
+
@logger.info "Loaded meta yaml: #{@mm}"
|
|
37
40
|
@data = @mm[:current]
|
|
38
41
|
@removed = @mm[:removed]
|
|
39
42
|
else
|
|
40
|
-
|
|
43
|
+
@logger.info "Creating new meta store in #{@file}"
|
|
41
44
|
end
|
|
42
45
|
rescue Exception => e
|
|
43
|
-
raise FileStoreException, "Couldn't load meta data from file #{@file}"
|
|
46
|
+
raise FileStoreException, "Couldn't load meta data from file #{@file}.\nCause: #{e}"
|
|
44
47
|
end
|
|
45
48
|
|
|
46
49
|
end
|
|
@@ -60,6 +63,9 @@ module FileStore
|
|
|
60
63
|
raise FileStoreException, "Only Strings can be used as keys" if not id.is_a?(String)
|
|
61
64
|
|
|
62
65
|
@data[id] = (@data.key?(id) ? @data[id].merge!(metaData) : @data[id] = metaData)
|
|
66
|
+
|
|
67
|
+
self.inform ObserverAction.new(:type => ObserverAction::TYPE_META_ADD,
|
|
68
|
+
:objects => [id, metaData], :msg => "Added/Updated file to meta store")
|
|
63
69
|
end
|
|
64
70
|
#
|
|
65
71
|
# see: MetaManager::remove
|
|
@@ -70,6 +76,9 @@ module FileStore
|
|
|
70
76
|
|
|
71
77
|
@removed[id] = @data[id]
|
|
72
78
|
@data.delete(id)
|
|
79
|
+
|
|
80
|
+
self.inform ObserverAction.new(:type => ObserverAction::TYPE_META_REMOVE,
|
|
81
|
+
:objects => [id], :msg => "Removed file to meta store")
|
|
73
82
|
end
|
|
74
83
|
#
|
|
75
84
|
# see: MetaManager::restore
|
|
@@ -80,6 +89,9 @@ module FileStore
|
|
|
80
89
|
|
|
81
90
|
@data[id] = @removed[id]
|
|
82
91
|
@removed.delete(id)
|
|
92
|
+
|
|
93
|
+
self.inform ObserverAction.new(:type => ObserverAction::TYPE_META_RESTORE,
|
|
94
|
+
:objects => [id], :msg => "Restored file in meta store")
|
|
83
95
|
end
|
|
84
96
|
#
|
|
85
97
|
# see: MetaManager::shutdown
|
|
@@ -91,6 +103,9 @@ module FileStore
|
|
|
91
103
|
end
|
|
92
104
|
|
|
93
105
|
@data = nil
|
|
106
|
+
|
|
107
|
+
self.inform ObserverAction.new(:type => ObserverAction::TYPE_META_SHUTDOWN,
|
|
108
|
+
:msg => "Restored file in meta store")
|
|
94
109
|
rescue Exception => e
|
|
95
110
|
raise FileStoreException, "Couldn't serialize meta manager to file #{@file}.\n#{e.message}"
|
|
96
111
|
end
|
|
@@ -4,20 +4,15 @@
|
|
|
4
4
|
# author: Thomas Stätter
|
|
5
5
|
# date: 2012/11/21
|
|
6
6
|
#
|
|
7
|
-
|
|
8
|
-
require 'filestore.rb'
|
|
9
|
-
require 'memory_meta.rb'
|
|
10
|
-
require 'log.rb'
|
|
11
|
-
require 'uuidtools'
|
|
12
|
-
require 'fileutils'
|
|
13
|
-
require 'yaml'
|
|
14
|
-
require 'singleton'
|
|
7
|
+
require "../module.rb"
|
|
15
8
|
|
|
16
9
|
module FileStore
|
|
17
10
|
#
|
|
18
11
|
# Singleton class implementing a multitenant file store
|
|
19
12
|
#
|
|
20
13
|
class MultiTenantFileStore
|
|
14
|
+
include Logger
|
|
15
|
+
include OberservedSubject
|
|
21
16
|
# Make this class a singleton class
|
|
22
17
|
include Singleton
|
|
23
18
|
# Accessors
|
|
@@ -28,6 +23,8 @@ module FileStore
|
|
|
28
23
|
def initialize()
|
|
29
24
|
@rootPath = Dir.getwd
|
|
30
25
|
@stores = {}
|
|
26
|
+
|
|
27
|
+
self.initialize_obs
|
|
31
28
|
end
|
|
32
29
|
#
|
|
33
30
|
# Sets the root path of the multitenant store. As FileStore::MultiTenantFileStore
|
|
@@ -58,10 +55,13 @@ module FileStore
|
|
|
58
55
|
begin
|
|
59
56
|
path = File.join(@rootPath, id)
|
|
60
57
|
FileUtils.mkdir path if not File.directory?(path)
|
|
61
|
-
mm = MemoryMetaManager.new(File.join(path, "meta.yaml"))
|
|
62
|
-
sfs = SimpleFileStore.new(mm, path)
|
|
58
|
+
mm = MemoryMetaManager.new(File.join(path, "meta.yaml"), self.logger)
|
|
59
|
+
sfs = SimpleFileStore.new(mm, path, self.logger)
|
|
63
60
|
|
|
64
61
|
@stores[id] = sfs
|
|
62
|
+
|
|
63
|
+
self.inform ObserverAction.new(:type => ObserverAction::TYPE_MSTORE_CREATE,
|
|
64
|
+
:msg => "Created new tenant store")
|
|
65
65
|
rescue Exception => e
|
|
66
66
|
raise FileStoreException, "Couldn't create multitenant store.\n#{e.message}"
|
|
67
67
|
end
|
|
@@ -110,6 +110,9 @@ module FileStore
|
|
|
110
110
|
raise FileStoreException, "Tenant #{tenant} not registered. File #{file} can't be added." if not @stores.key?(tenant)
|
|
111
111
|
|
|
112
112
|
@stores[tenant].add(file, md)
|
|
113
|
+
|
|
114
|
+
self.inform ObserverAction.new(:type => ObserverAction::TYPE_MSTORE_ADD,
|
|
115
|
+
:objects => [tenant, file], :msg => "Added file to tenant")
|
|
113
116
|
end
|
|
114
117
|
#
|
|
115
118
|
# Removes a file from the tenant's store
|
|
@@ -180,7 +183,7 @@ module FileStore
|
|
|
180
183
|
stores[tenant] = sfs
|
|
181
184
|
end
|
|
182
185
|
rescue Exception => e
|
|
183
|
-
|
|
186
|
+
@logger.error "Couldn't create store for tenant #{tenant}.\n#{e.message}"
|
|
184
187
|
end
|
|
185
188
|
}
|
|
186
189
|
|
data/lib/observer.rb
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#
|
|
2
|
+
# observer.rb
|
|
3
|
+
#
|
|
4
|
+
# author: Thomas Stätter
|
|
5
|
+
# date: 2014/01/05
|
|
6
|
+
#
|
|
7
|
+
require "../module.rb"
|
|
8
|
+
|
|
9
|
+
module FileStore
|
|
10
|
+
#
|
|
11
|
+
# Class FileStore::ObserverAction is used to encapsulate information
|
|
12
|
+
# describing actions occurring in an observed subject
|
|
13
|
+
#
|
|
14
|
+
class ObserverAction
|
|
15
|
+
TYPE_DEFAULT = "DEFAULT"
|
|
16
|
+
TYPE_STORE_ADD = "STORE_ADD_FILE"
|
|
17
|
+
TYPE_STORE_REMOVE = "STORE_REMOVE_FILE"
|
|
18
|
+
TYPE_STORE_GET = "STORE_GET_FILE"
|
|
19
|
+
TYPE_STORE_RESTORE = "STORE_RESTORE_FILE"
|
|
20
|
+
TYPE_STORE_SHUTDOWN = "STORE_SHUTDOWN"
|
|
21
|
+
TYPE_MSTORE_CREATE = "MSTORE_CREATE_TENANT"
|
|
22
|
+
TYPE_MSTORE_ADD = "MSTORE_ADD_FILE"
|
|
23
|
+
TYPE_MSTORE_REMOVE = "MSTORE_REMOVE_TENANT"
|
|
24
|
+
TYPE_META_ADD = "META_ADD_FILE"
|
|
25
|
+
TYPE_META_REMOVE = "META_REMOVE_FILE"
|
|
26
|
+
TYPE_META_RESTORE = "META_RESTORE_FILE"
|
|
27
|
+
TYPE_META_SHUTDOWN = "META_SHUTDOWN"
|
|
28
|
+
#
|
|
29
|
+
# Attribute accessors for instance variable defining the type of
|
|
30
|
+
# action
|
|
31
|
+
#
|
|
32
|
+
attr_accessor :type
|
|
33
|
+
#
|
|
34
|
+
# Attribute accessors for instance variable containing references
|
|
35
|
+
# to affected objects
|
|
36
|
+
#
|
|
37
|
+
attr_accessor :objects
|
|
38
|
+
#
|
|
39
|
+
# Attribute accessors for instance variable containing a message
|
|
40
|
+
# providing useful information
|
|
41
|
+
#
|
|
42
|
+
attr_accessor :message
|
|
43
|
+
|
|
44
|
+
def initialize(type = TYPE_DEFAULT, objects = [], message = "")
|
|
45
|
+
@type = type
|
|
46
|
+
@objects = objects
|
|
47
|
+
@message = message
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def to_s
|
|
51
|
+
return "(ActionType) #{@type} || (Objects) #{@objects} || (Message) #{@message}"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
#
|
|
55
|
+
# Module FileStore::OberservedSubject can be mixed in to implement an
|
|
56
|
+
# observed object.
|
|
57
|
+
#
|
|
58
|
+
module OberservedSubject
|
|
59
|
+
#
|
|
60
|
+
# Reader for collection of observers
|
|
61
|
+
#
|
|
62
|
+
attr_reader :observers
|
|
63
|
+
#
|
|
64
|
+
# Module hook executed after the inclusion. Currently nothing
|
|
65
|
+
# happens here
|
|
66
|
+
#
|
|
67
|
+
def self.included(klass)
|
|
68
|
+
end
|
|
69
|
+
#
|
|
70
|
+
# Initializes needed attributes for implementing observer. Should
|
|
71
|
+
# be called in any constructor including this module
|
|
72
|
+
#
|
|
73
|
+
def initialize_obs
|
|
74
|
+
@observers = []
|
|
75
|
+
self.logger.debug "Initialized ObservedStore, added observers array" if not self.logger.nil?
|
|
76
|
+
end
|
|
77
|
+
#
|
|
78
|
+
# Registers an concrete observer
|
|
79
|
+
#
|
|
80
|
+
# Arguments:
|
|
81
|
+
# obj: The object added as an observer. Must be an instance of
|
|
82
|
+
# FileStore::Observer
|
|
83
|
+
#
|
|
84
|
+
def register(obj)
|
|
85
|
+
if obj.is_a?(Observer) and not obj.nil? and not @observers.include?(obj) then
|
|
86
|
+
@observers << obj
|
|
87
|
+
self.logger.debug "Added #{obj} to observers" if not self.logger.nil?
|
|
88
|
+
else
|
|
89
|
+
raise FileStoreException, "Only instances of FileStore::Observer can be registered"
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
#
|
|
93
|
+
# Removes a concrete observer
|
|
94
|
+
#
|
|
95
|
+
# Arguments:
|
|
96
|
+
# obj: The observer to be removed. Obviously, it needs to be
|
|
97
|
+
# registered before-hand
|
|
98
|
+
#
|
|
99
|
+
def unregister(obj)
|
|
100
|
+
if @observers.include?(obj) then
|
|
101
|
+
@observers.delete_at(@observers.index(obj))
|
|
102
|
+
self.logger.debug "Removed observing object #{obj} from the list" if not self.logger.nil?
|
|
103
|
+
else
|
|
104
|
+
raise FileStoreException, "Object #{obj} isn't a registered observer"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
#
|
|
108
|
+
# Informs registered observers about an action
|
|
109
|
+
#
|
|
110
|
+
# Arguments:
|
|
111
|
+
# msg: Some information sent to all registered observers
|
|
112
|
+
#
|
|
113
|
+
def inform(msg)
|
|
114
|
+
@observers.each do |o|
|
|
115
|
+
o.notify msg, self
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
#
|
|
121
|
+
# Module FileStore::Observer can be mixed in to implement a
|
|
122
|
+
# observer. Observers are notified about actions occurring
|
|
123
|
+
# in the observed subject, an instance of FileStore::SimpleStore
|
|
124
|
+
# or FileStore::MultiTenantFileStore, respectively.
|
|
125
|
+
#
|
|
126
|
+
module Observer
|
|
127
|
+
#
|
|
128
|
+
# Module hook executed after the inclusion. Currently nothing
|
|
129
|
+
# happens here
|
|
130
|
+
#
|
|
131
|
+
def self.included(klass)
|
|
132
|
+
end
|
|
133
|
+
#
|
|
134
|
+
# Method called via the observed subject to inform observers
|
|
135
|
+
# about an action occurred in the observed subject. Override
|
|
136
|
+
# this method to fit your needs.
|
|
137
|
+
#
|
|
138
|
+
# Arguments:
|
|
139
|
+
# msg: Some information about the action
|
|
140
|
+
# subject: A reference to the observed object
|
|
141
|
+
#
|
|
142
|
+
def notify(msg, subject)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
end
|
data/module.rb
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#
|
|
2
|
+
# filestore.rb
|
|
3
|
+
# @author Thomas Stätter
|
|
4
|
+
# @date 2012/11/26
|
|
5
|
+
# @description
|
|
6
|
+
#
|
|
7
|
+
module FileStore
|
|
8
|
+
VERSION = '0.0.8'
|
|
9
|
+
LIB_FILES = [
|
|
10
|
+
#
|
|
11
|
+
# Required 3rd party libs
|
|
12
|
+
#
|
|
13
|
+
'uuidtools',
|
|
14
|
+
'fileutils',
|
|
15
|
+
'yaml',
|
|
16
|
+
'singleton',
|
|
17
|
+
'etc',
|
|
18
|
+
#
|
|
19
|
+
# FileStore specific libraries. Order matters!
|
|
20
|
+
#
|
|
21
|
+
'lib/meta_manager.rb',
|
|
22
|
+
'lib/log.rb',
|
|
23
|
+
'lib/observer.rb',
|
|
24
|
+
'lib/filestore.rb',
|
|
25
|
+
'lib/multitenant_filestore.rb',
|
|
26
|
+
'lib/memory_meta.rb'
|
|
27
|
+
]
|
|
28
|
+
#
|
|
29
|
+
# Loads required libs as defined in FileStore::LIB_FILES
|
|
30
|
+
#
|
|
31
|
+
def self.load_required
|
|
32
|
+
$LOAD_PATH << File.dirname(File.new(__FILE__))
|
|
33
|
+
|
|
34
|
+
LIB_FILES.each do |l|
|
|
35
|
+
require l
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
FileStore::load_required
|
data/test/classes.rb
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
|
|
3
|
+
class FileStoreTest < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
def setup
|
|
6
|
+
# create test directory and file
|
|
7
|
+
@basePath = "#{Dir.getwd}/store_test"
|
|
8
|
+
@testFile = File.join(@basePath, "testfile.txt")
|
|
9
|
+
|
|
10
|
+
FileUtils.mkdir(@basePath) if not File.exists?(@basePath)
|
|
11
|
+
FileUtils.touch(@testFile) if not File.exists?(@testFile)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def teardown
|
|
15
|
+
# remove test directory and file
|
|
16
|
+
FileUtils.remove_dir(@basePath, true) if File.exists?(@basePath)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class ObserverClass
|
|
22
|
+
include Observer
|
|
23
|
+
include Logger
|
|
24
|
+
|
|
25
|
+
def initialize()
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def notify(msg, obj)
|
|
29
|
+
self.logger.info "[ObserverClass] received msg '#{msg.to_s}' from observed object #{obj}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class OtherObserverClass
|
|
34
|
+
include Observer
|
|
35
|
+
include Logger
|
|
36
|
+
|
|
37
|
+
def initialize
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def notify(msg, obj)
|
|
41
|
+
self.logger.info "[OtherObserverClass] received msg '#{msg.to_s}' from observed object #{obj}"
|
|
42
|
+
end
|
|
43
|
+
end
|
data/test/tc_filestore.rb
CHANGED
|
@@ -2,31 +2,73 @@
|
|
|
2
2
|
# tc_filestore.rb
|
|
3
3
|
# @author Thomas Stätter
|
|
4
4
|
# @date 2012/11/14
|
|
5
|
-
# @description Test script
|
|
6
5
|
#
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
require_relative '../lib/memory_meta.rb'
|
|
6
|
+
require_relative '../module.rb'
|
|
7
|
+
require './classes.rb'
|
|
8
|
+
require 'test/unit'
|
|
11
9
|
|
|
12
10
|
include FileStore
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
12
|
+
class TestFileStore < FileStoreTest
|
|
13
|
+
|
|
14
|
+
def test_init_shutdown
|
|
15
|
+
puts "=" * 80
|
|
16
|
+
puts "TestFileStore::test_init_shutdown"
|
|
17
|
+
puts "=" * 80
|
|
18
|
+
|
|
19
|
+
mm = MemoryMetaManager.new File.join(@basePath, "meta.yaml"), StdoutLogger
|
|
20
|
+
sfs = nil
|
|
21
|
+
|
|
22
|
+
assert_nothing_raised(FileStoreException) {
|
|
23
|
+
sfs = SimpleFileStore.new mm, @basePath, StdoutLogger
|
|
24
|
+
}
|
|
25
|
+
assert_not_nil(sfs)
|
|
26
|
+
assert_nothing_raised(FileStoreException) {
|
|
27
|
+
sfs.shutdown
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_registration_observer
|
|
32
|
+
puts "=" * 80
|
|
33
|
+
puts "TestFileStorage::test_registration_observer"
|
|
34
|
+
puts "=" * 80
|
|
35
|
+
|
|
36
|
+
mm = MemoryMetaManager.new File.join(@basePath, "meta.yaml"), StdoutLogger
|
|
37
|
+
sfs = SimpleFileStore.new mm, @basePath, StdoutLogger
|
|
38
|
+
o1 = OtherObserverClass.new
|
|
39
|
+
o2 = ObserverClass.new
|
|
40
|
+
|
|
41
|
+
assert_nothing_raised(FileStoreException) {
|
|
42
|
+
sfs.register o1
|
|
43
|
+
sfs.register o2
|
|
44
|
+
}
|
|
45
|
+
assert_raise(FileStoreException) { sfs.register o1 }
|
|
46
|
+
assert_nothing_raised(FileStoreException) {
|
|
47
|
+
sfs.unregister o1
|
|
48
|
+
sfs.unregister o2
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_actions_with_observer
|
|
53
|
+
puts "=" * 80
|
|
54
|
+
puts "TestFileStorage::test_actions_with_observer"
|
|
55
|
+
puts "=" * 80
|
|
56
|
+
|
|
57
|
+
o1 = ObserverClass.new
|
|
58
|
+
o1.logger = StdoutLogger
|
|
59
|
+
mm = MemoryMetaManager.new File.join(@basePath, "meta.yaml"), StdoutLogger
|
|
60
|
+
sfs = SimpleFileStore.new mm, @basePath, StdoutLogger
|
|
61
|
+
id = nil
|
|
62
|
+
|
|
63
|
+
sfs.register o1
|
|
64
|
+
|
|
65
|
+
assert_nothing_raised(FileStoreException) {
|
|
66
|
+
id = sfs.add @testFile, { :original_file => @testFile }, false
|
|
67
|
+
}
|
|
68
|
+
assert_nothing_raised(FileStoreException) { file = sfs.get id }
|
|
69
|
+
assert_not_nil(sfs.get(id))
|
|
70
|
+
assert_nothing_raised(FileStoreException) { sfs.remove id }
|
|
71
|
+
assert_nothing_raised(FileStoreException) { sfs.shutdown }
|
|
72
|
+
end
|
|
73
|
+
|
|
32
74
|
end
|
data/test/tc_meta.rb
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#
|
|
2
|
+
# tc_meta.rb
|
|
3
|
+
# @author Thomas Stätter
|
|
4
|
+
# @date 2014/01/05
|
|
5
|
+
#
|
|
6
|
+
require_relative '../module.rb'
|
|
7
|
+
require './classes.rb'
|
|
8
|
+
require 'test/unit'
|
|
9
|
+
|
|
10
|
+
include FileStore
|
|
11
|
+
|
|
12
|
+
class TestMetaManager < FileStoreTest
|
|
13
|
+
|
|
14
|
+
def test_init_shutdown
|
|
15
|
+
puts "=" * 80
|
|
16
|
+
puts "TestMetaManager::test_init_shutdown"
|
|
17
|
+
puts "=" * 80
|
|
18
|
+
assert_nothing_raised(FileStoreException) {
|
|
19
|
+
MemoryMetaManager.new File.join(@basePath, "meta.yaml"), StdoutLogger
|
|
20
|
+
}
|
|
21
|
+
assert_nothing_raised(FileStoreException) {
|
|
22
|
+
mm = MemoryMetaManager.new File.join(@basePath, "meta.yaml"), StdoutLogger
|
|
23
|
+
|
|
24
|
+
mm.shutdown
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_registration_observer
|
|
29
|
+
puts "=" * 80
|
|
30
|
+
puts "TestMetaManager::test_registration_observer"
|
|
31
|
+
puts "=" * 80
|
|
32
|
+
|
|
33
|
+
o1 = ObserverClass.new
|
|
34
|
+
o2 = OtherObserverClass.new
|
|
35
|
+
|
|
36
|
+
o1.logger = StdoutLogger
|
|
37
|
+
o2.logger = StdoutLogger
|
|
38
|
+
|
|
39
|
+
mm = MemoryMetaManager.new(File.join(@basePath, "meta.yaml"), StdoutLogger)
|
|
40
|
+
|
|
41
|
+
assert_nothing_raised(FileStoreException) {
|
|
42
|
+
mm.register o1
|
|
43
|
+
mm.register o2
|
|
44
|
+
}
|
|
45
|
+
assert_raise(FileStoreException) { mm.register o1 }
|
|
46
|
+
assert_nothing_raised(FileStoreException) {
|
|
47
|
+
mm.unregister(o1)
|
|
48
|
+
mm.unregister(o2)
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_actions_with_observer
|
|
53
|
+
puts "=" * 80
|
|
54
|
+
puts "TestMetaManager::test_actions_with_observer"
|
|
55
|
+
puts "=" * 80
|
|
56
|
+
|
|
57
|
+
o1 = ObserverClass.new
|
|
58
|
+
o1.logger = StdoutLogger
|
|
59
|
+
mm = MemoryMetaManager.new(File.join(@basePath, "meta.yaml"), StdoutLogger)
|
|
60
|
+
|
|
61
|
+
mm.register o1
|
|
62
|
+
|
|
63
|
+
assert_nothing_raised(Exception) { mm.add_or_update "1", {} }
|
|
64
|
+
assert_nothing_raised(Exception) { mm.add_or_update "1", {} }
|
|
65
|
+
assert_nothing_raised(Exception) { mm.remove "1" }
|
|
66
|
+
assert_nothing_raised(Exception) { mm.restore "1" }
|
|
67
|
+
assert_nothing_raised(Exception) { mm.shutdown }
|
|
68
|
+
end
|
|
69
|
+
end
|
data/test/tc_module.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#
|
|
2
|
+
# tc_module.rb
|
|
3
|
+
# @author Thomas Stätter
|
|
4
|
+
# @date 2014/01/05
|
|
5
|
+
#
|
|
6
|
+
require 'test/unit'
|
|
7
|
+
require '../module.rb'
|
|
8
|
+
|
|
9
|
+
include FileStore
|
|
10
|
+
|
|
11
|
+
class TestModule < Test::Unit::TestCase
|
|
12
|
+
|
|
13
|
+
def test_inclusion
|
|
14
|
+
puts "=" * 80
|
|
15
|
+
puts "TestModule::test_inclusion"
|
|
16
|
+
puts "=" * 80
|
|
17
|
+
assert_nothing_raised(NameError) { ObserverAction }
|
|
18
|
+
assert_nothing_raised(NameError) { OberservedSubject }
|
|
19
|
+
assert_nothing_raised(NameError) { Observer }
|
|
20
|
+
assert_nothing_raised(NameError) { SimpleFileStore }
|
|
21
|
+
assert_nothing_raised(NameError) { MultiTenantFileStore }
|
|
22
|
+
assert_nothing_raised(NameError) { MemoryMetaManager }
|
|
23
|
+
assert_nothing_raised(NameError) { MetaManager }
|
|
24
|
+
assert_nothing_raised(NameError) { FileStoreException }
|
|
25
|
+
end
|
|
26
|
+
end
|
data/test/tc_multitenant.rb
CHANGED
|
@@ -1,29 +1,51 @@
|
|
|
1
1
|
#
|
|
2
2
|
# tc_multitenant.rb
|
|
3
|
+
#
|
|
3
4
|
# @author Thomas Stätter
|
|
4
5
|
# @date 2012/11/21
|
|
5
6
|
# @description Test script
|
|
6
7
|
#
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
require 'fileutils'
|
|
8
|
+
require_relative '../module.rb'
|
|
9
|
+
require './classes.rb'
|
|
10
|
+
require 'test/unit'
|
|
11
11
|
|
|
12
12
|
include FileStore
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
class TestMultiTenantFileStore < FileStoreTest
|
|
15
|
+
|
|
16
|
+
def test_registration_observer
|
|
17
|
+
puts "=" * 80
|
|
18
|
+
puts "TestMultiTenantFileStore::test_registration_observer"
|
|
19
|
+
puts "=" * 80
|
|
20
|
+
|
|
21
|
+
MultiTenantFileStore.instance.set_root_path @basePath
|
|
22
|
+
MultiTenantFileStore.instance.logger = StdoutLogger
|
|
23
|
+
tenant = MultiTenantFileStore.instance.create_tenant_store
|
|
24
|
+
o1 = OtherObserverClass.new
|
|
25
|
+
o2 = ObserverClass.new
|
|
26
|
+
|
|
27
|
+
assert_nothing_raised(FileStoreException) {
|
|
28
|
+
MultiTenantFileStore.instance.register o1
|
|
29
|
+
MultiTenantFileStore.instance.register o2
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_actions_with_observer
|
|
34
|
+
puts "=" * 80
|
|
35
|
+
puts "TestMultiTenantFileStore::test_actions_with_observer"
|
|
36
|
+
puts "=" * 80
|
|
37
|
+
|
|
38
|
+
MultiTenantFileStore.instance.set_root_path @basePath
|
|
39
|
+
MultiTenantFileStore.instance.logger = StdoutLogger
|
|
40
|
+
o1 = OtherObserverClass.new
|
|
41
|
+
o1.logger = StdoutLogger
|
|
42
|
+
MultiTenantFileStore.instance.register o1
|
|
43
|
+
|
|
44
|
+
assert_nothing_raised(FileStoreException) {
|
|
45
|
+
tenant = MultiTenantFileStore.instance.create_tenant_store
|
|
46
|
+
MultiTenantFileStore.instance.add_to_tenant tenant,
|
|
47
|
+
@testFile, { :original_file => @testFile }
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
data/test/ts_all.rb
ADDED
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.8
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2014-01-05 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: uuidtools
|
|
@@ -61,15 +61,19 @@ executables: []
|
|
|
61
61
|
extensions: []
|
|
62
62
|
extra_rdoc_files: []
|
|
63
63
|
files:
|
|
64
|
-
-
|
|
64
|
+
- module.rb
|
|
65
65
|
- lib/filestore.rb
|
|
66
66
|
- lib/memory_meta.rb
|
|
67
67
|
- lib/log.rb
|
|
68
68
|
- lib/meta_manager.rb
|
|
69
69
|
- lib/multitenant_filestore.rb
|
|
70
|
+
- lib/observer.rb
|
|
71
|
+
- test/classes.rb
|
|
72
|
+
- test/tc_meta.rb
|
|
73
|
+
- test/tc_module.rb
|
|
70
74
|
- test/tc_filestore.rb
|
|
71
75
|
- test/tc_multitenant.rb
|
|
72
|
-
- test/
|
|
76
|
+
- test/ts_all.rb
|
|
73
77
|
homepage: https://github.com/tstaetter/filestore-gem
|
|
74
78
|
licenses: []
|
|
75
79
|
post_install_message:
|
|
@@ -96,6 +100,9 @@ signing_key:
|
|
|
96
100
|
specification_version: 3
|
|
97
101
|
summary: Simple file storage
|
|
98
102
|
test_files:
|
|
103
|
+
- test/classes.rb
|
|
104
|
+
- test/tc_meta.rb
|
|
105
|
+
- test/tc_module.rb
|
|
99
106
|
- test/tc_filestore.rb
|
|
100
107
|
- test/tc_multitenant.rb
|
|
101
|
-
- test/
|
|
108
|
+
- test/ts_all.rb
|
data/filestore.rb
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
#
|
|
2
|
-
# filestore.rb
|
|
3
|
-
# @author Thomas Stätter
|
|
4
|
-
# @date 2012/11/26
|
|
5
|
-
# @description
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
require 'lib/meta_manager.rb'
|
|
9
|
-
require 'lib/log.rb'
|
|
10
|
-
require 'lib/filestore.rb'
|
|
11
|
-
require 'lib/multitenant_filestore.rb'
|
|
12
|
-
|
|
13
|
-
module FileStore
|
|
14
|
-
VERSION = '0.0.5'
|
|
15
|
-
end
|
data/test/testfile.txt
DELETED
|
File without changes
|