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 }