diff --git a/caches/manager.go b/caches/manager.go new file mode 100644 index 00000000..05045210 --- /dev/null +++ b/caches/manager.go @@ -0,0 +1,56 @@ +// Copyright 2020 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package caches + +import "sync" + +type Manager struct { + cacher Cacher + disableGlobalCache bool + + cachers map[string]Cacher + cacherLock sync.RWMutex +} + +func NewManager() *Manager { + return &Manager{ + cachers: make(map[string]Cacher), + } +} + +// SetDisableGlobalCache disable global cache or not +func (mgr *Manager) SetDisableGlobalCache(disable bool) { + if mgr.disableGlobalCache != disable { + mgr.disableGlobalCache = disable + } +} + +func (mgr *Manager) SetCacher(tableName string, cacher Cacher) { + mgr.cacherLock.Lock() + mgr.cachers[tableName] = cacher + mgr.cacherLock.Unlock() +} + +func (mgr *Manager) GetCacher(tableName string) Cacher { + var cacher Cacher + var ok bool + mgr.cacherLock.RLock() + cacher, ok = mgr.cachers[tableName] + mgr.cacherLock.RUnlock() + if !ok && !mgr.disableGlobalCache { + cacher = mgr.cacher + } + return cacher +} + +// SetDefaultCacher set the default cacher. Xorm's default not enable cacher. +func (mgr *Manager) SetDefaultCacher(cacher Cacher) { + mgr.cacher = cacher +} + +// GetDefaultCacher returns the default cacher +func (mgr *Manager) GetDefaultCacher() Cacher { + return mgr.cacher +} diff --git a/engine.go b/engine.go index 1ab2eed2..68de5196 100644 --- a/engine.go +++ b/engine.go @@ -40,8 +40,7 @@ type Engine struct { TagIdentifier string Tables map[reflect.Type]*schemas.Table - mutex *sync.RWMutex - Cacher caches.Cacher + mutex *sync.RWMutex showSQL bool showExecTime bool @@ -50,42 +49,20 @@ type Engine struct { TZLocation *time.Location // The timezone of the application DatabaseTZ *time.Location // The timezone of the database - disableGlobalCache bool - tagHandlers map[string]tagHandler engineGroup *EngineGroup - - cachers map[string]caches.Cacher - cacherLock sync.RWMutex + cacherMgr *caches.Manager defaultContext context.Context } -func (engine *Engine) setCacher(tableName string, cacher caches.Cacher) { - engine.cacherLock.Lock() - engine.cachers[tableName] = cacher - engine.cacherLock.Unlock() -} - func (engine *Engine) SetCacher(tableName string, cacher caches.Cacher) { - engine.setCacher(tableName, cacher) -} - -func (engine *Engine) getCacher(tableName string) caches.Cacher { - var cacher caches.Cacher - var ok bool - engine.cacherLock.RLock() - cacher, ok = engine.cachers[tableName] - engine.cacherLock.RUnlock() - if !ok && !engine.disableGlobalCache { - cacher = engine.Cacher - } - return cacher + engine.cacherMgr.SetCacher(tableName, cacher) } func (engine *Engine) GetCacher(tableName string) caches.Cacher { - return engine.getCacher(tableName) + return engine.cacherMgr.GetCacher(tableName) } // BufferSize sets buffer size for iterate @@ -152,9 +129,7 @@ func (engine *Engine) SetLogLevel(level log.LogLevel) { // SetDisableGlobalCache disable global cache or not func (engine *Engine) SetDisableGlobalCache(disable bool) { - if engine.disableGlobalCache != disable { - engine.disableGlobalCache = disable - } + engine.cacherMgr.SetDisableGlobalCache(disable) } // DriverName return the current sql driver's name @@ -244,12 +219,12 @@ func (engine *Engine) SetMaxIdleConns(conns int) { // SetDefaultCacher set the default cacher. Xorm's default not enable cacher. func (engine *Engine) SetDefaultCacher(cacher caches.Cacher) { - engine.Cacher = cacher + engine.cacherMgr.SetDefaultCacher(cacher) } // GetDefaultCacher returns the default cacher func (engine *Engine) GetDefaultCacher() caches.Cacher { - return engine.Cacher + return engine.cacherMgr.GetDefaultCacher() } // NoCache If you has set default cacher, and you want temporilly stop use cache, @@ -269,7 +244,7 @@ func (engine *Engine) NoCascade() *Session { // MapCacher Set a table use a special cacher func (engine *Engine) MapCacher(bean interface{}, cacher caches.Cacher) error { - engine.setCacher(engine.TableName(bean, true), cacher) + engine.SetCacher(engine.TableName(bean, true), cacher) return nil } @@ -799,7 +774,7 @@ func (engine *Engine) autoMapType(v reflect.Value) (*schemas.Table, error) { } engine.Tables[t] = table - if engine.Cacher != nil { + if engine.GetDefaultCacher() != nil { if v.CanAddr() { engine.GobRegister(v.Addr().Interface()) } else { @@ -1030,17 +1005,17 @@ func (engine *Engine) mapType(v reflect.Value) (*schemas.Table, error) { } if hasCacheTag { - if engine.Cacher != nil { // !nash! use engine's cacher if provided + if engine.GetDefaultCacher() != nil { // !nash! use engine's cacher if provided engine.logger.Info("enable cache on table:", table.Name) - engine.setCacher(table.Name, engine.Cacher) + engine.SetCacher(table.Name, engine.GetDefaultCacher()) } else { engine.logger.Info("enable LRU cache on table:", table.Name) - engine.setCacher(table.Name, caches.NewLRUCacher2(caches.NewMemoryStore(), time.Hour, 10000)) + engine.SetCacher(table.Name, caches.NewLRUCacher2(caches.NewMemoryStore(), time.Hour, 10000)) } } if hasNoCacheTag { engine.logger.Info("disable cache on table:", table.Name) - engine.setCacher(table.Name, nil) + engine.SetCacher(table.Name, nil) } return table, nil @@ -1152,7 +1127,7 @@ func (engine *Engine) CreateUniques(bean interface{}) error { // ClearCacheBean if enabled cache, clear the cache bean func (engine *Engine) ClearCacheBean(bean interface{}, id string) error { tableName := engine.TableName(bean) - cacher := engine.getCacher(tableName) + cacher := engine.GetCacher(tableName) if cacher != nil { cacher.ClearIds(tableName) cacher.DelBean(tableName, id) @@ -1164,7 +1139,7 @@ func (engine *Engine) ClearCacheBean(bean interface{}, id string) error { func (engine *Engine) ClearCache(beans ...interface{}) error { for _, bean := range beans { tableName := engine.TableName(bean) - cacher := engine.getCacher(tableName) + cacher := engine.GetCacher(tableName) if cacher != nil { cacher.ClearIds(tableName) cacher.ClearBeans(tableName) diff --git a/session_delete.go b/session_delete.go index 2afe068d..94cf833d 100644 --- a/session_delete.go +++ b/session_delete.go @@ -28,7 +28,7 @@ func (session *Session) cacheDelete(table *schemas.Table, tableName, sqlStr stri return ErrCacheFailed } - cacher := session.engine.getCacher(tableName) + cacher := session.engine.GetCacher(tableName) pkColumns := table.PKColumns() ids, err := caches.GetCacheSql(cacher, tableName, newsql, args) if err != nil { @@ -206,7 +206,7 @@ func (session *Session) Delete(bean interface{}) (int64, error) { }) } - if cacher := session.engine.getCacher(tableNameNoQuote); cacher != nil && session.statement.UseCache { + if cacher := session.engine.GetCacher(tableNameNoQuote); cacher != nil && session.statement.UseCache { session.cacheDelete(table, tableNameNoQuote, deleteSQL, argsForCache...) } diff --git a/session_find.go b/session_find.go index 251691b1..cdf086d0 100644 --- a/session_find.go +++ b/session_find.go @@ -183,7 +183,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) } if session.canCache() { - if cacher := session.engine.getCacher(session.statement.TableName()); cacher != nil && + if cacher := session.engine.GetCacher(session.statement.TableName()); cacher != nil && !session.statement.IsDistinct && !session.statement.unscoped { err = session.cacheFind(sliceElementType, sqlStr, rowsSlicePtr, args...) @@ -329,7 +329,7 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in } tableName := session.statement.TableName() - cacher := session.engine.getCacher(tableName) + cacher := session.engine.GetCacher(tableName) if cacher == nil { return nil } diff --git a/session_get.go b/session_get.go index c42361a8..fd66c438 100644 --- a/session_get.go +++ b/session_get.go @@ -65,7 +65,7 @@ func (session *Session) get(bean interface{}) (bool, error) { table := session.statement.RefTable if session.canCache() && beanValue.Elem().Kind() == reflect.Struct { - if cacher := session.engine.getCacher(session.statement.TableName()); cacher != nil && + if cacher := session.engine.GetCacher(session.statement.TableName()); cacher != nil && !session.statement.unscoped { has, err := session.cacheGet(bean, sqlStr, args...) if err != ErrCacheFailed { @@ -280,7 +280,7 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf } tableName := session.statement.TableName() - cacher := session.engine.getCacher(tableName) + cacher := session.engine.GetCacher(tableName) session.engine.logger.Debug("[cache] Get SQL:", newsql, args) table := session.statement.RefTable diff --git a/session_insert.go b/session_insert.go index b788e629..fcd7b2b5 100644 --- a/session_insert.go +++ b/session_insert.go @@ -613,7 +613,7 @@ func (session *Session) cacheInsert(table string) error { if !session.statement.UseCache { return nil } - cacher := session.engine.getCacher(table) + cacher := session.engine.GetCacher(table) if cacher == nil { return nil } diff --git a/session_update.go b/session_update.go index c95b23c5..c1f1e0bf 100644 --- a/session_update.go +++ b/session_update.go @@ -42,7 +42,7 @@ func (session *Session) cacheUpdate(table *schemas.Table, tableName, sqlStr stri } } - cacher := session.engine.getCacher(tableName) + cacher := session.engine.GetCacher(tableName) session.engine.logger.Debug("[cacheUpdate] get cache sql", newsql, args[nStart:]) ids, err := caches.GetCacheSql(cacher, tableName, newsql, args[nStart:]) if err != nil { @@ -412,7 +412,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 } } - if cacher := session.engine.getCacher(tableName); cacher != nil && session.statement.UseCache { + if cacher := session.engine.GetCacher(tableName); cacher != nil && session.statement.UseCache { // session.cacheUpdate(table, tableName, sqlStr, args...) session.engine.logger.Debug("[cacheUpdate] clear table ", tableName) cacher.ClearIds(tableName) diff --git a/xorm.go b/xorm.go index e7e98739..0f27f8e4 100644 --- a/xorm.go +++ b/xorm.go @@ -68,8 +68,8 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) { TagIdentifier: "xorm", TZLocation: time.Local, tagHandlers: defaultTagHandlers, - cachers: make(map[string]caches.Cacher), defaultContext: context.Background(), + cacherMgr: caches.NewManager(), } if uri.DBType == schemas.SQLITE {