@@ -146,18 +146,16 @@ int Directory::ReadAndReply(fuse_req_t req, size_t size, off_t off) {
146
146
return fuse_reply_err (req, EISDIR);
147
147
}
148
148
149
+ /* The cookie uses 32 bits, with the higher 16 bit the key to the readdir
150
+ * context, and the lower 16 bit representing the index of the directory entry.
151
+ */
149
152
Directory::ReadDirCtx* Directory::PrepareReaddir (off_t cookie) {
153
+ off_t key = 0 ;
150
154
if (cookie != 0 ) {
151
155
/* NOTE: Will throw std::out_of_range if no entry is found */
152
- Directory::ReadDirCtx* ctx = readdirStates.at (cookie);
153
-
154
- /* If we have reached the end of the iterator, we should destroy this context
155
- * to release memory */
156
- if (ctx->it == ctx->children .end ()) {
157
- Directory::readdirStates.erase (cookie);
158
- delete ctx;
159
- throw (std::out_of_range (" Not found" ));
160
- }
156
+ key = (cookie & 0xffff0000 ) >> 16 ;
157
+ Directory::ReadDirCtx* ctx = readdirStates.at (key);
158
+
161
159
return ctx;
162
160
}
163
161
/* Make a copy of children */
@@ -166,16 +164,31 @@ Directory::ReadDirCtx* Directory::PrepareReaddir(off_t cookie) {
166
164
lk.unlock ();
167
165
168
166
/* Add it to the table */
169
- cookie = rand ();
167
+ key = rand () & 0xffff ;
170
168
/* Make sure there is no duplicate */
171
- while (readdirStates.find (cookie ) != readdirStates.end ()) {
172
- cookie = rand ();
169
+ while (readdirStates.find (key ) != readdirStates.end ()) {
170
+ key = rand () & 0xffff ;
173
171
}
172
+ cookie = 0 ;
173
+ cookie = key << 16 ;
174
174
ReadDirCtx *newctx = new ReadDirCtx (cookie, copiedChildren);
175
- readdirStates.insert ({cookie , newctx});
175
+ readdirStates.insert ({key , newctx});
176
176
return newctx;
177
177
}
178
178
179
+ void Directory::RecycleStates () {
180
+ // find context objects whose iterators have reached the end, and free them
181
+ for (auto ctxiter = readdirStates.begin (); ctxiter != readdirStates.end ();) {
182
+ Directory::ReadDirCtx *ctx = ctxiter->second ;
183
+ if (ctx->it == ctx->children .end ()) {
184
+ delete ctx;
185
+ ctxiter = readdirStates.erase (ctxiter);
186
+ } else {
187
+ ++ctxiter;
188
+ }
189
+ }
190
+ }
191
+
179
192
bool Directory::IsEmpty () {
180
193
std::shared_lock<std::shared_mutex> lk (childrenRwSem);
181
194
for (auto it = m_children.begin (); it != m_children.end (); ++it) {
0 commit comments