aboutsummaryrefslogtreecommitdiffstats
path: root/modules/nosql/manager_leveldb.go
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2022-02-27 19:45:06 +0000
committerGitHub <noreply@github.com>2022-02-27 19:45:06 +0000
commit4697735c8da31fb0c48686e0b02634df86de1319 (patch)
tree0cd09c1a5d097fc277a6c94b9fb7b030af67c0fa /modules/nosql/manager_leveldb.go
parent548adb94b4435b1304151150aa926f09a7a62255 (diff)
downloadgitea-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.go48
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 {