-
Notifications
You must be signed in to change notification settings - Fork 21
/
error.go
148 lines (129 loc) · 5.52 KB
/
error.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package mdbx
/*
#include <stdlib.h>
#include <stdio.h>
#include "mdbxgo.h"
*/
import "C"
import (
"os"
"syscall"
)
// OpError is an error returned by the C API. Not all errors returned by
// lmdb-go have type OpError but typically they do. The Errno field will
// either have type Errno or syscall.Errno.
type OpError struct {
Errno error
Op string
}
// Error implements the error interface.
func (err *OpError) Error() string {
return err.Op + ": " + err.Errno.Error()
}
// Errno is an error type that represents the (unique) errno values defined by
// LMDB. Other errno values (such as EINVAL) are represented with type
// syscall.Errno. On Windows, LMDB return codes are translated into portable
// syscall.Errno constants (e.g. syscall.EINVAL, syscall.EACCES, etc.).
//
// Most often helper functions such as IsNotFound may be used instead of
// dealing with Errno values directly.
//
// lmdb.IsNotFound(err)
// lmdb.IsErrno(err, lmdb.TxnFull)
// lmdb.IsErrnoSys(err, syscall.EINVAL)
// lmdb.IsErrnoFn(err, os.IsPermission)
type Errno C.int
// The most common error codes do not need to be handled explicity. Errors can
// be checked through helper functions IsNotFound, IsMapFull, etc, Otherwise
// they should be checked using the IsErrno function instead of direct
// comparison because they will typically be wrapped with an OpError.
const (
// Error codes defined by LMDB. See the list of LMDB return codes for more
// information about each
//
// http://symas.com/mdb/doc/group__errors.html
KeyExist Errno = C.MDBX_KEYEXIST
NotFound Errno = C.MDBX_NOTFOUND
PageNotFound Errno = C.MDBX_PAGE_NOTFOUND
Corrupted Errno = C.MDBX_CORRUPTED
Panic Errno = C.MDBX_PANIC
VersionMismatch Errno = C.MDBX_VERSION_MISMATCH
Invalid Errno = C.MDBX_INVALID
MapFull Errno = C.MDBX_MAP_FULL
DBsFull Errno = C.MDBX_DBS_FULL
ReadersFull Errno = C.MDBX_READERS_FULL
TxnFull Errno = C.MDBX_TXN_FULL
CursorFull Errno = C.MDBX_CURSOR_FULL
PageFull Errno = C.MDBX_PAGE_FULL
Incompatible Errno = C.MDBX_INCOMPATIBLE
BadRSlot Errno = C.MDBX_BAD_RSLOT
BadTxn Errno = C.MDBX_BAD_TXN
BadValSize Errno = C.MDBX_BAD_VALSIZE
BadDBI Errno = C.MDBX_BAD_DBI
Perm Errno = C.MDBX_EPERM
//TLSFull Errno = C.MDBX_TLS_FULL
//MapResized Errno = C.MDBX_MAP_RESIZED
)
// minimum and maximum values produced for the Errno type. syscall.Errnos of
// other values may still be produced.
const minErrno, maxErrno C.int = C.MDBX_KEYEXIST, C.MDBX_LAST_ADDED_ERRCODE
// App can re-define this messages from init() func
var CorruptErrorHardwareRecommendations = "Maybe free space is over on disk. Otherwise it's hardware failure. Before creating issue please use tools like https://www.memtest86.com to test RAM and tools like https://www.smartmontools.org to test Disk. To handle hardware risks: use ECC RAM, use RAID of disks, run multiple application instances (or do backups). If hardware checks passed - check FS settings - 'fsync' and 'flock' must be enabled. "
var CorruptErrorBacktraceRecommendations = "Otherwise - please create issue in Application repo." // with backtrace or coredump. To create coredump set compile option 'MDBX_FORCE_ASSERTIONS=1' and env variable 'GOTRACEBACK=crash'."
var CorruptErrorRecoveryRecommendations = "On default DURABLE mode, power outage can't cause this error. On other modes - power outage may break last transaction and mdbx_chk can recover db in this case, see '-t' and '-0|1|2' options."
var CorruptErrorMessage = CorruptErrorHardwareRecommendations + " " + CorruptErrorBacktraceRecommendations + " " + CorruptErrorRecoveryRecommendations
func (e Errno) Error() string {
if e == Corrupted {
return "MDBX_CORRUPTED: " + CorruptErrorMessage
} else if e == Panic {
return "MDBX_PANIC: " + CorruptErrorMessage
}
return C.GoString(C.mdbx_strerror(C.int(e)))
}
// _operrno is for use by tests that can't import C
func _operrno(op string, ret int) error {
return operrno(op, C.int(ret))
}
// IsNotFound returns true if the key requested in Txn.Get or Cursor.Get does
// not exist or if the Cursor reached the end of the database without locating
// a value (EOF).
func IsNotFound(err error) bool {
return IsErrno(err, NotFound)
}
func IsKeyExists(err error) bool {
return IsErrno(err, KeyExist)
}
// IsNotExist returns true the path passed to the Env.Open method does not
// exist.
func IsNotExist(err error) bool {
return IsErrnoFn(err, os.IsNotExist)
}
// IsMapFull returns true if the environment map size has been reached.
func IsMapFull(err error) bool {
return IsErrno(err, MapFull)
}
// IsMapResized returns true if the environment has grown too large for the
// current map after being resized by another process.
//func IsMapResized(err error) bool {
// return IsErrno(err, MapResized)
//}
// IsErrno returns true if err's errno is the given errno.
func IsErrno(err error, errno Errno) bool {
return IsErrnoFn(err, func(err error) bool { return err == errno }) //nolint:goerr113
}
// IsErrnoSys returns true if err's errno is the given errno.
func IsErrnoSys(err error, errno syscall.Errno) bool {
return IsErrnoFn(err, func(err error) bool { return err == errno }) //nolint:goerr113
}
// IsErrnoFn calls fn on the error underlying err and returns the result. If
// err is an *OpError then err.Errno is passed to fn. Otherwise err is passed
// directly to fn.
func IsErrnoFn(err error, fn func(error) bool) bool {
if err == nil {
return false
}
if err, ok := err.(*OpError); ok {
return fn(err.Errno)
}
return fn(err)
}