Class: Storazzo::RicDisk

Inherits:
Object
  • Object
show all
Extended by:
Colors, Common
Includes:
Common, Hashify
Defined in:
lib/storazzo/ric_disk.rb

Constant Summary collapse

ConfigFiles =

in order of finding, so the first will be the one we actually READ and use. I could looknat the date but cmon… These are the files I do accept.

%w[ricdisk.yaml .ricdisk storazzo.yaml].freeze
DefaultConfigFile =

.ricdisk }

'storazzo.yaml'
RicdiskVersion =
'2.1'
RicdiskHistory =
[
  '2022-07-29 2.1 Added timestamp',
  '2022-07-28 2.0 Added tags, siz, unique_hash, computation_hostname, wr, ...'
].freeze
DefaultGemfileTestDiskFolder =

was: @@default_gemfile_test_disks_folder

"#{Storazzo.root}/var/test/disks/"
DefaultMediaFolders =

Immutable

%w[
  /Volumes/
  /mnt/
].append(DefaultGemfileTestDiskFolder).append("/media/#{ENV['USER']}/")

Constants included from Colors

Colors::PREPEND_ME

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Common

bug, deb, err, fatal, if_deb?, linux?, mac?, ppp, pverbose, warn

Methods included from Colors

azure, blue, deb2, gray, green, orange, pgreen, pred, purple, pwhite, pyellow, red, white, yellow

Methods included from Hashify

#ivars_excluded_from_hash, #obj_to_hash, #obj_to_yaml, #to_hash, #to_yaml

Constructor Details

#initialize(ric_disk_object, opts = {}) ⇒ RicDisk

Returns a new instance of RicDisk.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/storazzo/ric_disk.rb', line 47

def initialize(ric_disk_object, opts = {})
  verbose = opts.fetch :verbose, true
  pverbose verbose,
           "This needs an object of type Storazzo::Media::AbstractRicDisk now (this case: #{ric_disk_object.class})"
  raise "Woopsie, not a Storazzo::Media::AbstractRicDisk! Intead its a #{ric_disk_object.class}" unless ric_disk_object.class.superclass == Storazzo::Media::AbstractRicDisk

  # ok back to business, now path is a String :)
  path = ric_disk_object.path
  deb "RicDisk initialize.. path=#{path}"
  deb "RicDisk initialize.. path=#{path}"
  @local_mountpoint = File.expand_path(path)
  @ard = ric_disk_object # AbstractRicDiskObject
  @description = "This is an automated RicDisk description from v.#{RicdiskVersion}. Created on #{Time.now}'"
  @ricdisk_version = RicdiskVersion
  @ricdisk_file = compute_ricdisk_file # Storazzo::RicDisk.get_ricdisk_file(path)
  @ricdisk_file_full = "#{@local_mountpoint}/#{@ricdisk_file}"
  @label = path.split('/').last
  @name = path.split('/').last
  # @wr = File.writable?("#{path}/#{ricdisk_file}" ) # .writeable?
  # @wr = writeable?
  @tags = %w[ricdisk storazzo]
  @size = RicDisk._compute_size_could_take_long(path)
  @unique_hash = "MD5::#{Digest::MD5.hexdigest(File.expand_path(path))}" #   hash = Digest::MD5.hexdigest(File.expand_path(get_local_mountpoint))
  @computation_hostname = Socket.gethostname
  @created_at = Time.now

  @ricdisk_file_empty = ricdisk_file_empty?

  # @config = RicDiskConfig.instance.get_config
  # #puts @config if @config
  # find_info_from_mount(path)
  deb "RicDisk initialize. to_s: #{self}"
  # find_info_from_df()
end

Instance Attribute Details

#active_dirsObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def active_dirs
  @active_dirs
end

#descriptionObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def description
  @description
end

#local_mountpointObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def local_mountpoint
  @local_mountpoint
end

#nameObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def name
  @name
end

#pathObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def path
  @path
end

#ricdisk_fileObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def ricdisk_file
  @ricdisk_file
end

#ricdisk_file_emptyObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def ricdisk_file_empty
  @ricdisk_file_empty
end

#ricdisk_file_fullObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def ricdisk_file_full
  @ricdisk_file_full
end

#ricdisk_versionObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def ricdisk_version
  @ricdisk_version
end

#sizeObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def size
  @size
end

#unique_hashObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def unique_hash
  @unique_hash
end

#wrObject

# todo substitute with protobuf..



35
36
37
# File 'lib/storazzo/ric_disk.rb', line 35

