require "aruba/file_size" module Aruba module Platforms # Determinate disk usage # # @private class DetermineDiskUsage def call(paths) size = paths.flatten.sum { |path| minimum_disk_space_used path } FileSize.new(size) end private # TODO: Aruba.config.physical_block_size could be allowed to be nil # (So the unit size can be autodetected) # Report minimum disk space used # # This estimates the minimum bytes allocated by the path. # # E.g. a 1-byte text file on a typical EXT-3 filesystem takes up 4096 bytes # (could be more if it was truncated or less for sparse files). # # Both `File::Stat` and the `stat()` system call will report 8 `blocks` # (each "usually" represents 512 bytes). So 8 * 512 is exactly 4096 bytes. # # (The "magic" 512 bye implied makes the value of "blocks" so confusing). # # Currently Aruba allows you to set what's called the `physical_block_size`, # which is a bit misleading - it's the "512" value. So if you somehow have a # "filesystem unit size" of 8192 (instead of a typical 4KB), set the # `physical_block_size` to 1024 (yes, divide by 8: 8192/8 = 1024). # # Ideally, Aruba should provide e.g. `Aruba.config.fs_allocation_unit` # (with 4096 as the default), so you wouldn't have to "divide by 8". # # (typical_fs_unit / typical_dev_bsize = 4096 / 512 = 8) # # # @return [Integer] # Total bytes allocate # # TODO: this is recommended over the above "blocks" def minimum_disk_space_used(path) # TODO: replace Aruba.config.physical_block_size # with something like Aruba.config.fs_allocation_unit dev_bsize = Aruba.config.physical_block_size stat = File::Stat.new(path.to_s) blocks = stat.blocks return (blocks * dev_bsize) if blocks typical_fs_unit = 4096 typical_dev_bsize = 512 # google dev_bsize for more info block_multiplier = typical_fs_unit / typical_dev_bsize fs_unit_size = dev_bsize * block_multiplier fs_units = (stat.size + fs_unit_size - 1) / fs_unit_size fs_units = 1 if fs_units.zero? fs_units * fs_unit_size end end end end