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 { // 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) fmt.Fprintln(w, "package "+f.Package) // 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 f.structMatch(line) { if argv.Mutex { // log.Info("Adding Mutex to:", line) fmt.Fprintln(w, line) fmt.Fprintln(w, "\tLock sync.RWMutex // auto-added by go.wit.com/apps/autogenpb") // this must be 'Lock' or Marshal() panics? // fmt.Fprintln(w, "\t// auto-added by go.wit.com/apps/autogenpb") // fmt.Fprintln(w, "\tsync.RWMutex") fmt.Fprintln(w, "") } else { // log.Info("Skipping. Mutex = false for:", line) fmt.Fprintln(w, line) fmt.Fprintln(w, "\t// Lock sync.RWMutex // autogenpb skipped this. needs --mutex command line arg") fmt.Fprintln(w, "") } } else { fmt.Fprintln(w, line) } } 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) bool { var msg *MsgName var start string msg = pf.Bases start = "type " + msg.Name + " struct {" if strings.HasPrefix(line, start) { msg.MutexFound = true return true } // 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.MutexFound = true msg.Lockname = "x.Lock" return true } for _, msg = range pf.MsgNames { start = "type " + msg.Name + " struct {" if strings.HasPrefix(line, start) { msg.MutexFound = true if msg.NoMutex { msg.Lockname = pf.Filebase + "Mu" // this should be lowercase. do not export the Mutex } else { msg.Lockname = "x.Lock" } return true } } return false }