From 19460e3c9f49e4c3690e7c6584c2c3c699a95be3 Mon Sep 17 00:00:00 2001 From: notzippy Date: Sat, 5 Mar 2022 08:03:12 -0800 Subject: [PATCH] Added write lock mechanizim around controller reuse closes 1547 --- controller.go | 6 ++++++ model/revel_controller.go | 7 ++++++- revel.go | 2 ++ server.go | 2 ++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/controller.go b/controller.go index 2f4235c7..945c56db 100644 --- a/controller.go +++ b/controller.go @@ -410,15 +410,21 @@ func (c *Controller) SetTypeAction(controllerName, methodName string, typeOfCont } if RevelConfig.Controller.Reuse { + RevelConfig.Controller.CacheMapLocked.RLock() if _, ok := RevelConfig.Controller.CachedMap[c.Name]; !ok { // Create a new stack for this controller localType := c.Type.Type + RevelConfig.Controller.CacheMapLocked.RUnlock() + RevelConfig.Controller.CacheMapLocked.Lock() + defer RevelConfig.Controller.CacheMapLocked.Unlock() RevelConfig.Controller.CachedMap[c.Name] = utils.NewStackLock( RevelConfig.Controller.CachedStackSize, RevelConfig.Controller.CachedStackMaxSize, func() interface{} { return reflect.New(localType).Interface() }) + } else { + defer RevelConfig.Controller.CacheMapLocked.RUnlock() } // Instantiate the controller. c.AppController = RevelConfig.Controller.CachedMap[c.Name].Pop() diff --git a/model/revel_controller.go b/model/revel_controller.go index e3dcc435..3b3cc299 100644 --- a/model/revel_controller.go +++ b/model/revel_controller.go @@ -1,11 +1,16 @@ package model -import "github.com/revel/revel/utils" +import ( + "sync" + + "github.com/revel/revel/utils" +) type RevelController struct { Reuse bool // True if the controllers are reused Set via revel.controller.reuse Stack *utils.SimpleLockStack // size set by revel.controller.stack, revel.controller.maxstack CachedMap map[string]*utils.SimpleLockStack // The map of reusable controllers + CacheMapLocked *sync.RWMutex // A locking mechanizim to prevent concurrent writes to the cache CachedStackSize int // The default size of each stack in CachedMap Set via revel.cache.controller.stack CachedStackMaxSize int // The max size of each stack in CachedMap Set via revel.cache.controller.maxstack } diff --git a/revel.go b/revel.go index d328fec9..36979889 100644 --- a/revel.go +++ b/revel.go @@ -229,6 +229,8 @@ func updateLog(inputmode string) (returnMode string) { packagePathMap[k] = v.(string) } } + } else { + RevelLog.Warn("Failed to unpack json file", "error", err, "Json", inputmode) } var newContext *config.Context diff --git a/server.go b/server.go index b9eb2d8c..f7cc6cb5 100644 --- a/server.go +++ b/server.go @@ -9,6 +9,7 @@ import ( "os" "strconv" "strings" + "sync" "github.com/revel/revel/session" "github.com/revel/revel/utils" @@ -146,6 +147,7 @@ func initControllerStack() { RevelConfig.Controller.CachedStackSize = Config.IntDefault("revel.cache.controller.stack", 10) RevelConfig.Controller.CachedStackMaxSize = Config.IntDefault("revel.cache.controller.maxstack", 100) RevelConfig.Controller.CachedMap = map[string]*utils.SimpleLockStack{} + RevelConfig.Controller.CacheMapLocked = &sync.RWMutex{} } }