Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 150 lines (136 sloc) 5.429 kB
4d4d90b @hzeller o More legalese
authored
1 // Folve - A fuse filesystem that convolves audio files on-the-fly.
2 //
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
3 // Copyright (C) 2012 Henner Zeller <h.zeller@acm.org>
10e003a @hzeller o Be consistent: forward class became defined as struct.
authored
4 //
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>
17
18 #include <assert.h>
19 #include <stdio.h>
20
21 #include <map>
f581c5d @hzeller o Give recency cache LRU semantics.
authored
22 #include <vector>
b4eec5c @hzeller o libboost caused too many troubles in embedded systems with weak
authored
23 #include <algorithm>
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
24
25 #include "file-handler.h"
26 #include "file-handler-cache.h"
c1a03f2 @hzeller o Needed convenient sub-second resolution time. Added CurrentTime()
authored
27 #include "util.h"
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
28
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
29 struct FileHandlerCache::Entry {
30 Entry(FileHandler *h) : handler(h), references(0), last_access(0) {}
31 FileHandler *const handler;
32 int references;
33 double last_access; // seconds since epoch, sub-second resolution.
34 };
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
35
36 FileHandler *FileHandlerCache::InsertPinned(const std::string &key,
37 FileHandler *handler) {
5ec3966 @hzeller o Only have one pre-buffer thread to only use at most one more core
authored
38 std::vector<FileHandler *> to_delete;
39 FileHandler *result = NULL;
40 {
41 folve::MutexLock l(&mutex_);
42 CacheMap::iterator ins
43 = cache_.insert(std::make_pair(key, (Entry*)NULL)).first;
44 if (ins->second == NULL) {
45 ins->second = new Entry(handler);
46 } else {
47 delete handler;
48 }
49 ++ins->second->references;
50 if (cache_.size() > max_size_) {
51 CleanupOldestUnreferenced_Locked(&to_delete);
52 }
53 ins->second->last_access = folve::CurrentTime();
54 if (observer_) observer_->InsertHandlerEvent(ins->second->handler);
55 result = ins->second->handler;
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
56 }
5ec3966 @hzeller o Only have one pre-buffer thread to only use at most one more core
authored
57 // Items that are to be deleted need to be deleted ouside of the lock,
58 // otherwise there is a chance of a deadlock in the gapless case.
59 // t1: open new file -> need to retire old file
60 // -> delete while mutex held(*1)
61 // -> buffer being workd on in buffer thred
62 // -> wait-for-buffer-cache (*2) (current_item != buffer)
63 // buffer thread: (current_item, condition current_item == buffer) (*2)
64 // -> call AddMoreSndData()
65 // -> open new file for gapless -> call FileHandlerCache
66 // -> wait-for-mutex (*1)
67 for (size_t i = 0; i < to_delete.size(); ++i) {
68 delete to_delete[i];
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
69 }
5ec3966 @hzeller o Only have one pre-buffer thread to only use at most one more core
authored
70 return result;
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
71 }
72
73 FileHandler *FileHandlerCache::FindAndPin(const std::string &key) {
b4eec5c @hzeller o libboost caused too many troubles in embedded systems with weak
authored
74 folve::MutexLock l(&mutex_);
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
75 CacheMap::iterator found = cache_.find(key);
76 if (found == cache_.end())
77 return NULL;
78 ++found->second->references;
a9d3e53 @hzeller o Found a project name: "Folve". Some renamings because of that.
authored
79 found->second->last_access = folve::CurrentTime();
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
80 return found->second->handler;
81 }
82
83 void FileHandlerCache::Unpin(const std::string &key) {
5ec3966 @hzeller o Only have one pre-buffer thread to only use at most one more core
authored
84 FileHandler *to_delete = NULL;
85 {
86 folve::MutexLock l(&mutex_);
87 CacheMap::iterator found = cache_.find(key);
88 assert(found != cache_.end());
89 --found->second->references;
90 // If we are already beyond cache size, clean up as soon as we get idle.
91 if (found->second->references == 0 && cache_.size() > max_size_) {
92 to_delete = Erase_Locked(found);
93 }
7c00d62 @hzeller o new version
authored
94 }
5ec3966 @hzeller o Only have one pre-buffer thread to only use at most one more core
authored
95 delete to_delete;
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
96 }
97
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
98 void FileHandlerCache::SetObserver(Observer *observer) {
99 assert(observer_ == NULL);
100 observer_ = observer;
101 }
102
103 void FileHandlerCache::GetStats(std::vector<HandlerStats> *stats) {
104 HandlerStats s;
b4eec5c @hzeller o libboost caused too many troubles in embedded systems with weak
authored
105 folve::MutexLock l(&mutex_);
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
106 for (CacheMap::iterator it = cache_.begin(); it != cache_.end(); ++it) {
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
107 it->second->handler->GetHandlerStatus(&s);
108 s.status = ((it->second->references == 0)
109 ? HandlerStats::IDLE
110 : HandlerStats::OPEN);
111 s.last_access = it->second->last_access;
112 stats->push_back(s);
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
113 }
114 }
115
5ec3966 @hzeller o Only have one pre-buffer thread to only use at most one more core
authored
116 FileHandler *FileHandlerCache::Erase_Locked(CacheMap::iterator &cache_it) {
7c00d62 @hzeller o new version
authored
117 if (observer_) observer_->RetireHandlerEvent(cache_it->second->handler);
5ec3966 @hzeller o Only have one pre-buffer thread to only use at most one more core
authored
118 FileHandler *result = cache_it->second->handler; // don't delete in mutex.
7c00d62 @hzeller o new version
authored
119 delete cache_it->second; // Entry
120 cache_.erase(cache_it);
5ec3966 @hzeller o Only have one pre-buffer thread to only use at most one more core
authored
121 return result;
7c00d62 @hzeller o new version
authored
122 }
123
6c6dedb @hzeller o Some readme tweaks and readability improvements.
authored
124 struct FileHandlerCache::CompareAge {
125 bool operator() (const CacheMap::iterator &a, const CacheMap::iterator &b) {
126 return a->second->last_access < b->second->last_access;
127 }
128 };
5ec3966 @hzeller o Only have one pre-buffer thread to only use at most one more core
authored
129 void FileHandlerCache::CleanupOldestUnreferenced_Locked(
130 std::vector<FileHandler*> *to_delete) {
f581c5d @hzeller o Give recency cache LRU semantics.
authored
131 assert(cache_.size() > max_size_); // otherwise we shouldn't have been called
132 // While this iterating through the whole cache might look expensive,
133 // in practice we're talking about 3 elements here.
134 // If we had significantly more, e.g. broken clients that don't close files,
135 // we need to keep better track of age.
136 std::vector<CacheMap::iterator> for_removal;
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
137 for (CacheMap::iterator it = cache_.begin(); it != cache_.end(); ++it) {
6c6dedb @hzeller o Some readme tweaks and readability improvements.
authored
138 if (it->second->references == 0) for_removal.push_back(it);
f581c5d @hzeller o Give recency cache LRU semantics.
authored
139 }
140
141 const size_t to_erase_count = std::min(cache_.size() - max_size_,
142 for_removal.size());
143 CompareAge comparator;
144 std::sort(for_removal.begin(), for_removal.end(), comparator);
145 for (size_t i = 0; i < to_erase_count; ++i) {
5ec3966 @hzeller o Only have one pre-buffer thread to only use at most one more core
authored
146 to_delete->push_back(Erase_Locked(for_removal[i]));
15b305a @hzeller o Build infrastructure to re-use file handler objects. Files seem to
authored
147 }
148 }
b4eec5c @hzeller o libboost caused too many troubles in embedded systems with weak
authored
149
Something went wrong with that request. Please try again.