예제 #1
0
 void _applyOpToDataFiles( const string& database, FileOp &fo, bool afterAllocator, const string& path ) {
     if ( afterAllocator )
         FileAllocator::get()->waitUntilFinished();
     string c = database;
     c += '.';
     boost::filesystem::path p(path);
     if (storageGlobalParams.directoryperdb)
         p /= database;
     boost::filesystem::path q;
     q = p / (c+"ns");
     bool ok = false;
     MONGO_ASSERT_ON_EXCEPTION( ok = fo.apply( q ) );
     if ( ok ) {
         LOG(2) << fo.op() << " file " << q.string() << endl;
     }
     int i = 0;
     int extra = 10; // should not be necessary, this is defensive in case there are missing files
     while ( 1 ) {
         verify( i <= DiskLoc::MaxFiles );
         stringstream ss;
         ss << c << i;
         q = p / ss.str();
         MONGO_ASSERT_ON_EXCEPTION( ok = fo.apply(q) );
         if ( ok ) {
             if ( extra != 10 ) {
                 LOG(1) << fo.op() << " file " << q.string() << endl;
                 log() << "  _applyOpToDataFiles() warning: extra == " << extra << endl;
             }
         }
         else if ( --extra <= 0 )
             break;
         i++;
     }
 }
예제 #2
0
// this function is shared by chmod/utime/chown maybe others
// it's here for directories which may span multiple backends
// returns PLFS_SUCCESS or PLFS_E*
static plfs_error_t plfs_flatfile_operation(struct plfs_physpathinfo *ppip,
                                   FileOp& op, IOStore *ios) {
    plfs_error_t ret = PLFS_SUCCESS; 
    vector<plfs_pathback> dirs;
    struct stat st;
    mode_t mode = 0;

    ret = ppip->canback->store->Lstat(ppip->canbpath.c_str(), &st);
    if (ret != PLFS_SUCCESS){
        mode = 0;
    } else {
        mode = st.st_mode;
    }
    
    //perform operation on ALL directories
    if (S_ISDIR(mode)){
        ret = generate_backpaths(ppip, dirs);
        vector<plfs_pathback>::reverse_iterator ritr;
        for(ritr = dirs.rbegin(); ritr != dirs.rend() && ret == PLFS_SUCCESS; ++ritr) {
            ret = op.op(ritr->bpath.c_str(),DT_DIR,ritr->back->store);
        }
    }
    //we hit a regular flat file
    else if(S_ISREG(mode)){
        ret = op.op(ppip->canbpath.c_str(), DT_REG, ios);
    }
    //symlink
    else if (S_ISLNK(mode)){
        ret = op.op(ppip->canbpath.c_str(), DT_LNK, ios);
    }
    return(ret);
}
예제 #3
0
/**
 * plfs_backends_op: apply a fileop to all the backends in a mount.
 * currently used by readdir, rmdir, mkdir
 * this doesn't require the dires to already exist
 *
 * @param ppip the phyiscal path we are operating on
 * @param op the file op to apply
 * @return PLFS_SUCCESS or PLFS_E*
 */
plfs_error_t
plfs_backends_op(struct plfs_physpathinfo *ppip, FileOp& op)
{
    plfs_error_t ret = PLFS_SUCCESS;
    vector<plfs_pathback> exps;
    vector<plfs_pathback>::iterator itr;
    if ( (ret = generate_backpaths(ppip, exps)) != PLFS_SUCCESS ) {
        return(ret);
    }
    for(itr = exps.begin(); itr != exps.end() && ret == PLFS_SUCCESS; itr++ ) {
        ret = op.op(itr->bpath.c_str(),DT_DIR,itr->back->store);
        mlog(INT_DCOMMON, "%s on %s: %d",op.name(),itr->bpath.c_str(),ret);
    }
    return(ret);
}
예제 #4
0
// this function is shared by chmod/utime/chown maybe others
// it's here for directories which may span multiple backends
// returns 0 or -err
int plfs_flatfile_operation(const char *logical, FileOp& op, IOStore *ios) {
    FLAT_ENTER;
    vector<plfs_pathback> dirs;
    mode_t mode = 0;
    ret = is_plfs_file(logical, &mode);
    //perform operation on ALL directories
    if (S_ISDIR(mode)){

        ret = find_all_expansions(logical, dirs);
        vector<plfs_pathback>::reverse_iterator ritr;
        for(ritr = dirs.rbegin(); ritr != dirs.rend() && ret == 0; ++ritr) {
            ret = op.op(ritr->bpath.c_str(),DT_DIR,ritr->back->store);
        }
    }
    //we hit a regular flat file
    else if(S_ISREG(mode)){
        ret = op.op(path.c_str(), DT_REG, ios);
    }
    //symlink
    else{
        ret = op.op(path.c_str(), DT_LNK, ios);
    }
    FLAT_EXIT(ret);
}
예제 #5
0
/**
 * plfs_file_operation: this function is shared by
 * chmod/utime/chown/etc.  anything that needs to operate on possibly
 * a lot of items either on a bunch of dirs across the backends or on
 * a bunch of entries within a container Be careful.  This performs a
 * stat.  Do not use for performance critical operations.  If needed,
 * then you'll have to figure out how to cheaply pass the mode_t in
 *
 * @param ppip the phyiscal path we are working with
 * @param op the FileOp operation we are going to perform
 * @return PLFS_SUCCESS or PLFS_E*
 */
