func main() {
	runtime.GOMAXPROCS(runtime.NumCPU()) // Use all the machine's cores
	if len(os.Args) != 2 || os.Args[1] == "-h" || os.Args[1] == "--help" {
		fmt.Printf("usage: %s <file.log>\n", filepath.Base(os.Args[0]))
		os.Exit(1)
	}
	lines := make(chan string)
	done := make(chan struct{}, workers)
	pageList := safeslice.New()
	go readLines(os.Args[1], lines)
	getRx := regexp.MustCompile(`GET[ \t]+([^ \t\n]+[.]html?)`)
	for i := 0; i < workers; i++ {
		go processLines(done, getRx, pageList, lines)
	}
	waitUntil(done)
	showResults(pageList)
}
Example #2
0
func TestSafeSlice(t *testing.T) {
	store := safeslice.New()
	fmt.Printf("Initially has %d items\n", store.Len())

	deleted := []int{0, 2, 3, 5, 7, 20, 399, 25, 30, 1000, 91, 97, 98, 99}

	var waiter sync.WaitGroup

	waiter.Add(1)
	go func() { // Concurrent Inserter
		for i := 0; i < 100; i++ {
			store.Append(fmt.Sprintf("%04X", i))
			if i > 0 && i%15 == 0 {
				fmt.Printf("Inserted %d items\n", store.Len())
			}
		}
		fmt.Printf("Inserted %d items\n", store.Len())
		waiter.Done()
	}()

	waiter.Add(1)
	go func() { // Concurrent Deleter
		for _, i := range deleted {
			before := store.Len()
			store.Delete(i)
			fmt.Printf("Deleted m[%d] before=%d after=%d\n",
				i, before, store.Len())
		}
		waiter.Done()
	}()

	waiter.Add(1)
	go func() { // Concurrent Finder
		for _, i := range deleted {
			for _, j := range []int{i, i + 1} {
				item := store.At(j)
				if item != nil {
					fmt.Printf("Found m[%d] == %s\n", j, item)
				} else {
					fmt.Printf("Not found m[%d]\n", j)
				}
			}
		}
		waiter.Done()
	}()

	waiter.Wait()

	fmt.Printf("Finished with %d items\n", store.Len())
	updater := func(value interface{}) interface{} {
		return value.(string) + ":updated"
	}
	for i := 0; i < store.Len() && i < 5; i++ {
		fmt.Printf("m[%d] == %s -> ", i, store.At(i))
		store.Update(i, updater)
		fmt.Printf("%s\n", store.At(i))
	}
	list := store.Close()
	fmt.Println("Closed")
	fmt.Printf("len == %d\n", len(list))
	fmt.Println()
}