func createCurrentScan() { // We are not going to call the function FinishAnalyzingDomainForScan because it will reset the // current scan information model.StartNewScan() model.LoadedDomainForScan() model.LoadedDomainForScan() model.LoadedDomainForScan() model.FinishAnalyzingDomainForScan(false) model.LoadedDomainForScan() model.LoadedDomainForScan() model.FinishLoadingDomainsForScan() model.FinishAnalyzingDomainForScan(false) model.FinishAnalyzingDomainForScan(false) model.FinishAnalyzingDomainForScan(true) }
// This method is the last part of the scan, when the new state of the domain object is // persisted back to the database. It receives a go routine control group to sinalize to // the main thread when the scan ends, a domain channel to receive each domain that need // to be save and an error channel to send back all errors while persisting the data. It // was created to be asynchronous and finish after receiving a poison pill from querier // dispatcher func (c *Collector) Start(scanGroup *sync.WaitGroup, domainsToSaveChannel chan *model.Domain, errorsChannel chan error) { // Add one more to the group of scan go routines scanGroup.Add(1) go func() { // Initialize Domain DAO using injected database connection domainDAO := dao.DomainDAO{ Database: c.Database, } // Add a safety check to avoid an infinite loop if c.SaveAtOnce == 0 { c.SaveAtOnce = 1 } finished := false nameserverStatistics := make(map[string]uint64) dsStatistics := make(map[string]uint64) for { // Using make for faster allocation domains := make([]*model.Domain, 0, c.SaveAtOnce) for i := 0; i < c.SaveAtOnce; i++ { domain := <-domainsToSaveChannel // Detect poison pill. We don't return from function here because we can still // have some domains to save in the domains array if domain == nil { finished = true break } // Count this domain for the scan information to estimate the scan progress model.FinishAnalyzingDomainForScan(len(domain.DSSet) > 0) // Keep track of nameservers statistics for _, nameserver := range domain.Nameservers { status := model.NameserverStatusToString(nameserver.LastStatus) nameserverStatistics[status] += 1 } // Keep track of DS statistics for _, ds := range domain.DSSet { status := model.DSStatusToString(ds.LastStatus) dsStatistics[status] += 1 } domains = append(domains, domain) } domainsResults := domainDAO.SaveMany(domains) for _, domainResult := range domainsResults { if domainResult.Error != nil { // Error channel should have a buffer or this will block the collector until // someone check this error. One question here is that we are returning the // error, but not telling wich domain got the error, we should improve the error // communication system between the go routines errorsChannel <- domainResult.Error } } // Now that everything is done, check if we received a poison pill if finished { model.StoreStatisticsOfTheScan(nameserverStatistics, dsStatistics) scanGroup.Done() return } } }() }