static plfs_error_t
plfs_file_operation(struct plfs_physpathinfo *ppip, FileOp& op)
{
    plfs_error_t ret = PLFS_SUCCESS;
    vector<plfs_pathback> files, dirs, links;
    string accessfile;
    struct plfs_pathback pb;

    // first go through and find the set of physical files and dirs
    // that need to be operated on
    // if it's a PLFS file, then maybe we just operate on
    // the access file, or maybe on all subentries
    // if it's a directory, then we operate on all backend copies
    // else just operate on whatever it is (ENOENT, symlink)
    mode_t mode = 0;
    ret = (is_container_file(ppip,&mode) == false) ? PLFS_SUCCESS : PLFS_TBD;
    bool is_container = false; // differentiate btwn logical dir and container

    if (S_ISREG(mode)) { // it's a PLFS file
        if (op.onlyAccessFile()) {
            pb.bpath = Container::getAccessFilePath(ppip->canbpath);
            pb.back = ppip->canback;
            files.push_back(pb);
            ret = PLFS_SUCCESS;    // ret was one from is_container_file
        } else {
            // everything
            is_container = true;
            accessfile = Container::getAccessFilePath(ppip->canbpath);
            ret = plfs_collect_from_containers(ppip,files,dirs,links);
        }
    } else if (S_ISDIR(mode)) { // need to iterate across dirs
        ret = generate_backpaths(ppip, dirs);
    } else {
        // ENOENT, a symlink, somehow a flat file in here
        pb.bpath = ppip->canbpath;
        pb.back = ppip->canback;
        files.push_back(pb);  // we might want to reset ret to 0 here
    }
    // now apply the operation to each operand so long as ret==0.  dirs must be
    // done in reverse order and files must be done first.  This is necessary
    // for when op is unlink since children must be unlinked first.  for the
    // other ops, order doesn't matter.
    vector<plfs_pathback>::reverse_iterator ritr;
    for(ritr = files.rbegin(); ritr != files.rend() && ret == PLFS_SUCCESS; ++ritr) {
        // In container mode, we want to special treat accessfile deletion,
        // because once accessfile deleted, the top directory will no longer
        // be viewed as a container. Defer accessfile deletion until last moment
        // so that if anything fails in the middle, the container information
        // remains.
        if (is_container && accessfile == ritr->bpath) {
            mlog(INT_DCOMMON, "%s skipping accessfile %s",
                              __FUNCTION__, ritr->bpath.c_str());
            continue;
        }
        mlog(INT_DCOMMON, "%s on %s",__FUNCTION__,ritr->bpath.c_str());
        ret = op.op(ritr->bpath.c_str(),DT_REG,ritr->back->store); 
    }
    for(ritr = links.rbegin(); ritr != links.rend() && ret == PLFS_SUCCESS; ++ritr) {
        op.op(ritr->bpath.c_str(),DT_LNK,ritr->back->store);
    }
    for(ritr = dirs.rbegin(); ritr != dirs.rend() && ret == PLFS_SUCCESS; ++ritr) {
        if (is_container && ritr->bpath == ppip->canbpath) {
            mlog(INT_DCOMMON, "%s skipping canonical top directory%s",
                              __FUNCTION__, ppip->canbpath.c_str());
            continue;
        }
        ret = op.op(ritr->bpath.c_str(),
                    is_container?(unsigned char)DT_CONTAINER:(unsigned char)DT_DIR,
                    ritr->back->store);
    }
    if (is_container) {
        mlog(INT_DCOMMON, "%s processing access file and canonical top dir",
                          __FUNCTION__);
        ret = op.op(accessfile.c_str(), DT_REG, ppip->canback->store);
        if (ret == PLFS_SUCCESS)
            ret = op.op(ppip->canbpath.c_str(), DT_CONTAINER,
                        ppip->canback->store);
    }
    mlog(INT_DAPI, "%s: ret %d", __FUNCTION__,ret);
    return(ret);
}