github.com/wasbazi/deis@v1.7.1-0.20150609203025-5765871615de/logspout/routes.go (about)

     1  package main
     2  
     3  import (
     4  	"crypto/sha1"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"log"
     9  	"os"
    10  	"strconv"
    11  	"strings"
    12  	"sync"
    13  	"time"
    14  )
    15  
    16  type RouteStore interface {
    17  	Get(id string) (*Route, error)
    18  	GetAll() ([]*Route, error)
    19  	Add(route *Route) error
    20  	Remove(id string) bool
    21  }
    22  
    23  type RouteManager struct {
    24  	sync.Mutex
    25  	persistor RouteStore
    26  	attacher  *AttachManager
    27  	routes    map[string]*Route
    28  }
    29  
    30  func NewRouteManager(attacher *AttachManager) *RouteManager {
    31  	return &RouteManager{attacher: attacher, routes: make(map[string]*Route)}
    32  }
    33  
    34  func (rm *RouteManager) Load(persistor RouteStore) error {
    35  	routes, err := persistor.GetAll()
    36  	if err != nil {
    37  		return err
    38  	}
    39  	for _, route := range routes {
    40  		rm.Add(route)
    41  	}
    42  	rm.persistor = persistor
    43  	return nil
    44  }
    45  
    46  func (rm *RouteManager) Get(id string) (*Route, error) {
    47  	rm.Lock()
    48  	defer rm.Unlock()
    49  	route, ok := rm.routes[id]
    50  	if !ok {
    51  		return nil, os.ErrNotExist
    52  	}
    53  	return route, nil
    54  }
    55  
    56  func (rm *RouteManager) GetAll() ([]*Route, error) {
    57  	rm.Lock()
    58  	defer rm.Unlock()
    59  	routes := make([]*Route, 0)
    60  	for _, route := range rm.routes {
    61  		routes = append(routes, route)
    62  	}
    63  	return routes, nil
    64  }
    65  
    66  func (rm *RouteManager) Add(route *Route) error {
    67  	rm.Lock()
    68  	defer rm.Unlock()
    69  	if route.ID == "" {
    70  		h := sha1.New()
    71  		io.WriteString(h, strconv.Itoa(int(time.Now().UnixNano())))
    72  		route.ID = fmt.Sprintf("%x", h.Sum(nil))[:12]
    73  	}
    74  	route.closer = make(chan bool)
    75  	rm.routes[route.ID] = route
    76  	types := []string{}
    77  	if route.Source != nil {
    78  		types = append(types, route.Source.Types...)
    79  	}
    80  	go func() {
    81  		logstream := make(chan *Log)
    82  		defer close(logstream)
    83  		go syslogStreamer(route.Target, types, logstream)
    84  		rm.attacher.Listen(route.Source, logstream, route.closer)
    85  	}()
    86  	if rm.persistor != nil {
    87  		if err := rm.persistor.Add(route); err != nil {
    88  			log.Println("persistor:", err)
    89  		}
    90  	}
    91  	return nil
    92  }
    93  
    94  func (rm *RouteManager) Remove(id string) bool {
    95  	rm.Lock()
    96  	defer rm.Unlock()
    97  	route, ok := rm.routes[id]
    98  	if ok && route.closer != nil {
    99  		route.closer <- true
   100  	}
   101  	delete(rm.routes, id)
   102  	if rm.persistor != nil {
   103  		rm.persistor.Remove(id)
   104  	}
   105  	return ok
   106  }
   107  
   108  type RouteFileStore string
   109  
   110  func (fs RouteFileStore) Filename(id string) string {
   111  	return string(fs) + "/" + id + ".json"
   112  }
   113  
   114  func (fs RouteFileStore) Get(id string) (*Route, error) {
   115  	file, err := os.Open(fs.Filename(id))
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	route := new(Route)
   120  	if err = unmarshal(file, route); err != nil {
   121  		return nil, err
   122  	}
   123  	return route, nil
   124  }
   125  
   126  func (fs RouteFileStore) GetAll() ([]*Route, error) {
   127  	files, err := ioutil.ReadDir(string(fs))
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  	var routes []*Route
   132  	for _, file := range files {
   133  		fileparts := strings.Split(file.Name(), ".")
   134  		if len(fileparts) > 1 && fileparts[1] == "json" {
   135  			route, err := fs.Get(fileparts[0])
   136  			if err == nil {
   137  				routes = append(routes, route)
   138  			}
   139  		}
   140  	}
   141  	return routes, nil
   142  }
   143  
   144  func (fs RouteFileStore) Add(route *Route) error {
   145  	return ioutil.WriteFile(fs.Filename(route.ID), marshal(route), 0644)
   146  }
   147  
   148  func (fs RouteFileStore) Remove(id string) bool {
   149  	if _, err := os.Stat(fs.Filename(id)); err == nil {
   150  		if err := os.Remove(fs.Filename(id)); err != nil {
   151  			return true
   152  		}
   153  	}
   154  	return false
   155  }