Permalink
Browse files

o Provide a way to select between different filter diretories.

  - The option -c can be supplied multiple times.
  - The HTTP server provides a drop-down list to select the filter from.
  • Loading branch information...
1 parent 06a0312 commit ee675fea3dd24b1549429a9683a5a2bf5cebd0ab @hzeller committed Sep 18, 2012
Showing with 221 additions and 97 deletions.
  1. +6 −0 file-handler.h
  2. +87 −28 folve-filesystem.cc
  3. +39 −14 folve-filesystem.h
  4. +38 −47 folve-main.cc
  5. +44 −7 status-server.cc
  6. +7 −1 status-server.h
View
@@ -41,14 +41,20 @@ struct HandlerStats {
// fuse filesystem (see file-handler-cache.h for rationale)
class FileHandler {
public:
+ explicit FileHandler(int filter_id) : filter_id_(filter_id) {}
virtual ~FileHandler() {}
+ int filter_id() const { return filter_id_; }
+
// 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;
// Get handler status.
virtual void GetHandlerStatus(struct HandlerStats *s) = 0;
+
+private:
+ const int filter_id_;
};
#endif // FOLVE_FILE_HANDLER_H
View
@@ -50,8 +50,9 @@ namespace {
// everything that is not a sound-file.
class PassThroughFilter : public FileHandler {
public:
- PassThroughFilter(int filedes, const HandlerStats &known_stats)
- : filedes_(filedes), info_stats_(known_stats) {
+ PassThroughFilter(int filedes, int filter_id,
+ const HandlerStats &known_stats)
+ : FileHandler(filter_id), filedes_(filedes), info_stats_(known_stats) {
info_stats_.message.append("; pass through.");
LOGF(stderr, "Creating PassThrough filter for '%s'\n",
known_stats.filename.c_str());
@@ -85,6 +86,7 @@ class SndFileHandler :
// error message.
static FileHandler *Create(int filedes, const char *fs_path,
const char *underlying_file,
+ int filter_id,
const std::string &zita_config_dir,
HandlerStats *partial_file_info) {
SF_INFO in_info;
@@ -105,22 +107,22 @@ class SndFileHandler :
in_info.samplerate / 1000.0, bits);
partial_file_info->duration_seconds = in_info.frames / in_info.samplerate;
- std::string config_name;
- Appendf(&config_name, "filter-%d-%d-%d.conf", in_info.samplerate,
- bits, in_info.channels);
- const std::string config_path = zita_config_dir + "/" + config_name;
+ std::string config_path;
+ Appendf(&config_path, "%s/filter-%d-%d-%d.conf", zita_config_dir.c_str(),
+ in_info.samplerate, bits, in_info.channels);
const bool found_config = (access(config_path.c_str(), R_OK) == 0);
if (found_config) {
LOGF(stderr, "File %s: filter config %s\n", underlying_file,
config_path.c_str());
} else {
LOG_ERROR(stderr, "File %s: couldn't find filter config %s\n",
underlying_file, config_path.c_str());
- partial_file_info->message = "Missing [" + config_name + "]";
+ partial_file_info->message = "Missing [" + config_path + "]";
sf_close(snd);
return NULL;
}
- return new SndFileHandler(fs_path, underlying_file, filedes, snd, in_info,
+ return new SndFileHandler(fs_path, filter_id,
+ underlying_file, filedes, snd, in_info,
*partial_file_info, config_path);
}
@@ -191,11 +193,13 @@ class SndFileHandler :
}
private:
- SndFileHandler(const char *fs_path,
+ // TODO(hzeller): trim parameter list.
+ SndFileHandler(const char *fs_path, int filter_id,
const char *underlying_file, int filedes, SNDFILE *snd_in,
const SF_INFO &in_info, const HandlerStats &file_info,
const std::string &config_path)
- : filedes_(filedes), snd_in_(snd_in), total_frames_(in_info.frames),
+ : FileHandler(filter_id),
+ filedes_(filedes), snd_in_(snd_in), total_frames_(in_info.frames),
channels_(in_info.channels), base_stats_(file_info),
config_path_(config_path),
error_(false), output_buffer_(NULL),
@@ -461,53 +465,108 @@ class SndFileHandler :
FileHandler *FolveFilesystem::CreateFromDescriptor(int filedes,
+ int cfg_idx,
const char *fs_path,
const char *underlying_file) {
HandlerStats file_info;
file_info.filename = fs_path;
- FileHandler *filter = SndFileHandler::Create(filedes, fs_path,
- underlying_file,
- zita_config_dir_, &file_info);
- if (filter != NULL) return filter;
+ if (cfg_idx != 0) {
+ FileHandler *filter = SndFileHandler::Create(filedes, fs_path,
+ underlying_file,
+ cfg_idx,
+ config_dirs()[cfg_idx],
+ &file_info);
+ if (filter != NULL) return filter;
+ } else {
+ file_info.message = "No filter config selected.";
+ }
// Every other file-type is just passed through as is.
- return new PassThroughFilter(filedes, file_info);
+ return new PassThroughFilter(filedes, cfg_idx, file_info);
+}
+
+std::string FolveFilesystem::CacheKey(int config_idx, const char *fs_path) {
+ std::string result;
+ Appendf(&result, "%d/%s", config_idx, fs_path);
+ return result;
}
// Implementation of the C functions in filter-interface.h
FileHandler *FolveFilesystem::CreateHandler(const char *fs_path,
const char *underlying_path) {
- FileHandler *handler = open_file_cache_.FindAndPin(fs_path);
+ const int config_idx = current_cfg_index_;
+ const std::string cache_key = CacheKey(config_idx, fs_path);
+ FileHandler *handler = open_file_cache_.FindAndPin(cache_key);
if (handler == NULL) {
int filedes = open(underlying_path, O_RDONLY);
if (filedes < 0)
return NULL;
++total_file_openings_;
- handler = CreateFromDescriptor(filedes, fs_path, underlying_path);
- handler = open_file_cache_.InsertPinned(fs_path, handler);
+ handler = CreateFromDescriptor(filedes, config_idx,
+ fs_path, underlying_path);
+ handler = open_file_cache_.InsertPinned(cache_key, handler);
} else {
++total_file_reopen_;
}
return handler;
}
int FolveFilesystem::StatByFilename(const char *fs_path, struct stat *st) {
- FileHandler *handler = open_file_cache_.FindAndPin(fs_path);
+ const std::string cache_key = CacheKey(current_cfg_index_, fs_path);
+ FileHandler *handler = open_file_cache_.FindAndPin(cache_key);
if (handler == 0)
return -1;
ssize_t result = handler->Stat(st);
- open_file_cache_.Unpin(fs_path);
+ open_file_cache_.Unpin(cache_key);
return result;
}
-void FolveFilesystem::Close(const char *fs_path) {
- open_file_cache_.Unpin(fs_path);
+void FolveFilesystem::Close(const char *fs_path, const FileHandler *handler) {
+ const std::string cache_key = CacheKey(handler->filter_id(), fs_path);
+ open_file_cache_.Unpin(cache_key);
+}
+
+FolveFilesystem::FolveFilesystem()
+ : current_cfg_index_(0),
+ open_file_cache_(3), total_file_openings_(0), total_file_reopen_(0) {
+ config_dirs_.push_back(""); // The first config is special: empty.
+}
+
+void FolveFilesystem::SwitchCurrentConfigIndex(int i) {
+ if (i < 0 || i >= (int) config_dirs_.size())
+ return;
+ current_cfg_index_ = i;
}
-FolveFilesystem::FolveFilesystem(const char *version_info,
- const char *unerlying_dir,
- const char *zita_config_dir)
- : version_info_(version_info), underlying_dir_(unerlying_dir),
- zita_config_dir_(zita_config_dir), open_file_cache_(3),
- total_file_openings_(0), total_file_reopen_(0) {
+static bool IsDirectory(const std::string &path) {
+ if (path.empty()) return false;
+ struct stat st;
+ if (stat(path.c_str(), &st) != 0)
+ return false;
+ return (st.st_mode & S_IFMT) == S_IFDIR;
+}
+
+bool FolveFilesystem::CheckInitialized() {
+ if (underlying_dir().empty()) {
+ fprintf(stderr, "Don't know the underlying directory to read from.\n");
+ return false;
+ }
+ if (!IsDirectory(underlying_dir())) {
+ fprintf(stderr, "<underlying-dir>: '%s' not a directory.\n",
+ underlying_dir().c_str());
+ return false;
+ }
+
+ for (size_t i = 1; i < config_dirs_.size(); ++i) {
+ if (!IsDirectory(config_dirs_[i])) {
+ fprintf(stderr, "<config-dir>: '%s' not a directory.\n",
+ config_dirs_[i].c_str());
+ return false;
+ }
+ }
+ if (config_dirs_.size() > 1) {
+ // By default, lets set the index to the first filter the user provided.
+ SwitchCurrentConfigIndex(1);
+ }
+ return true;
}
View
@@ -19,15 +19,39 @@
#include <unistd.h>
+#include <string>
+#include <vector>
+
#include "file-handler-cache.h"
#include "file-handler.h"
+#ifndef FOLVE_VERSION
+#define FOLVE_VERSION "[unknown version - compile from git]"
+#endif
+
class FolveFilesystem {
public:
- // version_info and underlying_dir need to stay allocated by the calling
- // context.
- FolveFilesystem(const char *version_info, const char *underlying_dir,
- const char *zita_config_dir);
+ // Create a new filesystem. At least SetBasedir() needs to be called
+ // for this to be properly initialized.
+ FolveFilesystem();
+
+ // Underlying directory - the directory we read files from.
+ void set_underlying_dir(const std::string &dir) { underlying_dir_ = dir; }
+ const std::string &underlying_dir() const { return underlying_dir_; }
+
+ // Config directories contain the filter configurations.
+ void add_config_dir(const char *config_dir) {
+ config_dirs_.push_back(config_dir);
+ }
+ const std::vector<std::string> &config_dirs() const { return config_dirs_; }
+
+ // Switch the current config to i. Values out of range are not accepted.
+ void SwitchCurrentConfigIndex(int i);
+ int current_cfg_index() const { return current_cfg_index_; }
+
+ // Check if properly initialized. Return 'false' if not and print a message
+ // to stderr.
+ bool CheckInitialized();
// Create a new filter given the filesystem path and the underlying
// path.
@@ -38,27 +62,28 @@ class FolveFilesystem {
// Return dynamic size of file.
int StatByFilename(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.
- void Close(const char *fs_path);
+ // Inform filesystem that this file handler is not needed anymore
+ // (FS still might consider keeping it around for a while).
+ void Close(const char *fs_path, const FileHandler *handler);
- const char *version() const { return version_info_; }
- const char *underlying_dir() const { return underlying_dir_; }
- const char *config_dir() const { return zita_config_dir_.c_str(); }
FileHandlerCache *handler_cache() { return &open_file_cache_; }
// Some stats.
int total_file_openings() { return total_file_openings_; }
int total_file_reopen() { return total_file_reopen_; }
private:
+ // Get cache key, depending on the given configuration.
+ std::string CacheKey(int config_idx, const char *fs_path);
- FileHandler *CreateFromDescriptor(int filedes, const char *fs_path,
+ FileHandler *CreateFromDescriptor(int filedes, int cfg_idx,
+ const char *fs_path,
const char *underlying_file);
- const char *const version_info_;
- const char *const underlying_dir_;
- const std::string zita_config_dir_;
+ std::string underlying_dir_;
+ std::vector<std::string> config_dirs_;
+ int current_cfg_index_;
+
FileHandlerCache open_file_cache_;
int total_file_openings_;
int total_file_reopen_;
Oops, something went wrong.

0 comments on commit ee675fe

Please sign in to comment.