Ejemplo n.º 1
0
    Collection* Database::getCollection( OperationContext* txn, const StringData& ns ) {
        invariant( _name == nsToDatabaseSubstring( ns ) );

        scoped_lock lk( _collectionLock );

        CollectionMap::const_iterator it = _collections.find( ns );
        if ( it != _collections.end() && it->second ) {
            return it->second;
        }

        auto_ptr<CollectionCatalogEntry> catalogEntry( _dbEntry->getCollectionCatalogEntry( txn, ns ) );
        if ( !catalogEntry.get() )
            return NULL;

        auto_ptr<RecordStore> rs( _dbEntry->getRecordStore( txn, ns ) );
        invariant( rs.get() ); // if catalogEntry exists, so should this

        Collection* c = new Collection( txn, ns, catalogEntry.release(), rs.release(), this );
        _collections[ns] = c;
        return c;
    }
Ejemplo n.º 2
0
Archivo: dir.c Proyecto: alhazred/onarm
/*
 * visitNodes()
 *
 * This is the main workhouse routine for traversing pcfs metadata.
 * There isn't a lot to the metadata.  Basically there is a root
 * directory somewhere (either in its own special place outside the
 * data area or in a data cluster).  The root directory (and all other
 * directories) are filled with a number of fixed size entries.  An
 * entry has the filename and extension, the file's attributes, the
 * file's size, and the starting data cluster of the storage allocated
 * to the file.  To determine which clusters are assigned to the file,
 * you start at the starting cluster entry in the FAT, and follow the
 * chain of entries in the FAT.
 *
 *	Arguments are:
 *	fd
 *		descriptor for accessing the raw file system data
 *	currentCluster
 *		original caller supplies the initial starting cluster,
 *		subsequent recursive calls are made with updated
 *		cluster numbers for the sub-directories.
 *	dirData
 *		pointer to the directory data bytes
 *	dirDataLen
 *		size of the whole buffer of data bytes (usually it is
 *		the size of a cluster, but the root directory on
 *		FAT12/16 is not necessarily the same size as a cluster).
 *	depth
 *		original caller should set it to zero (assuming they are
 *		starting from the root directory).  This number is used to
 *		change the indentation of file names presented as debug info.
 *	descend
 *		boolean indicates if we should descend into subdirectories.
 *	operation
 *		what, if any, matching should be performed.
 *		The PCFS_TRAVERSE_ALL operation is a depth first traversal
 *		of all nodes in the metadata tree, that tracks all the
 *		clusters in use (according to the meta-data, at least)
 *	matchRequired
 *		value to be matched (if any)
 *	found
 *		output parameter
 *		used to return pointer to a directory entry that matches
 *		the search requirement
 *		original caller should pass in a pointer to a NULL pointer.
 *	lastDirCluster
 *		output parameter
 *		if no match found, last cluster num of starting directory
 *	dirEnd
 *		output parameter
 *		if no match found, return parameter stores pointer to where
 *		new directory entry could be appended to existing directory
 *	recordPath
 *		output parameter
 *		as files are discovered, and directories traversed, this
 *		buffer is used to store the current full path name.
 *	pathLen
 *		output parameter
 *		this is in the integer length of the current full path name.
 */
static void
visitNodes(int fd, int32_t currentCluster, ClusterContents *dirData,
    int32_t dirDataLen, int depth, int descend, int operation,
    char matchRequired,  struct pcdir **found, int32_t *lastDirCluster,
    struct pcdir **dirEnd, char *recordPath, int *pathLen)
{
	struct pcdir *longdp = NULL;
	struct pcdir *dp;
	int32_t longStart;
	int withinLongName = 0;
	int saveLen = *pathLen;

	dp = dirData->dirp;

	/*
	 *  A directory entry where the first character of the name is
	 *  PCD_UNUSED indicates the end of the directory.
	 */
	while ((uchar_t *)dp < dirData->bytes + dirDataLen &&
	    dp->pcd_filename[0] != PCD_UNUSED) {
		/*
		 *  Handle the special case find operations.
		 */
		searchChecks(dp, operation, matchRequired, found);
		if (*found)
			break;
		/*
		 * Are we looking at part of a long file name entry?
		 * If so, we may need to note the start of the name.
		 * We don't do any further processing of long file
		 * name entries.
		 *
		 * We also skip deleted entries and the '.' and '..'
		 * entries.
		 */
		if ((dp->pcd_attr & PCDL_LFN_BITS) == PCDL_LFN_BITS) {
			if (!withinLongName) {
				withinLongName++;
				longStart = currentCluster;
				longdp = dp;
			}
			dp++;
			continue;
		} else if ((dp->pcd_filename[0] == PCD_ERASED) ||
		    (dp->pcd_filename[0] == '.')) {
			/*
			 * XXX - if we were within a long name, then
			 * its existence is bogus, because it is not
			 * attached to any real file.
			 */
			withinLongName = 0;
			dp++;
			continue;
		}
		withinLongName = 0;
		if (operation == PCFS_TRAVERSE_ALL)
			catalogEntry(fd, dp, longdp, longStart, depth,
			    recordPath, pathLen);
		longdp = NULL;
		longStart = 0;
		if (dp->pcd_attr & PCA_DIR && descend == PCFS_VISIT_SUBDIRS) {
			traverseDir(fd, extractStartCluster(dp), depth + 1,
			    descend, operation, matchRequired, found,
			    lastDirCluster, dirEnd, recordPath, pathLen);
			if (*found)
				break;
		}
		dp++;
		*pathLen = saveLen;
	}
	if (*found)
		return;
	if ((uchar_t *)dp < dirData->bytes + dirDataLen) {
		/*
		 * We reached the end of directory before the end of
		 * our provided data (a cluster).  That means this cluster
		 * is the last one in this directory's chain.  It also
		 * means we've just looked at the last directory entry.
		 */
		*lastDirCluster = currentCluster;
		*dirEnd = dp;
		return;
	}
	/*
	 * If there is more to the directory we'll go get it otherwise we
	 * are done traversing this directory.
	 */
	if ((currentCluster == FAKE_ROOTDIR_CLUST) ||
	    (lastInFAT(currentCluster))) {
		*lastDirCluster = currentCluster;
		return;
	} else {
		traverseDir(fd, nextInChain(currentCluster),
		    depth, descend, operation, matchRequired,
		    found, lastDirCluster, dirEnd, recordPath, pathLen);
		*pathLen = saveLen;
	}
}