<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"os"
	"os/signal"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/gorilla/mux"
	"github.com/miekg/dns"
	"github.com/rancher/rancher-dns/cache"
)

var (
	showVersion     = flag.Bool("version", false, "Show version")
	debug           = flag.Bool("debug", false, "Debug")
	listen          = flag.String("listen", ":53", "Address to listen to (TCP and UDP)")
	listenReload    = flag.String("listenReload", "127.0.0.1:8113", "Address to listen to for reload requests (TCP)")
	answersFile     = flag.String("answers", "./answers.yaml", "File containing the answers to respond with")
	defaultTtl      = flag.Uint("ttl", 600, "TTL for answers")
	recurserTimeout = flag.Uint("recurser-timeout", 2, "timeout (in seconds) for recurser")
	ndots           = flag.Uint("ndots", 0, "Queries with more than this number of dots will not use search paths")
	cacheCapacity   = flag.Uint("cache-capacity", 1000, "Cache capacity")
	logFile         = flag.String("log", "", "Log file")
	pidFile         = flag.String("pid-file", "", "PID to write to")
	metadataServer  = flag.String("metadata-server", "", "Metadata server url")
	metadataAnswer  = flag.String("rancher-metadata-answer", "169.254.169.250", "Metadata IP address(es), comma-delimited (adds static A records)")
	neverRecurseTo  = flag.String("never-recurse-to", "169.254.169.250", "Never recurse to IP address(es), comma-delimited")
	namespace       = flag.String("namespace", "discover.internal", "Global namespace")

	answers                   Answers
	globalCache               *cache.Cache
	clientSpecificCaches      map[string]*cache.Cache
	clientSpecificCachesMutex sync.RWMutex
	VERSION                   string
	reloadChan                = make(chan chan error)
	serial                    = uint32(1)
	configGenerator           *ConfigGenerator
)

func metadataDriven() bool {
	return *metadataServer != ""
}

func main() {
	parseFlags()

	log.Infof("Starting rancher-dns %s", VERSION)
	err := loadAnswers()
	if err != nil {
		log.Fatal("Cannot startup without a valid Answers file")
	}

	if *showVersion {
		fmt.Printf("%s\n", VERSION)
		os.Exit(0)
	}

	if metadataDriven() {
		configGenerator = &ConfigGenerator{}
		err = configGenerator.Init(metadataServer)
		if err != nil {
			log.Fatalf("Cannot startup: failed to init config generator: %v", err)
		}
	}

	watchSignals()
	watchHttp()

	seed := time.Now().UTC().UnixNano()
	log.Debug("Set random seed to ", seed)
	rand.Seed(seed)

	udpServer := &dns.Server{Addr: *listen, Net: "udp"}
	tcpServer := &dns.Server{Addr: *listen, Net: "tcp"}

	globalCache = cache.New(int(*cacheCapacity), int(*defaultTtl))
	clientSpecificCaches = make(map[string]*cache.Cache)

	dns.HandleFunc(".", route)

	go func() {
		log.Fatal(udpServer.ListenAndServe())
	}()
	log.Info("Listening on ", *listen)
	log.Fatal(tcpServer.ListenAndServe())
}

func parseFlags() {
	flag.Parse()

	if *debug {
		log.SetLevel(log.DebugLevel)
	}

	if *logFile != "" {
		if output, err := os.OpenFile(*logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666); err != nil {
			log.Fatalf("Failed to log to file %s: %v", *logFile, err)
		} else {
			log.SetOutput(output)
		}
	}

	if *pidFile != "" {
		log.Infof("Writing pid %d to %s", os.Getpid(), *pidFile)
		if err := ioutil.WriteFile(*pidFile, []byte(strconv.Itoa(os.Getpid())), 0644); err != nil {
			log.Fatalf("Failed to write pid file %s: %v", *pidFile, err)
		}
	}
}

