|
@@ -2,7 +2,11 @@
|
|
|
|
|
|
require 'digest/md5'
|
|
|
|
|
|
+
|
|
|
class Store < ApplicationModel
|
|
|
+ require 'store/object'
|
|
|
+ require 'store/file'
|
|
|
+
|
|
|
store :preferences
|
|
|
belongs_to :store_object, :class_name => 'Store::Object'
|
|
|
belongs_to :store_file, :class_name => 'Store::File'
|
|
@@ -35,28 +39,10 @@ returns
|
|
|
store_object = Store::Object.create_if_not_exists( :name => data['object'] )
|
|
|
data['store_object_id'] = store_object.id
|
|
|
|
|
|
- # check if record already exists
|
|
|
- # store = Store.where( :store_object_id => store_object.id, :o_id => data['o_id'], ).first
|
|
|
- # if store != nil
|
|
|
- # return store
|
|
|
- # end
|
|
|
+ # add to real store
|
|
|
+ file = Store::File.add( data['data'] )
|
|
|
|
|
|
- # check real store
|
|
|
- md5 = Digest::MD5.hexdigest( data['data'] )
|
|
|
data['size'] = data['data'].to_s.bytesize
|
|
|
-
|
|
|
- # file = Store::Provider::DB.create( data['data'], md5 )
|
|
|
-
|
|
|
- file = Store::File.where( :md5 => md5 ).first
|
|
|
-
|
|
|
- # store attachment
|
|
|
- if file == nil
|
|
|
- file = Store::File.create(
|
|
|
- :data => data['data'],
|
|
|
- :md5 => md5,
|
|
|
- )
|
|
|
- end
|
|
|
-
|
|
|
data['store_file_id'] = file.id
|
|
|
|
|
|
# not needed attributes
|
|
@@ -128,7 +114,6 @@ returns
|
|
|
# check backend for references
|
|
|
files = Store.where( :store_file_id => store.store_file_id )
|
|
|
if files.count == 1 && files.first.id == store.id
|
|
|
- # file = Store::Provider::DB.delete( store.store_file_id )
|
|
|
Store::File.find( store.store_file_id ).destroy
|
|
|
end
|
|
|
|
|
@@ -137,165 +122,19 @@ returns
|
|
|
return true
|
|
|
end
|
|
|
|
|
|
- # get attachment
|
|
|
def content
|
|
|
- # Store::Provider::DB.content( store.store_file_id )
|
|
|
file = Store::File.where( :id => self.store_file_id ).first
|
|
|
- return if !file
|
|
|
- if file.file_system
|
|
|
- return file.read_from_fs
|
|
|
+ if !file
|
|
|
+ raise "No such file #{ self.store_file_id }!"
|
|
|
end
|
|
|
- file.data
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-class Store::Object < ApplicationModel
|
|
|
- validates :name, :presence => true
|
|
|
-end
|
|
|
-
|
|
|
-class Store::File < ApplicationModel
|
|
|
- before_validation :add_md5
|
|
|
- before_create :check_location
|
|
|
- after_destroy :unlink_location
|
|
|
-
|
|
|
- # generate file location
|
|
|
- def get_locaton
|
|
|
-
|
|
|
- # generate directory
|
|
|
- base = Rails.root.to_s + '/storage/fs/'
|
|
|
- parts = self.md5.scan(/.{1,3}/)
|
|
|
- path = parts[ 1 .. 7 ].join('/') + '/'
|
|
|
- file = parts[ 8 .. parts.count ].join('')
|
|
|
- location = "#{base}/#{path}"
|
|
|
-
|
|
|
- # create directory if not exists
|
|
|
- if !File.exist?( location )
|
|
|
- FileUtils.mkdir_p( location )
|
|
|
- end
|
|
|
- location += file
|
|
|
+ file.content
|
|
|
end
|
|
|
|
|
|
- # read file from fs
|
|
|
- def unlink_location
|
|
|
- if File.exist?( self.get_locaton )
|
|
|
- puts "NOTICE: storge remove '#{self.get_locaton}'"
|
|
|
- File.delete( self.get_locaton )
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
- # read file from fs
|
|
|
- def read_from_fs
|
|
|
- puts "read from fs #{self.get_locaton}"
|
|
|
- return if !File.exist?( self.get_locaton )
|
|
|
- data = File.open( self.get_locaton, 'rb' )
|
|
|
- content = data.read
|
|
|
-
|
|
|
- # check md5
|
|
|
- md5 = Digest::MD5.hexdigest( content )
|
|
|
- if md5 != self.md5
|
|
|
- raise "ERROR: Corrupt file in fs #{self.get_locaton}, md5 should be #{self.md5} but is #{md5}"
|
|
|
- end
|
|
|
- content
|
|
|
- end
|
|
|
-
|
|
|
- # write file to fs
|
|
|
- def write_to_fs
|
|
|
-
|
|
|
- # install file
|
|
|
- permission = '600'
|
|
|
- if !File.exist?( self.get_locaton )
|
|
|
- puts "NOTICE: storge write '#{self.get_locaton}' (#{permission})"
|
|
|
- file = File.new( self.get_locaton, 'wb' )
|
|
|
- file.write( self.data )
|
|
|
- file.close
|
|
|
- end
|
|
|
- File.chmod( permission.to_i(8), self.get_locaton )
|
|
|
-
|
|
|
- # check md5
|
|
|
- md5 = Digest::MD5.hexdigest( self.read_from_fs )
|
|
|
- if md5 != self.md5
|
|
|
- raise "ERROR: Corrupt file in fs #{self.get_locaton}, md5 should be #{self.md5} but is #{md5}"
|
|
|
- end
|
|
|
-
|
|
|
- true
|
|
|
- end
|
|
|
-
|
|
|
- # write file to db
|
|
|
- def write_to_db
|
|
|
-
|
|
|
- # read and check md5
|
|
|
- content = self.read_from_fs
|
|
|
-
|
|
|
- # store in database
|
|
|
- self.data = content
|
|
|
- self.save
|
|
|
-
|
|
|
- # check md5 against db content
|
|
|
- md5 = Digest::MD5.hexdigest( self.data )
|
|
|
- if md5 != self.md5
|
|
|
- raise "ERROR: Corrupt file in db #{self.get_locaton}, md5 should be #{self.md5} but is #{md5}"
|
|
|
- end
|
|
|
-
|
|
|
- true
|
|
|
- end
|
|
|
-
|
|
|
- # check database data and md5, in case fix it
|
|
|
- def self.db_check_md5(fix_it = nil)
|
|
|
- Store::File.where( :file_system => false ).each {|item|
|
|
|
- md5 = Digest::MD5.hexdigest( item.data )
|
|
|
- if md5 != item.md5
|
|
|
- puts "DIFF: md5 diff of Store::File.find(#{item.id}) "
|
|
|
- if fix_it
|
|
|
- item.update_attribute( :md5, md5 )
|
|
|
- end
|
|
|
- end
|
|
|
- }
|
|
|
- true
|
|
|
- end
|
|
|
-
|
|
|
- def self.fs_check_md5(fix_it = nil)
|
|
|
- Store::File.where( :file_system => true ).each {|item|
|
|
|
- md5 = Digest::MD5.hexdigest( item.read_from_fs )
|
|
|
- if md5 != item.md5
|
|
|
- puts "DIFF: md5 diff of Store::File.find(#{item.id}) "
|
|
|
- if fix_it
|
|
|
- item.update_attribute( :md5, md5 )
|
|
|
- end
|
|
|
- end
|
|
|
- }
|
|
|
- true
|
|
|
- end
|
|
|
-
|
|
|
- def self.move_to_fs
|
|
|
- Store::File.where( :file_system => false ).each {|item|
|
|
|
- item.write_to_fs
|
|
|
- item.update_attribute( :file_system, true )
|
|
|
- item.update_attribute( :data, nil )
|
|
|
- }
|
|
|
- end
|
|
|
-
|
|
|
- def self.move_to_db
|
|
|
- Store::File.where( :file_system => true ).each {|item|
|
|
|
- item.write_to_db
|
|
|
- item.update_attribute( :file_system, false )
|
|
|
- item.unlink_location
|
|
|
- }
|
|
|
- end
|
|
|
-
|
|
|
- private
|
|
|
-
|
|
|
- def check_location
|
|
|
-
|
|
|
- # write initial to fs if needed
|
|
|
- if self.file_system && self.data
|
|
|
- self.write_to_fs
|
|
|
- self.data = nil
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
- def add_md5
|
|
|
- if self.data && !self.md5
|
|
|
- self.md5 = Digest::MD5.hexdigest( self.data )
|
|
|
+ def provider
|
|
|
+ file = Store::File.where( :id => self.store_file_id ).first
|
|
|
+ if !file
|
|
|
+ raise "No such file #{ self.store_file_id }!"
|
|
|
end
|
|
|
+ file.provider
|
|
|
end
|
|
|
end
|