// mapFP takes a raw fingerprint (as returned by Metrics.FastFingerprint) and // returns a truly unique fingerprint. The caller must have locked the raw // fingerprint. // // If an error is encountered, it is returned together with the unchanged raw // fingerprint. func (m *fpMapper) mapFP(fp model.Fingerprint, metric model.Metric) model.Fingerprint { // First check if we are in the reserved FP space, in which case this is // automatically a collision that has to be mapped. if fp <= maxMappedFP { return m.maybeAddMapping(fp, metric) } // Then check the most likely case: This fp belongs to a series that is // already in memory. s, ok := m.fpToSeries.get(fp) if ok { // FP exists in memory, but is it for the same metric? if metric.Equal(s.metric) { // Yupp. We are done. return fp } // Collision detected! return m.maybeAddMapping(fp, metric) } // Metric is not in memory. Before doing the expensive archive lookup, // check if we have a mapping for this metric in place already. m.mtx.RLock() mappedFPs, fpAlreadyMapped := m.mappings[fp] m.mtx.RUnlock() if fpAlreadyMapped { // We indeed have mapped fp historically. ms := metricToUniqueString(metric) // fp is locked by the caller, so no further locking of // 'collisions' required (it is specific to fp). mappedFP, ok := mappedFPs[ms] if ok { // Historical mapping found, return the mapped FP. return mappedFP } } // If we are here, FP does not exist in memory and is either not mapped // at all, or existing mappings for FP are not for m. Check if we have // something for FP in the archive. archivedMetric, err := m.p.archivedMetric(fp) if err != nil || archivedMetric == nil { // Either the archive lookup has returend an error, or fp does // not exist in the archive. In the former case, the storage has // been marked as dirty already. We just carry on for as long as // it goes, assuming that fp does not exist. In either case, // since now we know (or assume) now that fp does not exist, // neither in memory nor in archive, we can safely keep it // unmapped. return fp } // FP exists in archive, but is it for the same metric? if metric.Equal(archivedMetric) { // Yupp. We are done. return fp } // Collision detected! return m.maybeAddMapping(fp, metric) }