Skip to content

Commit 4697735

Browse files
authored
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 <[email protected]>
1 parent 548adb9 commit 4697735

File tree

1 file changed

+42
-6
lines changed

1 file changed

+42
-6
lines changed

modules/nosql/manager_leveldb.go

+42-6
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
package nosql
66

77
import (
8+
"fmt"
89
"path"
910
"strconv"
1011
"strings"
1112

13+
"code.gitea.io/gitea/modules/log"
1214
"github.com/syndtr/goleveldb/leveldb"
1315
"github.com/syndtr/goleveldb/leveldb/errors"
1416
"github.com/syndtr/goleveldb/leveldb/opt"
@@ -20,8 +22,16 @@ func (m *Manager) CloseLevelDB(connection string) error {
2022
defer m.mutex.Unlock()
2123
db, ok := m.LevelDBConnections[connection]
2224
if !ok {
23-
connection = ToLevelDBURI(connection).String()
24-
db, ok = m.LevelDBConnections[connection]
25+
// Try the full URI
26+
uri := ToLevelDBURI(connection)
27+
db, ok = m.LevelDBConnections[uri.String()]
28+
29+
if !ok {
30+
// Try the datadir directly
31+
dataDir := path.Join(uri.Host, uri.Path)
32+
33+
db, ok = m.LevelDBConnections[dataDir]
34+
}
2535
}
2636
if !ok {
2737
return nil
@@ -40,6 +50,12 @@ func (m *Manager) CloseLevelDB(connection string) error {
4050

4151
// GetLevelDB gets a levelDB for a particular connection
4252
func (m *Manager) GetLevelDB(connection string) (*leveldb.DB, error) {
53+
// Convert the provided connection description to the common format
54+
uri := ToLevelDBURI(connection)
55+
56+
// Get the datadir
57+
dataDir := path.Join(uri.Host, uri.Path)
58+
4359
m.mutex.Lock()
4460
defer m.mutex.Unlock()
4561
db, ok := m.LevelDBConnections[connection]
@@ -48,12 +64,28 @@ func (m *Manager) GetLevelDB(connection string) (*leveldb.DB, error) {
4864

4965
return db.db, nil
5066
}
51-
uri := ToLevelDBURI(connection)
67+
68+
db, ok = m.LevelDBConnections[uri.String()]
69+
if ok {
70+
db.count++
71+
72+
return db.db, nil
73+
}
74+
75+
// if there is already a connection to this leveldb reuse that
76+
// NOTE: if there differing options then only the first leveldb connection will be used
77+
db, ok = m.LevelDBConnections[dataDir]
78+
if ok {
79+
db.count++
80+
log.Warn("Duplicate connnection to level db: %s with different connection strings. Initial connection: %s. This connection: %s", dataDir, db.name[0], connection)
81+
db.name = append(db.name, connection)
82+
m.LevelDBConnections[connection] = db
83+
return db.db, nil
84+
}
5285
db = &levelDBHolder{
53-
name: []string{connection, uri.String()},
86+
name: []string{connection, uri.String(), dataDir},
5487
}
5588

56-
dataDir := path.Join(uri.Host, uri.Path)
5789
opts := &opt.Options{}
5890
for k, v := range uri.Query() {
5991
switch replacer.Replace(strings.ToLower(k)) {
@@ -134,7 +166,11 @@ func (m *Manager) GetLevelDB(connection string) (*leveldb.DB, error) {
134166
db.db, err = leveldb.OpenFile(dataDir, opts)
135167
if err != nil {
136168
if !errors.IsCorrupted(err) {
137-
return nil, err
169+
if strings.Contains(err.Error(), "resource temporarily unavailable") {
170+
return nil, fmt.Errorf("unable to lock level db at %s: %w", dataDir, err)
171+
}
172+
173+
return nil, fmt.Errorf("unable to open level db at %s: %w", dataDir, err)
138174
}
139175
db.db, err = leveldb.RecoverFile(dataDir, opts)
140176
if err != nil {

0 commit comments

Comments
 (0)