package main // will this help things? // this is a hack for testing for now // cram a mutex in the pb.go file import ( "fmt" "io" "os" "strings" "go.wit.com/log" ) func (msg *MsgName) getLockname(s string) string { if msg.NoMutex { // return "bad" return msg.Lockname } // leave this function stubbed in for development of autogenpb // if argv.Mutex { // // use the mutex lock from the modified protoc.pb.go file // return s + ".Lock" // // return s // causes Marshal() to panic? always use the variable name 'Lock'? // } // a single global lock by struct name return msg.Lockname } func (pf *File) syncLock(w io.Writer) { var LOCK string = pf.Filebase + "Mu" // this should be lowercase. do not export the Mutex fmt.Fprintln(w, "// a simple global lock") fmt.Fprintln(w, "var "+LOCK+" sync.RWMutex") fmt.Fprintln(w, "") /* // this was a note, but the note is wrong. it seems to work fine. my example/ code was wrong. I think. notsure fmt.Fprintln(w, "") fmt.Fprintln(w, "// this is needed because it seems Marshal() fails if locks are in the structs (?)") fmt.Fprintln(w, "// this might just be a syntactical runtime error. notsure.") fmt.Fprintln(w, "// maybe this autogen tool will help someone that actually knows what is going on inside") fmt.Fprintln(w, "// go/src/google.golang.org/protobuf/proto/proto_methods.go") fmt.Fprintln(w, "// go/src/google.golang.org/protobuf/proto/encode.go") fmt.Fprintln(w, "// my guess is that Marshal() needs to be told to ignore sync.RWMutex as it ephemeral and can't be stored") */ } func (pb *Files) addMutex(f *File) error { fullname := f.Pbfilename // log.Info("pb filename:", fullname) data, err := os.ReadFile(fullname) if err != nil { log.Info("pb filename failed to read:", err) return err } // check if autogenpb has already looked at this file for _, line := range strings.Split(string(data), "\n") { if strings.Contains(line, "autogenpb DO NOT EDIT") { // log.Info("autogenpb has already been run on", fullname) return nil } } w, _ := os.OpenFile(f.Pbfilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) // the default is to insert a mutex directly into the struct if argv.Mutex { pbHeaderComment(w) } lines := strings.Split(string(data), "\n") for _, line := range lines { if strings.HasPrefix(line, "package ") { // log.Info("CHANGING package:", line, "to package:", f.Package) if f.Package != "" { fmt.Fprintln(w, "package", f.Package, "// autogenpb changed the package name") } // log.Info("CHANGING package:", line, "to package:main") // fmt.Fprintln(w, "package "+"main") continue } // the default is to insert a mutex directly into the struct if !argv.Mutex { // mutex is not to be added, only fix the package name fmt.Fprintln(w, line) continue } if msg := f.structMatch(line); msg == nil { fmt.Fprintln(w, line) } else { fmt.Fprintln(w, line) if !argv.Mutex { fmt.Fprintln(w, "\t// sync.RWMutex // skipped. argv was --mutex=false") fmt.Fprintln(w, "") continue } if msg.NoMutex { fmt.Fprintln(w, "\t// sync.RWMutex // skipped. protobuf file has `autogenpb:nomutex`") fmt.Fprintln(w, "") continue } if argv.MutexName == "" { fmt.Fprintln(w, "\tsync.RWMutex // auto-added by go.wit.com/apps/autogenpb") // this must be 'Lock' or Marshal() panics? fmt.Fprintln(w, "") } else { fmt.Fprintf(w, "\t%s sync.RWMutex // auto-added by go.wit.com/apps/autogenpb\n", argv.MutexName) // this must be 'Lock' or Marshal() panics? fmt.Fprintln(w, "") } } } if argv.Mutex { // verify every structure was found for _, msg := range f.MsgNames { if !msg.MutexFound && msg.DoMutex { return fmt.Errorf("addMutex() parse didn't work for %s", msg.Name) } } } return nil } // is this struct supposed to have a Mutex added? func (pf *File) structMatch(line string) *MsgName { var msg *MsgName var start string msg = pf.Bases start = "type " + msg.Name + " struct {" if strings.HasPrefix(line, start) { msg.setupMutex(pf.Filebase + "Mu") return msg } // ONLY PASS THIS IF YOU DO NOT WANT TO USE MARSHAL() msg = pf.Base start = "type " + msg.Name + " struct {" if strings.HasPrefix(line, start) { msg.setupMutex(pf.Filebase + "Mu") return msg } for _, msg = range pf.MsgNames { start = "type " + msg.Name + " struct {" if strings.HasPrefix(line, start) { msg.setupMutex(pf.Filebase + "Mu") return msg } } return nil } // nameMu should probably be lowercase. // notsure if it ever makes sense to export a mutex or even if you can func (msg *MsgName) setupMutex(nameMu string) { msg.MutexFound = true if msg.NoMutex { msg.Lockname = nameMu return } if argv.MutexName == "" { msg.Lockname = "x" } else { msg.Lockname = "x." + argv.MutexName } }