diff options
Diffstat (limited to 'vendor/github.com/twinj/uuid/saver.go')
-rw-r--r-- | vendor/github.com/twinj/uuid/saver.go | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/vendor/github.com/twinj/uuid/saver.go b/vendor/github.com/twinj/uuid/saver.go new file mode 100644 index 0000000000..0b776a46a9 --- /dev/null +++ b/vendor/github.com/twinj/uuid/saver.go @@ -0,0 +1,140 @@ +package uuid + +/**************** + * Date: 21/06/15 + * Time: 5:48 PM + ***************/ + +import ( + "encoding/gob" + "log" + "os" + "time" +) + +func init() { + gob.Register(stateEntity{}) +} + +func SetupFileSystemStateSaver(pConfig StateSaverConfig) { + saver := &FileSystemSaver{} + saver.saveReport = pConfig.SaveReport + saver.saveSchedule = int64(pConfig.SaveSchedule) + SetupCustomStateSaver(saver) +} + +// A wrapper for default setup of the FileSystemStateSaver +type StateSaverConfig struct { + + // Print save log + SaveReport bool + + // Save every x nanoseconds + SaveSchedule time.Duration +} + +// *********************************************** StateEntity + +// StateEntity acts as a marshaller struct for the state +type stateEntity struct { + Past Timestamp + Node []byte + Sequence uint16 +} + +// This implements the StateSaver interface for UUIDs +type FileSystemSaver struct { + cache *os.File + saveState uint64 + saveReport bool + saveSchedule int64 +} + +// Saves the current state of the generator +// If the scheduled file save is reached then the file is synced +func (o *FileSystemSaver) Save(pState *State) { + if pState.past >= pState.next { + err := o.open() + defer o.cache.Close() + if err != nil { + log.Println("uuid.State.save:", err) + return + } + // do the save + o.encode(pState) + // a tick is 100 nano seconds + pState.next = pState.past + Timestamp(o.saveSchedule / 100) + if o.saveReport { + log.Printf("UUID STATE: SAVED %d", pState.past) + } + } +} + +func (o *FileSystemSaver) Init(pState *State) { + pState.saver = o + err := o.open() + defer o.cache.Close() + if err != nil { + if os.IsNotExist(err) { + log.Printf("'%s' created\n", "uuid.SaveState") + var err error + o.cache, err = os.Create(os.TempDir() + "/state.unique") + if err != nil { + log.Println("uuid.State.init: SaveState error:", err) + goto pastInit + } + o.encode(pState) + } else { + log.Println("uuid.State.init: SaveState error:", err) + goto pastInit + } + } + err = o.decode(pState) + if err != nil { + goto pastInit + } + pState.randomSequence = false +pastInit: + if timestamp() <= pState.past { + pState.sequence++ + } + pState.next = pState.past +} + +func (o *FileSystemSaver) reset() { + o.cache.Seek(0, 0) +} + +func (o *FileSystemSaver) open() error { + var err error + o.cache, err = os.OpenFile(os.TempDir()+"/state.unique", os.O_RDWR, os.ModeExclusive) + return err +} + +// Encodes State generator data into a saved file +func (o *FileSystemSaver) encode(pState *State) { + // ensure reader state is ready for use + o.reset() + enc := gob.NewEncoder(o.cache) + // Wrap private State data into the StateEntity + err := enc.Encode(&stateEntity{pState.past, pState.node, pState.sequence}) + if err != nil { + log.Panic("UUID.encode error:", err) + } +} + +// Decodes StateEntity data into the main State +func (o *FileSystemSaver) decode(pState *State) error { + o.reset() + dec := gob.NewDecoder(o.cache) + entity := stateEntity{} + err := dec.Decode(&entity) + if err != nil { + log.Println("uuid.decode error:", err) + return err + } + pState.past = entity.Past + pState.node = entity.Node + pState.sequence = entity.Sequence + return nil +} |