def wr
  @wr
end

Class Method Details

._compute_size_could_take_long(my_path) ⇒ Object

could take long.. def size

`du -s '#{path}'`.split(/\s/)[0]

end



112
113
114
115
116
# File 'lib/storazzo/ric_disk.rb', line 112

def self._compute_size_could_take_long(my_path)
  deb 'Could take long. TODO(ricc): add some sort of cutoff/timeout to 5 seconds.'
  puts azure('could take long. Please take precautions like forking with timeout of 5sec')
  `du -s '#{my_path}' 2>/dev/null`.chomp.split(/\s/)[0] # self.size
end

.calculate_stats_files_DUPLICATE_STATIC(_dir, _opts = {}) ⇒ Object



396
397
398
# File 'lib/storazzo/ric_disk.rb', line 396

def self.calculate_stats_files_DUPLICATE_STATIC(_dir, _opts = {})
  raise 'Please use object instead. If you cant, please move the object code to STATIC and dedupe code!'
end

.compute_stats_for_dir_into_file(dir, full_file_path, reason, opts = {}) ⇒ Object



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/storazzo/ric_disk.rb', line 374

def self.compute_stats_for_dir_into_file(dir, full_file_path, reason, opts = {})
  max_lines = opts.fetch :max_lines, 42 # TODO: move to nil or -1
  # full_file_path = "#{dir}/#{stats_file}"
  puts "Crunching data stats from '#{dir}' into '#{full_file_path}' ... please bear with me.. [reason: '#{reason}']"
  if max_lines.negative? # infinite
    command = "find . -print0 | xargs -0 stats-with-md5 --no-color | tee '#{full_file_path}'"
  elsif mac?
    # WOW! https://stackoverflow.com/questions/68599963/reliably-stop-bash-find-after-n-matches
    # find . -type f -iname "*.txt" -print0 |
    # head -z -n 10 |
    # xargs -r0 myscript.sh
    puts red('Sorry head -z doesnt work on Mac :/ so this head -N will be VERY approximate. Probably you should divide by ten or so :)')
    spannometric_lines = (max_lines / 10)
    command = "find . -print0 | head -n '#{spannometric_lines}' | xargs -r0 stats-with-md5 --no-color | tee '#{full_file_path}'"
  else
    command = "find . -print0 | head -z -n '#{max_lines}' | xargs -r0 stats-with-md5 --no-color | tee '#{full_file_path}'"
  end
  puts("[#{`pwd`.chomp}] Executing: #{azure command}")
  ret = backquote_execute(command)
  puts "Done. #{ret.split("\n").count} files processed."
end

.default_media_foldersObject

All places where to find for something :)



155
156
157
# File 'lib/storazzo/ric_disk.rb', line 155

def self.default_media_folders
  DefaultMediaFolders # was DEFAULT_MEDIA_FOLDERS
end

.find_active_dirs(base_dirs = nil, _also_mountpoints = true) ⇒ Object



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/storazzo/ric_disk.rb', line 172

def self.find_active_dirs(base_dirs = nil, _also_mountpoints = true)
  if base_dirs.nil?
    base_dirs = default_media_folders
    puts "find_active_dirs with empty input -> using default_media_folders: #{yellow default_media_folders}"
  end
  active_dirs = []
  base_dirs.each do |ugly_dir|
    # https://stackoverflow.com/questions/1899072/getting-a-list-of-folders-in-a-directory#:~:text=Dir.chdir(%27/destination_directory%27)%0ADir.glob(%27*%27).select%20%7B%7Cf%7C%20File.directory%3F%20f%7D
    dir = File.expand_path(ugly_dir)
    begin
      x = []
      #        puts "TEST2 DIR EXISTS: #{dir} -> #{Dir.exists?(dir)}"
      unless Dir.exist?(dir)
        deb "Dir doesnt exist, skipping: #{dir}"
        next
      end
      Dir.chdir(dir)
      x = Dir.glob('*').select { |f| File.directory? f }
      subdirs = x.map { |subdir| "#{dir}#{subdir}" }
      subdirs.each do |subdir|
        deb "Subdir: #{subdir}"
        puts `ls -al "#{subdir}"` # TODO: refactor in exec
        active_dirs << subdir if ok_dir? # self.ok_dir?(subdir)
      end
      # puts(white x)
    rescue Exception => e # optionally: `rescue Exception => ex`
      puts "Exception: '#{e}'"
      # will always get executed
      # deb 'Always gets executed.'
      # x = []
    end
  end
end

.interesting_mount_points(_opts = {}) ⇒ Object

