2015-02-10 13:19:34 +00:00
# -*- coding: utf-8 -*-
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import os
SIZE_UNITS = {
" b " : 1 ,
" k " : 1024 ,
" M " : 1024 * * 2 ,
" G " : 1024 * * 3 ,
}
def convert_media_size ( size ) :
if isinstance ( size , str ) :
if size [ - 1 ] in SIZE_UNITS :
num = int ( size [ : - 1 ] )
units = size [ - 1 ]
else :
num = int ( size )
units = " b "
result = num * SIZE_UNITS [ units ]
else :
result = int ( size )
if result < = 0 :
raise ValueError ( " Media size must be a positive number: %s " % size )
return result
def convert_file_size ( size , block_size = 2048 ) :
""" round file size to block """
blocks = int ( size / block_size )
if size % block_size :
blocks + = 1
return blocks * block_size
class MediaSplitter ( object ) :
2016-01-26 12:02:53 +00:00
def __init__ ( self , media_size , compose = None ) :
2015-02-10 13:19:34 +00:00
self . media_size = convert_media_size ( media_size )
self . files = [ ] # to preserve order
self . file_sizes = { }
self . sticky_files = set ( )
2016-01-26 12:02:53 +00:00
self . compose = compose
2015-02-10 13:19:34 +00:00
def add_file ( self , name , size , sticky = False ) :
name = os . path . normpath ( name )
size = int ( size )
old_size = self . file_sizes . get ( name , None )
if old_size is None :
self . files . append ( name )
self . file_sizes [ name ] = size
elif old_size != size :
raise ValueError ( " File size mismatch; file: %s ; sizes: %s vs %s " % ( name , old_size , size ) )
elif size > self . media_size :
raise ValueError ( " File is larger than media size: %s " % name )
if sticky :
self . sticky_files . add ( name )
'''
def load ( self , file_name ) :
f = open ( file_name , " r " )
for line in f :
line = line . strip ( )
if not line :
continue
name , size = line . split ( " " )
self . add_file ( name , size )
f . close ( )
def scan ( self , pattern ) :
for i in glob . glob ( pattern ) :
self . add_file ( i , os . path . getsize ( i ) )
def dump ( self , file_name ) :
f = open ( file_name , " w " )
for name in self . files :
f . write ( " %s %s \n " % ( os . path . basename ( name ) , self . file_sizes [ name ] ) )
f . close ( )
'''
@property
def total_size ( self ) :
return sum ( self . file_sizes . values ( ) )
@property
def total_size_in_blocks ( self ) :
return sum ( [ convert_file_size ( i ) for i in list ( self . file_sizes . values ( ) ) ] )
def split ( self , first_disk = 0 , all_disks = 0 ) :
all_files = [ ]
sticky_files = [ ]
sticky_files_size = 0
for name in self . files :
if name in self . sticky_files :
sticky_files . append ( name )
sticky_files_size + = convert_file_size ( self . file_sizes [ name ] )
else :
all_files . append ( name )
disks = [ ]
disk = { }
2016-01-26 12:02:53 +00:00
total_size_single = sticky_files_size # as it would be on single medium (sticky_files just once)
2015-02-10 13:19:34 +00:00
while all_files :
name = all_files . pop ( 0 )
size = convert_file_size ( self . file_sizes [ name ] )
if not disks or disk [ " size " ] + size > self . media_size :
disk = { " size " : 0 , " files " : [ ] }
disks . append ( disk )
disk [ " files " ] . extend ( sticky_files )
disk [ " size " ] + = sticky_files_size
disk [ " files " ] . append ( name )
2016-01-26 12:02:53 +00:00
disk [ " size " ] + = size
total_size_single + = size
if self . compose :
self . compose . log_debug ( " MediaSplitter: free space on single media would be %s . Total size of single medium: %s . " % ( self . media_size - total_size_single , total_size_single ) )
2015-02-10 13:19:34 +00:00
return disks