diff options
author | zeripath <art27@cantab.net> | 2022-02-27 19:45:06 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-27 19:45:06 +0000 |
commit | 4697735c8da31fb0c48686e0b02634df86de1319 (patch) | |
tree | 0cd09c1a5d097fc277a6c94b9fb7b030af67c0fa /modules/nosql/manager_leveldb.go | |
parent | 548adb94b4435b1304151150aa926f09a7a62255 (diff) | |
download | gitea-4697735c8da31fb0c48686e0b02634df86de1319.tar.gz gitea-4697735c8da31fb0c48686e0b02634df86de1319.zip |
Adjust error for already locked db and prevent level db lock on malformed connstr (#18923)
This PR adjusts the error returned when there is failure to lock the level db, and
permits a connections to the same leveldb where there is a different connection string.
Reference #18921
Reference #18917
Signed-off-by: Andrew Thornton <art27@cantab.net>
Diffstat (limited to 'modules/nosql/manager_leveldb.go')
-rw-r--r-- | modules/nosql/manager_leveldb.go | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/modules/nosql/manager_leveldb.go b/modules/nosql/manager_leveldb.go index eeb0cf74d9..97f917af78 100644 --- a/modules/nosql/manager_leveldb.go +++ b/modules/nosql/manager_leveldb.go @@ -5,10 +5,12 @@ package nosql import ( + "fmt" "path" "strconv" "strings" + "code.gitea.io/gitea/modules/log" "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/errors" "github.com/syndtr/goleveldb/leveldb/opt" @@ -20,8 +22,16 @@ func (m *Manager) CloseLevelDB(connection string) error { defer m.mutex.Unlock() db, ok := m.LevelDBConnections[connection] if !ok { - connection = ToLevelDBURI(connection).String() - db, ok = m.LevelDBConnections[connection] + // Try the full URI + uri := ToLevelDBURI(connection) + db, ok = m.LevelDBConnections[uri.String()] + + if !ok { + // Try the datadir directly + dataDir := path.Join(uri.Host, uri.Path) + + db, ok = m.LevelDBConnections[dataDir] + } } if !ok { return nil @@ -40,6 +50,12 @@ func (m *Manager) CloseLevelDB(connection string) error { // GetLevelDB gets a levelDB for a particular connection func (m *Manager) GetLevelDB(connection string) (*leveldb.DB, error) { + // Convert the provided connection description to the common format + uri := ToLevelDBURI(connection) + + // Get the datadir + dataDir := path.Join(uri.Host, uri.Path) + m.mutex.Lock() defer m.mutex.Unlock() db, ok := m.LevelDBConnections[connection] @@ -48,12 +64,28 @@ func (m *Manager) GetLevelDB(connection string) (*leveldb.DB, error) { return db.db, nil } - uri := ToLevelDBURI(connection) + + db, ok = m.LevelDBConnections[uri.String()] + if ok { + db.count++ + + return db.db, nil + } + + // if there is already a connection to this leveldb reuse that + // NOTE: if there differing options then only the first leveldb connection will be used + db, ok = m.LevelDBConnections[dataDir] + if ok { + db.count++ + log.Warn("Duplicate connnection to level db: %s with different connection strings. Initial connection: %s. This connection: %s", dataDir, db.name[0], connection) + db.name = append(db.name, connection) + m.LevelDBConnections[connection] = db + return db.db, nil + } db = &levelDBHolder{ - name: []string{connection, uri.String()}, + name: []string{connection, uri.String(), dataDir}, } - dataDir := path.Join(uri.Host, uri.Path) opts := &opt.Options{} for k, v := range uri.Query() { switch replacer.Replace(strings.ToLower(k)) { @@ -134,7 +166,11 @@ func (m *Manager) GetLevelDB(connection string) (*leveldb.DB, error) { db.db, err = leveldb.OpenFile(dataDir, opts) if err != nil { if !errors.IsCorrupted(err) { - return nil, err + if strings.Contains(err.Error(), "resource temporarily unavailable") { + return nil, fmt.Errorf("unable to lock level db at %s: %w", dataDir, err) + } + + return nil, fmt.Errorf("unable to open level db at %s: %w", dataDir, err) } db.db, err = leveldb.RecoverFile(dataDir, opts) if err != nil { |