// findSeriesByTags 根据标签查找序列 func (e *FileEngine) findSeriesByTags(tags map[string]string) ([]string, error) { e.tagIndex.mu.RLock() defer e.tagIndex.mu.RUnlock() if len(tags) == 0 { // 如果没有指定标签,返回所有序列 allSeries := make(map[string]struct{}) for _, valueMap := range e.tagIndex.index { for _, seriesIDs := range valueMap { for _, seriesID := range seriesIDs { allSeries[seriesID] = struct{}{} } } } // 转换为切片 result := make([]string, 0, len(allSeries)) for seriesID := range allSeries { result = append(result, seriesID) } return result, nil } // 对于每个标签,找到匹配的序列 var matchedSeries map[string]struct{} first := true for key, value := range tags { // 获取标签值映射 valueMap, ok := e.tagIndex.index[key] if !ok { // 如果标签键不存在,返回空结果 return []string{}, nil } // 获取匹配标签值的序列 seriesIDs, ok := valueMap[value] if !ok { // 如果标签值不存在,返回空结果 return []string{}, nil } // 初始化或取交集 if first { matchedSeries = make(map[string]struct{}) for _, id := range seriesIDs { matchedSeries[id] = struct{}{} } first = false } else { // 取交集 newMatched := make(map[string]struct{}) for _, id := range seriesIDs { if _, ok := matchedSeries[id]; ok { newMatched[id] = struct{}{} } } matchedSeries = newMatched } // 如果没有匹配的序列,提前返回 if len(matchedSeries) == 0 { return []string{}, nil } } // 转换为切片 result := make([]string, 0, len(matchedSeries)) for seriesID := range matchedSeries { result = append(result, seriesID) } return result, nil } // readPointsFromSegment 从段文件中读取数据点 func (e *FileEngine) readPointsFromSegment(segment *Segment, offset int64, count int) ([]engine.DataPoint, error) { segment.mu.RLock() defer segment.mu.RUnlock() // 如果文件为空,直接返回 if segment.size == 0 { return []engine.DataPoint{}, nil } // 移动文件指针到指定位置 _, err := segment.file.Seek(offset, 0) if err != nil { return nil, fmt.Errorf("failed to seek segment file: %v", err) } // 读取指定数量的数据点 points := make([]engine.DataPoint, 0, count) for i := 0; i < count; i++ { // 读取时间戳(8字节) var timestamp int64 err := binary.Read(segment.file, binary.LittleEndian, ×tamp) if err != nil { if err == io.EOF { break } return nil, fmt.Errorf("failed to read timestamp: %v", err) } // 读取值(8字节) var value float64 err = binary.Read(segment.file, binary.LittleEndian, &value) if err != nil { return nil, fmt.Errorf("failed to read value: %v", err) } // 创建数据点 point := engine.DataPoint{ Timestamp: timestamp, Value: value, } points = append(points, point) } return points, nil } // findTimeWindows 查找指定时间范围内的时间窗口 func (e *FileEngine) findTimeWindows(seriesID string, startTime, endTime int64) ([]timeWindow, error) { e.timeIndex.mu.RLock() defer e.timeIndex.mu.RUnlock() // 获取序列的所有时间窗口 windows, ok := e.timeIndex.windows[seriesID] if !ok { return nil, nil // 序列不存在 } // 找到所有与时间范围重叠的窗口 var matchedWindows []timeWindow for _, window := range windows { // 检查窗口是否与查询时间范围重叠 if window.endTime >= startTime && window.startTime <= endTime { matchedWindows = append(matchedWindows, window) } } // 按时间排序 sort.Slice(matchedWindows, func(i, j int) bool { return matchedWindows[i].startTime < matchedWindows[j].startTime }) return matchedWindows, nil } // getLabelsForSeries 获取序列的标签 func (e *FileEngine) getLabelsForSeries(seriesID string) map[string]string { e.tagIndex.mu.RLock() defer e.tagIndex.mu.RUnlock() labels := make(map[string]string) // 遍历所有标签 for key, valueMap := range e.tagIndex.index { // 遍历每个标签值 for value, seriesIDs := range valueMap { // 检查序列ID是否在列表中 for _, id := range seriesIDs { if id == seriesID { labels[key] = value break } } } } return labels } // newTimeIndex 创建新的时间索引 func newTimeIndex() *TimeIndex { return &TimeIndex{ windows: make(map[string][]timeWindow), } } // newTagIndex 创建新的标签索引 func newTagIndex() *TagIndex { return &TagIndex{ index: make(map[string]map[string][]string), } } // WritePoint 向段文件写入数据点 func (s *Segment) WritePoint(point engine.DataPoint) (int64, error) { s.mu.Lock() defer s.mu.Unlock() // 获取当前偏移量 offset, err := s.file.Seek(0, io.SeekCurrent) if err != nil { return 0, fmt.Errorf("failed to get file offset: %v", err) } // 写入时间戳(8字节) err = binary.Write(s.file, binary.LittleEndian, point.Timestamp) if err != nil { return 0, fmt.Errorf("failed to write timestamp: %v", err) } // 写入值(8字节) err = binary.Write(s.file, binary.LittleEndian, point.Value) if err != nil { return 0, fmt.Errorf("failed to write value: %v", err) } // 更新段文件信息 s.size += 16 // 每个数据点16字节 s.pointCount++ if s.startTime == 0 || point.Timestamp < s.startTime { s.startTime = point.Timestamp } if point.Timestamp > s.endTime { s.endTime = point.Timestamp } return offset, nil } // Close 关闭段文件 func (s *Segment) Close() error { s.mu.Lock() defer s.mu.Unlock() if s.file != nil { if err := s.file.Close(); err != nil { return fmt.Errorf("failed to close segment file: %v", err) } s.file = nil } return nil } // Sync 将段文件同步到磁盘 func (s *Segment) Sync() error { s.mu.Lock() defer s.mu.Unlock() if s.file != nil { if err := s.file.Sync(); err != nil { return fmt.Errorf("failed to sync segment file: %v", err) } } return nil }