// Creates or opens the relevant whisper db file, and returns running // WhisperRunner that will write to that file. func NewWhisperRunner(path_ string, archiveInfo []whisper.ArchiveInfo, aggMethod whisper.AggregationMethod, folderPerm os.FileMode, wg *sync.WaitGroup) (wr WhisperRunner, err error) { var db *whisper.Whisper if db, err = whisper.Open(path_); err != nil { if !os.IsNotExist(err) { // A real error. err = fmt.Errorf("Error opening whisper db: %s", err) return } // First make sure the folder is there. dir := filepath.Dir(path_) if _, err = os.Stat(dir); os.IsNotExist(err) { if err = os.MkdirAll(dir, folderPerm); err != nil { err = fmt.Errorf("Error creating whisper db folder '%s': %s", dir, err) return } } else if err != nil { err = fmt.Errorf("Error opening whisper db folder '%s': %s", dir, err) } createOptions := whisper.CreateOptions{0.1, aggMethod, false} if db, err = whisper.Create(path_, archiveInfo, createOptions); err != nil { err = fmt.Errorf("Error creating whisper db: %s", err) return } } inChan := make(chan *whisper.Point, 10) realWr := &wRunner{path_, db, inChan, wg} realWr.start() wr = realWr return }
func WhisperRunnerSpec(c gospec.Context) { tmpDir := os.TempDir() tmpFileName := fmt.Sprintf("heka-%d.wsp", time.Now().UTC().UnixNano()) tmpFileName = filepath.Join(tmpDir, tmpFileName) interval := uint32(10) archiveInfo := []whisper.ArchiveInfo{ whisper.ArchiveInfo{0, interval, 60}, whisper.ArchiveInfo{0, 60, 8}, } c.Specify("A WhisperRunner", func() { var wg sync.WaitGroup wg.Add(1) folderPerm := os.FileMode(0755) wr, err := NewWhisperRunner(tmpFileName, archiveInfo, whisper.AggregationSum, folderPerm, &wg) c.Assume(err, gs.IsNil) defer func() { os.Remove(tmpFileName) }() c.Specify("creates a whisper file of the correct size", func() { fi, err := os.Stat(tmpFileName) c.Expect(err, gs.IsNil) c.Expect(fi.Size(), gs.Equals, int64(856)) close(wr.InChan()) wg.Wait() }) c.Specify("writes a data point to the whisper file", func() { // Send a data point through and close. when := time.Now().UTC() val := float64(6) pt := whisper.NewPoint(when, val) wr.InChan() <- &pt close(wr.InChan()) wg.Wait() // Open db file and fetch interval including our data point. from := when.Add(-1 * time.Second).Unix() until := when.Add(1 * time.Second).Unix() db, err := whisper.Open(tmpFileName) c.Expect(err, gs.IsNil) _, fetched, _ := db.FetchUntil(uint32(from), uint32(until)) // Verify that our value is stored in the most recent interval and // that the diff btn our timestamp and the stored time value is // less than the interval duration. fpt := fetched[len(fetched)-1] diff := when.Sub(fpt.Time().UTC()) c.Expect(diff.Seconds() < float64(interval), gs.IsTrue) c.Expect(fpt.Value, gs.Equals, val) }) }) }