# new def self.get_ricdisk_file_obsolete(path)

if @ricdisk_file
  puts "[CACHE HIT] ricdisk_file"
  return @ricdisk_file
end
puts "RICC_WARNING This requires cmputation I wanna do it almost once"
ConfigFiles.each do |papable_config_filename|
  #return ".ricdisk.yaml" if File.exist?("#{path}/.ricdisk.yaml") #and File.empty?( "#{path}/.ricdisk.yaml")
  #return ".ricdisk" if File.exist?("#{path}/.ricdisk") # and File.empty?( "#{path}/.ricdisk")
  return papable_config_filename if File.exist?("#{path}/#{papable_config_filename}") # and File.empty?( "#{path}/.ricdisk")
end
return nil

end



251
252
253
254
# File 'lib/storazzo/ric_disk.rb', line 251

def self.interesting_mount_points(_opts = {})
  # https://unix.stackexchange.com/questions/177014/showing-only-interesting-mount-points-filtering-non-interesting-types
  `mount | grep -Ev 'type (proc|sysfs|tmpfs|devpts|debugfs|rpc_pipefs|nfsd|securityfs|fusectl|devtmpfs) '`.split(/\n+/)
end

.ok_dir?(subdir) ⇒ Boolean

TODO: obsolete this as i should NOT be calling it from clas, but from method.

Returns:

  • (Boolean)


327
328
329
# File 'lib/storazzo/ric_disk.rb', line 327

def self.ok_dir?(subdir)
  File.exist?("#{subdir}/.ricdisk") or File.exist?("#{subdir}/.ricdisk.yaml")
end

.testObject

_localgem_disks



160
161
162
163
164
165
# File 'lib/storazzo/ric_disk.rb', line 160

def self.test
  d = RicDisk.new(DefaultGemfileTestDiskFolder)
  puts(d)
  puts "do something with it: #{d}"
  # d.find_active_dirs()
end

Instance Method Details

#absolute_pathObject



167
168
169
170
# File 'lib/storazzo/ric_disk.rb', line 167

def absolute_path
  # @local_mountpoint + "/" +  @ricdisk_file
  "#{local_mountpoint}/#{ricdisk_file}"
end

#analyze_local_systemObject



92
93
94
95
96
97
98
# File 'lib/storazzo/ric_disk.rb', line 92

def analyze_local_system
  puts 'TODO This should analyzze the WHOLE system. TODO(ricc): move to another object which has to do with the system/computer.'
  puts "1. Interesting Mounts: #{green interesting_mount_points}"
  puts '2. Sbrodoling everything: :TODO'
  # find_info_from_mount(path)
  # find_info_from_df()
end

#compute_ricdisk_fileObject



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/storazzo/ric_disk.rb', line 206

def compute_ricdisk_file
  unless @ricdisk_file.nil?
    deb '[CACHE HIT] ricdisk_file (didnt have to recompute it - yay!)'
    return @ricdisk_file
  end
  deb '[compute_ricdisk_file] RICC_WARNING This requires cmputation I wanna do it almost once'
  ConfigFiles.each do |papable_config_filename|
    # return ".ricdisk.yaml" if File.exist?("#{path}/.ricdisk.yaml") #and File.empty?( "#{path}/.ricdisk.yaml")
    # return ".ricdisk" if File.exist?("#{path}/.ricdisk") # and File.empty?( "#{path}/.ricdisk")
    return papable_config_filename if File.exist?("#{path}/#{papable_config_filename}")
  end
  deb "File not found! Neither #{ConfigFiles} exist.."
  #      return nil
  DefaultConfigFile
end

#compute_stats_files(opts = {}) ⇒ Object



331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/storazzo/ric_disk.rb', line 331

