mirror of
https://github.com/ceph/ceph
synced 2025-01-10 21:20:46 +00:00
uclient: implement readdir_r_cb (callback based readdir)
This lets us know whether the caller is able to consume an entry before advancing our position.
This commit is contained in:
parent
c2c09be383
commit
561f302207
@ -4003,6 +4003,68 @@ int Client::readdirplus_r(DIR *d, struct dirent *de, struct stat *st, int *stmas
|
||||
assert(0);
|
||||
}
|
||||
|
||||
int Client::readdir_r_cb(DIR *d, add_dirent_cb_t cb, void *p)
|
||||
{
|
||||
DirResult *dirp = (DirResult*)d;
|
||||
|
||||
dout(10) << "readdir_r_cb " << *dirp->inode << " offset " << dirp->offset
|
||||
<< " frag " << dirp->frag() << " fragpos " << dirp->fragpos()
|
||||
<< " at_end=" << dirp->at_end()
|
||||
<< dendl;
|
||||
|
||||
struct dirent de;
|
||||
struct stat st;
|
||||
memset(&de, 0, sizeof(de));
|
||||
memset(&st, 0, sizeof(st));
|
||||
|
||||
while (1) {
|
||||
if (dirp->at_end())
|
||||
return 0;
|
||||
|
||||
if (dirp->buffer.count(dirp->frag()) == 0) {
|
||||
Mutex::Locker lock(client_lock);
|
||||
_readdir_get_frag(dirp);
|
||||
if (dirp->at_end())
|
||||
return 0;
|
||||
}
|
||||
|
||||
frag_t fg = dirp->frag();
|
||||
uint32_t pos = dirp->fragpos();
|
||||
assert(dirp->buffer.count(fg));
|
||||
vector<DirEntry> &ent = dirp->buffer[fg];
|
||||
|
||||
if (ent.empty() ||
|
||||
pos >= ent.size()) {
|
||||
dout(10) << "empty frag " << fg << ", moving on to next" << dendl;
|
||||
_readdir_next_frag(dirp);
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(pos < ent.size());
|
||||
_readdir_fill_dirent(&de, &ent[pos], dirp->offset);
|
||||
st = ent[pos].st;
|
||||
int stmask = ent[pos].stmask;
|
||||
|
||||
int r = cb(p, &de, &st, stmask, dirp->offset + 1); // _next_ offset
|
||||
if (r < 0)
|
||||
break;
|
||||
|
||||
dout(15) << " de " << de.d_name << " off " << dirp->offset
|
||||
<< " = " << r
|
||||
<< dendl;
|
||||
|
||||
pos++;
|
||||
dirp->offset++;
|
||||
|
||||
if (pos == ent.size())
|
||||
_readdir_next_frag(dirp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Client::_getdents(DIR *dir, char *buf, int buflen, bool fullent)
|
||||
{
|
||||
DirResult *dirp = (DirResult *)dir;
|
||||
|
@ -1173,6 +1173,9 @@ public:
|
||||
int readdir_r(DIR *dirp, struct dirent *de);
|
||||
int readdirplus_r(DIR *dirp, struct dirent *de, struct stat *st, int *stmask);
|
||||
|
||||
typedef int (*add_dirent_cb_t)(void *p, struct dirent *de, struct stat *st, int stmask, off_t off);
|
||||
int readdir_r_cb(DIR *dirp, add_dirent_cb_t cb, void *p);
|
||||
|
||||
int _getdents(DIR *dirp, char *buf, int buflen, bool ful); // get a bunch of dentries at once
|
||||
int getdents(DIR *dirp, char *buf, int buflen) {
|
||||
return _getdents(dirp, buf, buflen, true);
|
||||
|
Loading…
Reference in New Issue
Block a user