Handle failure of statfs to return available disc space on Samba shares mounted via GVFS, reporting available space as unknown in this case (#4657).

git-svn-id: svn://localhost/ardour2/branches/3.0@12674 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2012-06-12 16:41:29 +00:00
parent d1d08e3910
commit 92432f3e80
5 changed files with 70 additions and 17 deletions

View File

@ -1050,16 +1050,21 @@ ARDOUR_UI::update_disk_space()
return;
}
framecnt_t frames = _session->available_capture_duration();
boost::optional<framecnt_t> opt_frames = _session->available_capture_duration();
char buf[64];
framecnt_t fr = _session->frame_rate();
if (frames == max_framecnt) {
if (!opt_frames) {
/* Available space is unknown */
snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">Unknown</span>"));
} else if (opt_frames.get_value_or (0) == max_framecnt) {
snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">24hrs+</span>"));
} else {
rec_enabled_streams = 0;
_session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
framecnt_t frames = opt_frames.get_value_or (0);
if (rec_enabled_streams) {
frames /= rec_enabled_streams;
}

View File

@ -669,7 +669,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
/* s/w "RAID" management */
framecnt_t available_capture_duration();
boost::optional<framecnt_t> available_capture_duration();
/* I/O bundles */
@ -1329,16 +1329,21 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
/* S/W RAID */
struct space_and_path {
uint32_t blocks; /* 4kB blocks */
uint32_t blocks; ///< 4kB blocks
bool blocks_unknown; ///< true if blocks is unknown
std::string path;
space_and_path() {
blocks = 0;
}
space_and_path ()
: blocks (0)
, blocks_unknown (true)
{}
};
struct space_and_path_ascending_cmp {
bool operator() (space_and_path a, space_and_path b) {
if (a.blocks_unknown != b.blocks_unknown) {
return !a.blocks_unknown;
}
return a.blocks > b.blocks;
}
};
@ -1348,6 +1353,11 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
std::vector<space_and_path> session_dirs;
std::vector<space_and_path>::iterator last_rr_session_dir;
uint32_t _total_free_4k_blocks;
/** If this is true, _total_free_4k_blocks is not definite,
as one or more of the session directories' filesystems
could not report free space.
*/
bool _total_free_4k_blocks_uncertain;
Glib::Mutex space_lock;
bool no_questions_about_missing_files;

View File

@ -143,6 +143,7 @@ Session::Session (AudioEngine &eng,
, _all_route_group (new RouteGroup (*this, "all"))
, routes (new RouteList)
, _total_free_4k_blocks (0)
, _total_free_4k_blocks_uncertain (false)
, _bundles (new BundleList)
, _bundle_xml_node (0)
, _current_trans (0)
@ -3501,9 +3502,16 @@ Session::graph_reordered ()
}
}
framecnt_t
/** @return Number of frames that there is disk space available to write,
* if known.
*/
boost::optional<framecnt_t>
Session::available_capture_duration ()
{
if (_total_free_4k_blocks_uncertain) {
return boost::optional<framecnt_t> ();
}
float sample_bytes_on_disk = 4.0; // keep gcc happy
switch (config.get_native_file_data_format()) {

View File

@ -46,6 +46,10 @@
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
#include <glib.h>
#include <glibmm.h>
@ -2079,23 +2083,48 @@ Session::save_template (string template_name)
void
Session::refresh_disk_space ()
{
#if HAVE_SYS_VFS_H
struct statfs statfsbuf;
vector<space_and_path>::iterator i;
#if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H
Glib::Mutex::Lock lm (space_lock);
double scale;
/* get freespace on every FS that is part of the session path */
_total_free_4k_blocks = 0;
_total_free_4k_blocks_uncertain = false;
for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
statfs ((*i).path.c_str(), &statfsbuf);
for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
scale = statfsbuf.f_bsize/4096.0;
struct statfs statfsbuf;
statfs (i->path.c_str(), &statfsbuf);
(*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
_total_free_4k_blocks += (*i).blocks;
double const scale = statfsbuf.f_bsize / 4096.0;
/* See if this filesystem is read-only */
struct statvfs statvfsbuf;
statvfs (i->path.c_str(), &statvfsbuf);
/* f_bavail can be 0 if it is undefined for whatever
filesystem we are looking at; Samba shares mounted
via GVFS are an example of this.
*/
if (statfsbuf.f_bavail == 0) {
/* block count unknown */
i->blocks = 0;
i->blocks_unknown = true;
} else if (statvfsbuf.f_flag & ST_RDONLY) {
/* read-only filesystem */
i->blocks = 0;
i->blocks_unknown = false;
} else {
/* read/write filesystem with known space */
i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
i->blocks_unknown = false;
}
_total_free_4k_blocks += i->blocks;
if (i->blocks_unknown) {
_total_free_4k_blocks_uncertain = true;
}
}
#endif
}

View File

@ -289,6 +289,7 @@ def configure(conf):
conf.define('CURRENT_SESSION_FILE_VERSION', CURRENT_SESSION_FILE_VERSION)
conf.check(header_name='sys/vfs.h', define_name='HAVE_SYS_VFS_H',mandatory=False)
conf.check(header_name='sys/statvfs.h', define_name='HAVE_SYS_STATVFS_H',mandatory=False)
conf.check(header_name='jack/session.h', uselib = [ 'JACK' ],
define_name='HAVE_JACK_SESSION')