@@ 2,12 2,17 @@ package main
import (
"encoding/json"
+ "errors"
"flag"
"fmt"
"log"
"net/http"
"os"
+ "path"
"strconv"
+ "sync"
+
+ "github.com/fsnotify/fsnotify"
)
type Zettel_Summary struct {
@@ 20,6 25,11 @@ type Zettel_Summary struct {
type ZK_Summaries map[int]Zettel_Summary
+type Safe_ZK_Summaries struct {
+ lock sync.Mutex
+ summaries ZK_Summaries
+ ready bool
+}
type UIDType int
const (
@@ 79,6 89,158 @@ func reply(summaries ZK_Summaries, uid s
}
}
+func testinotifyfn() {
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer watcher.Close()
+
+ done := make(chan bool)
+ go func() {
+ for {
+ select {
+ case event, ok := <-watcher.Events:
+ if !ok {
+ return
+ }
+ log.Println("event:", event)
+ log.Println(event.Op)
+ case err, ok := <-watcher.Errors:
+ if !ok {
+ return
+ }
+ log.Println("error:", err)
+
+ }
+ }
+ }()
+
+ err = watcher.Add("./test")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ <-done
+ log.Println("fin")
+}
+
+func update_summaries(filepath string, mutex_summaries *Safe_ZK_Summaries) {
+ log.Println("Updating...")
+ var summaries ZK_Summaries = read_json_file(filepath)
+ mutex_summaries.lock.Lock()
+ defer mutex_summaries.lock.Unlock()
+ mutex_summaries.summaries = summaries
+ mutex_summaries.ready = true
+}
+
+func watch_dir(filepath string) bool {
+ if _, err := os.Stat(filepath); err == nil {
+ log.Println("File found, not watching directory")
+ return true
+ }
+
+ log.Println("File not found, watching directory.")
+ var dirpath string = path.Dir(filepath)
+ var filename string = path.Base(filepath)
+
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer watcher.Close()
+
+ done := make(chan bool)
+ go func() {
+ for {
+ select {
+ case event, ok := <-watcher.Events:
+ if !ok {
+ done <- false
+ return
+ }
+ if filename == path.Base(event.Name) && event.Op == fsnotify.Create {
+ log.Println(event)
+ done <- true
+ return
+ }
+ case err, ok := <-watcher.Errors:
+ if !ok {
+ done <- false
+ return
+ }
+ log.Println("error:", err)
+ }
+ }
+ }()
+
+ watcher.Add(dirpath)
+
+ return <-done
+}
+
+func watch_file(filepath string, mu_zk_sum *Safe_ZK_Summaries) bool {
+ if _, err := os.Stat(filepath); errors.Is(err, os.ErrNotExist) {
+ log.Println("File not found, watching directory")
+ return false
+ }
+
+ log.Println("File found, update and watching it.")
+ update_summaries(filepath, mu_zk_sum)
+
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer watcher.Close()
+
+ done := make(chan bool)
+ go func() {
+ for {
+ select {
+ case event, ok := <-watcher.Events:
+ if !ok {
+ done <- false
+ return
+ }
+ switch event.Op {
+ case fsnotify.Remove, fsnotify.Rename:
+ done <- false
+ return
+ case fsnotify.Create, fsnotify.Write:
+ update_summaries(filepath, mu_zk_sum)
+ break
+ default:
+ log.Println(event)
+ }
+ case err, ok := <-watcher.Errors:
+ if !ok {
+ done <- false
+ return
+ }
+ log.Println("error:", err)
+ }
+ }
+ }()
+
+ watcher.Add(filepath)
+
+ return <-done
+}
+
+func watch(filepath string, mu_zk_sum *Safe_ZK_Summaries) {
+ var filestatus bool = false
+ for {
+ if filestatus {
+ log.Println("Watching file at path", filepath)
+ filestatus = watch_file(filepath, mu_zk_sum)
+ } else {
+ log.Println("Watching dir of", filepath)
+ filestatus = watch_dir(filepath)
+ }
+ }
+}
+
func main() {
var port int
var data string
@@ 87,13 249,26 @@ func main() {
flag.Parse()
- var summaries ZK_Summaries = read_json_file(data)
+ var mutex_summaries Safe_ZK_Summaries
+
+ go watch(data, &mutex_summaries)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ var summaries ZK_Summaries
+
+ mutex_summaries.lock.Lock()
+ if mutex_summaries.ready {
+ summaries = mutex_summaries.summaries
+ } else {
+ summaries = nil
+ }
+ mutex_summaries.lock.Unlock()
+
code, response := reply(summaries, r.FormValue("id"))
w.WriteHeader(code)
fmt.Fprintf(w, response)
})
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
+
}