github.com/Cloud-Foundations/Dominator@v0.3.4/lib/filegen/api.go (about)

     1  /*
     2  Package filegen manages the generation of computed files.
     3  
     4  Package filegen may be used to implement a computed file server. It
     5  registers a FileGenerator server with the lib/srpc package. The application
     6  may register multiple file generators.
     7  
     8  A generator for the /etc/mdb.json pathname is automatically registered.
     9  */
    10  package filegen
    11  
    12  import (
    13  	"io"
    14  	"sync"
    15  	"time"
    16  
    17  	"github.com/Cloud-Foundations/Dominator/lib/hash"
    18  	"github.com/Cloud-Foundations/Dominator/lib/log"
    19  	"github.com/Cloud-Foundations/Dominator/lib/mdb"
    20  	"github.com/Cloud-Foundations/Dominator/lib/objectserver/memory"
    21  	proto "github.com/Cloud-Foundations/Dominator/proto/filegenerator"
    22  )
    23  
    24  // FileGenerator is the interface that wraps the Generate method.
    25  //
    26  // Generate computes file data from the provided machine information.
    27  // The logger may be used to log problems.
    28  // It returns the data, a time.Time indicating when the data are valid until
    29  // (a zero time indicates the data are valid forever) and an error.
    30  type FileGenerator interface {
    31  	Generate(machine mdb.Machine, logger log.Logger) (
    32  		data []byte, validUntil time.Time, err error)
    33  }
    34  
    35  type expiringHash struct {
    36  	hash       hash.Hash
    37  	length     uint64
    38  	validUntil time.Time
    39  }
    40  
    41  type pathManager struct {
    42  	generator hashGenerator
    43  	rwMutex   sync.RWMutex
    44  	// Protected by lock.
    45  	machineHashes map[string]expiringHash
    46  }
    47  
    48  type Manager struct {
    49  	rwMutex sync.RWMutex
    50  	// Protected by lock.
    51  	pathManagers map[string]*pathManager
    52  	machineData  map[string]mdb.Machine
    53  	clients      map[<-chan *proto.ServerMessage]chan<- *proto.ServerMessage
    54  	// Not protected by lock.
    55  	objectServer *memory.ObjectServer
    56  	logger       log.Logger
    57  }
    58  
    59  // New creates a new *Manager. Only one should be created per application.
    60  // The logger will be used to log problems.
    61  func New(logger log.Logger) *Manager {
    62  	return newManager(logger)
    63  }
    64  
    65  // GetRegisteredPaths returns a slice of filenames which have generators.
    66  func (m *Manager) GetRegisteredPaths() []string {
    67  	return m.getRegisteredPaths()
    68  }
    69  
    70  // RegisterFileForPath registers a source file for a specific pathname. The
    71  // source file is used as the data source. If the source file changes, the data
    72  // are re-read.
    73  func (m *Manager) RegisterFileForPath(pathname string, sourceFile string) {
    74  	m.registerFileForPath(pathname, sourceFile)
    75  }
    76  
    77  // RegisterGeneratorForPath registers a FileGenerator for a specific pathname.
    78  // It returns a channel to which notification messages may be sent indicating
    79  // that the data should be regenerated, even if the machine data have not
    80  // changed. If the empty string is sent to the channel, it indicates that data
    81  // should be regenerated for all machines, otherwise it indicates that data
    82  // should be regenerated for a specific machine.
    83  // An internal goroutine reads from the channel, which terminates if the channel
    84  // is closed. The channel should be closed if the data should only be
    85  // regenerated if the machine data change.
    86  func (m *Manager) RegisterGeneratorForPath(pathname string,
    87  	gen FileGenerator) chan<- string {
    88  	return m.registerDataGeneratorForPath(pathname, gen)
    89  }
    90  
    91  // RegisterMdbFieldDirectoryForPath registers a generator for pathname which
    92  // yields data from files under the specified directory where the filenames
    93  // are taken from the specified field of the MDB data for a machine. The data
    94  // are periodically reloaded every specified interval (if greater than zero).
    95  func (m *Manager) RegisterMdbFieldDirectoryForPath(pathname string,
    96  	field, directory string, interval time.Duration) error {
    97  	return m.registerMdbFieldDirectoryForPath(pathname, field, directory,
    98  		interval)
    99  }
   100  
   101  // RegisterMdbGeneratorForPath registers a generator for pathname which yields
   102  // the MDB data in JSON format for a machine.
   103  func (m *Manager) RegisterMdbGeneratorForPath(pathname string) {
   104  	m.registerMdbGeneratorForPath(pathname)
   105  }
   106  
   107  // RegisterTemplateFileForPath registers a template file for a specific
   108  // pathname.
   109  // The template file is used to generate the data, modified by the machine data.
   110  // If the template file changes and watchForUpdates is true, the template file
   111  // is re-read and the data are regenerated.
   112  // The template file syntax is defined by the text/template standard package.
   113  func (m *Manager) RegisterTemplateFileForPath(pathname string,
   114  	templateFile string, watchForUpdates bool) error {
   115  	return m.registerTemplateFileForPath(pathname, templateFile,
   116  		watchForUpdates)
   117  }
   118  
   119  // WriteHtml will write status information about the Manager to w, with
   120  // appropriate HTML markups.
   121  func (m *Manager) WriteHtml(writer io.Writer) {
   122  	m.writeHtml(writer)
   123  }