func loadAnswersFromMeta(name string) {
	newAnswers, err := configGenerator.GenerateAnswers()
	if err != nil {
		log.Errorf("Failed to generate answers: %v", err)
	}
	ConvertPtrIps(&newAnswers)

	if reflect.DeepEqual(newAnswers, answers) {
		log.Debug("No changes in dns data")
		return
	}

	log.Infof("Reloading answers")
	clearClientSpecificCaches()
	answers = newAnswers
	// write to file (debugging purposes)
	b, err := json.Marshal(answers)
	if err != nil {
		log.Errorf("Failed to marshall answers: %v", err)<commit_msg>do not reload answers if fail to generate<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"os"
	"os/signal"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/gorilla/mux"
	"github.com/miekg/dns"
	"github.com/rancher/rancher-dns/cache"
)

var (
	showVersion     = flag.Bool("version", false, "Show version")
	debug           = flag.Bool("debug", false, "Debug")
	listen          = flag.String("listen", ":53", "Address to listen to (TCP and UDP)")
	listenReload    = flag.String("listenReload", "127.0.0.1:8113", "Address to listen to for reload requests (TCP)")
	answersFile     = flag.String("answers", "./answers.yaml", "File containing the answers to respond with")
	defaultTtl      = flag.Uint("ttl", 600, "TTL for answers")
	recurserTimeout = flag.Uint("recurser-timeout", 2, "timeout (in seconds) for recurser")
	ndots           = flag.Uint("ndots", 0, "Queries with more than this number of dots will not use search paths")
	cacheCapacity   = flag.Uint("cache-capacity", 1000, "Cache capacity")
	logFile         = flag.String("log", "", "Log file")
	pidFile         = flag.String("pid-file", "", "PID to write to")
	metadataServer  = flag.String("metadata-server", "", "Metadata server url")
	metadataAnswer  = flag.String("rancher-metadata-answer", "169.254.169.250", "Metadata IP address(es), comma-delimited (adds static A records)")
	neverRecurseTo  = flag.String("never-recurse-to", "169.254.169.250", "Never recurse to IP address(es), comma-delimited")
	namespace       = flag.String("namespace", "discover.internal", "Global namespace")

	answers                   Answers
	globalCache               *cache.Cache
	clientSpecificCaches      map[string]*cache.Cache
	clientSpecificCachesMutex sync.RWMutex
	VERSION                   string
	reloadChan                = make(chan chan error)
	serial                    = uint32(1)
	configGenerator           *ConfigGenerator
)

func metadataDriven() bool {
	return *metadataServer != ""
}

func main() {
	parseFlags()

	log.Infof("Starting rancher-dns %s", VERSION)
	err := loadAnswers()
	if err != nil {
		log.Fatal("Cannot startup without a valid Answers file")
	}

	if *showVersion {
		fmt.Printf("%s\n", VERSION)
		os.Exit(0)
	}

	if metadataDriven() {
		configGenerator = &ConfigGenerator{}
		err = configGenerator.Init(metadataServer)
		if err != nil {
			log.Fatalf("Cannot startup: failed to init config generator: %v", err)
		}
	}

	watchSignals()
	watchHttp()

	seed := time.Now().UTC().UnixNano()
	log.Debug("Set random seed to ", seed)
	rand.Seed(seed)

	udpServer := &dns.Server{Addr: *listen, Net: "udp"}
	tcpServer := &dns.Server{Addr: *listen, Net: "tcp"}

	globalCache = cache.New(int(*cacheCapacity), int(*defaultTtl))
	clientSpecificCaches = make(map[string]*cache.Cache)

	dns.HandleFunc(".", route)

	go func() {
		log.Fatal(udpServer.ListenAndServe())
	}()
	log.Info("Listening on ", *listen)
	log.Fatal(tcpServer.ListenAndServe())
}

func parseFlags() {
	flag.Parse()

	if *debug {
		log.SetLevel(log.DebugLevel)
	}

	if *logFile != "" {
		if output, err := os.OpenFile(*logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666); err != nil {
			log.Fatalf("Failed to log to file %s: %v", *logFile, err)
		} else {
			log.SetOutput(output)
		}
	}

	if *pidFile != "" {
		log.Infof("Writing pid %d to %s", os.Getpid(), *pidFile)
		if err := ioutil.WriteFile(*pidFile, []byte(strconv.Itoa(os.Getpid())), 0644); err != nil {
			log.Fatalf("Failed to write pid file %s: %v", *pidFile, err)
		}
	}
}

func loadAnswersFromMeta(name string) {
	newAnswers, err := configGenerator.GenerateAnswers()
	if err != nil {
		log.Errorf("Failed to generate answers: %v", err)
		return
	}
	ConvertPtrIps(&newAnswers)

	if reflect.DeepEqual(newAnswers, answers) {
		log.Debug("No changes in dns data")
		return
	}

	log.Infof("Reloading answers")
	clearClientSpecificCaches()
	answers = newAnswers
	// write to file (debugging purposes)
	b, err := json.Marshal(answers)
	if err != nil {
		log.Errorf("Failed to marshall answers: %v", err)
{'fraction_non_alphanumeric': 0.15450018219361109, 'fraction_numerical': 0.013846714441880239, 'mean_word_length': 3.745821325648415, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 6, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4270840', 'n_tokens_mistral': 3117, 'n_tokens_neox': 2889, 'n_words': 685}