Beispiel #1
0
// Subscribe registers handler to be invoked on any event that matches prefix topicPrefix.
//
// The handlers registered with Subscribe are invoked asynchronously using go when an event
// matching the relevant prefix is received.
func (exchange *Exchange) Subscribe(topicPrefix Topic, handler EventHandler) (Handle, error) {
	exchange.cond.L.Lock()
	defer exchange.cond.L.Unlock()

	if exchange.state != stateRunning {
		return 0, ErrInvalidState
	}

	handle, err := exchange.getHandle(topicPrefix)
	if err != nil {
		return 0, err
	}

	record := &handlerRecord{
		handle:  handle,
		handler: handler,
	}

	if item := exchange.trie.Get(patricia.Prefix(topicPrefix)); item == nil {
		records := []*handlerRecord{record}
		exchange.trie.Insert(patricia.Prefix(topicPrefix), &records)
	} else {
		records := item.(*[]*handlerRecord)
		*records = append(*records, record)
	}

	return record.handle, nil
}
Beispiel #2
0
// MkPath makes a new directory under the current rootPath.  The path variable
// is expected to be relative to the rootPath.  The diectory will both be added
// to the internal representation AND be added to the real filesystem.  Fails
// if the  specified path is a file, returns nil if the specified path already
// exists.
func (fs *TransientFilesystem) MkPath(path string) error {
	absPath := realPath(fs, path)

	// actually make path
	if absPath == fs.RootPath() {
		return nil
	}
	fi, err := os.Stat(absPath)
	if err != nil && !os.IsNotExist(err) {
		return ErrFileNoExist
	}
	if fi != nil && !fi.IsDir() {
		return ErrFileExists
	}
	doTrieGet := func() (bool, error) {
		fs.lock.RLock()
		defer fs.lock.RUnlock()
		if fs.trie.Match(trie.Prefix(absPath)) {
			if fs.trie.Get(trie.Prefix(absPath)).(os.FileInfo).IsDir() {
				return true, nil
			} else {
				return false, fmt.Errorf("specified path %s exists in memory as a file, but does not exist on disk", path)
			}
		}
		return false, nil
	}
	existsInMem, err := doTrieGet()
	if err != nil {
		return err
	} else if existsInMem {
		return nil
	}
	if err = os.MkdirAll(absPath, 0755); err != nil {
		return err
	}
	fi, err = os.Stat(absPath)
	if err != nil {
		return err
	}

	// insert into trie
	insertIntoTrie := func() error {
		fs.lock.Lock()
		defer fs.lock.Unlock()
		if success := fs.trie.Insert(trie.Prefix(absPath), fi); !success {
			return fmt.Errorf("path %s already exists in memory", path)
		}
		return nil
	}
	if err := insertIntoTrie(); err != nil {
		// recover
		if rmErr := os.RemoveAll(absPath); rmErr != nil {
			// wow this is bad, failure inserting into the trie, AND failure
			// cleaning up after ourselves
			return fmt.Errorf("failure creating path %s in memory: %s, and failure cleaning up alrready created path %s: %s", path, err.Error(), path, rmErr.Error())
		}
		return err
	}
	return nil
}
Beispiel #3
0
func main() {
	key := flag.String("key", "", "key in dot notation")
	version := flag.Bool("v", false, "show version and exit")

	flag.Parse()

	if *version {
		fmt.Println(Version)
		os.Exit(0)
	}

	if *key == "" {
		log.Fatal("key is required")
	}

	var reader *bufio.Reader
	if flag.NArg() < 1 {
		reader = bufio.NewReader(os.Stdin)
	} else {
		file, err := os.Open(flag.Arg(0))
		if err != nil {
			log.Fatal(err)
		}
		defer file.Close()
		reader = bufio.NewReader(file)
	}

	trie := patricia.NewTrie()

	for {
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}
		doc := make(map[string]interface{})
		err = json.Unmarshal([]byte(line), &doc)
		if err != nil {
			log.Fatal(err)
		}
		val, err := StringValue(*key, doc)
		if err != nil {
			log.Fatal(err)
		}
		if trie.Match(patricia.Prefix(val)) {
			log.Println("SKIP")
			continue
		}
		b, err := json.Marshal(doc)
		if err != nil {
			log.Fatal(err)
		}
		trie.Insert(patricia.Prefix(val), 1)
		fmt.Println(string(b))
	}
}
Beispiel #4
0
func (lm *LocationMuxer) longestMatchingPath(path string) *types.Location {
	pathAsPrefix := patricia.Prefix(path)
	var matchSoFar patricia.Prefix
	var matchedItem *types.Location
	err := lm.locationTrie.Visit(func(prefix patricia.Prefix, item patricia.Item) error {
		if len(prefix) > len(pathAsPrefix) {
			return patricia.SkipSubtree
		} else if len(prefix) > len(matchSoFar) && bytes.EqualFold(prefix, pathAsPrefix[:len(prefix)]) {
			exactMatch := len(prefix) == len(pathAsPrefix)
			matchedLocation := item.(*types.Location)
			if isLocationType(matchedLocation, exact) && !exactMatch {
				return nil
			}

			matchedItem = matchedLocation
			matchSoFar = prefix
			if exactMatch {
				return errExactMatch // not an error, just so the search is canceled
			}
		}
		return nil
	})

	if err != nil && err != errExactMatch {
		panic(err) // an impossible error
	}

	return matchedItem
}
Beispiel #5
0
// Get retrieves an ID from the TruncIndex. If there are multiple IDs
// with the given prefix, an error is thrown.
func (idx *TruncIndex) Get(s string) (string, error) {
	if s == "" {
		return "", ErrEmptyPrefix
	}
	var (
		id string
	)
	subTreeVisitFunc := func(prefix patricia.Prefix, item patricia.Item) error {
		if id != "" {
			// we haven't found the ID if there are two or more IDs
			id = ""
			return ErrAmbiguousPrefix
		}
		id = string(prefix)
		return nil
	}

	idx.RLock()
	defer idx.RUnlock()
	if err := idx.trie.VisitSubtree(patricia.Prefix(s), subTreeVisitFunc); err != nil {
		return "", err
	}
	if id != "" {
		return id, nil
	}
	return "", fmt.Errorf("no such id: %s", s)
}
Beispiel #6
0
// MkFile makes a file consisting of the provided content at the given path.
// If the path does not already exist, an error will be returned.  If the file
// already exists, an error will be returned.
func (fs *TransientFilesystem) MkFile(path string, content []byte) error {
	if !fs.PathExists(filepath.Dir(path)) {
		return ErrPathNoExist
	} else if fs.PathExists(path) {
		return ErrFileExists
	}

	absPath := realPath(fs, path)
	if err := ioutil.WriteFile(absPath, content, 0644); err != nil {
		return err
	}
	doInsertTrie := func() error {
		fs.lock.Lock()
		defer fs.lock.Unlock()
		fi, err := os.Stat(absPath)
		if err != nil {
			return err
		}
		if success := fs.trie.Insert(trie.Prefix(absPath), fi); !success {
			// path already exists in trie
			if err := os.RemoveAll(absPath); err != nil {
				// this is bad
				return fmt.Errorf("file %s already exists in memory and error removing file %s: %s", path, path, err)
			}
			// technically this is a little misleading, as it refers to the
			// trie, not what's on disk, but c'est la vie
			return ErrFileExists
		}
		return nil
	}
	if err := doInsertTrie(); err != nil {
		return err
	}
	return nil
}
Beispiel #7
0
// RmPath recursively removes a path from the filesystem.  The path argument
// can be either a file or directory relative to the rootPath.  Returns an
// error if the path does not exist, or if there was an error removing
// part of the path.
func (fs *TransientFilesystem) RmPath(path string) error {

	absPath := realPath(fs, path)
	switch path {
	case "/", "":
		return fmt.Errorf("unwilling to delete root filesystem path %s", fs.RootPath())
	default:
	}

	doGet := func() interface{} {
		fs.lock.RLock()
		defer fs.lock.RUnlock()
		return fs.trie.Get(trie.Prefix(absPath))
	}
	item := doGet()
	if item == nil {
		return ErrPathNoExist
	}
	if !item.(os.FileInfo).IsDir() {
		return ErrFileExists
	}
	// Make this a function so we can release the mutex ASAP
	doTrieDelete := func() error {
		fs.lock.Lock()
		defer fs.lock.Unlock()
		if deleted := fs.trie.Delete(trie.Prefix(absPath)); !deleted {
			return fmt.Errorf("path %s does not exist in memory", path)
		}
		return nil
	}
	if err := doTrieDelete(); err != nil {
		return err
	}
	if err := os.RemoveAll(absPath); err != nil {
		// put item back in the tree
		// eat the error here
		fs.trie.Insert(trie.Prefix(absPath), item)
		// possibly in an unknown state at this point.  whomp whomp.
		return err
	}
	return nil
}
Beispiel #8
0
// Delete removes an ID from the TruncIndex. If there are multiple IDs
// with the given prefix, an error is thrown.
func (idx *TruncIndex) Delete(id string) error {
	idx.Lock()
	defer idx.Unlock()
	if _, exists := idx.ids[id]; !exists || id == "" {
		return fmt.Errorf("no such id: '%s'", id)
	}
	delete(idx.ids, id)
	if deleted := idx.trie.Delete(patricia.Prefix(id)); !deleted {
		return fmt.Errorf("no such id: '%s'", id)
	}
	return nil
}
Beispiel #9
0
func LoadDictionaries() {
	var newDictionaryMap = make(map[string]*patricia.Trie)
	var itemMap = ImportDictionaries()

	numPrefixes := 0
	numSuggestions := 0
	numDictionaries := 0

	for dictionaryName, suggestItems := range itemMap {
		numDictionaries++
		log.Print("Loading dictionary " + dictionaryName)
		// First see if the trie already exists
		var trie, ok = newDictionaryMap[dictionaryName]
		if !ok {
			trie = patricia.NewTrie()
		}

		// Great, we have a trie, now let's see if prefixes for the
		// suggestItems exist in the trie
		for _, suggestItem := range suggestItems {
			numSuggestions++
			//Tokenize the suggested term by whitespace.  Each token will become a prefix in the trie
			var tokens = strings.Fields(suggestItem.Term)
			tokens = append(tokens, suggestItem.Term)
			for _, token := range tokens {
				numPrefixes++
				//TODO: use ascii folding
				lowerToken := strings.ToLower(token)
				// The values in the trie are sorted sets of SuggestItems
				trieItem := trie.Get([]byte(lowerToken))
				if trieItem != nil {
					suggestItemSet := trieItem.(treeset.Set)
					//If the set already exists, add the new suggestion to the set
					suggestItemSet.Add(suggestItem)

				} else {
					// Otherwise create a new set, add the SuggestItem, and insert it into
					// the trie using the lowercase token for the prefix
					suggestItemSet := treeset.NewWith(models.SuggestItemComparator)
					//					log.Printf("Inserting suggestion item %s (%s)", lowerToken, suggestItem.Term)
					suggestItemSet.Add(suggestItem)
					trie.Insert(patricia.Prefix([]byte(lowerToken)), *suggestItemSet)
				}
			}
		}
		newDictionaryMap[dictionaryName] = trie
		log.Print("Dictionary " + dictionaryName + " loaded")
	}
	//Atomic swap
	DictionaryMap = newDictionaryMap
	log.Printf("All dictionaries updated")
}
Beispiel #10
0
// NewDefaultRouter creates a very basic WAMP router.
func NewNode() Router {
	log.Println("Creating new Rabric Node")

	trie := patricia.NewTrie()
	r := &Realm{URI: "pd"}
	trie.Insert(patricia.Prefix("pd"), r)

	return &node{
		realms:                make(map[URI]Realm),
		sessionOpenCallbacks:  []func(uint, string){},
		sessionCloseCallbacks: []func(uint, string){},
		root: trie,
	}
}
Beispiel #11
0
// Unsubscribe cancels the event handler represented by handle.
func (exchange *Exchange) Unsubscribe(handle Handle) error {
	exchange.cond.L.Lock()
	defer exchange.cond.L.Unlock()

	if exchange.state != stateRunning {
		return ErrInvalidState
	}

	topic, ok := exchange.topicForHandle[handle]
	if !ok {
		return ErrInvalidHandle
	}

	delete(exchange.topicForHandle, handle)

	item := exchange.trie.Get(patricia.Prefix(topic))
	if item == nil {
		return ErrInvalidHandle
	}

	records := item.(*[]*handlerRecord)
	if len(*records) == 1 {
		if exchange.trie.Delete(patricia.Prefix(topic)) {
			return nil
		}
	} else {
		for i, record := range *records {
			if record.handle == handle {
				*records = append((*records)[:i], (*records)[i+1:]...)
				return nil
			}
		}
	}

	return ErrInvalidHandle
}
Beispiel #12
0
func (suite *TheSuite) TestTransientFilesystemerCreate(c *C) {
	fileMap := suite.mkDirs(c, suite.tmpdir)
	fs := suite.mkTFS()
	c.Assert(fs.trie.Get(trie.Prefix("aaaaaaaaaaa")), IsNil)
	c.Assert(fs.trie.Get(trie.Prefix(fs.rootPath)), NotNil)
	c.Assert(fs.trie.Get(trie.Prefix(fileMap["d1"])), NotNil)
	c.Assert(fs.trie.Get(trie.Prefix(fileMap["f1"])), NotNil)
	c.Assert(fs.trie.Get(trie.Prefix(fileMap["f2"])), NotNil)
	c.Assert(fs.trie.Get(trie.Prefix(fileMap["f3"])), NotNil)
}
Beispiel #13
0
func (idx *TruncIndex) addID(id string) error {
	if strings.Contains(id, " ") {
		return ErrIllegalChar
	}
	if id == "" {
		return ErrEmptyPrefix
	}
	if _, exists := idx.ids[id]; exists {
		return fmt.Errorf("id already exists: '%s'", id)
	}
	idx.ids[id] = struct{}{}
	if inserted := idx.trie.Insert(patricia.Prefix(id), struct{}{}); !inserted {
		return fmt.Errorf("failed to insert id: %s", id)
	}
	return nil
}
Beispiel #14
0
func (idx *TruncIndex) addId(id string) error {
	if strings.Contains(id, " ") {
		return fmt.Errorf("Illegal character: ' '")
	}
	if id == "" {
		return ErrNoID
	}
	if _, exists := idx.ids[id]; exists {
		return fmt.Errorf("Id already exists: '%s'", id)
	}
	idx.ids[id] = struct{}{}
	if inserted := idx.trie.Insert(patricia.Prefix(id), struct{}{}); !inserted {
		return fmt.Errorf("Failed to insert id: %s", id)
	}
	return nil
}
Beispiel #15
0
// GetFile gets the file at path and returns a FSFiler object, which both
// describes the file and has a pointer to a copy of the file in a byte slice.
// If the files does not exist or path is actually a directory, an error is returned.
func (fs *TransientFilesystem) GetFile(path string) (FSFiler, error) {
	absPath := realPath(fs, path)
	if !fs.PathExists(path) {
		return nil, ErrFileNoExist
	} else if fi, err := os.Stat(realPath(fs, path)); err != nil || fi.IsDir() {
		if err != nil {
			return nil, err
		}
		return nil, fmt.Errorf("Specified path %s is a directory", realPath(fs, path))
	}
	item := fs.trie.Get(trie.Prefix(absPath))
	if item == nil {
		return nil, ErrPathNoExist
	}
	fi, _ := os.Stat(realPath(fs, path))
	return &FSFile{FileInfo: fi, absPath: absPath}, nil
}
Beispiel #16
0
func (suite *TheSuite) TestTransientFilesystem_Sync(c *C) {
	fs := suite.mkTFS()
	fileMap := suite.mkDirs(c, suite.tmpdir)
	if err := fs.Sync(); err != nil {
		c.Error(err)
	}
	c.Assert(fs.trie.Get(trie.Prefix("aaaaaaaaaaa")), IsNil)
	c.Assert(fs.trie.Get(trie.Prefix(fs.rootPath)), NotNil)
	c.Assert(fs.trie.Get(trie.Prefix(fileMap["d1"])), NotNil)
	c.Assert(fs.trie.Get(trie.Prefix(fileMap["f1"])), NotNil)
	c.Assert(fs.trie.Get(trie.Prefix(fileMap["f2"])), NotNil)
	c.Assert(fs.trie.Get(trie.Prefix(fileMap["f3"])), NotNil)
}
Beispiel #17
0
// Publish can be used for inserting the events into the exchange.
//
// This methods triggers all the relevant handlers and runs them in separate
// goroutines.
func (exchange *Exchange) Publish(topic Topic, event Event) error {
	exchange.mu.RLock()

	if exchange.state != stateRunning {
		return ErrInvalidState
	}

	exchange.trie.VisitPrefixes(
		patricia.Prefix(topic),
		func(prefix patricia.Prefix, item patricia.Item) error {
			for _, record := range *(item.(*[]*handlerRecord)) {
				exchange.runHandler(record.handler, topic, event)
			}
			return nil
		})

	exchange.mu.RUnlock()
	return nil
}
Beispiel #18
0
// Sync brings the in-memory struct and underlying file system into sync.
// Walk the entire tree and recreate it from scratch.
func (fs *TransientFilesystem) Sync() error {
	newTrie := trie.NewTrie()
	err := filepath.Walk(fs.RootPath(), func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		fi, err := os.Stat(path)
		if err != nil {
			return err
		}
		if !newTrie.Insert(trie.Prefix(path), fi) {
			return fmt.Errorf("Path %s already exists in tree", path)
		}
		return nil
	})
	if err != nil {
		return err
	}

	fs.lock.Lock()
	defer fs.lock.Unlock()
	fs.trie = newTrie
	return nil
}
Beispiel #19
0
func (_ Test) Patricia() {
	e.InfoLog.Println("\nPatricia:")
	printItem := func(prefix patricia.Prefix, item patricia.Item) error {
		e.InfoLog.Println(string(prefix), item.(uint32))
		return nil
	}
	trie := patricia.NewTrie()

	for i := range ExampleWords {
		trie.Insert(patricia.Prefix(ExampleWords[i]), ExampleUint32[i])
	}
	trie.Set(patricia.Prefix("coca cola"), 188)

	e.InfoLog.Println("SubTree:")
	trie.VisitSubtree(patricia.Prefix("blost"), printItem)
	e.InfoLog.Println("Prefixes:")
	trie.VisitPrefixes(patricia.Prefix("borte med blesten mega"), printItem)

	trie.Delete(patricia.Prefix("coca cola"))
	trie.DeleteSubtree(patricia.Prefix("blost"))

	e.InfoLog.Println("What is left:")
	trie.Visit(printItem)
}
Beispiel #20
0
func TwoCentsHandlerV1(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	dictionaryName := vars["dictionary"]
	limit := 10
	limitParam := vars["limit"]
	if limitParam != "" {
		limit, _ = strconv.Atoi(limitParam)
	}

	//case-insensitive filter
	filter := vars["filter"]
	if filter != "" {
		filter = strings.ToLower(filter)
	}

	dictionaryTrie, found := DictionaryMap[dictionaryName]
	if !found {
		http.NotFound(w, r)
		return
	}
	//TODO: use ascii folding
	query := vars["query"]

	/*
		The values in the patricia-trie are sets of SuggestItems.  patricia-trie won't return the list of nodes
		for you, but will invoke a function on all visited nodes.  This []treeset.Set will hold the results of the
		visited nodes.  visitorFunc will actually add those sets to that array.
	*/
	trieItems := []treeset.Set{}
	visitorFunc := func(prefix patricia.Prefix, item patricia.Item) error {
		trieItems = append(trieItems, item.(treeset.Set))
		return nil
	}
	dictionaryTrie.VisitSubtree(patricia.Prefix([]byte(strings.ToLower(query))), visitorFunc)

	/*
		This set will hold the SuggestItems we pull from the front of every set retrieve from the patricia-trie.  Since
		it's tree set, the items are sorted using the SuggestItemComparator, which compares by weight and string,
		guaranteeing the items within a set are ordered
	*/
	collatedSuggestionSet := treeset.NewWith(models.SuggestItemComparator)

	//If there were fewer suggestions than the requested limit, lower the limit
	totalSuggestions := 0
	for _, suggestionSetItem := range trieItems {
		totalSuggestions += suggestionSetItem.Size()
	}
	if totalSuggestions < limit {
		limit = totalSuggestions
	}

	/*
		The results from the patrica-trie visit are all sorted sets.  However, they're only sorted within the set.  Since
		we know that they're in weight-descending order, we can reliably pick the first element from each set, and insert
		them into another sorted result set.  After <limit> iterations, we're guaranteed to have the top weighted items
		in weight-descending order, and we only need to slice the array
	*/
	finalSuggestionSetPosition := 0
	for finalSuggestionSetPosition < limit && collatedSuggestionSet.Size() < limit {
		for _, suggestionSetItem := range trieItems {
			if suggestionSetItem.Size() > finalSuggestionSetPosition {
				thisItem := suggestionSetItem.Values()[finalSuggestionSetPosition].(*models.SuggestItem)
				//case-insensitive filter
				if filter != "" {
					if strings.Contains(strings.ToLower(thisItem.Term), filter) {
						collatedSuggestionSet.Add(thisItem)
					}
				} else {
					collatedSuggestionSet.Add(thisItem)
				}

			}
		}
		finalSuggestionSetPosition++
	}

	if len(collatedSuggestionSet.Values()) < limit {
		limit = len(collatedSuggestionSet.Values())
	}
	suggestions := []string{}
	for _, suggestion := range collatedSuggestionSet.Values()[0:limit] {
		suggestions = append(suggestions, suggestion.(*models.SuggestItem).Term)
	}

	t := TwoCentsV1{
		Suggestions: suggestions,
	}

	j, _ := json.Marshal(t)
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	if AllowedOrigin != "" {
		w.Header().Set("Access-Control-Allow-Origin", AllowedOrigin)
	}
	w.Write(j)

}
Beispiel #21
0
func dodiffRecursive(firstClnt, secondClnt client.Client, ch chan DiffMessage) {
	firstTrie := patricia.NewTrie()
	secondTrie := patricia.NewTrie()
	wg := new(sync.WaitGroup)

	type urlAttr struct {
		Size int64
		Type os.FileMode
	}

	wg.Add(1)
	go func(ch chan<- DiffMessage) {
		defer wg.Done()
		for firstContentCh := range firstClnt.List(true) {
			if firstContentCh.Err != nil {
				ch <- DiffMessage{
					Error: firstContentCh.Err.Trace(firstClnt.URL().String()),
				}
				return
			}
			firstTrie.Insert(patricia.Prefix(firstContentCh.Content.Name), urlAttr{firstContentCh.Content.Size, firstContentCh.Content.Type})
		}
	}(ch)
	wg.Add(1)
	go func(ch chan<- DiffMessage) {
		defer wg.Done()
		for secondContentCh := range secondClnt.List(true) {
			if secondContentCh.Err != nil {
				ch <- DiffMessage{
					Error: secondContentCh.Err.Trace(secondClnt.URL().String()),
				}
				return
			}
			secondTrie.Insert(patricia.Prefix(secondContentCh.Content.Name), urlAttr{secondContentCh.Content.Size, secondContentCh.Content.Type})
		}
	}(ch)

	doneCh := make(chan struct{})
	defer close(doneCh)
	go func(doneCh <-chan struct{}) {
		cursorCh := cursorAnimate()
		for {
			select {
			case <-time.Tick(100 * time.Millisecond):
				if !globalQuietFlag && !globalJSONFlag {
					console.PrintC("\r" + "Scanning.. " + string(<-cursorCh))
				}
			case <-doneCh:
				return
			}
		}
	}(doneCh)
	wg.Wait()
	doneCh <- struct{}{}
	if !globalQuietFlag && !globalJSONFlag {
		console.Printf("%c[2K\n", 27)
		console.Printf("%c[A", 27)
	}

	matchNameCh := make(chan string, 10000)
	go func(matchNameCh chan<- string) {
		itemFunc := func(prefix patricia.Prefix, item patricia.Item) error {
			matchNameCh <- string(prefix)
			return nil
		}
		firstTrie.Visit(itemFunc)
		defer close(matchNameCh)
	}(matchNameCh)
	for matchName := range matchNameCh {
		firstURLDelimited := firstClnt.URL().String()[:strings.LastIndex(firstClnt.URL().String(), string(firstClnt.URL().Separator))+1]
		secondURLDelimited := secondClnt.URL().String()[:strings.LastIndex(secondClnt.URL().String(), string(secondClnt.URL().Separator))+1]
		firstURL := firstURLDelimited + matchName
		secondURL := secondURLDelimited + matchName
		if !secondTrie.Match(patricia.Prefix(matchName)) {
			ch <- DiffMessage{
				FirstURL:  firstURL,
				SecondURL: secondURL,
				Diff:      "only-in-first",
			}
		} else {
			firstURLAttr := firstTrie.Get(patricia.Prefix(matchName)).(urlAttr)
			secondURLAttr := secondTrie.Get(patricia.Prefix(matchName)).(urlAttr)

			if firstURLAttr.Type.IsRegular() {
				if !secondURLAttr.Type.IsRegular() {
					ch <- DiffMessage{
						FirstURL:  firstURL,
						SecondURL: secondURL,
						Diff:      "type",
					}
					continue
				}
			}

			if firstURLAttr.Type.IsDir() {
				if !secondURLAttr.Type.IsDir() {
					ch <- DiffMessage{
						FirstURL:  firstURL,
						SecondURL: secondURL,
						Diff:      "type",
					}
					continue
				}
			}

			if firstURLAttr.Size != secondURLAttr.Size {
				ch <- DiffMessage{
					FirstURL:  firstURL,
					SecondURL: secondURL,
					Diff:      "size",
				}
			}
		}
	}
}
Beispiel #22
0
func (r *node) Accept(client Peer) error {
	log.Println("Accepting a new connection from ", client)

	if r.closing {
		logErr(client.Send(&Abort{Reason: ErrSystemShutdown}))
		logErr(client.Close())
		return fmt.Errorf("Router is closing, no new connections are allowed")
	}

	msg, err := GetMessageTimeout(client, 5*time.Second)
	if err != nil {
		return err
	}

	// pprint the incoming details
	if b, err := json.MarshalIndent(msg, "", "  "); err != nil {
		fmt.Println("error:", err)
	} else {
		log.Printf("%s: %+v", msg.MessageType(), string(b))
	}
	// log.Printf("%s: %+v", msg.MessageType(), msg)

	hello, _ := msg.(*Hello)

	// Ensure the message is valid and well constructed
	if _, ok := msg.(*Hello); !ok {
		logErr(client.Send(&Abort{Reason: URI("wamp.error.protocol_violation")}))
		logErr(client.Close())

		return fmt.Errorf("protocol violation: expected HELLO, received %s", msg.MessageType())
	}

	// NOT IMPLEMENTED: Authenticate the user based on their provided credentials.
	// Extract their domain from said credentials. If no realm exists for that domain,
	// create it and add it to the trie.

	// New implementation: check for presence of realm
	key := patricia.Prefix(hello.Realm)

	if !r.root.MatchSubtree(key) {
		log.Println("Realm not found. Opening new realm ", hello.Realm)

		// Create the new realm
		newRealm := &Realm{URI: hello.Realm}
		newRealm.init()

		// Insert the realm into the tree
		r.root.Insert(patricia.Prefix(hello.Realm), newRealm)
		// log.Println("Created the new realm: ", newRealm)
	}

	// Extract the correct realm for this key
	// Sidenote: also an example of a cast... ish
	realm := r.root.Get(key).(*Realm)
	// log.Println("Sanity check: new realm for key: ", newRet.URI)

	// Old implementation
	// realm, _ := r.realms[hello.Realm]

	// if _, ok := r.realms[hello.Realm]; !ok {
	//     logErr(client.Send(&Abort{Reason: ErrNoSuchRealm}))
	//     logErr(client.Close())

	//     return NoSuchRealmError(hello.Realm)
	// }

	// Old implementation: the authentication must occur before fetching the realm
	welcome, err := realm.handleAuth(client, hello.Details)

	if err != nil {
		abort := &Abort{
			Reason:  ErrAuthorizationFailed, // TODO: should this be AuthenticationFailed?
			Details: map[string]interface{}{"error": err.Error()},
		}

		logErr(client.Send(abort))
		logErr(client.Close())
		return AuthenticationError(err.Error())
	}

	// No auth, no missing realms. Here is new implmementaton
	log.Println("Creating session, assigning to realm")
	// log.Println(r.root)

	// key := patricia.Prefix(hello.Realm)
	// fmt.Printf("Checking for id %q here? %v\n", key, trie.MatchSubtree(key))

	welcome.Id = NewID()

	if welcome.Details == nil {
		welcome.Details = make(map[string]interface{})
	}

	// add default details to welcome message
	for k, v := range defaultWelcomeDetails {
		if _, ok := welcome.Details[k]; !ok {
			welcome.Details[k] = v
		}
	}

	if err := client.Send(welcome); err != nil {
		return err
	}

	log.Println("Established session:", welcome.Id)

	sess := Session{Peer: client, Id: welcome.Id, kill: make(chan URI, 1)}

	// Alert any registered listeners of a new session
	for _, callback := range r.sessionOpenCallbacks {
		go callback(uint(sess.Id), string(hello.Realm))
	}

	// Does this block on handleSession, then fire off .Close()?
	// Doesn't really make sense as written. Is there a blocked goroutine
	// for each session created that waits for the session to terminate?
	go func() {
		realm.handleSession(sess, welcome.Details)
		sess.Close()

		for _, callback := range r.sessionCloseCallbacks {
			go callback(uint(sess.Id), string(hello.Realm))
		}
	}()

	return nil
}
Beispiel #23
0
// Log the whole trie
func (suite *TheSuite) TrieLog(c *C, fs *TransientFilesystem) {
	fs.trie.VisitSubtree(trie.Prefix(""), func(prefix trie.Prefix, item trie.Item) error {
		c.Logf("%q: %v\n", prefix, item)
		return nil
	})
}
Beispiel #24
0
// PathExists checks to see that the given path exists.
// The path argument is expected to be relative to the rootPath of the
// TransientFilesystem.  Works for files and directories.
func (fs *TransientFilesystem) PathExists(path string) bool {
	absPath := realPath(fs, path)
	fs.lock.RLock()
	defer fs.lock.RUnlock()
	return fs.trie.Match(trie.Prefix(absPath))
}
Beispiel #25
0
func deltaSourceTargets(sourceClnt client.Client, targetClnts []client.Client) <-chan mirrorURLs {
	mirrorURLsCh := make(chan mirrorURLs)
	go func() {
		defer close(mirrorURLsCh)
		sourceTrie := patricia.NewTrie()
		targetTries := make([]*patricia.Trie, len(targetClnts))
		wg := new(sync.WaitGroup)

		wg.Add(1)
		go func() {
			defer wg.Done()
			for sourceContentCh := range sourceClnt.List(true) {
				if sourceContentCh.Err != nil {
					mirrorURLsCh <- mirrorURLs{Error: sourceContentCh.Err.Trace()}
					return
				}
				if sourceContentCh.Content.Type.IsRegular() {
					sourceTrie.Insert(patricia.Prefix(sourceContentCh.Content.Name), sourceContentCh.Content.Size)
				}
			}
		}()

		for i, targetClnt := range targetClnts {
			wg.Add(1)
			go func(i int, targetClnt client.Client) {
				defer wg.Done()
				targetTrie := patricia.NewTrie()
				for targetContentCh := range targetClnt.List(true) {
					if targetContentCh.Err != nil {
						mirrorURLsCh <- mirrorURLs{Error: targetContentCh.Err.Trace()}
						return
					}
					if targetContentCh.Content.Type.IsRegular() {
						targetTrie.Insert(patricia.Prefix(targetContentCh.Content.Name), struct{}{})
					}
				}
				targetTries[i] = targetTrie
			}(i, targetClnt)
		}
		wg.Wait()

		matchNameCh := make(chan string, 10000)
		go func(matchNameCh chan<- string) {
			itemFunc := func(prefix patricia.Prefix, item patricia.Item) error {
				matchNameCh <- string(prefix)
				return nil
			}
			sourceTrie.Visit(itemFunc)
			defer close(matchNameCh)
		}(matchNameCh)
		for matchName := range matchNameCh {
			sourceContent := new(client.Content)
			var targetContents []*client.Content
			for i, targetTrie := range targetTries {
				if !targetTrie.Match(patricia.Prefix(matchName)) {
					sourceURLDelimited := sourceClnt.URL().String()[:strings.LastIndex(sourceClnt.URL().String(),
						string(sourceClnt.URL().Separator))+1]
					newTargetURLParse := *targetClnts[i].URL()
					newTargetURLParse.Path = filepath.Join(newTargetURLParse.Path, matchName)
					sourceContent.Size = sourceTrie.Get(patricia.Prefix(matchName)).(int64)
					sourceContent.Name = sourceURLDelimited + matchName
					targetContents = append(targetContents, &client.Content{Name: newTargetURLParse.String()})
				}
			}
			mirrorURLsCh <- mirrorURLs{
				SourceContent:  sourceContent,
				TargetContents: targetContents,
			}
		}
	}()
	return mirrorURLsCh
}
Beispiel #26
0
func initPrefixes() *gotrie.Trie {
	prefixes := gotrie.NewTrie()

	prefixes.Insert(gotrie.Prefix("1403"), "CA")
	prefixes.Insert(gotrie.Prefix("1587"), "CA")
	prefixes.Insert(gotrie.Prefix("1780"), "CA")
	prefixes.Insert(gotrie.Prefix("1825"), "CA")
	prefixes.Insert(gotrie.Prefix("1236"), "CA")
	prefixes.Insert(gotrie.Prefix("1250"), "CA")
	prefixes.Insert(gotrie.Prefix("1604"), "CA")
	prefixes.Insert(gotrie.Prefix("1672"), "CA")
	prefixes.Insert(gotrie.Prefix("1778"), "CA")
	prefixes.Insert(gotrie.Prefix("1204"), "CA")
	prefixes.Insert(gotrie.Prefix("1431"), "CA")
	prefixes.Insert(gotrie.Prefix("1506"), "CA")
	prefixes.Insert(gotrie.Prefix("1709"), "CA")
	prefixes.Insert(gotrie.Prefix("1782"), "CA")
	prefixes.Insert(gotrie.Prefix("1902"), "CA")
	prefixes.Insert(gotrie.Prefix("1548"), "CA")
	prefixes.Insert(gotrie.Prefix("1249"), "CA")
	prefixes.Insert(gotrie.Prefix("1289"), "CA")
	prefixes.Insert(gotrie.Prefix("1343"), "CA")
	prefixes.Insert(gotrie.Prefix("1365"), "CA")
	prefixes.Insert(gotrie.Prefix("1387"), "CA")
	prefixes.Insert(gotrie.Prefix("1416"), "CA")
	prefixes.Insert(gotrie.Prefix("1437"), "CA")
	prefixes.Insert(gotrie.Prefix("1519"), "CA")
	prefixes.Insert(gotrie.Prefix("1613"), "CA")
	prefixes.Insert(gotrie.Prefix("1647"), "CA")
	prefixes.Insert(gotrie.Prefix("1705"), "CA")
	prefixes.Insert(gotrie.Prefix("1742"), "CA")
	prefixes.Insert(gotrie.Prefix("1807"), "CA")
	prefixes.Insert(gotrie.Prefix("1905"), "CA")
	prefixes.Insert(gotrie.Prefix("1782"), "CA")
	prefixes.Insert(gotrie.Prefix("1902"), "CA")
	prefixes.Insert(gotrie.Prefix("1418"), "CA")
	prefixes.Insert(gotrie.Prefix("1438"), "CA")
	prefixes.Insert(gotrie.Prefix("1450"), "CA")
	prefixes.Insert(gotrie.Prefix("1514"), "CA")
	prefixes.Insert(gotrie.Prefix("1579"), "CA")
	prefixes.Insert(gotrie.Prefix("1581"), "CA")
	prefixes.Insert(gotrie.Prefix("1819"), "CA")
	prefixes.Insert(gotrie.Prefix("1873"), "CA")
	prefixes.Insert(gotrie.Prefix("1306"), "CA")
	prefixes.Insert(gotrie.Prefix("1639"), "CA")
	prefixes.Insert(gotrie.Prefix("1867"), "CA")
	prefixes.Insert(gotrie.Prefix("1"), "US")
	prefixes.Insert(gotrie.Prefix("1242"), "BS")
	prefixes.Insert(gotrie.Prefix("1246"), "BB")
	prefixes.Insert(gotrie.Prefix("1264"), "AI")
	prefixes.Insert(gotrie.Prefix("1268"), "AG")
	prefixes.Insert(gotrie.Prefix("1284"), "VG")
	prefixes.Insert(gotrie.Prefix("1340"), "VI")
	prefixes.Insert(gotrie.Prefix("1345"), "KY")
	prefixes.Insert(gotrie.Prefix("1441"), "BM")
	prefixes.Insert(gotrie.Prefix("1473"), "GD")
	prefixes.Insert(gotrie.Prefix("1649"), "TC")
	prefixes.Insert(gotrie.Prefix("1664"), "MS")
	prefixes.Insert(gotrie.Prefix("1670"), "MP")
	prefixes.Insert(gotrie.Prefix("1671"), "GU")
	prefixes.Insert(gotrie.Prefix("1684"), "AS")
	prefixes.Insert(gotrie.Prefix("1721"), "SX")
	prefixes.Insert(gotrie.Prefix("1758"), "LC")
	prefixes.Insert(gotrie.Prefix("1767"), "DM")
	prefixes.Insert(gotrie.Prefix("1784"), "VC")
	prefixes.Insert(gotrie.Prefix("1787"), "PR")
	prefixes.Insert(gotrie.Prefix("1809"), "DO")
	prefixes.Insert(gotrie.Prefix("1829"), "DO")
	prefixes.Insert(gotrie.Prefix("1849"), "DO")
	prefixes.Insert(gotrie.Prefix("1868"), "TT")
	prefixes.Insert(gotrie.Prefix("1869"), "KN")
	prefixes.Insert(gotrie.Prefix("1876"), "JM")
	prefixes.Insert(gotrie.Prefix("1939"), "PR")
	prefixes.Insert(gotrie.Prefix("20"), "EG")
	prefixes.Insert(gotrie.Prefix("211"), "SS")
	prefixes.Insert(gotrie.Prefix("212"), "MA")
	prefixes.Insert(gotrie.Prefix("213"), "DZ")
	prefixes.Insert(gotrie.Prefix("216"), "TN")
	prefixes.Insert(gotrie.Prefix("218"), "LY")
	prefixes.Insert(gotrie.Prefix("220"), "GM")
	prefixes.Insert(gotrie.Prefix("221"), "SN")
	prefixes.Insert(gotrie.Prefix("222"), "MR")
	prefixes.Insert(gotrie.Prefix("223"), "ML")
	prefixes.Insert(gotrie.Prefix("224"), "GN")
	prefixes.Insert(gotrie.Prefix("225"), "CI")
	prefixes.Insert(gotrie.Prefix("226"), "BF")
	prefixes.Insert(gotrie.Prefix("227"), "NE")
	prefixes.Insert(gotrie.Prefix("228"), "TG")
	prefixes.Insert(gotrie.Prefix("229"), "BJ")
	prefixes.Insert(gotrie.Prefix("230"), "MU")
	prefixes.Insert(gotrie.Prefix("231"), "LR")
	prefixes.Insert(gotrie.Prefix("232"), "SL")
	prefixes.Insert(gotrie.Prefix("233"), "GH")
	prefixes.Insert(gotrie.Prefix("234"), "NG")
	prefixes.Insert(gotrie.Prefix("235"), "TD")
	prefixes.Insert(gotrie.Prefix("236"), "CF")
	prefixes.Insert(gotrie.Prefix("237"), "CM")
	prefixes.Insert(gotrie.Prefix("238"), "CV")
	prefixes.Insert(gotrie.Prefix("239"), "ST")
	prefixes.Insert(gotrie.Prefix("240"), "GQ")
	prefixes.Insert(gotrie.Prefix("241"), "GA")
	prefixes.Insert(gotrie.Prefix("242"), "CG")
	prefixes.Insert(gotrie.Prefix("243"), "CD")
	prefixes.Insert(gotrie.Prefix("244"), "AO")
	prefixes.Insert(gotrie.Prefix("245"), "GW")
	prefixes.Insert(gotrie.Prefix("246"), "IO")
	prefixes.Insert(gotrie.Prefix("247"), "SH")
	prefixes.Insert(gotrie.Prefix("248"), "SC")
	prefixes.Insert(gotrie.Prefix("249"), "SD")
	prefixes.Insert(gotrie.Prefix("250"), "RW")
	prefixes.Insert(gotrie.Prefix("251"), "ET")
	prefixes.Insert(gotrie.Prefix("252"), "SO")
	prefixes.Insert(gotrie.Prefix("253"), "DJ")
	prefixes.Insert(gotrie.Prefix("254"), "KE")
	prefixes.Insert(gotrie.Prefix("255"), "TZ")
	prefixes.Insert(gotrie.Prefix("256"), "UG")
	prefixes.Insert(gotrie.Prefix("257"), "BI")
	prefixes.Insert(gotrie.Prefix("258"), "MZ")
	prefixes.Insert(gotrie.Prefix("260"), "ZM")
	prefixes.Insert(gotrie.Prefix("261"), "MG")
	prefixes.Insert(gotrie.Prefix("262"), "RE")
	prefixes.Insert(gotrie.Prefix("263"), "ZW")
	prefixes.Insert(gotrie.Prefix("264"), "NA")
	prefixes.Insert(gotrie.Prefix("265"), "MW")
	prefixes.Insert(gotrie.Prefix("266"), "LS")
	prefixes.Insert(gotrie.Prefix("267"), "BW")
	prefixes.Insert(gotrie.Prefix("268"), "SZ")
	prefixes.Insert(gotrie.Prefix("269"), "KM")
	prefixes.Insert(gotrie.Prefix("27"), "ZA")
	prefixes.Insert(gotrie.Prefix("290"), "SH")
	prefixes.Insert(gotrie.Prefix("291"), "ER")
	prefixes.Insert(gotrie.Prefix("297"), "AW")
	prefixes.Insert(gotrie.Prefix("298"), "FO")
	prefixes.Insert(gotrie.Prefix("299"), "GL")
	prefixes.Insert(gotrie.Prefix("30"), "GR")
	prefixes.Insert(gotrie.Prefix("31"), "NL")
	prefixes.Insert(gotrie.Prefix("32"), "BE")
	prefixes.Insert(gotrie.Prefix("33"), "FR")
	prefixes.Insert(gotrie.Prefix("34"), "ES")
	prefixes.Insert(gotrie.Prefix("350"), "GI")
	prefixes.Insert(gotrie.Prefix("351"), "PT")
	prefixes.Insert(gotrie.Prefix("352"), "LU")
	prefixes.Insert(gotrie.Prefix("353"), "IE")
	prefixes.Insert(gotrie.Prefix("354"), "IS")
	prefixes.Insert(gotrie.Prefix("355"), "AL")
	prefixes.Insert(gotrie.Prefix("356"), "MT")
	prefixes.Insert(gotrie.Prefix("357"), "CY")
	prefixes.Insert(gotrie.Prefix("358"), "FI")
	prefixes.Insert(gotrie.Prefix("359"), "BG")
	prefixes.Insert(gotrie.Prefix("36"), "HU")
	prefixes.Insert(gotrie.Prefix("370"), "LT")
	prefixes.Insert(gotrie.Prefix("371"), "LV")
	prefixes.Insert(gotrie.Prefix("372"), "EE")
	prefixes.Insert(gotrie.Prefix("373"), "MD")
	prefixes.Insert(gotrie.Prefix("374"), "AM")
	prefixes.Insert(gotrie.Prefix("375"), "BY")
	prefixes.Insert(gotrie.Prefix("376"), "AD")
	prefixes.Insert(gotrie.Prefix("377"), "MC")
	prefixes.Insert(gotrie.Prefix("378"), "SM")
	prefixes.Insert(gotrie.Prefix("379"), "VA")
	prefixes.Insert(gotrie.Prefix("380"), "UA")
	prefixes.Insert(gotrie.Prefix("381"), "RS")
	prefixes.Insert(gotrie.Prefix("381"), "XK")
	prefixes.Insert(gotrie.Prefix("382"), "ME")
	prefixes.Insert(gotrie.Prefix("385"), "HR")
	prefixes.Insert(gotrie.Prefix("386"), "SI")
	prefixes.Insert(gotrie.Prefix("386"), "XK")
	prefixes.Insert(gotrie.Prefix("387"), "BA")
	prefixes.Insert(gotrie.Prefix("389"), "MK")
	prefixes.Insert(gotrie.Prefix("39"), "IT")
	prefixes.Insert(gotrie.Prefix("39066"), "VA")
	prefixes.Insert(gotrie.Prefix("40"), "RO")
	prefixes.Insert(gotrie.Prefix("41"), "CH")
	prefixes.Insert(gotrie.Prefix("420"), "CZ")
	prefixes.Insert(gotrie.Prefix("421"), "SK")
	prefixes.Insert(gotrie.Prefix("423"), "LI")
	prefixes.Insert(gotrie.Prefix("43"), "AT")
	prefixes.Insert(gotrie.Prefix("44"), "GB")
	prefixes.Insert(gotrie.Prefix("45"), "DK")
	prefixes.Insert(gotrie.Prefix("46"), "SE")
	prefixes.Insert(gotrie.Prefix("47"), "NO")
	prefixes.Insert(gotrie.Prefix("4779"), "SJ")
	prefixes.Insert(gotrie.Prefix("48"), "PL")
	prefixes.Insert(gotrie.Prefix("49"), "DE")
	prefixes.Insert(gotrie.Prefix("500"), "FK")
	prefixes.Insert(gotrie.Prefix("501"), "BZ")
	prefixes.Insert(gotrie.Prefix("502"), "GT")
	prefixes.Insert(gotrie.Prefix("503"), "SV")
	prefixes.Insert(gotrie.Prefix("504"), "HN")
	prefixes.Insert(gotrie.Prefix("505"), "NI")
	prefixes.Insert(gotrie.Prefix("506"), "CR")
	prefixes.Insert(gotrie.Prefix("507"), "PA")
	prefixes.Insert(gotrie.Prefix("508"), "PM")
	prefixes.Insert(gotrie.Prefix("509"), "HT")
	prefixes.Insert(gotrie.Prefix("51"), "PE")
	prefixes.Insert(gotrie.Prefix("52"), "MX")
	prefixes.Insert(gotrie.Prefix("53"), "CU")
	prefixes.Insert(gotrie.Prefix("54"), "AR")
	prefixes.Insert(gotrie.Prefix("55"), "BR")
	prefixes.Insert(gotrie.Prefix("56"), "CL")
	prefixes.Insert(gotrie.Prefix("57"), "CO")
	prefixes.Insert(gotrie.Prefix("58"), "VE")
	prefixes.Insert(gotrie.Prefix("590"), "GP")
	prefixes.Insert(gotrie.Prefix("591"), "BO")
	prefixes.Insert(gotrie.Prefix("592"), "GY")
	prefixes.Insert(gotrie.Prefix("593"), "EC")
	prefixes.Insert(gotrie.Prefix("594"), "GF")
	prefixes.Insert(gotrie.Prefix("595"), "PY")
	prefixes.Insert(gotrie.Prefix("596"), "MQ")
	prefixes.Insert(gotrie.Prefix("597"), "SR")
	prefixes.Insert(gotrie.Prefix("598"), "UY")
	prefixes.Insert(gotrie.Prefix("5997"), "BQ")
	prefixes.Insert(gotrie.Prefix("5999"), "CW")
	prefixes.Insert(gotrie.Prefix("60"), "MY")
	prefixes.Insert(gotrie.Prefix("61"), "AU")
	prefixes.Insert(gotrie.Prefix("62"), "ID")
	prefixes.Insert(gotrie.Prefix("63"), "PH")
	prefixes.Insert(gotrie.Prefix("64"), "NZ")
	prefixes.Insert(gotrie.Prefix("65"), "SG")
	prefixes.Insert(gotrie.Prefix("66"), "TH")
	prefixes.Insert(gotrie.Prefix("670"), "TL")
	prefixes.Insert(gotrie.Prefix("672"), "NF")
	prefixes.Insert(gotrie.Prefix("673"), "BN")
	prefixes.Insert(gotrie.Prefix("674"), "NR")
	prefixes.Insert(gotrie.Prefix("675"), "PG")
	prefixes.Insert(gotrie.Prefix("676"), "TO")
	prefixes.Insert(gotrie.Prefix("677"), "SB")
	prefixes.Insert(gotrie.Prefix("678"), "VU")
	prefixes.Insert(gotrie.Prefix("679"), "FJ")
	prefixes.Insert(gotrie.Prefix("680"), "PW")
	prefixes.Insert(gotrie.Prefix("681"), "WF")
	prefixes.Insert(gotrie.Prefix("682"), "CK")
	prefixes.Insert(gotrie.Prefix("683"), "NU")
	prefixes.Insert(gotrie.Prefix("685"), "WS")
	prefixes.Insert(gotrie.Prefix("686"), "KI")
	prefixes.Insert(gotrie.Prefix("687"), "NC")
	prefixes.Insert(gotrie.Prefix("688"), "TV")
	prefixes.Insert(gotrie.Prefix("689"), "PF")
	prefixes.Insert(gotrie.Prefix("690"), "TK")
	prefixes.Insert(gotrie.Prefix("691"), "FM")
	prefixes.Insert(gotrie.Prefix("692"), "MH")
	prefixes.Insert(gotrie.Prefix("7"), "RU")
	prefixes.Insert(gotrie.Prefix("76"), "KZ")
	prefixes.Insert(gotrie.Prefix("77"), "KZ")
	prefixes.Insert(gotrie.Prefix("81"), "JP")
	prefixes.Insert(gotrie.Prefix("82"), "KR")
	prefixes.Insert(gotrie.Prefix("84"), "VN")
	prefixes.Insert(gotrie.Prefix("850"), "KP")
	prefixes.Insert(gotrie.Prefix("852"), "HK")
	prefixes.Insert(gotrie.Prefix("853"), "MO")
	prefixes.Insert(gotrie.Prefix("855"), "KH")
	prefixes.Insert(gotrie.Prefix("856"), "LA")
	prefixes.Insert(gotrie.Prefix("86"), "CN")
	prefixes.Insert(gotrie.Prefix("880"), "BD")
	prefixes.Insert(gotrie.Prefix("886"), "TW")
	prefixes.Insert(gotrie.Prefix("90"), "TR")
	prefixes.Insert(gotrie.Prefix("91"), "IN")
	prefixes.Insert(gotrie.Prefix("92"), "PK")
	prefixes.Insert(gotrie.Prefix("93"), "AF")
	prefixes.Insert(gotrie.Prefix("94"), "LK")
	prefixes.Insert(gotrie.Prefix("95"), "MM")
	prefixes.Insert(gotrie.Prefix("960"), "MV")
	prefixes.Insert(gotrie.Prefix("961"), "LB")
	prefixes.Insert(gotrie.Prefix("962"), "JO")
	prefixes.Insert(gotrie.Prefix("963"), "SY")
	prefixes.Insert(gotrie.Prefix("964"), "IQ")
	prefixes.Insert(gotrie.Prefix("965"), "KW")
	prefixes.Insert(gotrie.Prefix("966"), "SA")
	prefixes.Insert(gotrie.Prefix("967"), "YE")
	prefixes.Insert(gotrie.Prefix("968"), "OM")
	prefixes.Insert(gotrie.Prefix("970"), "PS")
	prefixes.Insert(gotrie.Prefix("971"), "AE")
	prefixes.Insert(gotrie.Prefix("972"), "IL")
	prefixes.Insert(gotrie.Prefix("973"), "BH")
	prefixes.Insert(gotrie.Prefix("974"), "QA")
	prefixes.Insert(gotrie.Prefix("975"), "BT")
	prefixes.Insert(gotrie.Prefix("976"), "MN")
	prefixes.Insert(gotrie.Prefix("977"), "NP")
	prefixes.Insert(gotrie.Prefix("98"), "IR")
	prefixes.Insert(gotrie.Prefix("992"), "TJ")
	prefixes.Insert(gotrie.Prefix("993"), "TM")
	prefixes.Insert(gotrie.Prefix("994"), "AZ")
	prefixes.Insert(gotrie.Prefix("995"), "GE")
	prefixes.Insert(gotrie.Prefix("996"), "KG")
	prefixes.Insert(gotrie.Prefix("998"), "UZ")

	return prefixes
}