Save to Disk: Do not run out memory when saving very large files on systems with low RAM. Fixes #990741 ("Out of memory" when saving to disk)

This commit is contained in:
Kovid Goyal 2012-04-29 09:18:51 +05:30
parent 658c2c7641
commit 42a13d1503

View File

@ -6,7 +6,7 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os, traceback, cStringIO, re import os, traceback, cStringIO, re, shutil
from calibre.constants import DEBUG from calibre.constants import DEBUG
from calibre.utils.config import Config, StringConfig, tweaks from calibre.utils.config import Config, StringConfig, tweaks
@ -19,6 +19,7 @@ from calibre.ebooks.metadata import fmt_sidx
from calibre.ebooks.metadata import title_sort from calibre.ebooks.metadata import title_sort
from calibre.utils.date import parse_date, as_local_time from calibre.utils.date import parse_date, as_local_time
from calibre import strftime, prints, sanitize_file_name_unicode from calibre import strftime, prints, sanitize_file_name_unicode
from calibre.ptempfile import SpooledTemporaryFile
plugboard_any_device_value = 'any device' plugboard_any_device_value = 'any device'
plugboard_any_format_value = 'any format' plugboard_any_format_value = 'any format'
@ -339,19 +340,16 @@ def do_save_book_to_disk(id_, mi, cover, plugboards,
for fmt in formats: for fmt in formats:
global plugboard_save_to_disk_value, plugboard_any_format_value global plugboard_save_to_disk_value, plugboard_any_format_value
cpb = find_plugboard(plugboard_save_to_disk_value, fmt, plugboards) cpb = find_plugboard(plugboard_save_to_disk_value, fmt, plugboards)
# Leave this here for a while, in case problems arise.
if cpb is not None:
prints('Save-to-disk using plugboard:', fmt, cpb)
fp = format_map.get(fmt, None) fp = format_map.get(fmt, None)
if fp is None: if fp is None:
continue continue
stream = SpooledTemporaryFile(20*1024*1024, '_save_to_disk.'+(fmt or
'tmp'))
with open(fp, 'rb') as f: with open(fp, 'rb') as f:
data = f.read() shutil.copyfileobj(f, stream)
stream.seek(0)
written = True written = True
if opts.update_metadata: if opts.update_metadata:
stream = cStringIO.StringIO()
stream.write(data)
stream.seek(0)
try: try:
if cpb: if cpb:
newmi = mi.deepcopy_metadata() newmi = mi.deepcopy_metadata()
@ -365,10 +363,9 @@ def do_save_book_to_disk(id_, mi, cover, plugboards,
if DEBUG: if DEBUG:
traceback.print_exc() traceback.print_exc()
stream.seek(0) stream.seek(0)
data = stream.read()
fmt_path = base_path+'.'+str(fmt) fmt_path = base_path+'.'+str(fmt)
with open(fmt_path, 'wb') as f: with open(fmt_path, 'wb') as f:
f.write(data) shutil.copyfileobj(stream, f)
return not written, id_, mi.title return not written, id_, mi.title