summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/twinj/uuid/saver.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/twinj/uuid/saver.go')
-rw-r--r--vendor/github.com/twinj/uuid/saver.go140
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
+}