func (f *RealIntervalIterFactory) Make(analyzerType string, mysqlConn mysql.Connector, tickChan chan time.Time) qan.IntervalIter { switch analyzerType { case "slowlog": // The interval iter gets the slow log file (@@global.slow_query_log_file) // every tick because it can change (not typical, but possible). If it changes, // the start offset is reset to 0 for the new file. getSlowLogFunc := func() (string, error) { if err := mysqlConn.Connect(1); err != nil { return "", err } defer mysqlConn.Close() // Slow log file can be absolute or relative. If it's relative, // then prepend the datadir. dataDir := mysqlConn.GetGlobalVarString("datadir") filename := AbsDataFile(dataDir, mysqlConn.GetGlobalVarString("slow_query_log_file")) return filename, nil } return slowlog.NewIter(pct.NewLogger(f.logChan, "qan-interval"), getSlowLogFunc, tickChan) case "perfschema": return perfschema.NewIter(pct.NewLogger(f.logChan, "qan-interval"), tickChan) default: panic("Invalid analyzerType: " + analyzerType) } }
func (s *IterTestSuite) TestIterFile(t *C) { tickChan := make(chan time.Time) // This is the file we iterate. It's 3 bytes large to start, // so that should be the StartOffset. tmpFile, _ := ioutil.TempFile("/tmp", "interval_test.") tmpFile.Close() fileName = tmpFile.Name() _ = ioutil.WriteFile(tmpFile.Name(), []byte("123"), 0777) defer func() { os.Remove(tmpFile.Name()) }() // Start interating the file, waiting for ticks. i := slowlog.NewIter(s.logger, getFilename, tickChan) i.Start() // Send a tick to start the interval t1 := time.Now() tickChan <- t1 // Write more data to the file, pretend time passes... _ = ioutil.WriteFile(tmpFile.Name(), []byte("123456"), 0777) // Send a 2nd tick to finish the interval t2 := time.Now() tickChan <- t2 // Get the interval got := <-i.IntervalChan() expect := &qan.Interval{ Number: 1, Filename: fileName, StartTime: t1, StopTime: t2, StartOffset: 3, EndOffset: 6, } t.Check(got, test.DeepEquals, expect) /** * Rename the file, then re-create it. The file change should be detected. */ oldFileName := tmpFile.Name() + "-old" os.Rename(tmpFile.Name(), oldFileName) defer os.Remove(oldFileName) // Re-create original file and write new data. We expect StartOffset=0 // because the file is new, and EndOffset=10 because that's the len of // the new data. The old ^ file/data had start/stop offset 3/6, so those // should not appear in next interval; if they do, then iter failed to // detect file change and is still reading old file. tmpFile, _ = os.Create(fileName) tmpFile.Close() _ = ioutil.WriteFile(fileName, []byte("123456789A"), 0777) t3 := time.Now() tickChan <- t3 got = <-i.IntervalChan() expect = &qan.Interval{ Number: 2, Filename: fileName, StartTime: t2, StopTime: t3, StartOffset: 0, EndOffset: 10, } t.Check(got, test.DeepEquals, expect) // Iter should no longer detect file change. _ = ioutil.WriteFile(fileName, []byte("123456789ABCDEF"), 0777) // ^^^^^ new data t4 := time.Now() tickChan <- t4 got = <-i.IntervalChan() expect = &qan.Interval{ Number: 3, Filename: fileName, StartTime: t3, StopTime: t4, StartOffset: 10, EndOffset: 15, } t.Check(got, test.DeepEquals, expect) i.Stop() }