Permalink
Browse files

o add infrastructure to provide Stat() output of currently open

  files. (Actual estimation not implemented).
o work around fuse that doesn't call fgetattr on fstat(), only
  getattr; needed a mapping to currently open files.
  • Loading branch information...
1 parent f11d8cd commit 9a8ea565d7a15256952b88789e8591fde47f5140 @hzeller committed Sep 12, 2012
Showing with 69 additions and 26 deletions.
  1. +47 −7 convolver.cc
  2. +7 −2 filter-interface.h
  3. +15 −17 fuse-convolve.c
View
@@ -13,15 +13,18 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
+#include <FLAC/metadata.h>
#include <errno.h>
#include <sndfile.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
-#include <FLAC/metadata.h>
#include <string>
+#include <map>
#include "filter-interface.h"
#include "conversion-buffer.h"
@@ -34,6 +37,7 @@ class FileFilter : public filter_object_t {
public:
// Returns bytes read or a negative value indicating a negative errno.
virtual int Read(char *buf, size_t size, off_t offset) = 0;
+ virtual int Stat(struct stat *st) = 0;
virtual int Close() = 0;
virtual ~FileFilter() {}
};
@@ -50,7 +54,10 @@ class PassThroughFilter : public FileFilter {
const int result = pread(filedes_, buf, size, offset);
return result == -1 ? -errno : result;
}
-
+
+ virtual int Stat(struct stat *st) {
+ return fstat(filedes_, st);
+ }
virtual int Close() {
return close(filedes_) == -1 ? -errno : 0;
}
@@ -116,6 +123,12 @@ class SndFileFilter :
return output_buffer_->Read(buf, size, offset);
}
+ virtual int Stat(struct stat *st) {
+ fstat(filedes_, st);
+ // TODO(hzeller): calculate estimated size.
+ return 0;
+ }
+
virtual int Close() {
output_buffer_->set_sndfile_writes_enabled(false);
if (snd_in_) sf_close(snd_in_);
@@ -340,24 +353,51 @@ class SndFileFilter :
};
} // namespace
-// Implementation of the C functions in filter-interface.h
-struct filter_object_t *create_filter(int filedes, const char *path) {
- FileFilter *filter = SndFileFilter::Create(filedes, path);
+// TODO(hzeller): add mutex.
+typedef std::map<std::string, FileFilter*> FileFilterMap;
+static FileFilterMap open_files_;
+
+static FileFilter *CreateFilterFromFileType(int filedes,
+ const char *underlying_file) {
+ FileFilter *filter = SndFileFilter::Create(filedes, underlying_file);
if (filter != NULL) return filter;
fprintf(stderr, "Cound't create filtered output\n");
// Every other file-type is just passed through as is.
- return new PassThroughFilter(filedes, path);
+ return new PassThroughFilter(filedes, underlying_file);
+}
+
+// Implementation of the C functions in filter-interface.h
+struct filter_object_t *create_filter(int filedes, const char *fs_path,
+ const char *underlying_path) {
+ FileFilter *filter = CreateFilterFromFileType(filedes, underlying_path);
+ open_files_[fs_path] = filter;
+ return filter;
}
int read_from_filter(struct filter_object_t *filter,
char *buf, size_t size, off_t offset) {
return reinterpret_cast<FileFilter*>(filter)->Read(buf, size, offset);
}
-int close_filter(struct filter_object_t *filter) {
+int fill_stat_by_filename(const char *fs_path, struct stat *st) {
+ // TODO(hzeller): mutex needed.
+ FileFilterMap::const_iterator found = open_files_.find(fs_path);
+ if (found == open_files_.end())
+ return -1;
+ return found->second->Stat(st);
+}
+int fill_fstat_file(struct filter_object_t *filter, struct stat *st) {
+ return reinterpret_cast<FileFilter*>(filter)->Stat(st);
+}
+
+int close_filter(const char *fs_path, struct filter_object_t *filter) {
FileFilter *file_filter = reinterpret_cast<FileFilter*>(filter);
int result = file_filter->Close();
+ FileFilterMap::iterator found = open_files_.find(fs_path);
+ if (found != open_files_.end() && found->second == file_filter) {
+ open_files_.erase(found);
+ }
delete file_filter;
return result;
}
View
@@ -29,16 +29,21 @@ void initialize_convolver_filter(const char *zita_config);
// Create a new filter given the open filedescriptor and the path. Returns
// that filter in an opaque filter_object_t*
-struct filter_object_t *create_filter(int filedes, const char *orig_path);
+struct filter_object_t *create_filter(int filedes, const char *fs_path,
+ const char *underlying_path);
// Read from the given filter at the file-offset "offset, up to "size" bytes
// into "buffer". Returns number of bytes read or a negative errno value.
int read_from_filter(struct filter_object_t *filter,
char *buffer, size_t size, off_t offset);
+// Return dynamic size of file.
+int fill_fstat_file(struct filter_object_t *filter, struct stat *st);
+int fill_stat_by_filename(const char *fs_path, struct stat *st);
+
// At the end of the operation, close filter. Return 0 on success or negative
// errno value on failure.
-int close_filter(struct filter_object_t *filter);
+int close_filter(const char *path, struct filter_object_t *filter);
#ifdef __cplusplus
} // extern "C"
View
@@ -72,24 +72,16 @@ static const char *assemble_orig_path(char *buf, const char *path) {
// Essentially lstat(). Just forward to the original filesystem (this
// will by lying: our convolved files are of different size...)
static int fuseconv_getattr(const char *path, struct stat *stbuf) {
+ // If this is a currently open filename, we might be able to output a better
+ // estimate.
+ int result = fill_stat_by_filename(path, stbuf);
+ if (result == 0) return result;
+
char path_buf[PATH_MAX];
- int result = lstat(assemble_orig_path(path_buf, path), stbuf);
+ result = lstat(assemble_orig_path(path_buf, path), stbuf);
if (result == -1)
return -errno;
- // The resulting flac file will be bigger, but some programs seem to
- // estimate size from input size. Lets exaggerate here :)
- //
- // Interestingly, some programs that rely dynamic size, seem to do stat
- // all the time. We could probably feed back a
- // max(stbuf->st_size, conversion_buffer->Tell()) in here to give them
- // a more accurate estimate.
- if (has_suffix_string(path, ".ogg.fuse.flac")) {
- stbuf->st_size *= 10;
- } else if (has_suffix_string(path, ".flac")) {
- stbuf->st_size *= 2; // Conservative.
- }
-
return 0;
}
@@ -154,7 +146,7 @@ static int fuseconv_open(const char *path, struct fuse_file_info *fi) {
// The file-handle has the neat property to be 64 bit - so we can actually
// store a pointer to our filter object in there :)
// (Yay, someone was thinking while developing that API).
- fi->fh = (uint64_t) create_filter(fd, orig_path);
+ fi->fh = (uint64_t) create_filter(fd, path, orig_path);
return 0;
}
@@ -166,7 +158,12 @@ static int fuseconv_read(const char *path, char *buf, size_t size, off_t offset,
static int fuseconv_release(const char *path, struct fuse_file_info *fi) {
fprintf(stderr, "===== close('%s') ==]\n", path);
- return close_filter((struct filter_object_t*) fi->fh);
+ return close_filter(path, (struct filter_object_t*) fi->fh);
+}
+
+static int fuseconv_fgetattr(const char *path, struct stat *result,
+ struct fuse_file_info *fi) {
+ return fill_fstat_file((struct filter_object_t*) fi->fh, result);
}
static struct fuse_operations fuseconv_operations = {
@@ -179,8 +176,9 @@ static struct fuse_operations fuseconv_operations = {
.open = fuseconv_open,
.release = fuseconv_release,
- // Actual workhorse: reading a file.
+ // Actual workhorse: reading a file and returning predicted file-size
.read = fuseconv_read,
+ .fgetattr = fuseconv_fgetattr,
};
static int usage(const char *prog) {

0 comments on commit 9a8ea56

Please sign in to comment.