def compute_stats_files(opts = {})
  # Storazzo::RicDisk.calculate_stats_files(path, opts)
  opts_upload_to_gcs = opts.fetch :upload_to_gcs, false
  opts_force_rewrite = opts.fetch :force, false
  opts_stats_file    = opts.fetch :stats_file, 'ricdisk_stats_v11.rds' # default. TODO point to proper..
  dir = path
  puts azure("[compute_stats_files] TODO implement natively. Now I'm being lazy. stats_file=#{opts_stats_file} dir=#{dir}")

  full_file_path = "#{dir}/#{opts_stats_file}"
  deb 'This refactor is for another day. Actually no, TODAY '
  pverbose true,
           "TODO(ricc): you should compute more SMARTLY the full_file_path (#{full_file_path}): if its R/O it should be elsewhere.."
  puts azure("- full_file_path: #{full_file_path}")
  puts azure("- writeable?: #{writeable?}")

  puts("compute_stats_files(#{white dir}): #{white full_file_path}")
  deb "TEST1 DIR EXISTS: #{dir} -> #{File.directory? dir}"
  raise "Directory doesnt exist: #{dir}" unless File.directory?(dir)

  Dir.chdir(dir)
  puts azure `ls` # im curious
  if File.exist?(full_file_path)
    if opts_force_rewrite
      # raise "TODO implement file exists and FORCE enabled"
      RicDisk.compute_stats_for_dir_into_file(dir, full_file_path, 'ReWrite enabled')
    else # File.exists?(full_file_path) and (opts_force)
      puts "File '#{opts_stats_file}' exists already." #  - now should see if its too old, like more than 1 week old"
      # TODO check for file time...
      print "Lines found: #{yellow `wc -l "#{full_file_path}" `.chomp}. File obsolescence (days): #{yellow obsolescence_days(full_file_path)}."
      if obsolescence_days(full_file_path) > 7
        # puts yellow("*** ACHTUNG *** FIle is pretty old. You might consider rotating: #{yellow "mv #{full_file_path} #{full_file_path}_old"}. Or invoke with --force")
        puts yellow("*** ACHTUNG *** FIle is pretty old. I'll force a rewrite")
        RicDisk.compute_stats_for_dir_into_file(dir, full_file_path,
                                                "File older than 7 days. Indeed: #{obsolescence_days(full_file_path)}")
      end
      upload_to_gcs(full_file_path) if opts_upload_to_gcs
    end
  else
    deb('File doesnt exist..')
    RicDisk.compute_stats_for_dir_into_file(dir, full_file_path, "ConfigFile doesn't exist")
  end
end

#initialize_old_way(_path, _opts = {}) ⇒ Object

INSTANCE methods



43
44
45
# File 'lib/storazzo/ric_disk.rb', line 43

def initialize_old_way(_path, _opts = {})
  raise 'Now I dont want a string in input, I want an OBJECT <  Storazzo::Media::AbstractRicDisk'
end

#obsolescence_days(file_path) ⇒ Object

maybe move to a RiccFile class? Maybe even INHERIT from FILE?



264
265
266
# File 'lib/storazzo/ric_disk.rb', line 264

def obsolescence_days(file_path)
  obsolescence_seconds(file_path) / 86_400
end

#obsolescence_seconds(file_path) ⇒ Object

maybe move to a RiccFile class? Maybe even INHERIT from FILE?



257
258
259
260
261
# File 'lib/storazzo/ric_disk.rb', line 257

def obsolescence_seconds(file_path)
  creation_time = File.stat(file_path).ctime
  deb("[obsolescence_seconds] File #{file_path}: #{creation_time} - #{Time.now - creation_time} seconds ago")
  (Time.now - creation_time).to_i
end

#ok_dir?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/storazzo/ric_disk.rb', line 88

def ok_dir?
  !ricdisk_file.nil?
end

#ricdisk_file_empty?Boolean

Returns:

  • (Boolean)


82
83
84
85
86
# File 'lib/storazzo/ric_disk.rb', line 82

def ricdisk_file_empty?
  #      File.empty?("#{local_mountpoint}/.ricdisk.yaml")
  puts "compute_ricdisk_file: #{compute_ricdisk_file}"
  File.empty?(compute_ricdisk_file.to_s) # was (get_ricdisk_file)
end

#to_sObject



104
105
106
# File 'lib/storazzo/ric_disk.rb', line 104

def to_s
  "RicDisk(paz=#{path}, r/w=#{writeable?}, size=#{size}B, f=#{ricdisk_file}, v#{ricdisk_version}, ard=#{@ard})"
end

#to_verbose_sObject



140
141
142
143
144
145
146
147
148
# File 'lib/storazzo/ric_disk.rb', line 140

def to_verbose_s
  h = {}
  h[:to_s] = to_s
  h[:wr] = wr
  h[:inspect] = inspect
  h[:writeable] = writeable?
  h[:ard] = @ard
  h
end

#write_config_yaml_to_disk(subdir, _opts = {}) ⇒ Object

FORMER SBRODOLA, now write_config_yaml_to_disk def self.write_config_yaml_to_disk(subdir, opts={}) # sbrodola_ricdisk(subdir) sbrodola_ricdisk(subdir)



271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/storazzo/ric_disk.rb', line 271

