package explorer // A simple JSON database for storing and retrieving p2p network tokens and a name and description. import ( "encoding/json" "os" "sort" "sync" "github.com/gofrs/flock" ) // Database is a simple JSON database for storing and retrieving p2p network tokens and a name and description. type Database struct { path string data map[string]TokenData flock *flock.Flock sync.Mutex } // TokenData is a p2p network token with a name and description. type TokenData struct { Name string `json:"name"` Description string `json:"description"` Clusters []ClusterData Failures int } type ClusterData struct { Workers []string Type string NetworkID string } // NewDatabase creates a new Database with the given path. func NewDatabase(path string) (*Database, error) { fileLock := flock.New(path + ".lock") db := &Database{ data: make(map[string]TokenData), path: path, flock: fileLock, } return db, db.load() } // Get retrieves a Token from the Database by its token. func (db *Database) Get(token string) (TokenData, bool) { db.flock.Lock() // we are making sure that the file is not being written to defer db.flock.Unlock() db.Lock() // we are making sure that is safe if called by another instance in the same process defer db.Unlock() db.load() t, ok := db.data[token] return t, ok } // Set stores a Token in the Database by its token. func (db *Database) Set(token string, t TokenData) error { db.flock.Lock() defer db.flock.Unlock() db.Lock() defer db.Unlock() db.load() db.data[token] = t return db.save() } // Delete removes a Token from the Database by its token. func (db *Database) Delete(token string) error { db.flock.Lock() defer db.flock.Unlock() db.Lock() defer db.Unlock() db.load() delete(db.data, token) return db.save() } func (db *Database) TokenList() []string { db.flock.Lock() defer db.flock.Unlock() db.Lock() defer db.Unlock() db.load() tokens := []string{} for k := range db.data { tokens = append(tokens, k) } sort.Slice(tokens, func(i, j int) bool { // sort by token return tokens[i] < tokens[j] }) return tokens } // load reads the Database from disk. func (db *Database) load() error { if _, err := os.Stat(db.path); os.IsNotExist(err) { return nil } // Read the file from disk // Unmarshal the JSON into db.data f, err := os.ReadFile(db.path) if err != nil { return err } return json.Unmarshal(f, &db.data) } // Save writes the Database to disk. func (db *Database) save() error { // Marshal db.data into JSON // Write the JSON to the file f, err := os.Create(db.path) if err != nil { return err } defer f.Close() return json.NewEncoder(f).Encode(db.data) }