예제 #1
0
// EvictCachedRangeMetadata will evict any cached metadata range descriptors for
// the given key. It is intended that this method be called from a consumer of
// RangeMetadataCache when the returned range metadata is discovered to be
// stale.
func (rmc *RangeMetadataCache) EvictCachedRangeMetadata(key storage.Key) {
	for {
		k, _ := rmc.getCachedRangeMetadata(key)
		if k != nil {
			rmc.rangeCacheMu.Lock()
			rmc.rangeCache.Del(k)
			rmc.rangeCacheMu.Unlock()
		}
		// Retrieve the metadata range key for the next level of metadata, and
		// evict that key as well.  This loop ends after the meta1 range, which
		// returns KeyMin as its metadata key.
		key = storage.RangeMetaKey(key)
		if len(key) == 0 {
			break
		}
	}
}
예제 #2
0
// getCachedRangeMetadata is a helper function to retrieve the metadata
// range which contains the given key, if present in the cache.
func (rmc *RangeMetadataCache) getCachedRangeMetadata(key storage.Key) (
	rangeCacheKey, *storage.RangeDescriptor) {
	metaKey := storage.RangeMetaKey(key)
	rmc.rangeCacheMu.RLock()
	defer rmc.rangeCacheMu.RUnlock()

	k, v, ok := rmc.rangeCache.Ceil(rangeCacheKey(metaKey))
	if !ok {
		return nil, nil
	}
	metaEndKey := k.(rangeCacheKey)
	rd := v.(*storage.RangeDescriptor)

	// Check that key actually belongs to range
	if !rd.ContainsKey(key) {
		return nil, nil
	}
	return metaEndKey, rd
}
예제 #3
0
파일: db.go 프로젝트: hahan/cockroach
// LookupRangeMetadata retrieves the range metadata for the range containing the
// given key.  Because range metadata in cockroach is stored using a multi-level
// lookup table, this method may be called recursively to look up higher-level
// ranges.  Recursive lookups are dispatched through the metadata range cache.
func (db *DistDB) LookupRangeMetadata(key storage.Key) (storage.Key, *storage.RangeDescriptor, error) {
	metadataKey := storage.RangeMetaKey(key)
	if len(metadataKey) == 0 {
		// Metadata range is the first range, the description of which is always
		// gossiped.
		infoI, err := db.gossip.GetInfo(gossip.KeyFirstRangeMetadata)
		if err != nil {
			return nil, nil, firstRangeMissingError{err}
		}
		info := infoI.(storage.RangeDescriptor)
		return storage.KeyMin, &info, nil
	}

	// Look up the range containing metadataKey in the cache, which will
	// recursively call into db.LookupRangeMetadata if it is not cached.
	metadataRange, err := db.rangeCache.LookupRangeMetadata(metadataKey)
	if err != nil {
		return nil, nil, err
	}
	return db.internalRangeLookup(metadataKey, metadataRange)
}
예제 #4
0
// LookupRangeMetadata attempts to locate metadata for the range containing the
// given Key. This is done by querying the two-level lookup table of range
// metadata which cockroach maintains.
//
// This method first looks up the specified key in the first level of range
// metadata, which returns the location of the key within the second level of
// range metadata. This second level location is then queried to retrieve
// metadata for the range where the key's value resides. Range metadata
// descriptors retrieved during each search are cached for subsequent lookups.
//
// This method returns the RangeDescriptor for the range containing the key's
// data, or an error if any occurred.
func (rmc *RangeMetadataCache) LookupRangeMetadata(key storage.Key) (*storage.RangeDescriptor, error) {
	metadataKey := storage.RangeMetaKey(key)
	if len(metadataKey) == 0 {
		// The description of the first range is gossiped, and thus does not
		// need to be cached.  Just ask the underlying db, which will return
		// immediately.
		_, r, err := rmc.db.LookupRangeMetadata(key)
		return r, err
	}

	_, r := rmc.getCachedRangeMetadata(key)
	if r != nil {
		return r, nil
	}

	k, r, err := rmc.db.LookupRangeMetadata(key)
	if err != nil {
		return nil, err
	}
	rmc.rangeCacheMu.Lock()
	rmc.rangeCache.Add(rangeCacheKey(k), r)
	rmc.rangeCacheMu.Unlock()
	return r, nil
}