def write_config_yaml_to_disk(subdir, _opts = {})
  # given a path, if .ricdisk exists i do stuff with it..
  disk_info = nil
  unless ok_dir? # self.ok_dir?(subdir)
    warn("[write_config_yaml_to_disk] Nothing for me here: '#{subdir}'. Existing")
    return
  end
  ConfigFiles.each do |papable_configfile_name|
    if File.exist?("#{subdir}/#{papable_configfile_name}") && File.empty?("#{subdir}/#{papable_configfile_name}")
      deb("Interesting. Empty file '#{papable_configfile_name}'! Now I write YAML with it.")
      disk_info = RicDisk.new(subdir, papable_configfile_name)
    end
  end
  # if File.exists?( "#{subdir}/.ricdisk") and File.empty?( "#{subdir}/.ricdisk")
  #   deb("Interesting1. Empty file! Now I write YAML with it.")
  #   disk_info = RicDisk.new(subdir, '.ricdisk')
  # end
  # if File.exists?( "#{subdir}/.ricdisk.yaml") and File.empty?( "#{subdir}/.ricdisk.yaml")
  #   deb("Interesting2. Empty file! TODO write YAML with it.")
  #   disk_info = RicDisk.new(subdir, '.ricdisk.yaml')
  #   puts(yellow disk_info.to_yaml)
  # end
  if disk_info.is_a?(RicDisk)
    deb yellow("disk_info.class: #{disk_info.class}")
    if File.empty?(disk_info.absolute_path) # and (disk_info.wr)
      puts(green("yay, we can now write the file '#{disk_info.absolute_path}' (which is R/W, I just checked!) with proper YAML content.."))
      if disk_info.wr
        ret = File.write(disk_info.absolute_path, disk_info.obj_to_yaml)
        puts green("Written file! ret=#{ret}")
      else
        raise 'TODO_IMPLEMENT: write in proper place in config dir'
        puts red('TODO implement me')
      end
    else
      puts(red("Something not right here: either file is NOT empty or disk is NOT writeable.. #{File.empty?(disk_info.absolute_path)}"))
      puts("File size: #{File.size(disk_info.absolute_path)}")
      puts(disk_info.to_s)
      puts(disk_info.obj_to_hash)
      puts(disk_info.obj_to_yaml)
    end
  else # not a RicDisk..
    puts "[write_config_yaml_to_disk] No DiskInfo found across #{ConfigFiles}. I leave this function empty-handed."
  end

  # disk_info.absolute_path
  # if File.exists?( "#{subdir}/.ricdisk") and ! File.empty?( "#{subdir}/.ricdisk")
  # if File.exists?(disk_info.absolute_path) and ! File.empty?(disk_info.absolute_path)
  #   puts("Config File found with old-style name: '#{subdir}/.ricdisk' ! Please move it to .ricdisk.yaml!")
  #   puts(white `cat "#{disk_info.absolute_path}"`)
  # else
  #   puts "WRITING NOW. [I BELIEVE THIS IS DUPE CODE - see a few lines above!] disk_info.obj_to_yaml .. to #{compute_ricdisk_file}"
  #   File.open(ricdisk_file_full, 'w').write(disk_info.obj_to_yaml)
  # end
end

#writeable?Boolean

Returns:

  • (Boolean)


118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/storazzo/ric_disk.rb', line 118

def writeable?
  # memoize
  return @wr unless @wr.nil?

  # NOW: CALCULATE it
  # Now I can do ONCE an EXPENSIVE calculation
  puts yellow("[RicDisk.writeable] TODO(ricc): Do expensive calculation if this FS is writeable: #{path} and write/memoize it on @wr once and for all")
  puts yellow('[RicDisk.writeable]             I have a feeling this should be delegated to praecipuus Storazzo::Media::Object we refer to (WR is different on GCS vs Local):') # infinite loop dammit #{self.to_verbose_s}")
  puts("Dir: #{azure path}")
  puts("absolute_path: #{azure absolute_path}")
  puts("File.writable?(absolute_path): #{azure File.writable?(absolute_path)}")
  bash_output = `if [ -w "#{absolute_path}" ]; then echo "WRITABLE"; else echo "NOT WRITABLE"; fi`
  puts("bash_output: #{azure bash_output}")
  # @wr = File.writable?(File.expand_path(@ricdisk_file)) # rescue false
  raise "for some reason an important info (ricdisk_file='#{absolute_path}') is missing!" if ricdisk_file.nil?

  @wr = File.writable?(absolute_path) # rescue false
  @wr
  # :boh_todo_fix_me_and_compute
  # false
end