aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeripath2022-02-28 15:45:38 +0000
committerGitHub2022-02-28 15:45:38 +0000
commit5f9c18b2b3053ff7d410625974f87d01d3c82b52 (patch)
tree984e565f5dc314f874d9c5b4aff57f879bf2341d
parent4384b85046c3fffe11d0dc459a5b64604337a72f (diff)
Adjust error for already locked db and prevent level db lock on malformed connstr (#18923) (#18938)
Backport #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>
-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 eeb0cf74d..97f917af7 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 {